mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 12:48:32 +09:00
[Feat] (MG_State/TextureState): Implement TextureState.
This commit is contained in:
@@ -54,6 +54,9 @@ set(SOURCE_FILES
|
||||
MobileGL/MG_State/GLState/BufferState/BufferObject.cpp
|
||||
MobileGL/MG_State/GLState/VertexArrayState/VertexArrayState.cpp
|
||||
MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.cpp
|
||||
MobileGL/MG_State/GLState/TextureState/TextureObject.cpp
|
||||
MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp
|
||||
MobileGL/MG_State/GLState/TextureState/TextureState.cpp
|
||||
)
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace MobileGL {
|
||||
m_errorState.RecordError(code, info);
|
||||
}
|
||||
|
||||
bool GLContext::HasGLError() const {
|
||||
Bool GLContext::HasGLError() const {
|
||||
return m_errorState.HasGLError();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace MobileGL {
|
||||
return m_errorState.PopGLError();
|
||||
}
|
||||
|
||||
bool GLContext::HasNonGLError() const {
|
||||
Bool GLContext::HasNonGLError() const {
|
||||
return m_errorState.HasNonGLError();
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ namespace MobileGL {
|
||||
m_bufferState.MarkBufferObjectForDeletion(index);
|
||||
}
|
||||
|
||||
bool GLContext::ValidateBufferName(Uint index) const {
|
||||
Bool GLContext::ValidateBufferName(Uint index) const {
|
||||
return m_bufferState.ValidateName(index);
|
||||
}
|
||||
|
||||
bool GLContext::ValidateBufferObject(Uint index) const {
|
||||
Bool GLContext::ValidateBufferObject(Uint index) const {
|
||||
return m_bufferState.ValidateBufferObject(index);
|
||||
}
|
||||
|
||||
@@ -108,17 +108,54 @@ namespace MobileGL {
|
||||
m_vertexArrayState.MarkVertexArrayForDeletion(index);
|
||||
}
|
||||
|
||||
bool GLContext::ValidateVertexArrayName(Uint index) const {
|
||||
Bool GLContext::ValidateVertexArrayName(Uint index) const {
|
||||
return m_vertexArrayState.ValidateName(index);
|
||||
}
|
||||
|
||||
bool GLContext::ValidateVertexArrayObject(Uint index) const {
|
||||
Bool GLContext::ValidateVertexArrayObject(Uint index) const {
|
||||
return m_vertexArrayState.ValidateVertexArrayObject(index);
|
||||
}
|
||||
|
||||
SharedPtr<VertexArrayObject> GLContext::GetBoundVertexArray() {
|
||||
return m_vertexArrayState.GetBoundVertexArray();
|
||||
}
|
||||
// Texture
|
||||
Vector<Uint> GLContext::GenTextureNames(Uint number) {
|
||||
return m_textureState.GenerateNames(number);
|
||||
}
|
||||
|
||||
SharedPtr<ITextureObject> GLContext::GetTextureObject(Uint index) {
|
||||
return m_textureState.GetTextureObject(index);
|
||||
}
|
||||
|
||||
SharedPtr<ITextureObject> GLContext::CreateTextureObject(Uint index, TextureTarget target) {
|
||||
return m_textureState.CreateTextureObject(index, target);
|
||||
}
|
||||
|
||||
void GLContext::MarkTextureObjectForDeletion(Uint index) {
|
||||
m_textureState.MarkTextureObjectForDeletion(index);
|
||||
}
|
||||
|
||||
TextureUnit& GLContext::GetTextureUnitObject() {
|
||||
return m_textureState.GetUnitObject();
|
||||
}
|
||||
|
||||
Bool GLContext::ValidateTextureName(Uint index) const {
|
||||
return m_textureState.ValidateName(index);
|
||||
}
|
||||
|
||||
Bool GLContext::ValidateTextureObject(Uint index) const {
|
||||
return m_textureState.ValidateTextureObject(index);
|
||||
}
|
||||
|
||||
Int GLContext::GetActiveTextureUnit() const {
|
||||
return m_textureState.GetActiveTextureUnit();
|
||||
}
|
||||
|
||||
void GLContext::SetActiveTextureUnit(Int unit) {
|
||||
m_textureState.SetActiveTextureUnit(unit);
|
||||
}
|
||||
|
||||
} // namespace GLState
|
||||
|
||||
GLState::GLContext* pGLContext;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include "BufferState/BufferState.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include "VertexArrayState/VertexArrayState.h"
|
||||
#include "ErrorState/Error.h"
|
||||
#include "ProgramState/ProgramState.h"
|
||||
#include "TextureState/TextureState.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
@@ -14,10 +16,10 @@ namespace MobileGL {
|
||||
|
||||
// Error
|
||||
void RecordError(ErrorCode code, SharedPtr<ErrorInfo> info = nullptr);
|
||||
bool HasGLError() const;
|
||||
Bool HasGLError() const;
|
||||
Optional<const Error> PeekGLError() const;
|
||||
Optional<Error> PopGLError();
|
||||
bool HasNonGLError() const;
|
||||
Bool HasNonGLError() const;
|
||||
Optional<const Error> PeekNonGLError() const;
|
||||
Optional<Error> PopNonGLError();
|
||||
void ClearErrors();
|
||||
@@ -28,8 +30,8 @@ namespace MobileGL {
|
||||
BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget target);
|
||||
SharedPtr<BufferObject> CreateBufferObject(Uint index);
|
||||
void MarkBufferObjectForDeletion(Uint index);
|
||||
bool ValidateBufferName(Uint index) const;
|
||||
bool ValidateBufferObject(Uint index) const;
|
||||
Bool ValidateBufferName(Uint index) const;
|
||||
Bool ValidateBufferObject(Uint index) const;
|
||||
|
||||
// VertexArray
|
||||
Vector<Uint> GenVertexArrayNames(Uint number);
|
||||
@@ -37,10 +39,21 @@ namespace MobileGL {
|
||||
void BindVertexArray(Uint index);
|
||||
SharedPtr<VertexArrayObject> CreateVertexArrayObject(Uint index);
|
||||
void MarkVertexArrayForDeletion(Uint index);
|
||||
bool ValidateVertexArrayName(Uint index) const;
|
||||
bool ValidateVertexArrayObject(Uint index) const;
|
||||
Bool ValidateVertexArrayName(Uint index) const;
|
||||
Bool ValidateVertexArrayObject(Uint index) const;
|
||||
SharedPtr<VertexArrayObject> GetBoundVertexArray();
|
||||
|
||||
// Texture
|
||||
Vector<Uint> GenTextureNames(Uint number);
|
||||
SharedPtr<ITextureObject> GetTextureObject(Uint index);
|
||||
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target);
|
||||
void MarkTextureObjectForDeletion(Uint index);
|
||||
TextureUnit& GetTextureUnitObject();
|
||||
Bool ValidateTextureName(Uint index) const;
|
||||
Bool ValidateTextureObject(Uint index) const;
|
||||
Int GetActiveTextureUnit() const;
|
||||
void SetActiveTextureUnit(Int unit);
|
||||
|
||||
private:
|
||||
// Error
|
||||
ErrorState m_errorState;
|
||||
@@ -50,6 +63,9 @@ namespace MobileGL {
|
||||
|
||||
// VertexArray
|
||||
VertexArrayState m_vertexArrayState;
|
||||
|
||||
// Texture
|
||||
TextureState m_textureState;
|
||||
};
|
||||
} // namespace GLState
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
|
||||
namespace MobileGL {
|
||||
enum class SamplerFilterMode {
|
||||
Nearest,
|
||||
Linear,
|
||||
SamplerFilterCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class SamplerMipmapMode {
|
||||
None,
|
||||
Nearest,
|
||||
SamplerMipmapModeCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class SamplerWrapMode {
|
||||
ClampToEdge,
|
||||
MirroredRepeat,
|
||||
Repeat,
|
||||
ClampToBorder,
|
||||
SamplerWrapModeCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class SamplerCompareMode {
|
||||
None,
|
||||
CompareToTexture,
|
||||
SamplerCompareModeCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class CompareFunc {
|
||||
Never,
|
||||
Less,
|
||||
Equal,
|
||||
LessEqual,
|
||||
Greater,
|
||||
NotEqual,
|
||||
GreaterEqual,
|
||||
Always,
|
||||
CompareFuncCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class SamplerObject {
|
||||
public:
|
||||
SamplerObject()
|
||||
: m_wrapS(SamplerWrapMode::Repeat), m_wrapT(SamplerWrapMode::Repeat),
|
||||
m_wrapR(SamplerWrapMode::Repeat), m_minFilter(SamplerFilterMode::Linear),
|
||||
m_magFilter(SamplerFilterMode::Linear), m_mipmapMode(SamplerMipmapMode::None), m_minLod(0.0f),
|
||||
m_maxLod(1000.0f), m_lodBias(0.0f), m_compareMode(SamplerCompareMode::None),
|
||||
m_compareFunc(CompareFunc::Less) {}
|
||||
|
||||
void SetWrapS(SamplerWrapMode mode) { m_wrapS = mode; }
|
||||
void SetWrapT(SamplerWrapMode mode) { m_wrapT = mode; }
|
||||
void SetWrapR(SamplerWrapMode mode) { m_wrapR = mode; }
|
||||
void SetMinFilter(SamplerFilterMode mode) { m_minFilter = mode; }
|
||||
void SetMagFilter(SamplerFilterMode mode) { m_magFilter = mode; }
|
||||
void SetMipmapMode(SamplerMipmapMode mode) { m_mipmapMode = mode; }
|
||||
void SetLodRange(Float minLod, Float maxLod) {
|
||||
if (minLod > maxLod) {
|
||||
THROW_EXCEPTION("minLod cannot be greater than maxLod");
|
||||
}
|
||||
m_minLod = minLod;
|
||||
m_maxLod = maxLod;
|
||||
}
|
||||
void SetLodBias(Float bias) { m_lodBias = bias; }
|
||||
void SetCompareFunc(CompareFunc func) { m_compareFunc = func; }
|
||||
void SetCompareMode(SamplerCompareMode mode) { m_compareMode = mode; }
|
||||
|
||||
SamplerWrapMode GetWrapS() const { return m_wrapS; }
|
||||
SamplerWrapMode GetWrapT() const { return m_wrapT; }
|
||||
SamplerWrapMode GetWrapR() const { return m_wrapR; }
|
||||
SamplerFilterMode GetMinFilter() const { return m_minFilter; }
|
||||
SamplerFilterMode GetMagFilter() const { return m_magFilter; }
|
||||
SamplerMipmapMode GetMipmapMode() const { return m_mipmapMode; }
|
||||
Float GetMinLod() const { return m_minLod; }
|
||||
Float GetMaxLod() const { return m_maxLod; }
|
||||
Float GetLodBias() const { return m_lodBias; }
|
||||
SamplerCompareMode GetCompareMode() const { return m_compareMode; }
|
||||
CompareFunc GetCompareFunc() const { return m_compareFunc; }
|
||||
|
||||
private:
|
||||
SamplerWrapMode m_wrapS, m_wrapT, m_wrapR;
|
||||
SamplerFilterMode m_minFilter, m_magFilter;
|
||||
SamplerMipmapMode m_mipmapMode;
|
||||
Float m_minLod, m_maxLod;
|
||||
Float m_lodBias;
|
||||
SamplerCompareMode m_compareMode;
|
||||
CompareFunc m_compareFunc;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "TextureObject.h"
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
// TextureObjectBase implementations
|
||||
TextureObjectBase::TextureObjectBase(TextureTarget target) : m_target(target), m_sampler(nullptr) {}
|
||||
|
||||
void TextureObjectBase::SetMipmapLevel(const MipmapLevelInput& level) {
|
||||
SetMipmapImpl(level);
|
||||
}
|
||||
|
||||
TextureSizedInternalFormat TextureObjectBase::GetFormat() const {
|
||||
return m_internalFormat;
|
||||
}
|
||||
|
||||
TextureTarget TextureObjectBase::GetTarget() const {
|
||||
return m_target;
|
||||
}
|
||||
|
||||
IntVec3 TextureObjectBase::GetBaseSize() const {
|
||||
if (m_mipmaps.empty()) {
|
||||
return {0, 0, 0};
|
||||
}
|
||||
return m_mipmaps[0].size;
|
||||
}
|
||||
|
||||
SharedPtr<SamplerObject> TextureObjectBase::GetSamplerObject() const {
|
||||
return m_sampler;
|
||||
}
|
||||
|
||||
const Vector<MipmapLevelInternal>& TextureObjectBase::GetMipmaps() const {
|
||||
return m_mipmaps;
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetInternalFormat(TextureSizedInternalFormat format) {
|
||||
m_internalFormat = format;
|
||||
}
|
||||
|
||||
// TextureObject1D
|
||||
TextureObject1D::TextureObject1D() : TextureObjectBase(TextureTarget::Texture1D) {}
|
||||
|
||||
void TextureObject1D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||
if (level.size.x() > 0) {
|
||||
m_mipmaps.push_back(level);
|
||||
}
|
||||
}
|
||||
|
||||
// TextureObject2D
|
||||
TextureObject2D::TextureObject2D() : TextureObjectBase(TextureTarget::Texture2D) {}
|
||||
|
||||
void TextureObject2D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||
if (level.size.x() > 0 && level.size.y() > 0) {
|
||||
m_mipmaps.push_back(level);
|
||||
}
|
||||
}
|
||||
|
||||
// TextureObject3D
|
||||
TextureObject3D::TextureObject3D() : TextureObjectBase(TextureTarget::Texture3D) {}
|
||||
|
||||
void TextureObject3D::SetMipmapImpl(const MipmapLevelInput& level) {
|
||||
if (level.size.x() > 0 && level.size.y() > 0 && level.size.z() > 0) {
|
||||
m_mipmaps.push_back(level);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add other texture types as needed
|
||||
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,221 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Math/VectorTypes.h>
|
||||
#include "MG_Util/Types.h"
|
||||
#include "SamplerObject.h"
|
||||
|
||||
namespace MobileGL {
|
||||
enum class TextureTarget {
|
||||
Texture1D,
|
||||
Texture2D,
|
||||
Texture3D,
|
||||
TextureCubeMap,
|
||||
Texture2DArray,
|
||||
Texture2DMultisample,
|
||||
TextureCubeMapArray,
|
||||
TextureTargetCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class TextureInputFormat {
|
||||
Red,
|
||||
RG,
|
||||
RGB,
|
||||
BFR,
|
||||
RGBA,
|
||||
BGRA,
|
||||
RInteger,
|
||||
RGInteger,
|
||||
RGBInteger,
|
||||
BGRInteger,
|
||||
RGBAInteger,
|
||||
BGRAInteger,
|
||||
StencilIndex,
|
||||
DepthComponent,
|
||||
DepthStencil,
|
||||
|
||||
FormatCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class TextureSizedInternalFormat {
|
||||
R8,
|
||||
R8Snorm,
|
||||
R16,
|
||||
R16Snorm,
|
||||
RG8,
|
||||
RG8Snorm,
|
||||
RG16,
|
||||
RG16Snorm,
|
||||
R3G3B2,
|
||||
RGB4,
|
||||
RGB5,
|
||||
RGB8,
|
||||
RGB8Snorm,
|
||||
RGB10,
|
||||
RGB12,
|
||||
RGB16Snorm,
|
||||
RGBA2,
|
||||
RGBA4,
|
||||
RGB5A1,
|
||||
RGBA8,
|
||||
RGBA8Snorm,
|
||||
RGB10A2,
|
||||
RGB10A2UI,
|
||||
RGBA12,
|
||||
RGBA16,
|
||||
SRGB8,
|
||||
SRGB8Alpha8,
|
||||
R16F,
|
||||
RG16F,
|
||||
RGB16F,
|
||||
RGBA16F,
|
||||
R32F,
|
||||
RG32F,
|
||||
RGB32F,
|
||||
RGBA32F,
|
||||
R11FG11FB10F,
|
||||
RGB9E5,
|
||||
R8I,
|
||||
R8UI,
|
||||
R16I,
|
||||
R16UI,
|
||||
R32I,
|
||||
R32UI,
|
||||
RG8I,
|
||||
RG8UI,
|
||||
RG16I,
|
||||
RG16UI,
|
||||
RG32I,
|
||||
RG32UI,
|
||||
RGB8I,
|
||||
RGB8UI,
|
||||
RGB16I,
|
||||
RGB16UI,
|
||||
RGB32I,
|
||||
RGB32UI,
|
||||
RGBA8I,
|
||||
RGBA8UI,
|
||||
RGBA16I,
|
||||
RGBA16UI,
|
||||
RGBA32I,
|
||||
RGBA32UI,
|
||||
|
||||
TextureSizedInternalFormatCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
enum class TexturePixelDataType {
|
||||
UnsignedByte,
|
||||
Byte,
|
||||
UnsignedShort,
|
||||
Short,
|
||||
UnsignedInt,
|
||||
Int,
|
||||
Float,
|
||||
UnsignedByte332,
|
||||
UnsignedByte233Rev,
|
||||
UnsignedShort565,
|
||||
UnsignedShort565Rev,
|
||||
UnsignedShort4444,
|
||||
UnsignedShort4444Rev,
|
||||
UnsignedShort5551,
|
||||
UnsignedShort1555Rev,
|
||||
UnsignedInt8888,
|
||||
UnsignedInt8888Rev,
|
||||
UnsignedInt1010102,
|
||||
UnsignedInt2101010Rev,
|
||||
|
||||
TypeCount,
|
||||
Unknown = -1
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
struct MipmapLevelBase {
|
||||
IntVec3 size = {0, 0, 0};
|
||||
Int level = 0;
|
||||
Bool compressed = false;
|
||||
Int compressedSize = 0;
|
||||
};
|
||||
|
||||
struct MipmapLevelInput : MipmapLevelBase {
|
||||
DataPtr inputData = {nullptr, 0};
|
||||
};
|
||||
|
||||
struct MipmapLevelInternal : MipmapLevelBase {
|
||||
Data data;
|
||||
|
||||
MipmapLevelInternal(const MipmapLevelInput& input) : MipmapLevelBase(input) {
|
||||
if (input.inputData.data && input.inputData.size > 0) {
|
||||
const Uint8* src = static_cast<const Uint8*>(input.inputData.data);
|
||||
data.assign(src, src + input.inputData.size);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ITextureObject {
|
||||
public:
|
||||
using TargetEnum = TextureTarget;
|
||||
virtual ~ITextureObject() = default;
|
||||
|
||||
virtual void SetMipmapLevel(const MipmapLevelInput& level) = 0;
|
||||
virtual TextureSizedInternalFormat GetFormat() const = 0;
|
||||
virtual TextureTarget GetTarget() const = 0;
|
||||
virtual IntVec3 GetBaseSize() const = 0;
|
||||
virtual SharedPtr<SamplerObject> GetSamplerObject() const = 0;
|
||||
virtual const Vector<MipmapLevelInternal>& GetMipmaps() const = 0;
|
||||
virtual void SetInternalFormat(TextureSizedInternalFormat format) = 0;
|
||||
};
|
||||
|
||||
class TextureObjectBase : public ITextureObject {
|
||||
public:
|
||||
TextureObjectBase(TextureTarget target);
|
||||
virtual ~TextureObjectBase() = default;
|
||||
|
||||
void SetMipmapLevel(const MipmapLevelInput& level) override;
|
||||
TextureSizedInternalFormat GetFormat() const override;
|
||||
TextureTarget GetTarget() const override;
|
||||
IntVec3 GetBaseSize() const override;
|
||||
SharedPtr<SamplerObject> GetSamplerObject() const override;
|
||||
const Vector<MipmapLevelInternal>& GetMipmaps() const override;
|
||||
void SetInternalFormat(TextureSizedInternalFormat format) override;
|
||||
|
||||
protected:
|
||||
virtual void SetMipmapImpl(const MipmapLevelInput& level) = 0;
|
||||
|
||||
const TextureTarget m_target = TextureTarget::Unknown;
|
||||
TextureSizedInternalFormat m_internalFormat = TextureSizedInternalFormat::Unknown;
|
||||
Vector<MipmapLevelInternal> m_mipmaps = {};
|
||||
SharedPtr<SamplerObject> m_sampler = nullptr;
|
||||
};
|
||||
|
||||
class TextureObject1D : public TextureObjectBase {
|
||||
public:
|
||||
explicit TextureObject1D();
|
||||
|
||||
protected:
|
||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||
};
|
||||
|
||||
class TextureObject2D : public TextureObjectBase {
|
||||
public:
|
||||
explicit TextureObject2D();
|
||||
|
||||
protected:
|
||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||
};
|
||||
|
||||
class TextureObject3D : public TextureObjectBase {
|
||||
public:
|
||||
explicit TextureObject3D();
|
||||
|
||||
protected:
|
||||
void SetMipmapImpl(const MipmapLevelInput& level) override;
|
||||
};
|
||||
|
||||
// TODO: Add other texture types as needed
|
||||
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "TextureState.h"
|
||||
#include "MG_State/GLState/TextureState/TextureObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
TextureState::TextureState() : m_indexGenerator(1024, 1) {
|
||||
for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) {
|
||||
m_textureUnits[i] = TextureUnit();
|
||||
}
|
||||
}
|
||||
|
||||
SharedPtr<ITextureObject> TextureState::GetTextureObject(Uint index) {
|
||||
auto it = m_textureObjects.find(index);
|
||||
if (it != m_textureObjects.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Vector<Uint> TextureState::GenerateNames(Uint number) {
|
||||
Vector<Uint> textures(number);
|
||||
m_indexGenerator.Generate(number, textures.data());
|
||||
return textures;
|
||||
}
|
||||
|
||||
SharedPtr<ITextureObject> TextureState::CreateTextureObject(Uint index, TextureTarget target) {
|
||||
SharedPtr<ITextureObject> textureObject = nullptr;
|
||||
switch (target) {
|
||||
case TextureTarget::Texture1D:
|
||||
textureObject = MakeShared<TextureObject1D>();
|
||||
break;
|
||||
case TextureTarget::Texture2D:
|
||||
textureObject = MakeShared<TextureObject2D>();
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
textureObject = MakeShared<TextureObject3D>();
|
||||
break;
|
||||
default:
|
||||
// TODO: implement more texture types
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_textureObjects[index] = textureObject;
|
||||
return textureObject;
|
||||
}
|
||||
|
||||
void TextureState::MarkTextureObjectForDeletion(Uint index) {
|
||||
if (m_indexGenerator.IsValid(index)) {
|
||||
auto it = m_textureObjects.find(index);
|
||||
if (it != m_textureObjects.end()) {
|
||||
for (auto& unit : m_textureUnits) {
|
||||
auto& bindingSlots = unit.GetAllBindingSlots();
|
||||
for (SizeT i = 0; i < bindingSlots.size(); ++i) {
|
||||
if (bindingSlots[i].GetBoundObject() == it->second) {
|
||||
bindingSlots[i].Bind(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_textureObjects.erase(it);
|
||||
}
|
||||
m_indexGenerator.Delete(index);
|
||||
}
|
||||
}
|
||||
|
||||
TextureUnit& TextureState::GetUnitObject() {
|
||||
if (m_activeTextureUnit < 0 || m_activeTextureUnit >= MAX_TEXTURE_IMAGE_UNITS) {
|
||||
THROW_EXCEPTION("Active texture unit is out of range");
|
||||
}
|
||||
return m_textureUnits[m_activeTextureUnit];
|
||||
}
|
||||
|
||||
Int TextureState::GetActiveTextureUnit() const {
|
||||
return m_activeTextureUnit;
|
||||
}
|
||||
|
||||
void TextureState::SetActiveTextureUnit(Int unit) {
|
||||
m_activeTextureUnit = unit;
|
||||
}
|
||||
|
||||
Bool TextureState::ValidateName(Uint index) const {
|
||||
return m_indexGenerator.IsValid(index);
|
||||
}
|
||||
|
||||
Bool TextureState::ValidateTextureObject(Uint index) const {
|
||||
return m_textureObjects.find(index) != m_textureObjects.end();
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Miscellany/IndexGenerator.h>
|
||||
#include "MG_State/GLState/TextureState/TextureObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include "TextureUnit.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
|
||||
class TextureState {
|
||||
public:
|
||||
static constexpr int MAX_TEXTURE_IMAGE_UNITS = 32;
|
||||
|
||||
TextureState();
|
||||
Vector<Uint> GenerateNames(Uint number);
|
||||
SharedPtr<ITextureObject> CreateTextureObject(Uint index, TextureTarget target);
|
||||
SharedPtr<ITextureObject> GetTextureObject(Uint index);
|
||||
TextureUnit& GetUnitObject();
|
||||
Int GetActiveTextureUnit() const;
|
||||
void SetActiveTextureUnit(Int unit);
|
||||
void MarkTextureObjectForDeletion(Uint index);
|
||||
Bool ValidateName(Uint index) const;
|
||||
Bool ValidateTextureObject(Uint index) const;
|
||||
|
||||
private:
|
||||
Int m_activeTextureUnit = 0;
|
||||
Array<TextureUnit, MAX_TEXTURE_IMAGE_UNITS> m_textureUnits;
|
||||
IndexGenerator<Uint> m_indexGenerator;
|
||||
UnorderedMap<GLuint, SharedPtr<ITextureObject>> m_textureObjects;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "TextureUnit.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
TextureUnit::TextureUnit() : m_sampler(nullptr) {
|
||||
for (int i = 0; i < (int)TextureTarget::TextureTargetCount; ++i) {
|
||||
m_slots[i] = BindingSlot<ITextureObject>(static_cast<TextureTarget>(i));
|
||||
}
|
||||
}
|
||||
|
||||
BindingSlot<ITextureObject>& TextureUnit::GetBindingSlot(TextureTarget target) {
|
||||
return m_slots[(int)target];
|
||||
}
|
||||
|
||||
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& TextureUnit::
|
||||
GetAllBindingSlots() {
|
||||
return m_slots;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include "MG_State/GLState/TextureState/SamplerObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include "TextureObject.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class TextureUnit {
|
||||
public:
|
||||
TextureUnit();
|
||||
BindingSlot<ITextureObject>& GetBindingSlot(TextureTarget target);
|
||||
SharedPtr<SamplerObject> GetSamplerObject() const;
|
||||
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount>& GetAllBindingSlots();
|
||||
|
||||
private:
|
||||
Array<BindingSlot<ITextureObject>, (int)TextureTarget::TextureTargetCount> m_slots;
|
||||
SharedPtr<SamplerObject> m_sampler;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,191 @@
|
||||
#pragma once
|
||||
|
||||
#include <Includes.h>
|
||||
|
||||
namespace MobileGL {
|
||||
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
struct VecBase {
|
||||
Array<T, N> data;
|
||||
|
||||
VecBase() { std::fill(data.begin(), data.end(), T(0)); }
|
||||
|
||||
VecBase(std::initializer_list<T> init) {
|
||||
std::copy_n(init.begin(), std::min(N, init.size()), data.begin());
|
||||
if (init.size() < N) {
|
||||
std::fill(data.begin() + init.size(), data.end(), T(0));
|
||||
}
|
||||
}
|
||||
|
||||
explicit VecBase(T scalar) { std::fill(data.begin(), data.end(), scalar); }
|
||||
|
||||
T& operator[](SizeT index) {
|
||||
if (index >= N) throw std::out_of_range("Vector index out of range");
|
||||
return data[index];
|
||||
}
|
||||
|
||||
const T& operator[](SizeT index) const {
|
||||
if (index >= N) throw std::out_of_range("Vector index out of range");
|
||||
return data[index];
|
||||
}
|
||||
|
||||
bool operator==(const VecBase& rhs) const { return data == rhs.data; }
|
||||
bool operator!=(const VecBase& rhs) const { return !(*this == rhs); }
|
||||
|
||||
Derived operator+(const VecBase& rhs) const {
|
||||
Derived result;
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result[i] = data[i] + rhs[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
Derived operator-(const VecBase& rhs) const {
|
||||
Derived result;
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result[i] = data[i] - rhs[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
Derived operator*(T scalar) const {
|
||||
Derived result;
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result[i] = data[i] * scalar;
|
||||
return result;
|
||||
}
|
||||
|
||||
Derived operator/(T scalar) const {
|
||||
if (scalar == 0) throw std::domain_error("Division by zero");
|
||||
T inv = T(1) / scalar;
|
||||
return *this * inv;
|
||||
}
|
||||
|
||||
T Dot(const VecBase& rhs) const {
|
||||
T result = T(0);
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result += data[i] * rhs[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
T Length() const { return std::sqrt(Dot(*this)); }
|
||||
|
||||
Derived Normalized() const {
|
||||
T len = Length();
|
||||
if (len > 0) {
|
||||
return *this * (T(1) / len);
|
||||
}
|
||||
return static_cast<const Derived&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Vec2 : public VecBase<Vec2<T>, T, 2> {
|
||||
using Base = VecBase<Vec2<T>, T, 2>;
|
||||
using Base::Base;
|
||||
|
||||
Vec2(T x, T y) : Base{x, y} {}
|
||||
|
||||
T& x() { return (*this)[0]; }
|
||||
T& y() { return (*this)[1]; }
|
||||
const T& x() const { return (*this)[0]; }
|
||||
const T& y() const { return (*this)[1]; }
|
||||
|
||||
T Cross(const Vec2& rhs) const { return x() * rhs.y() - y() * rhs.x(); }
|
||||
|
||||
Vec2 Rotated(T angle) const {
|
||||
T cosA = std::cos(angle);
|
||||
T sinA = std::sin(angle);
|
||||
return {x() * cosA - y() * sinA, x() * sinA + y() * cosA};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Vec3 : public VecBase<Vec3<T>, T, 3> {
|
||||
using Base = VecBase<Vec3<T>, T, 3>;
|
||||
using Base::Base;
|
||||
|
||||
Vec3(T x, T y, T z) : Base{x, y, z} {}
|
||||
explicit Vec3(const Vec2<T>& v2, T z = T(0)) : Base{v2.x(), v2.y(), z} {}
|
||||
|
||||
T& x() { return (*this)[0]; }
|
||||
T& y() { return (*this)[1]; }
|
||||
T& z() { return (*this)[2]; }
|
||||
const T& x() const { return (*this)[0]; }
|
||||
const T& y() const { return (*this)[1]; }
|
||||
const T& z() const { return (*this)[2]; }
|
||||
|
||||
Vec2<T> xy() const { return {x(), y()}; }
|
||||
Vec2<T> xz() const { return {x(), z()}; }
|
||||
Vec2<T> yz() const { return {y(), z()}; }
|
||||
|
||||
Vec3 Cross(const Vec3& rhs) const {
|
||||
return {y() * rhs.z() - z() * rhs.y(), z() * rhs.x() - x() * rhs.z(), x() * rhs.y() - y() * rhs.x()};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Vec4 : public VecBase<Vec4<T>, T, 4> {
|
||||
using Base = VecBase<Vec4<T>, T, 4>;
|
||||
using Base::Base;
|
||||
|
||||
Vec4(T x, T y, T z, T w) : Base{x, y, z, w} {}
|
||||
explicit Vec4(const Vec3<T>& v3, T w = T(1)) : Base{v3.x(), v3.y(), v3.z(), w} {}
|
||||
|
||||
T& x() { return (*this)[0]; }
|
||||
T& y() { return (*this)[1]; }
|
||||
T& z() { return (*this)[2]; }
|
||||
T& w() { return (*this)[3]; }
|
||||
const T& x() const { return (*this)[0]; }
|
||||
const T& y() const { return (*this)[1]; }
|
||||
const T& z() const { return (*this)[2]; }
|
||||
const T& w() const { return (*this)[3]; }
|
||||
|
||||
Vec3<T> xyz() const { return {x(), y(), z()}; }
|
||||
Vec3<T> Homogenized() const { return (w() != 0) ? xyz() / w() : xyz(); }
|
||||
};
|
||||
|
||||
using IntVec2 = Vec2<Int32>;
|
||||
using IntVec3 = Vec3<Int32>;
|
||||
using IntVec4 = Vec4<Int32>;
|
||||
using UintVec2 = Vec2<Uint32>;
|
||||
using UintVec3 = Vec3<Uint32>;
|
||||
using UintVec4 = Vec4<Uint32>;
|
||||
using FloatVec2 = Vec2<Float>;
|
||||
using FloatVec3 = Vec3<Float>;
|
||||
using FloatVec4 = Vec4<Float>;
|
||||
|
||||
using Size2D = IntVec2;
|
||||
using Size3D = IntVec3;
|
||||
using TextureSize = IntVec3;
|
||||
|
||||
using ColorRGB = FloatVec3;
|
||||
using ColorRGBA = FloatVec4;
|
||||
using ColorRGB8 = UintVec3;
|
||||
using ColorRGBA8 = UintVec4;
|
||||
|
||||
namespace MG_Util {
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
Derived Lerp(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b, Float t) {
|
||||
Derived result;
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result[i] = a[i] + (b[i] - a[i]) * t;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
Derived MultiplyComponents(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b) {
|
||||
Derived result;
|
||||
for (SizeT i = 0; i < N; ++i)
|
||||
result[i] = a[i] * b[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
T Distance(const VecBase<Derived, T, N>& a, const VecBase<Derived, T, N>& b) {
|
||||
return (a - b).Length();
|
||||
}
|
||||
|
||||
inline FloatVec3 Reflect(const FloatVec3& incident, const FloatVec3& normal) {
|
||||
return incident - normal * (2.0f * incident.Dot(normal));
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "TextureMetrics.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
SizeT GetTexturePixelSize(TextureSizedInternalFormat internal) {
|
||||
switch (internal) {
|
||||
case TextureSizedInternalFormat::R8:
|
||||
case TextureSizedInternalFormat::R8Snorm:
|
||||
case TextureSizedInternalFormat::R8I:
|
||||
case TextureSizedInternalFormat::R8UI:
|
||||
return 1;
|
||||
|
||||
case TextureSizedInternalFormat::R16:
|
||||
case TextureSizedInternalFormat::R16Snorm:
|
||||
case TextureSizedInternalFormat::R16I:
|
||||
case TextureSizedInternalFormat::R16UI:
|
||||
case TextureSizedInternalFormat::R16F:
|
||||
case TextureSizedInternalFormat::RG8:
|
||||
case TextureSizedInternalFormat::RG8Snorm:
|
||||
case TextureSizedInternalFormat::RG8I:
|
||||
case TextureSizedInternalFormat::RG8UI:
|
||||
return 2;
|
||||
|
||||
case TextureSizedInternalFormat::R3G3B2:
|
||||
case TextureSizedInternalFormat::RGB4:
|
||||
case TextureSizedInternalFormat::RGB5:
|
||||
case TextureSizedInternalFormat::RGB8:
|
||||
case TextureSizedInternalFormat::RGB8Snorm:
|
||||
case TextureSizedInternalFormat::SRGB8:
|
||||
case TextureSizedInternalFormat::RGB8I:
|
||||
case TextureSizedInternalFormat::RGB8UI:
|
||||
return 3;
|
||||
|
||||
case TextureSizedInternalFormat::RGBA2:
|
||||
case TextureSizedInternalFormat::RGBA4:
|
||||
case TextureSizedInternalFormat::RGB5A1:
|
||||
case TextureSizedInternalFormat::RGBA8:
|
||||
case TextureSizedInternalFormat::RGBA8Snorm:
|
||||
case TextureSizedInternalFormat::RGBA8I:
|
||||
case TextureSizedInternalFormat::RGBA8UI:
|
||||
case TextureSizedInternalFormat::SRGB8Alpha8:
|
||||
case TextureSizedInternalFormat::RGB10A2:
|
||||
case TextureSizedInternalFormat::RGB10A2UI:
|
||||
case TextureSizedInternalFormat::R32F:
|
||||
|
||||
case TextureSizedInternalFormat::RG16:
|
||||
case TextureSizedInternalFormat::RG16Snorm:
|
||||
case TextureSizedInternalFormat::RG16I:
|
||||
case TextureSizedInternalFormat::RG16UI:
|
||||
case TextureSizedInternalFormat::RG16F:
|
||||
return 4;
|
||||
|
||||
case TextureSizedInternalFormat::RGBA12:
|
||||
case TextureSizedInternalFormat::RGBA16:
|
||||
case TextureSizedInternalFormat::RGBA16I:
|
||||
case TextureSizedInternalFormat::RGBA16UI:
|
||||
case TextureSizedInternalFormat::RGBA16F:
|
||||
case TextureSizedInternalFormat::RG32F:
|
||||
case TextureSizedInternalFormat::RG32I:
|
||||
case TextureSizedInternalFormat::RG32UI:
|
||||
return 8;
|
||||
|
||||
case TextureSizedInternalFormat::RGB16F:
|
||||
case TextureSizedInternalFormat::RGB32F:
|
||||
case TextureSizedInternalFormat::RGB16I:
|
||||
case TextureSizedInternalFormat::RGB16UI:
|
||||
case TextureSizedInternalFormat::RGB32I:
|
||||
case TextureSizedInternalFormat::RGB32UI:
|
||||
return 12;
|
||||
|
||||
case TextureSizedInternalFormat::RGBA32F:
|
||||
case TextureSizedInternalFormat::RGBA32I:
|
||||
case TextureSizedInternalFormat::RGBA32UI:
|
||||
return 16;
|
||||
|
||||
case TextureSizedInternalFormat::R11FG11FB10F:
|
||||
case TextureSizedInternalFormat::RGB9E5:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_State/GLState/TextureState/TextureObject.h>
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
SizeT GetTexturePixelSize(TextureSizedInternalFormat internal);
|
||||
}
|
||||
} // namespace MobileGL
|
||||
Reference in New Issue
Block a user