mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
Merge branch 'dev' into Feat/Backend-Direct-Vulkan
This commit is contained in:
@@ -14,14 +14,18 @@ namespace MobileGL {
|
||||
namespace GLState {
|
||||
BufferObject::BufferObject(Uint externalIndex)
|
||||
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
|
||||
m_mappingAccess(BufferMappingAccessBit::Null), m_dirtyRange({0, 0}), m_mappedRange({0, 0}),
|
||||
m_dataPtr(MakeShared<Data>()) {}
|
||||
m_mappingAccess(BufferMappingAccessBit::Null),
|
||||
m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}),
|
||||
m_dataPtr(MakeShared<Data>()) {
|
||||
m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT);
|
||||
}
|
||||
|
||||
void BufferObject::Resize(SizeT size) {
|
||||
m_size = size;
|
||||
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
|
||||
m_dataPtr->resize(size);
|
||||
m_dirtyRange = {0, 0};
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
|
||||
}
|
||||
|
||||
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
|
||||
@@ -30,7 +34,14 @@ namespace MobileGL {
|
||||
data.size, m_size);
|
||||
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
|
||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
|
||||
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
|
||||
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
// This function may be called by `glBufferData`, but we still set the forbid bits above,
|
||||
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
|
||||
// The bits can fit the `glBufferSubData` semantics
|
||||
// (though `glBufferSubData` calls `UploadSubData` instead).
|
||||
}
|
||||
|
||||
void BufferObject::SetUsage(BufferUsage usage) {
|
||||
@@ -44,7 +55,8 @@ namespace MobileGL {
|
||||
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
|
||||
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
|
||||
m_mappedRange.end - m_mappedRange.start);
|
||||
m_dirtyRange.UnionUpdate(m_mappedRange.start, m_mappedRange.end);
|
||||
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
m_stagingData.clear();
|
||||
@@ -69,7 +81,8 @@ namespace MobileGL {
|
||||
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
|
||||
|
||||
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
|
||||
m_dirtyRange.UnionUpdate(start, end);
|
||||
m_change.DirtyRanges.Add({start, end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
|
||||
@@ -79,7 +92,10 @@ namespace MobileGL {
|
||||
atOffset, data.size, m_size);
|
||||
|
||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
|
||||
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
|
||||
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
}
|
||||
|
||||
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset,
|
||||
@@ -95,7 +111,8 @@ namespace MobileGL {
|
||||
|
||||
const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
|
||||
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
|
||||
m_dirtyRange.UnionUpdate(dstOffset, dstOffset + size);
|
||||
m_change.DirtyRanges.Add({dstOffset, dstOffset + size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
|
||||
@@ -144,6 +161,14 @@ namespace MobileGL {
|
||||
m_ownsStagingData = false;
|
||||
return m_dataPtr->data() + range.start;
|
||||
}
|
||||
|
||||
m_change.Bits |= !(access & BufferMappingAccessBit::InvalidateBuffer ||
|
||||
access & BufferMappingAccessBit::InvalidateRange)
|
||||
? BufferChangeBits::ForbidInvalidationBit
|
||||
: BufferChangeBits::None;
|
||||
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
|
||||
? BufferChangeBits::ForbidUnsynchronizationBit
|
||||
: BufferChangeBits::None;
|
||||
}
|
||||
|
||||
const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
|
||||
@@ -151,7 +176,8 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void BufferObject::ClearDirty() {
|
||||
m_dirtyRange = {0, 0};
|
||||
m_change.DirtyRanges.clear();
|
||||
m_change.Bits = BufferChangeBits::None;
|
||||
}
|
||||
|
||||
SizeT BufferObject::GetSize() const {
|
||||
@@ -162,8 +188,12 @@ namespace MobileGL {
|
||||
return m_usage;
|
||||
}
|
||||
|
||||
Range1D BufferObject::GetDirtyRange() const {
|
||||
return m_dirtyRange;
|
||||
const VecRange1D& BufferObject::GetDirtyRanges() const {
|
||||
return m_change.DirtyRanges;
|
||||
}
|
||||
|
||||
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
|
||||
return m_change.Bits;
|
||||
}
|
||||
|
||||
Bool BufferObject::IsMapped() const {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Math/VectorTypes.h>
|
||||
|
||||
namespace MobileGL {
|
||||
enum class BufferTarget {
|
||||
@@ -55,6 +56,23 @@ namespace MobileGL {
|
||||
Coherent = 0x80
|
||||
};
|
||||
|
||||
enum class BufferChangeBits : Uint8 {
|
||||
None = 0,
|
||||
DirtyBit = 1 << 0, // When not set, bits below are ignored and nothing should be synced to backend
|
||||
PreferReallocationBit =
|
||||
1 << 1, // <=> `glBufferData`; When set, ForbidInvalidationBit and ForbidUnsynchronizationBit are ignored
|
||||
ForbidInvalidationBit = 1 << 2, // Indidate that invalidation flags were not used during mapping, else we're
|
||||
// allowed to act as `GL_MAP_INVALIDATE_*` in backend
|
||||
ForbidUnsynchronizationBit = 1 << 3, // (the same description as above, but for unsynchronization)
|
||||
};
|
||||
|
||||
struct BufferChange {
|
||||
static constexpr int DEFAULT_RESERVED_DIRTY_RANGES_COUNT = 50;
|
||||
|
||||
Flags<BufferChangeBits> Bits = BufferChangeBits::None;
|
||||
VecRange1D DirtyRanges;
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class BufferObject {
|
||||
@@ -77,11 +95,12 @@ namespace MobileGL {
|
||||
Bool IsMapped() const;
|
||||
SizeT GetSize() const;
|
||||
BufferUsage GetUsage() const;
|
||||
Range1D GetDirtyRange() const;
|
||||
Range1D GetMappedRange() const;
|
||||
const SharedPtr<Data> GetDataReadOnly() const;
|
||||
Flags<BufferMappingAccessBit> GetMappingAccess() const;
|
||||
Uint GetExternalIndex() const;
|
||||
const VecRange1D& GetDirtyRanges() const;
|
||||
Flags<BufferChangeBits> GetChangeBits() const;
|
||||
|
||||
private:
|
||||
const Uint m_externalIndex = 0;
|
||||
@@ -90,7 +109,7 @@ namespace MobileGL {
|
||||
SharedPtr<Data> m_dataPtr;
|
||||
Bool m_isMapped;
|
||||
Flags<BufferMappingAccessBit> m_mappingAccess;
|
||||
Range1D m_dirtyRange;
|
||||
BufferChange m_change;
|
||||
Range1D m_mappedRange;
|
||||
Vector<Uint8> m_stagingData;
|
||||
Bool m_ownsStagingData;
|
||||
|
||||
@@ -220,6 +220,14 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
// RenderState
|
||||
Uint GLContext::GetRenderStateParametersVersion() const {
|
||||
return m_renderState.GetVersion();
|
||||
}
|
||||
|
||||
const RenderStateParameters& GLContext::GetRenderStateParameters() const {
|
||||
return m_renderState.GetAllParameters();
|
||||
}
|
||||
|
||||
void GLContext::SetViewport(IntVec4 viewport) {
|
||||
m_renderState.SetViewport(viewport);
|
||||
}
|
||||
@@ -236,6 +244,14 @@ namespace MobileGL {
|
||||
return m_renderState.IsCapabilityEnabled(cap);
|
||||
}
|
||||
|
||||
void GLContext::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) {
|
||||
m_renderState.SetCapabilityIndexed(cap, index, enabled);
|
||||
}
|
||||
|
||||
Bool GLContext::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const {
|
||||
return m_renderState.IsCapabilityEnabledIndexed(cap, index);
|
||||
}
|
||||
|
||||
void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha) {
|
||||
m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
@@ -246,6 +262,16 @@ namespace MobileGL {
|
||||
m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB,
|
||||
BlendFactor srcAlpha, BlendFactor dstAlpha) {
|
||||
m_renderState.SetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB,
|
||||
BlendFactor& srcAlpha, BlendFactor& dstAlpha) const {
|
||||
m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::SetDepthFunc(DepthTestFunc func) {
|
||||
m_renderState.SetDepthFunc(func);
|
||||
}
|
||||
|
||||
@@ -86,13 +86,21 @@ namespace MobileGL {
|
||||
SharedPtr<ProgramObject> GetCurrentProgram();
|
||||
|
||||
// RenderState
|
||||
Uint GetRenderStateParametersVersion() const;
|
||||
const RenderStateParameters& GetRenderStateParameters() const;
|
||||
void SetViewport(IntVec4 viewport); // x, y, width, height
|
||||
const IntVec4& GetViewport() const; // x, y, width, height
|
||||
void SetCapability(CapabilityInput cap, Bool enabled);
|
||||
Bool IsCapabilityEnabled(CapabilityInput cap) const;
|
||||
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
|
||||
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
|
||||
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
|
||||
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha);
|
||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
DepthTestFunc GetDepthFunc() const;
|
||||
void SetDepthMask(Bool flag);
|
||||
|
||||
@@ -12,41 +12,41 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
// FramebufferAttachment
|
||||
FramebufferAttachment::FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level)
|
||||
// FramebufferAttachmentObject
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level)
|
||||
: m_texture(texture), m_textureLevel(level) {}
|
||||
FramebufferAttachment::FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer)
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer)
|
||||
: m_renderbuffer(renderbuffer) {}
|
||||
FramebufferAttachment::FramebufferAttachment(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
|
||||
m_isValid = IsValid;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsTexture() const {
|
||||
Bool FramebufferAttachmentObject::IsTexture() const {
|
||||
return m_texture != nullptr;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsRenderbuffer() const {
|
||||
Bool FramebufferAttachmentObject::IsRenderbuffer() const {
|
||||
return m_renderbuffer != nullptr;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsEmpty() const {
|
||||
Bool FramebufferAttachmentObject::IsEmpty() const {
|
||||
return m_texture == nullptr && m_renderbuffer == nullptr;
|
||||
}
|
||||
|
||||
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachment::GetTexture() const {
|
||||
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachmentObject::GetTexture() const {
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
SharedPtr<RenderbufferObject> FramebufferAttachment::GetRenderbuffer() const {
|
||||
SharedPtr<RenderbufferObject> FramebufferAttachmentObject::GetRenderbuffer() const {
|
||||
return m_renderbuffer;
|
||||
}
|
||||
|
||||
Int FramebufferAttachment::GetTextureLevel() const {
|
||||
Int FramebufferAttachmentObject::GetTextureLevel() const {
|
||||
return m_textureLevel;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsComplete() const {
|
||||
Bool FramebufferAttachmentObject::IsComplete() const {
|
||||
if (IsTexture()) {
|
||||
Bool complete = m_texture->IsComplete();
|
||||
return complete;
|
||||
@@ -58,7 +58,7 @@ namespace MobileGL {
|
||||
return false;
|
||||
}
|
||||
|
||||
IntVec3 FramebufferAttachment::GetSize() const {
|
||||
IntVec3 FramebufferAttachmentObject::GetSize() const {
|
||||
if (IsTexture()) {
|
||||
// TODO: get correct upload target
|
||||
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
|
||||
@@ -71,56 +71,55 @@ namespace MobileGL {
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsValid() const {
|
||||
Bool FramebufferAttachmentObject::IsValid() const {
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
// FramebufferObject
|
||||
FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {
|
||||
m_attachments.fill(FramebufferAttachment(false));
|
||||
m_attachmentObjects.fill(FramebufferAttachmentObject(false));
|
||||
m_drawBuffers.fill(FramebufferAttachmentType::None);
|
||||
m_drawBuffers[0] = FramebufferAttachmentType::Color0;
|
||||
m_attachmentVersions.fill(0);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture,
|
||||
int level) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(std::move(texture), level);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(std::move(texture), level);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type,
|
||||
std::shared_ptr<RenderbufferObject> renderbuffer) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(renderbuffer);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
void FramebufferObject::Detach(FramebufferAttachmentType type) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(false);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
const FramebufferAttachment& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
|
||||
return m_attachments[static_cast<SizeT>(type)];
|
||||
const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
|
||||
return m_attachmentObjects[static_cast<SizeT>(type)];
|
||||
}
|
||||
|
||||
const Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
|
||||
FramebufferObject::GetAllAttachments() const {
|
||||
return m_attachments;
|
||||
const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects() const {
|
||||
return m_attachmentObjects;
|
||||
}
|
||||
|
||||
Bool FramebufferObject::CheckCompleteness() const {
|
||||
if (m_attachments.empty()) {
|
||||
if (m_attachmentObjects.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Int width = -1, height = -1;
|
||||
Int validAttachmentCount = 0;
|
||||
for (SizeT i = 0; i < m_attachments.size(); ++i) {
|
||||
if (!m_attachments[i].IsValid()) continue;
|
||||
for (SizeT i = 0; i < m_attachmentObjects.size(); ++i) {
|
||||
if (!m_attachmentObjects[i].IsValid()) continue;
|
||||
|
||||
++validAttachmentCount;
|
||||
const auto& attachment = m_attachments[i];
|
||||
const auto& attachment = m_attachmentObjects[i];
|
||||
auto attachmentSize = attachment.GetSize();
|
||||
Int w = attachmentSize.x();
|
||||
Int h = attachmentSize.y();
|
||||
@@ -143,26 +142,22 @@ namespace MobileGL {
|
||||
|
||||
void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
|
||||
if (m_drawBuffers[index] == buffer) return;
|
||||
m_drawBuffersDirty = true;
|
||||
m_drawBuffers[index] = buffer;
|
||||
BumpAttachmentVersion(buffer);
|
||||
}
|
||||
|
||||
// void FramebufferObject::SetDrawBuffers(const Vector<FramebufferAttachmentType>& buffers) {
|
||||
// m_drawBuffers = buffers;
|
||||
// m_drawBuffersDirty = true;
|
||||
// }
|
||||
// void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
|
||||
//
|
||||
// }
|
||||
|
||||
const Array<FramebufferAttachmentType, FramebufferObject::MAX_DRAW_BUFFERS>& FramebufferObject::
|
||||
GetDrawBuffers() const {
|
||||
const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
|
||||
return m_drawBuffers;
|
||||
}
|
||||
|
||||
Uint FramebufferObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
}
|
||||
|
||||
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
|
||||
++m_attachmentVersions[static_cast<SizeT>(type)];
|
||||
++m_objectVersion;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -69,11 +69,12 @@ namespace MobileGL {
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class FramebufferAttachment {
|
||||
class FramebufferAttachmentObject {
|
||||
public:
|
||||
explicit FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0);
|
||||
explicit FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer);
|
||||
explicit FramebufferAttachment(Bool IsValid = true);
|
||||
explicit FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level = 0);
|
||||
explicit FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer);
|
||||
explicit FramebufferAttachmentObject(Bool IsValid = true);
|
||||
|
||||
Bool IsTexture() const;
|
||||
Bool IsRenderbuffer() const;
|
||||
@@ -94,36 +95,51 @@ namespace MobileGL {
|
||||
|
||||
class FramebufferObject {
|
||||
public:
|
||||
using TargetEnum = FramebufferTarget;
|
||||
static constexpr Uint MAX_DRAW_BUFFERS = 8;
|
||||
|
||||
using TargetEnum = FramebufferTarget;
|
||||
using FramebufferAttachmentObjectArray =
|
||||
Array<FramebufferAttachmentObject,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
|
||||
using FramebufferAttachmentArray = Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>;
|
||||
using FramebufferAttachmentVersionArray =
|
||||
Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
|
||||
|
||||
FramebufferObject(Uint externalIndex);
|
||||
|
||||
void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0);
|
||||
void AttachRenderbuffer(FramebufferAttachmentType type,
|
||||
std::shared_ptr<RenderbufferObject> renderbuffer);
|
||||
void Detach(FramebufferAttachmentType type);
|
||||
const FramebufferAttachment& GetAttachment(FramebufferAttachmentType type) const;
|
||||
const Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
|
||||
GetAllAttachments() const;
|
||||
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
|
||||
const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const;
|
||||
Bool CheckCompleteness() const;
|
||||
// aka. `buffer` as in glDrawBuffers/glReadBuffers
|
||||
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
|
||||
bool DrawBuffersIsDirty() const { return m_drawBuffersDirty; }
|
||||
void ClearDrawBuffersDirtyState() { m_drawBuffersDirty = false; }
|
||||
const Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>& GetDrawBuffers() const;
|
||||
const FramebufferAttachmentArray& GetDrawBuffers() const;
|
||||
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
|
||||
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
|
||||
|
||||
const FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
|
||||
return m_attachmentVersions;
|
||||
}
|
||||
|
||||
Uint16 GetObjectVersion() const { return m_objectVersion; }
|
||||
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
private:
|
||||
void BumpAttachmentVersion(FramebufferAttachmentType type);
|
||||
|
||||
const Uint m_externalIndex = 0;
|
||||
Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>
|
||||
m_attachments;
|
||||
Bool m_drawBuffersDirty = false;
|
||||
Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS> m_drawBuffers;
|
||||
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0;
|
||||
FramebufferAttachmentObjectArray m_attachmentObjects;
|
||||
FramebufferAttachmentVersionArray m_attachmentVersions;
|
||||
|
||||
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
|
||||
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto
|
||||
|
||||
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
|
||||
Uint16 m_objectVersion = 0;
|
||||
};
|
||||
|
||||
} // namespace GLState
|
||||
|
||||
@@ -7,168 +7,246 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "RenderState.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
RenderState::RenderState() {}
|
||||
|
||||
Uint RenderState::GetVersion() const {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
const RenderStateParameters& RenderState::GetAllParameters() const {
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
// -------------------- Rasterization --------------------
|
||||
void RenderState::SetViewport(IntVec4 viewport) {
|
||||
m_viewport = viewport;
|
||||
if (m_parameters.Viewport == viewport) return;
|
||||
|
||||
m_parameters.Viewport = viewport;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const IntVec4& RenderState::GetViewport() const {
|
||||
return m_viewport;
|
||||
return m_parameters.Viewport;
|
||||
}
|
||||
|
||||
// -------------------- Capabilities --------------------
|
||||
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
|
||||
#define SET_CAPABILITY(capability, flag) \
|
||||
case CapabilityInput::capability: \
|
||||
if (m_parameters.capability##Enabled == flag) break; \
|
||||
m_parameters.capability##Enabled = flag; \
|
||||
++m_version; \
|
||||
break;
|
||||
|
||||
switch (cap) {
|
||||
case CapabilityInput::Blend:
|
||||
m_blendEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::DepthTest:
|
||||
m_depthTestEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::CullFace:
|
||||
m_cullFaceEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::ScissorTest:
|
||||
m_scissorTestEnabled = enabled;
|
||||
SET_CAPABILITY(DepthTest, enabled);
|
||||
SET_CAPABILITY(CullFace, enabled);
|
||||
SET_CAPABILITY(ScissorTest, enabled);
|
||||
case CapabilityInput::Blend: {
|
||||
Bool stateChanged = false;
|
||||
for (auto& blendState : m_parameters.BlendStates) {
|
||||
if (blendState.Enabled == enabled) continue;
|
||||
blendState.Enabled = enabled;
|
||||
stateChanged = true;
|
||||
}
|
||||
if (stateChanged) ++m_version;
|
||||
break;
|
||||
}
|
||||
default: // not supported currently
|
||||
break;
|
||||
}
|
||||
#undef SET_CAPABILITY
|
||||
}
|
||||
|
||||
Bool RenderState::IsCapabilityEnabled(CapabilityInput cap) const {
|
||||
#define RETURN_CAPABILITY(capability) \
|
||||
case CapabilityInput::capability: \
|
||||
return m_parameters.capability##Enabled;
|
||||
switch (cap) {
|
||||
RETURN_CAPABILITY(DepthTest);
|
||||
RETURN_CAPABILITY(CullFace);
|
||||
RETURN_CAPABILITY(ScissorTest);
|
||||
case CapabilityInput::Blend:
|
||||
return m_blendEnabled;
|
||||
case CapabilityInput::DepthTest:
|
||||
return m_depthTestEnabled;
|
||||
case CapabilityInput::CullFace:
|
||||
return m_cullFaceEnabled;
|
||||
case CapabilityInput::ScissorTest:
|
||||
return m_scissorTestEnabled;
|
||||
return m_parameters.BlendStates[0].Enabled;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderState::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) {
|
||||
// Only for BlendState currently
|
||||
if (cap != CapabilityInput::Blend) {
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
return;
|
||||
}
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
if (m_parameters.BlendStates[index].Enabled == enabled) return;
|
||||
|
||||
m_parameters.BlendStates[index].Enabled = enabled;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Bool RenderState::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const {
|
||||
// Only for BlendState currently
|
||||
if (cap != CapabilityInput::Blend) {
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
return false;
|
||||
}
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index);
|
||||
return false;
|
||||
}
|
||||
return m_parameters.BlendStates[index].Enabled;
|
||||
}
|
||||
|
||||
// -------------------- Blending --------------------
|
||||
void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha) {
|
||||
m_srcFactorRGB = srcRGB;
|
||||
m_dstFactorRGB = dstRGB;
|
||||
m_srcFactorAlpha = srcAlpha;
|
||||
m_dstFactorAlpha = dstAlpha;
|
||||
Bool stateChanged = false;
|
||||
for (auto& blendState : m_parameters.BlendStates) {
|
||||
if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB &&
|
||||
blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) {
|
||||
continue;
|
||||
}
|
||||
blendState.SrcFactorRGB = srcRGB;
|
||||
blendState.DstFactorRGB = dstRGB;
|
||||
blendState.SrcFactorAlpha = srcAlpha;
|
||||
blendState.DstFactorAlpha = dstAlpha;
|
||||
stateChanged = true;
|
||||
}
|
||||
if (!stateChanged) return;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void RenderState::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const {
|
||||
srcRGB = m_srcFactorRGB;
|
||||
dstRGB = m_dstFactorRGB;
|
||||
srcAlpha = m_srcFactorAlpha;
|
||||
dstAlpha = m_dstFactorAlpha;
|
||||
srcRGB = m_parameters.BlendStates[0].SrcFactorRGB;
|
||||
dstRGB = m_parameters.BlendStates[0].DstFactorRGB;
|
||||
srcAlpha = m_parameters.BlendStates[0].SrcFactorAlpha;
|
||||
dstAlpha = m_parameters.BlendStates[0].DstFactorAlpha;
|
||||
}
|
||||
|
||||
void RenderState::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB,
|
||||
BlendFactor srcAlpha, BlendFactor dstAlpha) {
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
PerBufferBlendState& blendState = m_parameters.BlendStates[index];
|
||||
if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB &&
|
||||
blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) {
|
||||
return;
|
||||
}
|
||||
blendState.SrcFactorRGB = srcRGB;
|
||||
blendState.DstFactorRGB = dstRGB;
|
||||
blendState.SrcFactorAlpha = srcAlpha;
|
||||
blendState.DstFactorAlpha = dstAlpha;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void RenderState::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB,
|
||||
BlendFactor& srcAlpha, BlendFactor& dstAlpha) const {
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
srcRGB = m_parameters.BlendStates[index].SrcFactorRGB;
|
||||
dstRGB = m_parameters.BlendStates[index].DstFactorRGB;
|
||||
srcAlpha = m_parameters.BlendStates[index].SrcFactorAlpha;
|
||||
dstAlpha = m_parameters.BlendStates[index].DstFactorAlpha;
|
||||
}
|
||||
|
||||
// -------------------- Depth --------------------
|
||||
void RenderState::SetDepthFunc(DepthTestFunc func) {
|
||||
m_depthFunc = func;
|
||||
if (m_parameters.DepthFunc == func) return;
|
||||
|
||||
m_parameters.DepthFunc = func;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
DepthTestFunc RenderState::GetDepthFunc() const {
|
||||
return m_depthFunc;
|
||||
return m_parameters.DepthFunc;
|
||||
}
|
||||
|
||||
void RenderState::SetDepthMask(Bool flag) {
|
||||
m_depthMask = flag;
|
||||
if (m_parameters.DepthMask == flag) return;
|
||||
|
||||
m_parameters.DepthMask = flag;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Bool RenderState::GetDepthMask() const {
|
||||
return m_depthMask;
|
||||
return m_parameters.DepthMask;
|
||||
}
|
||||
|
||||
// -------------------- Color Mask --------------------
|
||||
void RenderState::SetColorMask(BoolVec4 mask) {
|
||||
m_colorMask = mask;
|
||||
if (m_parameters.ColorMask == mask) return;
|
||||
|
||||
m_parameters.ColorMask = mask;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const BoolVec4 RenderState::GetColorMask() const {
|
||||
return m_colorMask;
|
||||
return m_parameters.ColorMask;
|
||||
}
|
||||
|
||||
// -------------------- Clear State --------------------
|
||||
void RenderState::SetClearColor(FloatVec4 color) {
|
||||
m_clearColor = color;
|
||||
if (m_parameters.ClearColor == color) return;
|
||||
|
||||
m_parameters.ClearColor = color;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const FloatVec4& RenderState::GetClearColor() const {
|
||||
return m_clearColor;
|
||||
return m_parameters.ClearColor;
|
||||
}
|
||||
|
||||
void RenderState::SetClearDepth(Float depth) {
|
||||
m_clearDepth = depth;
|
||||
if (m_parameters.ClearDepth == depth) return;
|
||||
|
||||
m_parameters.ClearDepth = depth;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Float RenderState::GetClearDepth() const {
|
||||
return m_clearDepth;
|
||||
return m_parameters.ClearDepth;
|
||||
}
|
||||
|
||||
// -------------------- Pixel Store --------------------
|
||||
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
|
||||
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
|
||||
case PixelStoreParam::paramNameHead##paramNameTail: \
|
||||
if (m_pixelStore##paramNameHead##Parameters.paramNameTail == val) break; \
|
||||
m_pixelStore##paramNameHead##Parameters.paramNameTail = val; \
|
||||
break;
|
||||
|
||||
switch (param) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
m_packParameters.Alignment = value;
|
||||
break;
|
||||
case PixelStoreParam::PackRowLength:
|
||||
m_packParameters.RowLength = value;
|
||||
break;
|
||||
case PixelStoreParam::PackImageHeight:
|
||||
m_packParameters.ImageHeight = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipPixels:
|
||||
m_packParameters.SkipPixels = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipRows:
|
||||
m_packParameters.SkipRows = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipImages:
|
||||
m_packParameters.SkipImages = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
m_packParameters.SwapBytes = value != 0;
|
||||
break;
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
m_packParameters.LSBFirst = value != 0;
|
||||
break;
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
m_unpackParameters.Alignment = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackRowLength:
|
||||
m_unpackParameters.RowLength = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackImageHeight:
|
||||
m_unpackParameters.ImageHeight = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipPixels:
|
||||
m_unpackParameters.SkipPixels = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipRows:
|
||||
m_unpackParameters.SkipRows = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipImages:
|
||||
m_unpackParameters.SkipImages = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
m_unpackParameters.SwapBytes = value != 0;
|
||||
MGLOG_D("%s: SwapBytes = %s", __func__, value ? "true" : "false");
|
||||
break;
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
m_unpackParameters.LSBFirst = value != 0;
|
||||
break;
|
||||
SET_PIXEL_STORE_PARAM(Pack, Alignment, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, RowLength, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, ImageHeight, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipPixels, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipRows, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipImages, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SwapBytes, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Pack, LSBFirst, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, Alignment, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, RowLength, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, ImageHeight, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipPixels, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipRows, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipImages, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SwapBytes, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, LSBFirst, value != 0);
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
|
||||
return;
|
||||
@@ -176,39 +254,26 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
Int RenderState::GetPixelStoreParam(PixelStoreParam param) const {
|
||||
#define RETURN_PIXEL_STORE_PARAM(paramNameHead, paramNameTail) \
|
||||
case PixelStoreParam::paramNameHead##paramNameTail: \
|
||||
return m_pixelStore##paramNameHead##Parameters.paramNameTail;
|
||||
switch (param) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
return m_packParameters.Alignment;
|
||||
case PixelStoreParam::PackRowLength:
|
||||
return m_packParameters.RowLength;
|
||||
case PixelStoreParam::PackImageHeight:
|
||||
return m_packParameters.ImageHeight;
|
||||
case PixelStoreParam::PackSkipPixels:
|
||||
return m_packParameters.SkipPixels;
|
||||
case PixelStoreParam::PackSkipRows:
|
||||
return m_packParameters.SkipRows;
|
||||
case PixelStoreParam::PackSkipImages:
|
||||
return m_packParameters.SkipImages;
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
return m_packParameters.SwapBytes ? 1 : 0;
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
return m_packParameters.LSBFirst ? 1 : 0;
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
return m_unpackParameters.Alignment;
|
||||
case PixelStoreParam::UnpackRowLength:
|
||||
return m_unpackParameters.RowLength;
|
||||
case PixelStoreParam::UnpackImageHeight:
|
||||
return m_unpackParameters.ImageHeight;
|
||||
case PixelStoreParam::UnpackSkipPixels:
|
||||
return m_unpackParameters.SkipPixels;
|
||||
case PixelStoreParam::UnpackSkipRows:
|
||||
return m_unpackParameters.SkipRows;
|
||||
case PixelStoreParam::UnpackSkipImages:
|
||||
return m_unpackParameters.SkipImages;
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
return m_unpackParameters.SwapBytes ? 1 : 0;
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
return m_unpackParameters.LSBFirst ? 1 : 0;
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, Alignment);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, RowLength);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, ImageHeight);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipPixels);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipRows);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipImages);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SwapBytes);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, LSBFirst);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, Alignment);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, RowLength);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, ImageHeight);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipPixels);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipRows);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipImages);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SwapBytes);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, LSBFirst);
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
|
||||
return 0;
|
||||
@@ -216,25 +281,31 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
PixelStoreParameters RenderState::GetPixelStoreParameters(Bool isUnpack) const {
|
||||
return isUnpack ? m_unpackParameters : m_packParameters;
|
||||
return isUnpack ? m_pixelStoreUnpackParameters : m_pixelStorePackParameters;
|
||||
}
|
||||
|
||||
// -------------------- Cull Face --------------------
|
||||
void RenderState::SetCullFaceMode(CullFaceMode mode) {
|
||||
m_cullFaceMode = mode;
|
||||
if (m_parameters.CullFaceModeSetting == mode) return;
|
||||
|
||||
m_parameters.CullFaceModeSetting = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
CullFaceMode RenderState::GetCullFaceMode() const {
|
||||
return m_cullFaceMode;
|
||||
return m_parameters.CullFaceModeSetting;
|
||||
}
|
||||
|
||||
// --------------------- Scissor ---------------------
|
||||
void RenderState::SetScissorBox(IntVec4 box) {
|
||||
m_scissorBox = box;
|
||||
if (m_parameters.ScissorBox == box) return;
|
||||
|
||||
m_parameters.ScissorBox = box;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const IntVec4& RenderState::GetScissorBox() const {
|
||||
return m_scissorBox;
|
||||
return m_parameters.ScissorBox;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
// End of Source File Header
|
||||
|
||||
#pragma once
|
||||
#include "MG_Util/Math/VectorTypes.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Math/VectorTypes.h>
|
||||
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
|
||||
|
||||
namespace MobileGL {
|
||||
enum class BlendFactor {
|
||||
@@ -53,7 +53,7 @@ namespace MobileGL {
|
||||
PackSkipPixels,
|
||||
PackSkipImages,
|
||||
PackSwapBytes,
|
||||
PackLsbFirst,
|
||||
PackLSBFirst,
|
||||
|
||||
// Unpack Parameters
|
||||
UnpackAlignment,
|
||||
@@ -63,7 +63,7 @@ namespace MobileGL {
|
||||
UnpackSkipPixels,
|
||||
UnpackSkipImages,
|
||||
UnpackSwapBytes,
|
||||
UnpackLsbFirst,
|
||||
UnpackLSBFirst,
|
||||
|
||||
PixelStoreParamCount,
|
||||
Unknown = -1
|
||||
@@ -128,12 +128,51 @@ namespace MobileGL {
|
||||
Int Alignment = 4;
|
||||
};
|
||||
|
||||
struct PerBufferBlendState {
|
||||
Bool Enabled = false;
|
||||
BlendFactor SrcFactorRGB = BlendFactor::One;
|
||||
BlendFactor DstFactorRGB = BlendFactor::Zero;
|
||||
BlendFactor SrcFactorAlpha = BlendFactor::One;
|
||||
BlendFactor DstFactorAlpha = BlendFactor::Zero;
|
||||
};
|
||||
|
||||
struct RenderStateParameters {
|
||||
// Rasterization
|
||||
IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
|
||||
// Blending
|
||||
Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates;
|
||||
|
||||
// Depth
|
||||
Bool DepthTestEnabled = false;
|
||||
DepthTestFunc DepthFunc = DepthTestFunc::Less;
|
||||
Bool DepthMask = true;
|
||||
|
||||
// Color Mask
|
||||
BoolVec4 ColorMask = BoolVec4(true, true, true, true);
|
||||
|
||||
// Clear State
|
||||
FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Float ClearDepth = 1.0f;
|
||||
|
||||
// Cull Face
|
||||
Bool CullFaceEnabled = false;
|
||||
CullFaceMode CullFaceModeSetting = CullFaceMode::Back;
|
||||
|
||||
// Scissor
|
||||
Bool ScissorTestEnabled = false;
|
||||
IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class RenderState {
|
||||
public:
|
||||
RenderState();
|
||||
|
||||
Uint GetVersion() const;
|
||||
const RenderStateParameters& GetAllParameters() const;
|
||||
|
||||
// Rasterization
|
||||
void SetViewport(IntVec4 viewport); // x, y, width, height
|
||||
const IntVec4& GetViewport() const; // x, y, width, height
|
||||
@@ -141,11 +180,17 @@ namespace MobileGL {
|
||||
// Capabilities
|
||||
void SetCapability(CapabilityInput cap, Bool enabled);
|
||||
Bool IsCapabilityEnabled(CapabilityInput cap) const;
|
||||
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
|
||||
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
|
||||
|
||||
// Blending
|
||||
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
|
||||
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha);
|
||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
|
||||
// Depth
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
@@ -177,39 +222,12 @@ namespace MobileGL {
|
||||
const IntVec4& GetScissorBox() const; // x, y, width, height
|
||||
|
||||
private:
|
||||
// Rasterization
|
||||
IntVec4 m_viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
|
||||
// Blending
|
||||
Bool m_blendEnabled = false;
|
||||
BlendFactor m_srcFactorRGB = BlendFactor::One;
|
||||
BlendFactor m_dstFactorRGB = BlendFactor::Zero;
|
||||
BlendFactor m_srcFactorAlpha = BlendFactor::One;
|
||||
BlendFactor m_dstFactorAlpha = BlendFactor::Zero;
|
||||
|
||||
// Depth
|
||||
Bool m_depthTestEnabled = false;
|
||||
DepthTestFunc m_depthFunc = DepthTestFunc::Less;
|
||||
Bool m_depthMask = true;
|
||||
|
||||
// Color Mask
|
||||
BoolVec4 m_colorMask = BoolVec4(true, true, true, true);
|
||||
|
||||
// Clear State
|
||||
FloatVec4 m_clearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Float m_clearDepth = 1.0f;
|
||||
Uint16 m_version = 0;
|
||||
RenderStateParameters m_parameters;
|
||||
|
||||
// Pixel Store
|
||||
PixelStoreParameters m_packParameters;
|
||||
PixelStoreParameters m_unpackParameters;
|
||||
|
||||
// Cull Face
|
||||
Bool m_cullFaceEnabled = false;
|
||||
CullFaceMode m_cullFaceMode = CullFaceMode::Back;
|
||||
|
||||
// Scissor
|
||||
Bool m_scissorTestEnabled = false;
|
||||
IntVec4 m_scissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
PixelStoreParameters m_pixelStorePackParameters;
|
||||
PixelStoreParameters m_pixelStoreUnpackParameters;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -14,47 +14,77 @@ namespace MobileGL {
|
||||
SamplerObject::SamplerObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
|
||||
|
||||
void SamplerObject::SetWrapS(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapS) return;
|
||||
|
||||
m_samplerParameters.wrapS = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetWrapT(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapT) return;
|
||||
|
||||
m_samplerParameters.wrapT = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetWrapR(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapR) return;
|
||||
|
||||
m_samplerParameters.wrapR = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMinFilter(SamplerFilterMode mode) {
|
||||
if (mode == m_samplerParameters.minFilter) return;
|
||||
|
||||
m_samplerParameters.minFilter = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMagFilter(SamplerFilterMode mode) {
|
||||
if (mode == m_samplerParameters.magFilter) return;
|
||||
|
||||
m_samplerParameters.magFilter = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMipmapMode(SamplerMipmapMode mode) {
|
||||
if (mode == m_samplerParameters.mipmapMode) return;
|
||||
|
||||
m_samplerParameters.mipmapMode = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
|
||||
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
|
||||
|
||||
if (minLod > maxLod) {
|
||||
THROW_EXCEPTION("minLod cannot be greater than maxLod");
|
||||
}
|
||||
m_samplerParameters.minLod = minLod;
|
||||
m_samplerParameters.maxLod = maxLod;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetLodBias(Float bias) {
|
||||
if (bias == m_samplerParameters.lodBias) return;
|
||||
|
||||
m_samplerParameters.lodBias = bias;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) {
|
||||
if (func == m_samplerParameters.compareFunc) return;
|
||||
|
||||
m_samplerParameters.compareFunc = func;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetCompareMode(SamplerCompareMode mode) {
|
||||
if (mode == m_samplerParameters.compareMode) return;
|
||||
|
||||
m_samplerParameters.compareMode = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
SamplerWrapMode SamplerObject::GetWrapS() const {
|
||||
@@ -108,6 +138,10 @@ namespace MobileGL {
|
||||
const SamplerParameters& SamplerObject::GetAllSamplerParameters() const {
|
||||
return m_samplerParameters;
|
||||
}
|
||||
|
||||
Uint16 SamplerObject::GetVersion() const {
|
||||
return m_version;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -98,10 +98,12 @@ namespace MobileGL {
|
||||
SamplerCompareMode GetCompareMode() const;
|
||||
SamplerCompareFunc GetSamplerCompareFunc() const;
|
||||
Uint GetExternalIndex() const;
|
||||
Uint16 GetVersion() const;
|
||||
const SamplerParameters& GetAllSamplerParameters() const;
|
||||
|
||||
private:
|
||||
const Uint m_externalIndex;
|
||||
Uint16 m_version = 0;
|
||||
SamplerParameters m_samplerParameters;
|
||||
};
|
||||
} // namespace GLState
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "TextureObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
|
||||
namespace MobileGL {
|
||||
@@ -43,7 +44,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
|
||||
if (format == m_internalFormat) return;
|
||||
|
||||
m_internalFormat = format;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint TextureObjectBase::GetExternalIndex() const {
|
||||
@@ -55,7 +59,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetBorderColor(const FloatVec4& color) {
|
||||
if (color == m_borderColor) return;
|
||||
|
||||
m_borderColor = color;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const {
|
||||
@@ -80,6 +87,8 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) {
|
||||
if (GetSwizzleParam(param) == value) return;
|
||||
|
||||
switch (param) {
|
||||
case TextureSwizzleParam::Red:
|
||||
m_swizzleParams.r() = value;
|
||||
@@ -98,9 +107,14 @@ namespace MobileGL {
|
||||
static_cast<Int>(param));
|
||||
break;
|
||||
}
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) {
|
||||
if (values == m_swizzleParams) return;
|
||||
|
||||
m_swizzleParams = values;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
const UintVec2& TextureObjectBase::GetLevelRange() const {
|
||||
@@ -108,11 +122,21 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
|
||||
if (baseLevel == m_levelRange.x()) return;
|
||||
|
||||
m_levelRange.x() = baseLevel;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
|
||||
if (maxLevel == m_levelRange.y()) return;
|
||||
|
||||
m_levelRange.y() = maxLevel;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
|
||||
return m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const {
|
||||
@@ -144,11 +168,11 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
bool dirty) {
|
||||
Bool dirty) {
|
||||
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||
}
|
||||
|
||||
bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
Bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
return m_textureStorage.IsDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel);
|
||||
}
|
||||
|
||||
@@ -170,7 +194,7 @@ namespace MobileGL {
|
||||
|
||||
// For some reason mojang decided to have 0x0 in last level mipmap
|
||||
// Relaxing checks for that
|
||||
bool hadZero = false;
|
||||
Bool hadZero = false;
|
||||
for (SizeT i = 0; i < levelCount; ++i) {
|
||||
const auto& levelSize = m_textureStorage.GetTexelSize(0, i);
|
||||
if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) {
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace MobileGL {
|
||||
virtual const UintVec2& GetLevelRange() const = 0;
|
||||
virtual void SetBaseLevel(Uint baseLevel) = 0;
|
||||
virtual void SetMaxLevel(Uint maxLevel) = 0;
|
||||
virtual Uint16 GetTextureParamsVersion() const = 0;
|
||||
|
||||
protected:
|
||||
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
|
||||
@@ -67,7 +68,7 @@ namespace MobileGL {
|
||||
const UintVec2& GetLevelRange() const override;
|
||||
void SetBaseLevel(Uint baseLevel) override;
|
||||
void SetMaxLevel(Uint maxLevel) override;
|
||||
|
||||
Uint16 GetTextureParamsVersion() const override;
|
||||
protected:
|
||||
const Uint m_externalIndex;
|
||||
const TextureTarget m_target = TextureTarget::Unknown;
|
||||
@@ -77,6 +78,7 @@ namespace MobileGL {
|
||||
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
||||
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
|
||||
UintVec2 m_levelRange = {0, 1000};
|
||||
Uint16 m_textureParamsVersion = 0;
|
||||
};
|
||||
|
||||
class TextureObjectMipmap : public TextureObjectBase {
|
||||
@@ -92,8 +94,9 @@ namespace MobileGL {
|
||||
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
|
||||
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
|
||||
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
|
||||
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0;
|
||||
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
|
||||
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
Bool dirty = true) = 0;
|
||||
virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
|
||||
};
|
||||
|
||||
class TextureObjectWithOneMipmap : public TextureObjectMipmap {
|
||||
@@ -108,7 +111,7 @@ namespace MobileGL {
|
||||
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
|
||||
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
|
||||
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override;
|
||||
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) override;
|
||||
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty) override;
|
||||
bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
|
||||
|
||||
IntVec3 GetBaseSize() const override;
|
||||
|
||||
@@ -22,20 +22,26 @@ namespace MobileGL {
|
||||
attr.Offset = 0;
|
||||
attr.Buffer = nullptr;
|
||||
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexArrayObject::EnableAttribute(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Enabled) return;
|
||||
|
||||
m_attributes[index].Enabled = true;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeSwitchVersion(index);
|
||||
}
|
||||
|
||||
void VertexArrayObject::DisableAttribute(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (!m_attributes[index].Enabled) return;
|
||||
|
||||
m_attributes[index].Enabled = false;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeSwitchVersion(index);
|
||||
}
|
||||
|
||||
Bool VertexArrayObject::IsAttributeEnabled(Uint index) const {
|
||||
@@ -47,6 +53,12 @@ namespace MobileGL {
|
||||
SizeT offset, Bool isInteger) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Size == size && m_attributes[index].Type == type &&
|
||||
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride &&
|
||||
m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < 1 || size > 4) {
|
||||
return;
|
||||
}
|
||||
@@ -59,13 +71,16 @@ namespace MobileGL {
|
||||
attr.Offset = offset;
|
||||
attr.IsInteger = isInteger;
|
||||
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
|
||||
void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Buffer == buffer) return;
|
||||
|
||||
m_attributes[index].Buffer = buffer;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeBufferVersion(index);
|
||||
}
|
||||
|
||||
BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() {
|
||||
@@ -83,22 +98,6 @@ namespace MobileGL {
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
void VertexArrayObject::MarkAttributeDirty(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
if (std::find(m_dirtyAttributes.begin(), m_dirtyAttributes.end(), index) != m_dirtyAttributes.end()) {
|
||||
return;
|
||||
}
|
||||
m_dirtyAttributes.push_back(index);
|
||||
}
|
||||
|
||||
const Vector<Uint>& VertexArrayObject::GetDirtyAttributeIndices() const {
|
||||
return m_dirtyAttributes;
|
||||
}
|
||||
|
||||
void VertexArrayObject::ClearDirtyAttributes() {
|
||||
m_dirtyAttributes.clear();
|
||||
}
|
||||
|
||||
Uint VertexArrayObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
}
|
||||
@@ -107,13 +106,39 @@ namespace MobileGL {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
if (m_attributes[index].Divisor == divisor) return;
|
||||
m_attributes[index].Divisor = divisor;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
|
||||
Uint VertexArrayObject::GetAttributeDivisor(Uint index) const {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return 0;
|
||||
return m_attributes[index].Divisor;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeFormatVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].FormatVersion;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeBufferVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].BufferVersion;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeSwitchVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].SwitchVersion;
|
||||
}
|
||||
|
||||
const VertexAttributeVersion& VertexArrayObject::GetAttributeVersion(Uint index) const {
|
||||
static VertexAttributeVersion emptyVersion;
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return emptyVersion;
|
||||
return m_attributeVersions[index];
|
||||
}
|
||||
|
||||
const Array<VertexAttributeVersion, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::
|
||||
GetAllAttributeVersions() const {
|
||||
return m_attributeVersions;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include "../BufferState/BufferObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
@@ -25,6 +26,12 @@ namespace MobileGL {
|
||||
SharedPtr<BufferObject> Buffer;
|
||||
};
|
||||
|
||||
struct VertexAttributeVersion {
|
||||
Uint16 FormatVersion = 0;
|
||||
Uint16 BufferVersion = 0;
|
||||
Uint16 SwitchVersion = 0;
|
||||
};
|
||||
|
||||
class VertexArrayObject {
|
||||
public:
|
||||
static constexpr int MAX_VERTEX_ATTRIBS = 16;
|
||||
@@ -45,19 +52,22 @@ namespace MobileGL {
|
||||
const VertexAttribute& GetAttribute(Uint index) const;
|
||||
const Array<VertexAttribute, MAX_VERTEX_ATTRIBS>& GetAllAttributes() const;
|
||||
|
||||
const Vector<Uint>& GetDirtyAttributeIndices() const;
|
||||
void ClearDirtyAttributes();
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
void SetAttributeDivisor(Uint index, Uint divisor);
|
||||
Uint GetAttributeDivisor(Uint index) const;
|
||||
|
||||
const VertexAttributeVersion& GetAttributeVersion(Uint index) const;
|
||||
const Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS>& GetAllAttributeVersions() const;
|
||||
|
||||
private:
|
||||
void MarkAttributeDirty(Uint index);
|
||||
void BumpAttributeFormatVersion(Uint index);
|
||||
void BumpAttributeBufferVersion(Uint index);
|
||||
void BumpAttributeSwitchVersion(Uint index);
|
||||
|
||||
const Uint m_externalIndex = 0;
|
||||
Array<VertexAttribute, MAX_VERTEX_ATTRIBS> m_attributes;
|
||||
Vector<Uint> m_dirtyAttributes;
|
||||
Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS> m_attributeVersions;
|
||||
BindingSlot<BufferObject> m_indexBufferBindingSlot;
|
||||
};
|
||||
} // namespace GLState
|
||||
|
||||
Reference in New Issue
Block a user