From c037512f8efd35348246cc6b3e300966ee2479c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Sun, 25 Oct 2015 22:11:18 +0200 Subject: [PATCH] Refactor|libgui: Added abstract IAtlas interface More flexibility for TextureBank and ModelDrawable: MultiAtlas::AllocGroup can be used instead of a regular atlas. --- .../sdk/libgui/include/de/graphics/atlas.h | 56 +++++++++++++------ .../include/de/graphics/modeldrawable.h | 6 +- .../libgui/include/de/graphics/multiatlas.h | 13 +++-- .../libgui/include/de/graphics/texturebank.h | 8 +-- .../sdk/libgui/src/graphics/modeldrawable.cpp | 8 ++- .../sdk/libgui/src/graphics/multiatlas.cpp | 25 ++++++--- .../sdk/libgui/src/graphics/texturebank.cpp | 6 +- 7 files changed, 80 insertions(+), 42 deletions(-) diff --git a/doomsday/sdk/libgui/include/de/graphics/atlas.h b/doomsday/sdk/libgui/include/de/graphics/atlas.h index b6b3252a1c..f914aea43d 100644 --- a/doomsday/sdk/libgui/include/de/graphics/atlas.h +++ b/doomsday/sdk/libgui/include/de/graphics/atlas.h @@ -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. * @@ -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; @@ -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. @@ -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. @@ -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; diff --git a/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h b/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h index 34e8ec99c7..f9a417b0b5 100644 --- a/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h +++ b/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h @@ -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. } }; @@ -425,7 +425,7 @@ 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 @@ -433,6 +433,8 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup */ void unsetAtlas(); + IAtlas *atlas() const; + /** * Sets which textures are to be passed to the model shader via the GL buffer. * diff --git a/doomsday/sdk/libgui/include/de/graphics/multiatlas.h b/doomsday/sdk/libgui/include/de/graphics/multiatlas.h index 87eb6657f1..d4372b7c4d 100644 --- a/doomsday/sdk/libgui/include/de/graphics/multiatlas.h +++ b/doomsday/sdk/libgui/include/de/graphics/multiatlas.h @@ -47,7 +47,6 @@ class LIBGUI_PUBLIC MultiAtlas { public: DENG2_ERROR(InvalidError); - DENG2_ERROR(OutOfSpaceError); /** * Group of allocations. @@ -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); @@ -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. diff --git a/doomsday/sdk/libgui/include/de/graphics/texturebank.h b/doomsday/sdk/libgui/include/de/graphics/texturebank.h index 4f7e6b5ad5..6327bb5676 100644 --- a/doomsday/sdk/libgui/include/de/graphics/texturebank.h +++ b/doomsday/sdk/libgui/include/de/graphics/texturebank.h @@ -20,12 +20,12 @@ #define LIBGUI_TEXTUREBANK_H #include -#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. * @@ -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); diff --git a/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp b/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp index df49b7ef8f..1377d94da0 100644 --- a/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp +++ b/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp @@ -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); } @@ -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; diff --git a/doomsday/sdk/libgui/src/graphics/multiatlas.cpp b/doomsday/sdk/libgui/src/graphics/multiatlas.cpp index b42e728cc8..deec24a8dc 100644 --- a/doomsday/sdk/libgui/src/graphics/multiatlas.cpp +++ b/doomsday/sdk/libgui/src/graphics/multiatlas.cpp @@ -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"); } }; @@ -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; } @@ -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) { @@ -236,7 +236,18 @@ void MultiAtlas::AllocGroup::commit() delete i.value(); // free the Image } d->pending.clear(); - setState(Ready); + + const_cast(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 diff --git a/doomsday/sdk/libgui/src/graphics/texturebank.cpp b/doomsday/sdk/libgui/src/graphics/texturebank.cpp index 071a66dbab..71c3497871 100644 --- a/doomsday/sdk/libgui/src/graphics/texturebank.cpp +++ b/doomsday/sdk/libgui/src/graphics/texturebank.cpp @@ -58,7 +58,7 @@ DENG2_PIMPL(TextureBank) } }; - AtlasTexture *atlas { nullptr }; + IAtlas *atlas { nullptr }; QHash pathForAtlasId; // reverse lookup Instance(Public *i) : Base(i) {} @@ -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; }