Skip to content

Commit

Permalink
Refactor|libgui: Added abstract IAtlas interface
Browse files Browse the repository at this point in the history
More flexibility for TextureBank and ModelDrawable:
MultiAtlas::AllocGroup can be used instead of a regular atlas.
  • Loading branch information
skyjake committed Oct 25, 2015
1 parent 7a952fd commit c037512
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 42 deletions.
56 changes: 38 additions & 18 deletions doomsday/sdk/libgui/include/de/graphics/atlas.h
Expand Up @@ -31,6 +31,26 @@

namespace de {

/**
* Interface for any Atlas-type class. @ingroup gl
*
* The allocations must be committed before being used.
*/
class LIBGUI_PUBLIC IAtlas
{
public:
DENG2_ERROR(OutOfSpaceError);

virtual ~IAtlas() {}

virtual Id alloc(Image const &image, Id const &chosenId = Id::None) = 0;
virtual void release(Id const &id) = 0;
virtual bool contains(Id const &id) const = 0;
virtual void commit() const = 0;

virtual Rectanglef imageRectf(Id const &id) const = 0;
};

/**
* Abstract image-based atlas.
*
Expand All @@ -39,7 +59,7 @@ namespace de {
*
* @ingroup gl
*/
class LIBGUI_PUBLIC Atlas : public Lockable
class LIBGUI_PUBLIC Atlas : public IAtlas, public Lockable
{
public:
typedef Image::Size Size;
Expand Down Expand Up @@ -201,16 +221,29 @@ class LIBGUI_PUBLIC Atlas : public Lockable
* @return Identifier of the allocated image. If Id::None, the allocation
* failed because the atlas is too full.
*/
Id alloc(Image const &image, Id const &chosenId = Id::None);
Id alloc(Image const &image, Id const &chosenId = Id::None) override;

/**
* Releases a previously allocated image from the atlas.
*
* @param id Identifier of an allocated image.
*/
void release(Id const &id);
void release(Id const &id) override;

bool contains(Id const &id) const override;

/**
* Request committing the backing store to the physical atlas storage.
* This does nothing if there are no changes in the atlas.
*
* Deferred commits will also be committed.
*/
void commit() const override;

bool contains(Id const &id) const;
/**
* Deferred allocations will all be cancelled.
*/
void cancelDeferred();

/**
* Returns the number of images in the atlas.
Expand Down Expand Up @@ -242,7 +275,7 @@ class LIBGUI_PUBLIC Atlas : public Lockable
* @return Normalized coordinates of the image on the atlas. Always within
* [0,1].
*/
Rectanglef imageRectf(Id const &id) const;
Rectanglef imageRectf(Id const &id) const override;

/**
* Returns the image content allocated earlier. Requires BackingStore.
Expand All @@ -253,19 +286,6 @@ class LIBGUI_PUBLIC Atlas : public Lockable
*/
Image image(Id const &id) const;

/**
* Request committing the backing store to the physical atlas storage.
* This does nothing if there are no changes in the atlas.
*
* Deferred commits will also be committed.
*/
void commit() const;

/**
* Deferred allocations will all be cancelled.
*/
void cancelDeferred();

protected:
virtual void commitFull(Image const &fullImage) const = 0;

Expand Down
6 changes: 4 additions & 2 deletions doomsday/sdk/libgui/include/de/graphics/modeldrawable.h
Expand Up @@ -276,7 +276,7 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup
gl::BlendOp blendOp = gl::Add;

bool operator == (Pass const &other) const {
return name == other.name; // Passes are uniquely identified by names.
return name == other.name; // Passes are uniquely identified by names.
}
};

Expand Down Expand Up @@ -425,14 +425,16 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup
*
* @param atlas Atlas for model textures.
*/
void setAtlas(AtlasTexture &atlas);
void setAtlas(IAtlas &atlas);

/**
* Removes the model's atlas. All allocations this model has made from the atlas
* are freed.
*/
void unsetAtlas();

IAtlas *atlas() const;

/**
* Sets which textures are to be passed to the model shader via the GL buffer.
*
Expand Down
13 changes: 7 additions & 6 deletions doomsday/sdk/libgui/include/de/graphics/multiatlas.h
Expand Up @@ -47,7 +47,6 @@ class LIBGUI_PUBLIC MultiAtlas
{
public:
DENG2_ERROR(InvalidError);
DENG2_ERROR(OutOfSpaceError);

/**
* Group of allocations.
Expand All @@ -57,7 +56,7 @@ class LIBGUI_PUBLIC MultiAtlas
*
* When deleted, releases all allocations.
*/
class LIBGUI_PUBLIC AllocGroup : public Asset
class LIBGUI_PUBLIC AllocGroup : public IAtlas, public Asset
{
public:
AllocGroup(MultiAtlas &multiAtlas);
Expand All @@ -69,16 +68,18 @@ class LIBGUI_PUBLIC MultiAtlas
* @return Id of the new allocation. This Id will be used for final
* committed allocation, too.
*/
Id alloc(Image const &image);
Id alloc(Image const &image, Id const &knownId = Id::None) override;

void release(Id const &id);
void release(Id const &id) override;

bool contains(Id const &id) const;
bool contains(Id const &id) const override;

/**
* Commit all the allocated images.
*/
void commit();
void commit() const override;

Rectanglef imageRectf(Id const &id) const override;

/**
* Returns the Atlas where the group's images have been allocated to.
Expand Down
8 changes: 4 additions & 4 deletions doomsday/sdk/libgui/include/de/graphics/texturebank.h
Expand Up @@ -20,12 +20,12 @@
#define LIBGUI_TEXTUREBANK_H

#include <de/Bank>
#include "../AtlasTexture"
#include "../Atlas"

namespace de {

/**
* Bank that stores images on a texture atlas for use in GL drawing.
* Bank that stores images on an atlas.
*
* The data item sources in the bank must be derived from TextureBank::ImageSource.
*
Expand Down Expand Up @@ -58,9 +58,9 @@ class LIBGUI_PUBLIC TextureBank : public Bank
*
* @param atlas Texture atlas. Ownership not taken.
*/
void setAtlas(AtlasTexture *atlas);
void setAtlas(IAtlas *atlas);

AtlasTexture *atlas();
IAtlas *atlas();

Id const &texture(DotPath const &id);

Expand Down
8 changes: 6 additions & 2 deletions doomsday/sdk/libgui/src/graphics/modeldrawable.cpp
Expand Up @@ -1446,9 +1446,8 @@ bool ModelDrawable::nodeExists(String const &name) const
return d->nodeNameToPtr.contains(name);
}

void ModelDrawable::setAtlas(AtlasTexture &atlas)
void ModelDrawable::setAtlas(IAtlas &atlas)
{
//d->glData.atlas = &atlas;
d->glData.textureBank.setAtlas(&atlas);
}

Expand All @@ -1458,6 +1457,11 @@ void ModelDrawable::unsetAtlas()
d->glData.textureBank.setAtlas(nullptr);
}

