mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
- ROADMAP P0.5 / ARCHITECTURE.md value-header manifest: MGPipeTypes.h embedded RenderStateParameters and PixelStoreParameters through RenderState.h, which drags FramebufferObject.h and the whole texture/renderbuffer/sampler chain into MG_Pipe; purity gate A (no MG_State/MG_Impl/MG_Backend/MG_Remote in the closure) could not be armed for anything in MG_Pipe while that include existed. - MGPipeValueTypes.h is a verbatim cut, comments included: the eleven RenderState.h enums (all of them - a split would be the maintenance trap), PixelStoreParameters, PerBufferBlendState, StencilFaceState, RenderStateParameters (member order untouched: DirectGLES' offsetof spans and PipeSpanTable.inc name the members), the six SamplerObject.h enums and SamplerParameters (BorderColorForm stays Uint8, it sets the tail padding), and VertexAttribute / VertexBufferBindingPoint / VertexAttributeVersion, which keep namespace MobileGL::MG_State::GLState with a forward-declared BufferObject so no mangled name changes. - MAX_DRAW_BUFFERS becomes inline constexpr kMGMaxDrawBuffers in namespace MobileGL and FramebufferObject::MAX_DRAW_BUFFERS is defined from it, so the eighty existing spellings keep working and the two cannot drift. No other constant is added. - The four MG_State headers become forwarders (include the value header, keep their class definitions); RenderState.cpp gains a direct FramebufferObject.h include because it spells FramebufferObject::MAX_DRAW_BUFFERS and only ever got that header transitively. No other TU lost a transitive include: the full build (Release, clang, tests + integration tests) passed without touching anything under MG_Backend, MG_Impl or MG_Util. - DynamicBackendParameters does NOT move (SizeT members and TextureTarget-taking member functions make that a type change, not a move); MGPipeTypes.h keeps its BackendObject.h include and the debt comment now says so, which is why gate A asserts MGPipeValueTypes.h rather than MGPipeTypes.h. - New trip wires in the header: trivially-copyable + exact sizeof for PixelStoreParameters/PerBufferBlendState/StencilFaceState (28), SamplerParameters (100), VertexAttributeVersion (6), RenderStateParameters (1168, standard layout, BlendStates before LogicOp, BlendStates sized by kMGMaxDrawBuffers). Their runtime twins ValueTypeLayoutsArePinned and the carrier check ResidualBlockIsExactlyItsTwoValueStructsPlusPatchTail (Pack at 1168, CapabilityBits at 1200) are added to PipeCatalogueTest without a new include. - gen_pipe.py's "field lists of their own in P0.5" comment now says P1 (the comparator needs std::array<struct> support first); PipeVerify.inc regenerated. - Verified: ctest -L unit 1460/1460 and -L integration-gpu green; ctest -N names a superset of feat/disaggregated@6672778b (two added, none lost); one definition per moved type; the -H closure of the new header contains no MG_State/MG_Backend/ MG_Impl/MG_Remote header and the header compiles alone; nm --defined-only -S against the base libMobileGL.so: 0 added / 0 removed / 0 resized, .text byte-identical, the only differing bytes are the build-id and two stamp strings.
189 lines
7.4 KiB
C++
189 lines
7.4 KiB
C++
// MobileGL - MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include "MG_Util/Types.h"
|
|
#include <Includes.h>
|
|
#include <MG_State/GLState/TextureState/TextureObject.h>
|
|
#include <MG_State/GLState/RenderbufferState/RenderbufferObject.h>
|
|
#include <MG_Pipe/MGPipeValueTypes.h>
|
|
|
|
namespace MobileGL {
|
|
enum class FramebufferTarget {
|
|
Draw,
|
|
Read,
|
|
FramebufferTargetCount,
|
|
Unknown = -1
|
|
};
|
|
|
|
enum class FramebufferAttachmentType {
|
|
None,
|
|
|
|
FrontLeft,
|
|
FrontRight,
|
|
BackLeft,
|
|
BackRight,
|
|
|
|
Depth,
|
|
Stencil,
|
|
|
|
Color0,
|
|
Color1,
|
|
Color2,
|
|
Color3,
|
|
Color4,
|
|
Color5,
|
|
Color6,
|
|
Color7,
|
|
Color8,
|
|
Color9,
|
|
Color10,
|
|
Color11,
|
|
Color12,
|
|
Color13,
|
|
Color14,
|
|
Color15,
|
|
Color16,
|
|
Color17,
|
|
Color18,
|
|
Color19,
|
|
Color20,
|
|
Color21,
|
|
Color22,
|
|
Color23,
|
|
Color24,
|
|
Color25,
|
|
Color26,
|
|
Color27,
|
|
Color28,
|
|
Color29,
|
|
Color30,
|
|
Color31,
|
|
ColorMax = Color31,
|
|
|
|
FramebufferAttachmentTypeCount,
|
|
Unknown = -1
|
|
};
|
|
|
|
namespace MG_State::GLState {
|
|
class FramebufferAttachmentObject {
|
|
public:
|
|
explicit FramebufferAttachmentObject(const SharedPtr<MG_State::GLState::ITextureObject>& texture,
|
|
TextureUploadTarget textureUploadTarget,
|
|
Int level = 0, Int layer = 0, Bool layered = false);
|
|
explicit FramebufferAttachmentObject(const SharedPtr<RenderbufferObject>& renderbuffer);
|
|
explicit FramebufferAttachmentObject(Bool IsValid = true);
|
|
|
|
Bool IsTexture() const;
|
|
Bool IsRenderbuffer() const;
|
|
Bool IsEmpty() const;
|
|
const SharedPtr<MG_State::GLState::ITextureObject>& GetTexture() const;
|
|
const SharedPtr<RenderbufferObject>& GetRenderbuffer() const;
|
|
Int GetTextureLevel() const;
|
|
Int GetTextureLayer() const;
|
|
Bool IsLayered() const;
|
|
TextureUploadTarget GetTextureUploadTarget() const;
|
|
Bool IsComplete() const;
|
|
IntVec3 GetSize() const;
|
|
Bool IsValid() const;
|
|
|
|
private:
|
|
SharedPtr<MG_State::GLState::ITextureObject> m_texture = nullptr;
|
|
SharedPtr<RenderbufferObject> m_renderbuffer = nullptr;
|
|
TextureUploadTarget m_textureUploadTarget = TextureUploadTarget::Unknown;
|
|
Int m_textureLevel = 0;
|
|
Int m_textureLayer = 0;
|
|
Bool m_layered = false;
|
|
Bool m_isValid = true;
|
|
};
|
|
|
|
class FramebufferObject {
|
|
public:
|
|
static constexpr Uint MAX_DRAW_BUFFERS = MobileGL::kMGMaxDrawBuffers;
|
|
|
|
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, const SharedPtr<ITextureObject>& texture,
|
|
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown, int level = 0,
|
|
int layer = 0, Bool layered = false);
|
|
void AttachRenderbuffer(FramebufferAttachmentType type, const SharedPtr<RenderbufferObject>& renderbuffer);
|
|
void Detach(FramebufferAttachmentType type);
|
|
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);
|
|
const FramebufferAttachmentArray& GetDrawBuffers() const;
|
|
void SetReadBuffer(FramebufferAttachmentType buf);
|
|
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
|
|
|
|
// GL_ARB_framebuffer_no_attachments state (GL 4.6 core table 23.24). The shape a
|
|
// framebuffer with no attachments would rasterize at; all zero / FALSE until set.
|
|
Int GetDefaultWidth() const { return m_defaultWidth; }
|
|
Int GetDefaultHeight() const { return m_defaultHeight; }
|
|
Int GetDefaultLayers() const { return m_defaultLayers; }
|
|
Int GetDefaultSamples() const { return m_defaultSamples; }
|
|
Bool GetDefaultFixedSampleLocations() const { return m_defaultFixedSampleLocations; }
|
|
void SetDefaultWidth(Int value);
|
|
void SetDefaultHeight(Int value);
|
|
void SetDefaultLayers(Int value);
|
|
void SetDefaultSamples(Int value);
|
|
void SetDefaultFixedSampleLocations(Bool value);
|
|
|
|
FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
|
|
return m_attachmentVersions;
|
|
}
|
|
|
|
Uint16 GetObjectVersion() const { return m_objectVersion; }
|
|
|
|
// Globally-unique, never-reused id for THIS object's lifetime - the same
|
|
// contract as VertexArrayObject::GetLifetimeId(), and needed for the same
|
|
// reason: neither the GL name nor the heap address can tell a
|
|
// deleted-and-recreated framebuffer from the original, and m_objectVersion
|
|
// starts at 0 for every new object, so a backend memo keyed on
|
|
// (pointer, version) alone would silently inherit the dead object's entry
|
|
// (see VkRenderPassManager's per-draw fast-path memo).
|
|
Uint64 GetLifetimeId() const { return m_lifetimeId; }
|
|
|
|
Uint GetExternalIndex() const;
|
|
Bool IsDefaultFramebuffer() const { return m_externalIndex == 0; }
|
|
|
|
private:
|
|
static Uint64 AllocateLifetimeId();
|
|
|
|
void BumpAttachmentVersion(FramebufferAttachmentType type);
|
|
|
|
const Uint m_externalIndex = 0;
|
|
const Uint64 m_lifetimeId = AllocateLifetimeId();
|
|
FramebufferAttachmentObjectArray m_attachmentObjects;
|
|
FramebufferAttachmentVersionArray m_attachmentVersions;
|
|
|
|
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
|
|
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::None;
|
|
|
|
Int m_defaultWidth = 0;
|
|
Int m_defaultHeight = 0;
|
|
Int m_defaultLayers = 0;
|
|
Int m_defaultSamples = 0;
|
|
Bool m_defaultFixedSampleLocations = false;
|
|
|
|
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
|
|
Uint16 m_objectVersion = 0;
|
|
};
|
|
|
|
} // namespace MG_State::GLState
|
|
} // namespace MobileGL
|