You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
16 KiB
485 lines
16 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* 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 <GLcommon/ShareGroup.h>
|
|
#include <GLcommon/ObjectNameSpace.h>
|
|
#include <GLcommon/GLEScontext.h>
|
|
|
|
#include "base/Lock.h"
|
|
#include "base/Lookup.h"
|
|
#include "GLcommon/FramebufferData.h"
|
|
|
|
#include "host-common/logging.h"
|
|
|
|
#include <array>
|
|
#include <utility>
|
|
|
|
static constexpr int toIndex(NamedObjectType type) {
|
|
return static_cast<int>(type);
|
|
}
|
|
|
|
struct ShareGroup::ObjectDataAutoLock {
|
|
ObjectDataAutoLock(ShareGroup* self) : self(self) {
|
|
self->lockObjectData();
|
|
}
|
|
~ObjectDataAutoLock() {
|
|
self->unlockObjectData();
|
|
}
|
|
|
|
ShareGroup* self;
|
|
};
|
|
|
|
ShareGroup::ShareGroup(GlobalNameSpace *globalNameSpace,
|
|
uint64_t sharedGroupID,
|
|
android::base::Stream* stream,
|
|
const ObjectData::loadObject_t& loadObject) :
|
|
m_sharedGroupID(sharedGroupID) {
|
|
ObjectDataAutoLock lock(this);
|
|
for (int i = 0; i < toIndex(NamedObjectType::NUM_OBJECT_TYPES);
|
|
i++) {
|
|
m_nameSpace[i] = new NameSpace(static_cast<NamedObjectType>(i),
|
|
globalNameSpace, stream, loadObject);
|
|
}
|
|
if (stream) {
|
|
m_needLoadRestore = true;
|
|
int i = 0;
|
|
for (auto ns : m_nameSpace) {
|
|
GL_LOG("ShareGroup::%s: %p: start restore namespace for type %d\n", __func__, this, i);
|
|
ns->postLoad(
|
|
[this](NamedObjectType p_type, ObjectLocalName p_localName) {
|
|
return this->getObjectDataPtrNoLock(p_type, p_localName);
|
|
});
|
|
GL_LOG("ShareGroup::%s: %p: finish restore namespace for type %d\n", __func__, this, i);
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ShareGroup::preSave(GlobalNameSpace *globalNameSpace) {
|
|
ObjectDataAutoLock lock(this);
|
|
if (m_saveStage == PreSaved) return;
|
|
assert(m_saveStage == Empty);
|
|
m_saveStage = PreSaved;
|
|
m_nameSpace[(int)NamedObjectType::TEXTURE]->preSave(globalNameSpace);
|
|
}
|
|
|
|
void ShareGroup::onSave(android::base::Stream* stream) {
|
|
// we do not save m_nameSpace
|
|
ObjectDataAutoLock lock(this);
|
|
if (m_saveStage == Saved) return;
|
|
assert(m_saveStage == PreSaved);
|
|
m_saveStage = Saved;
|
|
int i = 0;
|
|
for (auto ns : m_nameSpace) {
|
|
GL_LOG("ShareGroup::%s: %p: start saving type %d\n", __func__, this, i);
|
|
ns->onSave(stream);
|
|
GL_LOG("ShareGroup::%s: %p: finish saving type %d\n", __func__, this, i);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
void ShareGroup::postSave(android::base::Stream* stream) {
|
|
(void)stream;
|
|
m_saveStage = Empty;
|
|
// We need to mark the textures dirty, for those that has been bound to
|
|
// a potential render target.
|
|
NameSpace* renderbufferNs = m_nameSpace[(int)NamedObjectType::RENDERBUFFER];
|
|
for (ObjectDataMap::const_iterator it = renderbufferNs->objDataMapBegin();
|
|
it != renderbufferNs->objDataMapEnd();
|
|
it ++) {
|
|
RenderbufferData* rbData = (RenderbufferData*)it->second.get();
|
|
rbData->makeTextureDirty();
|
|
}
|
|
}
|
|
|
|
void ShareGroup::postLoadRestore() {
|
|
android::base::AutoLock lock(m_restoreLock);
|
|
if (m_needLoadRestore) {
|
|
int i = 0;
|
|
for (auto ns : m_nameSpace) {
|
|
GL_LOG("ShareGroup::%s: %p: start post load restore namespace for type %d\n", __func__, this, i);
|
|
ns->postLoadRestore([this](NamedObjectType p_type,
|
|
ObjectLocalName p_localName) {
|
|
return getGlobalName(p_type, p_localName);
|
|
});
|
|
GL_LOG("ShareGroup::%s: %p: end post load restore namespace for type %d\n", __func__, this, i);
|
|
++i;
|
|
}
|
|
m_needLoadRestore = false;
|
|
}
|
|
}
|
|
|
|
bool ShareGroup::needRestore() {
|
|
return m_needLoadRestore;
|
|
}
|
|
|
|
void ShareGroup::lockObjectData() {
|
|
while (m_objectsDataLock.test_and_set(std::memory_order_acquire)) {
|
|
;
|
|
}
|
|
}
|
|
|
|
void ShareGroup::unlockObjectData() {
|
|
m_objectsDataLock.clear(std::memory_order_release);
|
|
}
|
|
|
|
ShareGroup::~ShareGroup()
|
|
{
|
|
{
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
ObjectDataAutoLock objDataLock(this);
|
|
for (auto n : m_nameSpace) {
|
|
delete n;
|
|
}
|
|
}
|
|
}
|
|
|
|
ObjectLocalName
|
|
ShareGroup::genName(GenNameInfo genNameInfo,
|
|
ObjectLocalName p_localName,
|
|
bool genLocal)
|
|
{
|
|
assert(genNameInfo.m_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(genNameInfo.m_type) >=
|
|
toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return 0;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
ObjectLocalName localName =
|
|
m_nameSpace[toIndex(genNameInfo.m_type)]->genName(
|
|
genNameInfo,
|
|
p_localName, genLocal);
|
|
return localName;
|
|
}
|
|
|
|
ObjectLocalName ShareGroup::genName(NamedObjectType namedObjectType,
|
|
ObjectLocalName p_localName,
|
|
bool genLocal) {
|
|
return genName(GenNameInfo(namedObjectType), p_localName, genLocal);
|
|
}
|
|
|
|
ObjectLocalName ShareGroup::genName(ShaderProgramType shaderProgramType,
|
|
ObjectLocalName p_localName,
|
|
bool genLocal,
|
|
GLuint existingGlobal) {
|
|
return genName(GenNameInfo(shaderProgramType, existingGlobal), p_localName, genLocal);
|
|
}
|
|
|
|
unsigned int
|
|
ShareGroup::getGlobalName(NamedObjectType p_type,
|
|
ObjectLocalName p_localName)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return 0;
|
|
}
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
return m_nameSpace[toIndex(p_type)]->getGlobalName(p_localName);
|
|
}
|
|
|
|
ObjectLocalName
|
|
ShareGroup::getLocalName(NamedObjectType p_type,
|
|
unsigned int p_globalName)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return 0;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
return m_nameSpace[toIndex(p_type)]->getLocalName(p_globalName);
|
|
}
|
|
|
|
NamedObjectPtr ShareGroup::getNamedObject(NamedObjectType p_type,
|
|
ObjectLocalName p_localName) {
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return 0;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
return m_nameSpace[toIndex(p_type)]->getNamedObject(p_localName);
|
|
}
|
|
|
|
void
|
|
ShareGroup::deleteName(NamedObjectType p_type, ObjectLocalName p_localName)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
ObjectDataAutoLock objDataLock(this);
|
|
m_nameSpace[toIndex(p_type)]->deleteName(p_localName);
|
|
}
|
|
|
|
bool
|
|
ShareGroup::isObject(NamedObjectType p_type, ObjectLocalName p_localName)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return 0;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
return m_nameSpace[toIndex(p_type)]->isObject(p_localName);
|
|
}
|
|
|
|
void
|
|
ShareGroup::replaceGlobalObject(NamedObjectType p_type,
|
|
ObjectLocalName p_localName,
|
|
NamedObjectPtr p_globalObject)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
m_nameSpace[toIndex(p_type)]->replaceGlobalObject(p_localName,
|
|
p_globalObject);
|
|
}
|
|
|
|
void
|
|
ShareGroup::setGlobalObject(NamedObjectType p_type,
|
|
ObjectLocalName p_localName,
|
|
NamedObjectPtr p_globalObject)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return;
|
|
}
|
|
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
m_nameSpace[toIndex(p_type)]->setGlobalObject(p_localName,
|
|
p_globalObject);
|
|
}
|
|
|
|
void
|
|
ShareGroup::setObjectData(NamedObjectType p_type,
|
|
ObjectLocalName p_localName,
|
|
ObjectDataPtr data) {
|
|
ObjectDataAutoLock lock(this);
|
|
setObjectDataLocked(p_type, p_localName, std::move(data));
|
|
}
|
|
|
|
void
|
|
ShareGroup::setObjectDataLocked(NamedObjectType p_type,
|
|
ObjectLocalName p_localName,
|
|
ObjectDataPtr&& data)
|
|
{
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
if (toIndex(p_type) >= toIndex(NamedObjectType::NUM_OBJECT_TYPES)) {
|
|
return;
|
|
}
|
|
m_nameSpace[toIndex(p_type)]->setObjectData(p_localName, data);
|
|
}
|
|
|
|
const ObjectDataPtr& ShareGroup::getObjectDataPtrNoLock(
|
|
NamedObjectType p_type, ObjectLocalName p_localName) {
|
|
assert(p_type != NamedObjectType::FRAMEBUFFER);
|
|
return m_nameSpace[toIndex(p_type)]->getObjectDataPtr(p_localName);
|
|
}
|
|
|
|
ObjectData* ShareGroup::getObjectData(NamedObjectType p_type,
|
|
ObjectLocalName p_localName) {
|
|
if (toIndex(p_type) >=
|
|
toIndex(NamedObjectType::NUM_OBJECT_TYPES))
|
|
return nullptr;
|
|
|
|
ObjectDataAutoLock lock(this);
|
|
return getObjectDataPtrNoLock(p_type, p_localName).get();
|
|
}
|
|
|
|
ObjectDataPtr ShareGroup::getObjectDataPtr(NamedObjectType p_type,
|
|
ObjectLocalName p_localName)
|
|
{
|
|
if (toIndex(p_type) >=
|
|
toIndex(NamedObjectType::NUM_OBJECT_TYPES))
|
|
return {};
|
|
|
|
ObjectDataAutoLock lock(this);
|
|
return getObjectDataPtrNoLock(p_type, p_localName);
|
|
}
|
|
|
|
#define CC_LIKELY( exp ) (__builtin_expect( !!(exp), true ))
|
|
#define CC_UNLIKELY( exp ) (__builtin_expect( !!(exp), false ))
|
|
|
|
unsigned int ShareGroup::ensureObjectOnBind(NamedObjectType p_type, ObjectLocalName p_localName) {
|
|
android::base::AutoLock lock(m_namespaceLock);
|
|
|
|
auto ns = m_nameSpace[toIndex(p_type)];
|
|
|
|
bool isObj;
|
|
unsigned int globalName = ns->getGlobalName(p_localName, &isObj);
|
|
|
|
if (CC_LIKELY(isObj)) {
|
|
bool everBound = ns->everBound(p_localName);
|
|
if (CC_LIKELY(everBound)) return globalName;
|
|
|
|
auto ptr = ns->getObjectDataPtr(p_localName);
|
|
|
|
if (ptr) {
|
|
switch (p_type) {
|
|
case NamedObjectType::VERTEXBUFFER: {
|
|
auto vbo = ((GLESbuffer*)(ptr.get()));
|
|
vbo->setBinded();
|
|
break;
|
|
}
|
|
// TODO: Add other object types here
|
|
default:
|
|
fprintf(stderr, "%s: Warning: Unhandled object type 0x%x\n",
|
|
__func__, (uint32_t)p_type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ns->setBoundAtLeastOnce(p_localName);
|
|
return globalName;
|
|
}
|
|
|
|
// No such object, generate one and bind it
|
|
bool genLocal = false;
|
|
auto gi = GenNameInfo(p_type);
|
|
ns->genName( gi, p_localName, genLocal);
|
|
|
|
switch (p_type) {
|
|
case NamedObjectType::VERTEXBUFFER: {
|
|
auto vbo = new GLESbuffer;
|
|
vbo->setBinded();
|
|
ns->setObjectData(p_localName, ObjectDataPtr(vbo));
|
|
break;
|
|
}
|
|
// TODO: Add other object types here
|
|
default:
|
|
fprintf(stderr, "%s: Warning: Unhandled object type 0x%x\n",
|
|
__func__, (uint32_t)p_type);
|
|
break;
|
|
}
|
|
|
|
ns->setBoundAtLeastOnce(p_localName);
|
|
return (uint32_t)(ns->getGlobalName(p_localName));
|
|
}
|
|
|
|
ObjectNameManager::ObjectNameManager(GlobalNameSpace *globalNameSpace) :
|
|
m_globalNameSpace(globalNameSpace) {}
|
|
|
|
ShareGroupPtr
|
|
ObjectNameManager::createShareGroup(void *p_groupName, uint64_t sharedGroupID,
|
|
android::base::Stream* stream, const ObjectData::loadObject_t& loadObject)
|
|
{
|
|
android::base::AutoLock lock(m_lock);
|
|
|
|
ShareGroupPtr& shareGroupReturn = m_groups[p_groupName];
|
|
if (!shareGroupReturn) {
|
|
if (!sharedGroupID) {
|
|
while (m_nextSharedGroupID == 0 ||
|
|
android::base::contains(m_usedSharedGroupIDs,
|
|
m_nextSharedGroupID)) {
|
|
m_nextSharedGroupID ++;
|
|
}
|
|
sharedGroupID = m_nextSharedGroupID;
|
|
m_usedSharedGroupIDs.insert(sharedGroupID);
|
|
++m_nextSharedGroupID;
|
|
} else {
|
|
assert(!m_usedSharedGroupIDs.count(sharedGroupID));
|
|
m_usedSharedGroupIDs.insert(sharedGroupID);
|
|
}
|
|
shareGroupReturn.reset(new ShareGroup(m_globalNameSpace, sharedGroupID,
|
|
stream, loadObject));
|
|
} else {
|
|
assert(sharedGroupID == 0
|
|
|| sharedGroupID == shareGroupReturn->getId());
|
|
}
|
|
|
|
return shareGroupReturn;
|
|
}
|
|
|
|
ShareGroupPtr
|
|
ObjectNameManager::getShareGroup(void *p_groupName)
|
|
{
|
|
android::base::AutoLock lock(m_lock);
|
|
|
|
ShareGroupPtr shareGroupReturn;
|
|
|
|
ShareGroupsMap::iterator s( m_groups.find(p_groupName) );
|
|
if (s != m_groups.end()) {
|
|
shareGroupReturn = (*s).second;
|
|
}
|
|
|
|
return shareGroupReturn;
|
|
}
|
|
|
|
ShareGroupPtr
|
|
ObjectNameManager::attachShareGroup(void *p_groupName,
|
|
void *p_existingGroupName)
|
|
{
|
|
android::base::AutoLock lock(m_lock);
|
|
|
|
ShareGroupsMap::iterator s( m_groups.find(p_existingGroupName) );
|
|
if (s == m_groups.end()) {
|
|
// ShareGroup is not found !!!
|
|
return ShareGroupPtr();
|
|
}
|
|
|
|
ShareGroupPtr shareGroupReturn((*s).second);
|
|
if (m_groups.find(p_groupName) == m_groups.end()) {
|
|
m_groups.emplace(p_groupName, shareGroupReturn);
|
|
m_usedSharedGroupIDs.insert(shareGroupReturn->getId());
|
|
}
|
|
return shareGroupReturn;
|
|
}
|
|
|
|
ShareGroupPtr ObjectNameManager::attachOrCreateShareGroup(void *p_groupName,
|
|
uint64_t p_existingGroupID, android::base::Stream* stream,
|
|
const ObjectData::loadObject_t& loadObject) {
|
|
assert(m_groups.find(p_groupName) == m_groups.end());
|
|
ShareGroupsMap::iterator ite = p_existingGroupID ? m_groups.begin()
|
|
: m_groups.end();
|
|
while (ite != m_groups.end() && ite->second->getId() != p_existingGroupID) {
|
|
++ite;
|
|
}
|
|
if (ite == m_groups.end()) {
|
|
return createShareGroup(p_groupName, p_existingGroupID, stream,
|
|
loadObject);
|
|
} else {
|
|
return attachShareGroup(p_groupName, ite->first);
|
|
}
|
|
}
|
|
|
|
void
|
|
ObjectNameManager::deleteShareGroup(void *p_groupName)
|
|
{
|
|
android::base::AutoLock lock(m_lock);
|
|
auto sharedGroup = m_groups.find(p_groupName);
|
|
if (sharedGroup == m_groups.end()) return;
|
|
m_usedSharedGroupIDs.erase(sharedGroup->second->getId());
|
|
m_groups.erase(sharedGroup);
|
|
}
|
|
|
|
void *ObjectNameManager::getGlobalContext()
|
|
{
|
|
android::base::AutoLock lock(m_lock);
|
|
return m_groups.empty() ? nullptr : m_groups.begin()->first;
|
|
}
|
|
|
|
void ObjectNameManager::preSave() {
|
|
for (auto& shareGroup : m_groups) {
|
|
shareGroup.second->preSave(m_globalNameSpace);
|
|
}
|
|
}
|