IAtlas *ModelDrawable::atlas() const
{
return d->glData.textureBank.atlas();
}

ModelDrawable::Mapping ModelDrawable::diffuseNormalsSpecularEmission() // static
{
return Mapping() << Diffuse << Normals << Specular << Emissive;
Expand Down
25 changes: 18 additions & 7 deletions doomsday/sdk/libgui/src/graphics/multiatlas.cpp
Expand Up @@ -101,8 +101,8 @@ DENG2_PIMPL(MultiAtlas)
{
return *blank;
}
throw OutOfSpaceError("MultiAtlas::allocatePending",
"Even an empty atlas cannot fit the pending allocations");
throw IAtlas::OutOfSpaceError("MultiAtlas::allocatePending",
"Even an empty atlas cannot fit the pending allocations");
}
};

Expand Down Expand Up @@ -177,20 +177,20 @@ MultiAtlas::AllocGroup::AllocGroup(MultiAtlas &multiAtlas)
: d(new Instance(this, multiAtlas))
{}

Id MultiAtlas::AllocGroup::alloc(Image const &image)
Id MultiAtlas::AllocGroup::alloc(Image const &image, Id const &knownId)
{
if(!d->atlas)
{
// This will be a pending allocation until the group is committed.
// This Id will be used in the atlas when committing.
Id allocId;
Id allocId { knownId.isNone()? Id() : knownId };
d->pending.insert(allocId, new Image(image));
return allocId;
}
else
{
// After committing, allocations are always done in the chosen atlas.
Id allocId { d->atlas->alloc(image) };
Id allocId { d->atlas->alloc(image, knownId) };
d->allocated.insert(allocId);
return allocId;
}
Expand Down Expand Up @@ -218,7 +218,7 @@ bool MultiAtlas::AllocGroup::contains(Id const &id) const
return d->pending.contains(id) || d->allocated.contains(id);
}

void MultiAtlas::AllocGroup::commit()
void MultiAtlas::AllocGroup::commit() const
{
if(!d->owner)
{
Expand All @@ -236,7 +236,18 @@ void MultiAtlas::AllocGroup::commit()
delete i.value(); // free the Image
}
d->pending.clear();
setState(Ready);

const_cast<MultiAtlas::AllocGroup *>(this)->setState(Ready);
}

Rectanglef MultiAtlas::AllocGroup::imageRectf(Id const &id) const
{
if(d->atlas)
{
return d->atlas->imageRectf(id);
}
throw InvalidError("MultiAtlas::AllocGroup::imageRectf",
"Allocation group has not yet been committed to an atlas");
}

Atlas const *MultiAtlas::AllocGroup::atlas() const
Expand Down
6 changes: 3 additions & 3 deletions doomsday/sdk/libgui/src/graphics/texturebank.cpp
Expand Up @@ -58,7 +58,7 @@ DENG2_PIMPL(TextureBank)
}
};

AtlasTexture *atlas { nullptr };
IAtlas *atlas { nullptr };
QHash<Id::Type, String> pathForAtlasId; // reverse lookup

Instance(Public *i) : Base(i) {}
Expand All @@ -73,12 +73,12 @@ DENG2_PIMPL(TextureBank)
TextureBank::TextureBank() : Bank("TextureBank"), d(new Instance(this))
{}

void TextureBank::setAtlas(AtlasTexture *atlas)
void TextureBank::setAtlas(IAtlas *atlas)
{
d->atlas = atlas;
}

AtlasTexture *TextureBank::atlas()
IAtlas *TextureBank::atlas()
{
return d->atlas;
}
Expand Down

0 comments on commit c037512

Please sign in to comment.