Merge branch 'dev' into Feat/Backend-Direct-Vulkan

This commit is contained in:
BZLZHH
2026-02-07 11:41:11 +08:00
50 changed files with 2525 additions and 1136 deletions
+51 -30
View File
@@ -13,10 +13,32 @@ if (ANDROID)
endif() endif()
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT) if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT)
# Check if ThinLTO or LTO is suppported
include(CheckIPOSupported) include(CheckIPOSupported)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
check_ipo_supported(RESULT LTOSupported OUTPUT LTOError) check_ipo_supported(RESULT LTOSupported OUTPUT LTOError)
if (LTOSupported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) check_c_compiler_flag("-flto" HAS_LTO_C)
check_cxx_compiler_flag("-flto" HAS_LTO_CXX)
if (LTOSupported OR (HAS_LTO_C AND HAS_LTO_CXX))
# Check ThinLTO
check_c_compiler_flag("-flto=thin" HAS_THINLTO_C)
check_cxx_compiler_flag("-flto=thin" HAS_THINLTO_CXX)
if (HAS_THINLTO_C AND HAS_THINLTO_CXX)
message(STATUS "ThinLTO supported, using -flto=thin")
add_compile_options(-flto=thin)
add_link_options(-flto=thin)
else()
# ThinLTO is not supported
message(STATUS "ThinLTO not available, fallback to CMAKE IPO")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
else()
message(STATUS "IPO not supported: ${LTOError}")
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT MATCHES "AppleClang") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT MATCHES "AppleClang")
@@ -103,7 +125,9 @@ set(SOURCE_FILES
MobileGL/MG_Util/Debug/Log.cpp MobileGL/MG_Util/Debug/Log.cpp
MobileGL/MG_Util/Math/VectorTypes.cpp
MobileGL/MG_Util/Metrics/TextureMetrics.cpp MobileGL/MG_Util/Metrics/TextureMetrics.cpp
MobileGL/MG_Util/Metrics/BufferMetrics.cpp MobileGL/MG_Util/Metrics/BufferMetrics.cpp
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
@@ -256,33 +280,35 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
${MOBILEGL_LINK_LIBRARIES} ${MOBILEGL_LINK_LIBRARIES}
) )
add_library(${CMAKE_PROJECT_NAME}_s STATIC if(NOT ANDROID)
${SOURCE_FILES} add_library(${CMAKE_PROJECT_NAME}_s STATIC
) ${SOURCE_FILES}
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET default
CXX_VISIBILITY_PRESET default
VISIBILITY_INLINES_HIDDEN OFF
) )
else()
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES if (CMAKE_BUILD_TYPE STREQUAL "Debug")
C_VISIBILITY_PRESET hidden set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
CXX_VISIBILITY_PRESET hidden C_VISIBILITY_PRESET default
VISIBILITY_INLINES_HIDDEN ON CXX_VISIBILITY_PRESET default
VISIBILITY_INLINES_HIDDEN OFF
)
else()
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
endif()
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC
${MOBILEGL_INCLUDE_DIR}
)
target_link_libraries(${CMAKE_PROJECT_NAME}_s
PRIVATE
${MOBILEGL_LINK_LIBRARIES}
) )
endif() endif()
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC
${MOBILEGL_INCLUDE_DIR}
)
target_link_libraries(${CMAKE_PROJECT_NAME}_s
PRIVATE
${MOBILEGL_LINK_LIBRARIES}
)
if (TRACY_ENABLE) if (TRACY_ENABLE)
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient) target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient)
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient) target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient)
@@ -296,11 +322,6 @@ if (ANDROID)
log log
vulkan vulkan
) )
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC
android
log
vulkan
)
endif() endif()
if (NOT ANDROID) if (NOT ANDROID)
+2 -2
View File
@@ -15,7 +15,7 @@ namespace MobileGL {
inline const String ProjectName = "MobileGL"; inline const String ProjectName = "MobileGL";
inline const String CoreName = "MobileGL Core"; inline const String CoreName = "MobileGL Core";
inline const String CoreVendor = "MobileGL-Dev (BZLZHH, Swung0x48, Tungsten)"; inline const String CoreVendor = "MobileGL-Dev (BZLZHH, Swung0x48, Tungsten)";
inline const Version CoreVersion = {26, 1, 0, "-dev", VersionType::Development}; inline const Version CoreVersion = {26, 2, 0, "-dev", VersionType::Development};
inline const VersionStringFormatAttrib DefaultVersionStringFormatAttrib = {2, 2, 0, true, true}; inline const VersionStringFormatAttrib DefaultVersionStringFormatAttrib = {2, 2, 0, true, true};
extern UniquePtr<RendererInfo> RendererInfoPtr; extern UniquePtr<RendererInfo> RendererInfoPtr;
@@ -28,4 +28,4 @@ namespace MobileGL {
} }
} // namespace Backend } // namespace Backend
} // namespace MG_Config } // namespace MG_Config
} // namespace MobileGL } // namespace MobileGL
File diff suppressed because it is too large Load Diff
@@ -8,6 +8,8 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureState.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
#define CallAndCheck(operation) \ #define CallAndCheck(operation) \
MGLOG_D("Call GLES func: %s", #operation); \ MGLOG_D("Call GLES func: %s", #operation); \
@@ -51,4 +53,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLsizei height); GLsizei height);
void GenerateMipmap(GLenum target); void GenerateMipmap(GLenum target);
const GLubyte* GetString(GLenum name); const GLubyte* GetString(GLenum name);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
File diff suppressed because it is too large Load Diff
+39 -16
View File
@@ -16,25 +16,26 @@
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl { namespace BufferImpl {
const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
class BackendBufferObject { class BackendBufferObject {
public: public:
BackendBufferObject(); BackendBufferObject();
void SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
Uint GetBackendBufferId() { return m_backendBufferId; } Uint GetBackendBufferId() { return m_backendBufferId; }
void Bind(); void Bind(GLenum target = TempBufferTarget);
void Bind(GLenum target);
private: private:
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject); void SyncToBackend_glBufferSubData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
void SyncToBackend_glMapBufferRange(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject, void SyncToBackend_glMapBufferRange(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject,
Bool invalidate = true); Bool invalidate = true, Bool unsynchronized = true);
Uint m_backendBufferId = 0; Uint m_backendBufferId = 0;
SizeT m_prevBufferSize = 0; SizeT m_prevBufferSize = 0;
Bool m_isInitialized = false; Bool m_isInitialized = false;
}; };
extern BackendBufferObject* g_boundVertexBufferObject;
extern UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>>
g_backendBufferObjects; g_backendBufferObjects;
} // namespace BufferImpl } // namespace BufferImpl
@@ -43,13 +44,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
class BackendVertexArrayObject { class BackendVertexArrayObject {
public: public:
BackendVertexArrayObject(); BackendVertexArrayObject();
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, Bool needDivisor); void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
Uint GetBackendVertexArrayId() { return m_backendVAOId; } Uint GetBackendVertexArrayId() { return m_backendVAOId; }
void Bind(); void Bind();
private: private:
void BindAttributeBuffer(Uint index, const MG_State::GLState::VertexAttribute& attrib);
Uint m_backendVAOId = 0; Uint m_backendVAOId = 0;
Bool m_isInitialized = false; Bool m_isInitialized = false;
Uint16 m_syncedIndexBufferVersion = 0;
Array<MG_State::GLState::VertexAttributeVersion, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS>
m_syncedAttributeVersions;
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::VertexArrayObject>, SharedPtr<BackendVertexArrayObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::VertexArrayObject>, SharedPtr<BackendVertexArrayObject>>
@@ -82,11 +88,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); } bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
}; };
inline const Uint TempTextureUnit = 0;
class BackendTextureObject { class BackendTextureObject {
public: public:
BackendTextureObject(); BackendTextureObject();
void SyncToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target); void SyncBuiltinSamplerToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncTextureParamsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target, Uint unit = TempTextureUnit);
Uint GetBackendTextureId(); Uint GetBackendTextureId();
private: private:
@@ -98,10 +107,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
FloatVec4 m_cacheBorderColor = {0.0f, 0.0f, 0.0f, 0.0f}; FloatVec4 m_cacheBorderColor = {0.0f, 0.0f, 0.0f, 0.0f};
Vec4<TextureSwizzleParam> m_cacheSwizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green, Vec4<TextureSwizzleParam> m_cacheSwizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha}; TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
Uint16 m_syncedSamplerVersion = 0;
Uint16 m_syncedTextureParamsVersion = 0;
}; };
void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>>
g_backendTextureObjects; g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache;
extern Uint g_activeTextureUnit;
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {
@@ -112,7 +129,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferTarget asTarget); FramebufferTarget asTarget);
Uint GetBackendFramebufferId() { return m_backendFBOId; } Uint GetBackendFramebufferId() { return m_backendFBOId; }
void Bind(FramebufferTarget target); void Bind(FramebufferTarget target);
FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index); bool SyncAttachmentObject(GLenum glFBOTarget,
const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
GLenum glBackendAttachment);
// FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const;
private: private:
Uint m_backendFBOId = 0; Uint m_backendFBOId = 0;
@@ -125,25 +146,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
*/ */
FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = { FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
FramebufferAttachmentType::None}; FramebufferAttachmentType::None};
/* this will save buffers in its compacted GL form,
not consecutive is not allowed
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT5, COLOR_ATTACHMENT4]
(no GL_NONE among those)
*/
FramebufferAttachmentType
m_compactedFrontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
FramebufferAttachmentType::None};
/* this will save buffers in stricter ES rules /* this will save buffers in stricter ES rules
reversion, absence or not consecutive are not allowed, according to ES spec reversion, absence or not consecutive are not allowed, according to ES spec
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, NONE, ...] i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, COLOR_ATTACHMENT3, ...]
this array could be provided as data directly to ES `glDrawBuffers` function this array could be provided as data directly to ES `glDrawBuffers` function
*/ */
GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE}; GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};
FramebufferAttachmentType m_frontendReadBuffer = FramebufferAttachmentType::Color0; FramebufferAttachmentType m_frontendReadBuffer = FramebufferAttachmentType::Color0;
GLenum m_backendReadBuffer = GL_COLOR_ATTACHMENT0;
using FramebufferObject = MG_State::GLState::FramebufferObject;
FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0};
}; };
extern UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
g_backendFramebufferObjects; g_backendFramebufferObjects;
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
} // namespace FramebufferImpl } // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
@@ -178,8 +196,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
Uint m_backendSamplerId = 0; Uint m_backendSamplerId = 0;
Bool m_isInitialized = false; Bool m_isInitialized = false;
SamplerParameters m_cacheSamplerParameters; SamplerParameters m_cacheSamplerParameters;
Uint16 m_syncedSamplerVersion = 0;
}; };
void UnbindSampler(Uint unit);
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache;
extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>>
g_backendSamplerObjects; g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
+3 -83
View File
@@ -19,55 +19,11 @@
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h> #include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl { namespace BufferImpl {} // namespace BufferImpl
BackendBufferBindingProtector::BackendBufferBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding);
}
BackendBufferBindingProtector::~BackendBufferBindingProtector() { namespace VertexArrayImpl {} // namespace VertexArrayImpl
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindBuffer(m_target, m_previousBinding);
}
} // namespace BufferImpl
namespace VertexArrayImpl {
BackendVertexArrayBindingProtector::BackendVertexArrayBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &m_previousBinding);
}
BackendVertexArrayBindingProtector::~BackendVertexArrayBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindVertexArray(m_previousBinding);
}
} // namespace VertexArrayImpl
namespace TextureImpl { namespace TextureImpl {
BackendTextureBindingProtector::BackendTextureBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, true), &m_previousBinding);
}
BackendTextureBindingProtector::~BackendTextureBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindTexture(m_target, m_previousBinding);
}
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat, void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
GLenum* outFormat, GLenum* outType) { GLenum* outFormat, GLenum* outType) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
@@ -81,43 +37,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {} // namespace FramebufferImpl
BackendFramebufferBindingProtector::BackendFramebufferBindingProtector(GLenum target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
m_target = target;
MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding);
}
BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding);
}
GLuint BackendFramebufferBindingProtector::GetTempFBO(FramebufferTarget target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target);
GLuint& fbo = (glTarget == GL_DRAW_FRAMEBUFFER) ? s_tempDrawFBO : s_tempReadFBO;
if (fbo == 0) {
MG_External::GLES::glGenFramebuffers(1, &fbo);
}
return fbo;
}
void BackendFramebufferBindingProtector::BindTempFBO(MobileGL::FramebufferTarget target) {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
GLuint fbo = GetTempFBO(target);
GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target);
MG_External::GLES::glBindFramebuffer(glTarget, fbo);
}
} // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
String ProcessOutColorLocations(const String& glslCode) { String ProcessOutColorLocations(const String& glslCode) {
+2 -50
View File
@@ -27,66 +27,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
}; };
} // namespace DebugImpl } // namespace DebugImpl
namespace BufferImpl { namespace BufferImpl {} // namespace BufferImpl
class BackendBufferBindingProtector {
public:
BackendBufferBindingProtector(GLenum target);
~BackendBufferBindingProtector();
private:
GLenum m_target;
GLint m_previousBinding = 0;
};
} // namespace BufferImpl
namespace VertexArrayImpl { namespace VertexArrayImpl {
GLenum GetBindingQuery(GLenum target, bool isTexture); GLenum GetBindingQuery(GLenum target, bool isTexture);
class BackendVertexArrayBindingProtector {
public:
BackendVertexArrayBindingProtector();
~BackendVertexArrayBindingProtector();
private:
GLint m_previousBinding = 0;
};
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
namespace TextureImpl { namespace TextureImpl {
class BackendTextureBindingProtector {
public:
BackendTextureBindingProtector(GLenum target);
~BackendTextureBindingProtector();
private:
GLenum m_target;
GLint m_previousBinding = 0;
};
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat, void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
GLenum* outFormat, GLenum* outType); GLenum* outFormat, GLenum* outType);
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {} // namespace FramebufferImpl
class BackendFramebufferBindingProtector {
public:
BackendFramebufferBindingProtector(GLenum target);
~BackendFramebufferBindingProtector();
static GLuint GetTempFBO(FramebufferTarget target);
static void BindTempFBO(FramebufferTarget target);
private:
GLenum m_target;
GLint m_previousBinding = 0;
inline static GLuint s_tempReadFBO = 0;
inline static GLuint s_tempDrawFBO = 0;
};
} // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
String ProcessOutColorLocations(const String& glslCode); String ProcessOutColorLocations(const String& glslCode);
@@ -574,6 +574,7 @@ namespace MobileGL {
return MapBuffer_State(target, access); return MapBuffer_State(target, access);
} }
// FIXME: this should be a "backend" function
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size) { GLsizeiptr size) {
CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size); CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size);
@@ -151,7 +151,7 @@ DECLARE_GL_FUNCTION_HEAD(void, LineWidth, GLfloat width) DECLARE_GL_FUNCTION_END
DECLARE_GL_FUNCTION_HEAD(void, LinkProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, LinkProgram, program) DECLARE_GL_FUNCTION_HEAD(void, LinkProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, LinkProgram, program)
DECLARE_GL_FUNCTION_HEAD(void, PixelStorei, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PixelStorei, pname, param) DECLARE_GL_FUNCTION_HEAD(void, PixelStorei, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PixelStorei, pname, param)
DECLARE_GL_FUNCTION_HEAD(void, PolygonOffset, GLfloat factor, GLfloat units) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffset, factor, units) DECLARE_GL_FUNCTION_HEAD(void, PolygonOffset, GLfloat factor, GLfloat units) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffset, factor, units)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReadPixels, x, y, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, ReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadPixels, x, y, width, height, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_HEAD(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReleaseShaderCompiler)
DECLARE_GL_FUNCTION_HEAD(void, RenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, RenderbufferStorage, target, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, RenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, RenderbufferStorage, target, internalformat, width, height)
DECLARE_GL_FUNCTION_HEAD(void, SampleCoverage, GLfloat value, GLboolean invert) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleCoverage, value, invert) DECLARE_GL_FUNCTION_HEAD(void, SampleCoverage, GLfloat value, GLboolean invert) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleCoverage, value, invert)
@@ -385,15 +385,15 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetObjectLabel, GLenum identifier, GLuint na
DECLARE_GL_FUNCTION_STUB_HEAD(void, ObjectPtrLabel, const void* ptr, GLsizei length, const GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ObjectPtrLabel, ptr, length, label) DECLARE_GL_FUNCTION_STUB_HEAD(void, ObjectPtrLabel, const void* ptr, GLsizei length, const GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ObjectPtrLabel, ptr, length, label)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetObjectPtrLabel, const void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetObjectPtrLabel, ptr, bufSize, length, label) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetObjectPtrLabel, const void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetObjectPtrLabel, ptr, bufSize, length, label)
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetPointerv, GLenum pname, void** params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetPointerv, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetPointerv, GLenum pname, void** params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetPointerv, pname, params)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Enablei, target, index) DECLARE_GL_FUNCTION_HEAD(void, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Enablei, target, index)
DECLARE_GL_FUNCTION_STUB_HEAD(void, Disablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Disablei, target, index) DECLARE_GL_FUNCTION_HEAD(void, Disablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Disablei, target, index)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationi, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationi, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationiARB, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationiARB, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparatei, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparatei, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparateiARB, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparateiARB, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunci, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunci, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunciARB, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunciARB, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha) DECLARE_GL_FUNCTION_HEAD(void, BlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha)
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparateiARB, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparateiARB, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMaski, index, r, g, b, a) DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMaski, index, r, g, b, a)
DECLARE_GL_FUNCTION_HEAD(GLboolean, IsEnabledi, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END(GLboolean, IsEnabledi, target, index) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsEnabledi, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END(GLboolean, IsEnabledi, target, index)
@@ -9,6 +9,7 @@
#include "GL_Framebuffer.h" #include "GL_Framebuffer.h"
#include "Validators.h" #include "Validators.h"
#include "Config.h" #include "Config.h"
#include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_Impl/GLImpl/Texture/Validators.h> #include <MG_Impl/GLImpl/Texture/Validators.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
@@ -304,6 +305,25 @@ namespace MobileGL {
} }
} }
void ReadBuffer_State(GLenum mode) {
auto attType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(mode);
// ------------------- Check validity begin ------------------------
if (attType == FramebufferAttachmentType::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
std::format("`mode` = {} is not an accepted value.", MG_Util::ConvertGLEnumToString(mode))));
return;
}
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto fbo = bindingSlot.GetBoundObject();
fbo->SetReadBuffer(attType);
}
void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) { void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) {
if (n < 0) { if (n < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
@@ -488,7 +508,142 @@ namespace MobileGL {
#endif #endif
} }
void ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels) {
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
// Check width/height
if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Width and height must be non-negative"));
return;
}
// Validate format
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
return;
}
// Validate type
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
return;
}
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No framebuffer bound to read target"));
return;
}
// Check framebuffer completeness
if (!framebufferObject->CheckCompleteness()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
return;
}
// Check for required buffers
if (textureInputFormat == TextureInputFormat::StencilIndex) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No stencil buffer for stencil index format"));
return;
}
} else if (textureInputFormat == TextureInputFormat::DepthComponent) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth buffer for depth component format"));
return;
}
} else if (textureInputFormat == TextureInputFormat::DepthStencil) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() ||
!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth/stencil buffer for depth-stencil format"));
return;
}
// Validate type for depth/stencil
if (texturePixelDataType != TexturePixelDataType::UnsignedInt248 &&
texturePixelDataType != TexturePixelDataType::Float32UnsignedInt248Rev) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Invalid type for depth-stencil format"));
return;
}
}
// Check PBO state
const auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
if (pixelPackBufferObject) {
// Check if PBO is mapped
if (pixelPackBufferObject->IsMapped()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel pack buffer is currently mapped"));
return;
}
// Check alignment
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel data not aligned for pixel pack buffer"));
return;
}
}
// Check multisampling
if (framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).IsRenderbuffer()) {
auto rbo = framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).GetRenderbuffer();
if (rbo && rbo->GetSamples() > 1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"ReadPixels not supported for multisampled framebuffers"));
return;
}
}
}
void ReadPixels_Backend(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels) {
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::ReadPixels(x, y, width, height, format, type, pixels);
#endif
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
ReadPixels_State(x, y, width, height, format, type, pixels);
ReadPixels_Backend(x, y, width, height, format, type, pixels);
}
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
ClearBufferfi_Backend(buffer, drawbuffer, depth, stencil); ClearBufferfi_Backend(buffer, drawbuffer, depth, stencil);
} }
@@ -575,6 +730,10 @@ namespace MobileGL {
DrawBuffers_State(n, bufs); DrawBuffers_State(n, bufs);
} }
void ReadBuffer(GLenum src) {
ReadBuffer_State(src);
}
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
DeleteRenderbuffers_State(n, renderbuffers); DeleteRenderbuffers_State(n, renderbuffers);
} }
@@ -14,6 +14,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
@@ -46,6 +47,7 @@ namespace MobileGL {
void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void DrawBuffer(GLenum buf); void DrawBuffer(GLenum buf);
void DrawBuffers(GLsizei n, const GLenum* bufs); void DrawBuffers(GLsizei n, const GLenum* bufs);
void ReadBuffer(GLenum src);
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers); void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
GLenum CheckFramebufferStatus(GLenum target); GLenum CheckFramebufferStatus(GLenum target);
+2 -2
View File
@@ -567,7 +567,7 @@ namespace MobileGL {
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackImageHeight); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackImageHeight);
break; break;
case GL_PACK_LSB_FIRST: case GL_PACK_LSB_FIRST:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLsbFirst); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLSBFirst);
break; break;
case GL_PACK_ROW_LENGTH: case GL_PACK_ROW_LENGTH:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackRowLength); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackRowLength);
@@ -839,7 +839,7 @@ namespace MobileGL {
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackImageHeight); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackImageHeight);
break; break;
case GL_UNPACK_LSB_FIRST: case GL_UNPACK_LSB_FIRST:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLsbFirst); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLSBFirst);
break; break;
case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_ROW_LENGTH:
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackRowLength); *params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackRowLength);
@@ -111,13 +111,32 @@ namespace MobileGL {
} }
GLboolean IsEnabledi_State(GLenum target, GLuint index) { GLboolean IsEnabledi_State(GLenum target, GLuint index) {
// TODO: implement CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
return GL_FALSE; if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "IsEnabledi_State",
"Capability enum " +
MG_Util::ConvertCapabilityInputToString(capInput) + "(" +
MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return GL_FALSE;
}
return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE;
} }
GLboolean IsEnabled_State(GLenum cap) { GLboolean IsEnabled_State(GLenum cap) {
// TODO: implement CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
return GL_FALSE; if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "IsEnabled_State",
"Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) +
"(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported."));
return GL_FALSE;
}
return MG_State::pGLContext->IsCapabilityEnabled(capInput) ? GL_TRUE : GL_FALSE;
} }
void Hint_State(GLenum target, GLenum mode) { void Hint_State(GLenum target, GLenum mode) {
@@ -241,10 +260,6 @@ namespace MobileGL {
// TODO: implement // TODO: implement
} }
void ReadBuffer_State(GLenum src) {
// TODO: implement
}
void ClearStencil_State(GLint s) { void ClearStencil_State(GLint s) {
// TODO: implement // TODO: implement
} }
@@ -257,7 +272,67 @@ namespace MobileGL {
MG_State::pGLContext->SetClearColor(FloatVec4(red, green, blue, alpha)); MG_State::pGLContext->SetClearColor(FloatVec4(red, green, blue, alpha));
} }
void BlendFuncSeparatei_State(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
if (buf >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "BlendFuncSeparatei_State",
"Buffer index " + std::to_string(buf) + " is out of range. Max supported is " +
std::to_string(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS - 1) + "."));
return;
}
BlendFactor srcRGBM = MG_Util::ConvertGLEnumToBlendFactor(srcRGB);
BlendFactor dstRGBM = MG_Util::ConvertGLEnumToBlendFactor(dstRGB);
BlendFactor srcAlphaM = MG_Util::ConvertGLEnumToBlendFactor(srcAlpha);
BlendFactor dstAlphaM = MG_Util::ConvertGLEnumToBlendFactor(dstAlpha);
MG_State::pGLContext->SetBlendFuncIndexed(buf, srcRGBM, dstRGBM, srcAlphaM, dstAlphaM);
}
void Disablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Disablei_State",
"Capability enum " +
MG_Util::ConvertCapabilityInputToString(capInput) + "(" +
MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, false);
}
void Enablei_State(GLenum target, GLuint index) {
auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
if (capInput == CapabilityInput::Unknown) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "Enablei_State",
"Capability enum " +
MG_Util::ConvertCapabilityInputToString(capInput) + "(" +
MG_Util::ConvertGLEnumToString(target) + ") is not supported."));
return;
}
MG_State::pGLContext->SetCapabilityIndexed(capInput, index, true);
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void Disablei(GLenum target, GLuint index) {
Disablei_State(target, index);
}
void Enablei(GLenum target, GLuint index) {
Enablei_State(target, index);
}
void BlendFunc(GLenum sfactor, GLenum dfactor) { void BlendFunc(GLenum sfactor, GLenum dfactor) {
BlendFunc_State(sfactor, dfactor); BlendFunc_State(sfactor, dfactor);
} }
@@ -390,10 +465,6 @@ namespace MobileGL {
BlendColor_State(red, green, blue, alpha); BlendColor_State(red, green, blue, alpha);
} }
void ReadBuffer(GLenum src) {
ReadBuffer_State(src);
}
void ClearStencil(GLint s) { void ClearStencil(GLint s) {
ClearStencil_State(s); ClearStencil_State(s);
} }
@@ -12,6 +12,9 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
void Disablei(GLenum target, GLuint index);
void Enablei(GLenum target, GLuint index);
void BlendFunc(GLenum sfactor, GLenum dfactor); void BlendFunc(GLenum sfactor, GLenum dfactor);
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
@@ -45,7 +48,6 @@ namespace MobileGL {
void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
void BlendEquation(GLenum mode); void BlendEquation(GLenum mode);
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void ReadBuffer(GLenum src);
void ClearStencil(GLint s); void ClearStencil(GLint s);
void ClearDepth(GLclampd depth); void ClearDepth(GLclampd depth);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+189 -22
View File
@@ -7,26 +7,27 @@
// End of Source File Header // End of Source File Header
#include "GL_Texture.h" #include "GL_Texture.h"
#include "GL/gl.h"
#include "Config.h" #include "Config.h"
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
#include <MG_Backend/DirectGLES/DirectGLES.h>
#endif
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include "Validators.h" #include "Validators.h"
#include "ProxyTexture.h" #include "ProxyTexture.h"
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include "MG_Util/Texture/TextureFormatProcessor.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/TextureMetrics.h> #include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Texture/PixelStoreProcessor.h> #include <MG_Util/Texture/PixelStoreProcessor.h>
#include <MG_Util/Texture/TextureFormatProcessor.h>
#include <MG_Util/Classifiers/TextureEnumClassifier.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h> #include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h> #include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
#include <MG_State/GLState/TextureState/TextureObjectBuffer.h>
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
#include <MG_Backend/DirectGLES/DirectGLES.h>
#endif
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
@@ -714,9 +715,6 @@ namespace MobileGL {
MGLOG_D("%s: Allocating %d bytes at mip %d", __func__, internalBytes, level); MGLOG_D("%s: Allocating %d bytes at mip %d", __func__, internalBytes, level);
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes}); textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes});
MGLOG_D("%s: mark mip %d as dirty", __func__, level);
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
if (!originalPixels) { if (!originalPixels) {
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__); MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
return; return;
@@ -740,6 +738,9 @@ namespace MobileGL {
} }
free(processedPixels); free(processedPixels);
MGLOG_D("%s: mark mip %d as dirty", __func__, level);
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
} }
void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border,
@@ -1163,10 +1164,6 @@ namespace MobileGL {
} }
} }
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
// TODO: implement
}
void GetCompressedTexImage_State(GLenum target, GLint level, void* img) { void GetCompressedTexImage_State(GLenum target, GLint level, void* img) {
// TODO: implement // TODO: implement
} }
@@ -1228,12 +1225,57 @@ namespace MobileGL {
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
GLsizei height, GLint border) { GLsizei height, GLint border) {
GLenum outInternalFormat, format, type; auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, const auto& currentReadFBO =
&type); MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
if (!currentReadFBO) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", "CopyTexImage2D_State",
"No framebuffer is currently bound to the GL_READ_FRAMEBUFFER target."));
return;
}
Bool isDepth = MG_Util::IsDepthFormatInternalFormat(internalFormat);
Bool isStencil = MG_Util::IsStencilFormatInternalFormat(internalFormat);
TextureInternalFormat srcInternalFormat = TextureInternalFormat::Unknown;
#define GET_SRC_INTERNAL_FORMAT(AttachmentType) \
const auto& srcAttachment = currentReadFBO->GetAttachment(AttachmentType); \
if (srcAttachment.IsTexture()) { \
const auto& texObj = srcAttachment.GetTexture(); \
srcInternalFormat = texObj->GetFormat(); \
} else if (srcAttachment.IsRenderbuffer()) { \
const auto& rboObj = srcAttachment.GetRenderbuffer(); \
srcInternalFormat = rboObj->GetInternalFormat(); \
} else { \
MG_State::pGLContext->RecordError( \
ErrorCode::InvalidOperation, \
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "CopyTexImage2D_State", \
"The attachment specified by the read buffer is incomplete.")); \
return; \
}
if (isDepth) {
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Depth);
} else if (isStencil) {
GET_SRC_INTERNAL_FORMAT(FramebufferAttachmentType::Stencil);
} else {
const auto& readBufferType = currentReadFBO->GetReadBuffer();
GET_SRC_INTERNAL_FORMAT(readBufferType);
}
if (!TextureImpl::ValidateBaseInternalFormatMatch(internalFormat, srcInternalFormat))
THROW_UNIMPL_EXCEPTION;
GLenum outInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(srcInternalFormat);
GLenum realInternalFormat = GL_RGBA8;
GLenum format = GL_DEPTH_COMPONENT;
GLenum type = GL_UNSIGNED_INT;
MG_Util::TextureFormatProcessor::NormalizePixelFormat(
outInternalFormat, PixelFormatNormalizeOptionBit::None, &realInternalFormat, &format, &type);
const auto pixelUnpackBufferObject = const auto pixelUnpackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr); TexImage2D_State(target, level, realInternalFormat, width, height, border, format, type, nullptr);
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject);
} }
@@ -1332,7 +1374,136 @@ namespace MobileGL {
MG_State::pGLContext->SetActiveTextureUnit(texture - GL_TEXTURE0); MG_State::pGLContext->SetActiveTextureUnit(texture - GL_TEXTURE0);
} }
void GetTexImage_Backend(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::GetTexImage(target, level, format, type, pixels);
#endif
}
// Add to GL_Texture.cpp
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
// ======================= Converting ================================
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
// ===================== Error Checking ==============================
// Validate target
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid texture target"));
return;
}
// Validate level
if (level < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Level must be non-negative"));
return;
}
// Validate format
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid format"));
return;
}
// Validate type
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid pixel data type"));
return;
}
// Get texture object
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
if (TextureImpl::IsProxyTextureTarget(textureUploadTarget)) {
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadTarget);
} else {
auto activeUnit =
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
textureObject = bindingSlot.GetBoundObject();
}
if (!TextureImpl::ValidateTextureObject(textureObject)) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No valid texture bound to target"));
return;
}
// Check texture completeness
if (!textureObject->IsComplete()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete"));
return;
}
// Check PBO state
const auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
if (pixelPackBufferObject) {
// Check if PBO is mapped
if (pixelPackBufferObject->IsMapped()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel pack buffer is currently mapped"));
return;
}
// Check alignment
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel data not aligned for pixel pack buffer"));
return;
}
}
// Special case for depth/stencil
if (textureInputFormat == TextureInputFormat::StencilIndex) {
if (textureObject->GetFormat() != TextureInternalFormat::DepthStencil &&
textureObject->GetFormat() != TextureInternalFormat::Depth24Stencil8 &&
textureObject->GetFormat() != TextureInternalFormat::Depth32FStencil8) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No stencil buffer for stencil index format"));
return;
}
}
// Check for multisampling
if (textureObject->GetStorageType() == TextureStorageType::Mipmap) {
auto mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
if (mipmapObject->GetMipmapLevelCount() > 1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Multisampled textures not supported for GetTexImage"));
return;
}
}
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
GetTexImage_State(target, level, format, type, pixels);
GetTexImage_Backend(target, level, format, type, pixels);
}
void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) {
TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
@@ -1429,10 +1600,6 @@ namespace MobileGL {
GetTexLevelParameterfv_State(target, level, pname, params); GetTexLevelParameterfv_State(target, level, pname, params);
} }
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
GetTexImage_State(target, level, format, type, pixels);
}
void GetCompressedTexImage(GLenum target, GLint level, void* img) { void GetCompressedTexImage(GLenum target, GLint level, void* img) {
GetCompressedTexImage_State(target, level, img); GetCompressedTexImage_State(target, level, img);
} }
+1 -1
View File
@@ -12,6 +12,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
@@ -43,7 +44,6 @@ namespace MobileGL {
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params); void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
void GetCompressedTexImage(GLenum target, GLint level, void* img); void GetCompressedTexImage(GLenum target, GLint level, void* img);
void GenTextures(GLsizei n, GLuint* textures); void GenTextures(GLsizei n, GLuint* textures);
void DeleteTextures(GLsizei n, const GLuint* textures); void DeleteTextures(GLsizei n, const GLuint* textures);
+19 -3
View File
@@ -7,13 +7,12 @@
// End of Source File Header // End of Source File Header
#include "Validators.h" #include "Validators.h"
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_Util/Types.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h> #include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h> #include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl { namespace MobileGL::MG_Impl::GLImpl {
@@ -170,6 +169,7 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
return true; return true;
} }
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
TextureInternalFormat internalFormat, TextureInternalFormat internalFormat,
TexturePixelDataType type) { TexturePixelDataType type) {
@@ -303,5 +303,21 @@ namespace MobileGL::MG_Impl::GLImpl {
} }
return true; return true;
} }
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2) {
auto unsizedFormat1 = MG_Util::ConvertInternalFormatToUnsized(format1);
auto unsizedFormat2 = MG_Util::ConvertInternalFormatToUnsized(format2);
if (unsizedFormat1 != unsizedFormat2) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>(
std::format("MG_Impl/GLImpl", "ValidateBaseInternalFormatMatch",
"The base internal format of the two formats do not match ({} vs. {})",
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat1).c_str(),
MG_Util::ConvertTextureInternalFormatToString(unsizedFormat2).c_str())));
return false;
}
return true;
} // namespace TextureImpl
} // namespace TextureImpl } // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
@@ -7,6 +7,7 @@
// End of Source File Header // End of Source File Header
#pragma once #pragma once
#include "MG_State/GLState/TextureState/TextureEnum.h"
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureObject.h> #include <MG_State/GLState/TextureState/TextureObject.h>
@@ -32,5 +33,6 @@ namespace MobileGL::MG_Impl::GLImpl {
TextureTarget target); TextureTarget target);
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset, Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset,
Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0); Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0);
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2);
} // namespace TextureImpl } // namespace TextureImpl
} // namespace MobileGL::MG_Impl::GLImpl } // namespace MobileGL::MG_Impl::GLImpl
@@ -14,14 +14,18 @@ namespace MobileGL {
namespace GLState { namespace GLState {
BufferObject::BufferObject(Uint externalIndex) BufferObject::BufferObject(Uint externalIndex)
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false), : 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_mappingAccess(BufferMappingAccessBit::Null),
m_dataPtr(MakeShared<Data>()) {} 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) { void BufferObject::Resize(SizeT size) {
m_size = size; m_size = size;
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
m_dataPtr->resize(size); 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) { void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
@@ -30,7 +34,14 @@ namespace MobileGL {
data.size, m_size); data.size, m_size);
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped."); MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
Memcpy(m_dataPtr->data() + atOffset, data.data, data.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;
// 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) { void BufferObject::SetUsage(BufferUsage usage) {
@@ -44,7 +55,8 @@ namespace MobileGL {
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(), Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
m_mappedRange.end - m_mappedRange.start); 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(); m_stagingData.clear();
@@ -69,7 +81,8 @@ namespace MobileGL {
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end); "Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length); 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) { void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
@@ -79,7 +92,10 @@ namespace MobileGL {
atOffset, data.size, m_size); atOffset, data.size, m_size);
Memcpy(m_dataPtr->data() + atOffset, data.data, data.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, 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; const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
Memcpy(m_dataPtr->data() + dstOffset, srcData, size); 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) { void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
@@ -144,6 +161,14 @@ namespace MobileGL {
m_ownsStagingData = false; m_ownsStagingData = false;
return m_dataPtr->data() + range.start; 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 { const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
@@ -151,7 +176,8 @@ namespace MobileGL {
} }
void BufferObject::ClearDirty() { void BufferObject::ClearDirty() {
m_dirtyRange = {0, 0}; m_change.DirtyRanges.clear();
m_change.Bits = BufferChangeBits::None;
} }
SizeT BufferObject::GetSize() const { SizeT BufferObject::GetSize() const {
@@ -162,8 +188,12 @@ namespace MobileGL {
return m_usage; return m_usage;
} }
Range1D BufferObject::GetDirtyRange() const { const VecRange1D& BufferObject::GetDirtyRanges() const {
return m_dirtyRange; return m_change.DirtyRanges;
}
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
return m_change.Bits;
} }
Bool BufferObject::IsMapped() const { Bool BufferObject::IsMapped() const {
@@ -9,6 +9,7 @@
#pragma once #pragma once
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include <Includes.h> #include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
namespace MobileGL { namespace MobileGL {
enum class BufferTarget { enum class BufferTarget {
@@ -55,6 +56,23 @@ namespace MobileGL {
Coherent = 0x80 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 MG_State {
namespace GLState { namespace GLState {
class BufferObject { class BufferObject {
@@ -77,11 +95,12 @@ namespace MobileGL {
Bool IsMapped() const; Bool IsMapped() const;
SizeT GetSize() const; SizeT GetSize() const;
BufferUsage GetUsage() const; BufferUsage GetUsage() const;
Range1D GetDirtyRange() const;
Range1D GetMappedRange() const; Range1D GetMappedRange() const;
const SharedPtr<Data> GetDataReadOnly() const; const SharedPtr<Data> GetDataReadOnly() const;
Flags<BufferMappingAccessBit> GetMappingAccess() const; Flags<BufferMappingAccessBit> GetMappingAccess() const;
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
const VecRange1D& GetDirtyRanges() const;
Flags<BufferChangeBits> GetChangeBits() const;
private: private:
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
@@ -90,7 +109,7 @@ namespace MobileGL {
SharedPtr<Data> m_dataPtr; SharedPtr<Data> m_dataPtr;
Bool m_isMapped; Bool m_isMapped;
Flags<BufferMappingAccessBit> m_mappingAccess; Flags<BufferMappingAccessBit> m_mappingAccess;
Range1D m_dirtyRange; BufferChange m_change;
Range1D m_mappedRange; Range1D m_mappedRange;
Vector<Uint8> m_stagingData; Vector<Uint8> m_stagingData;
Bool m_ownsStagingData; Bool m_ownsStagingData;
+26
View File
@@ -220,6 +220,14 @@ namespace MobileGL {
} }
// RenderState // RenderState
Uint GLContext::GetRenderStateParametersVersion() const {
return m_renderState.GetVersion();
}
const RenderStateParameters& GLContext::GetRenderStateParameters() const {
return m_renderState.GetAllParameters();
}
void GLContext::SetViewport(IntVec4 viewport) { void GLContext::SetViewport(IntVec4 viewport) {
m_renderState.SetViewport(viewport); m_renderState.SetViewport(viewport);
} }
@@ -236,6 +244,14 @@ namespace MobileGL {
return m_renderState.IsCapabilityEnabled(cap); 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, void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor dstAlpha) { BlendFactor dstAlpha) {
m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
@@ -246,6 +262,16 @@ namespace MobileGL {
m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); 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) { void GLContext::SetDepthFunc(DepthTestFunc func) {
m_renderState.SetDepthFunc(func); m_renderState.SetDepthFunc(func);
} }
+8
View File
@@ -86,13 +86,21 @@ namespace MobileGL {
SharedPtr<ProgramObject> GetCurrentProgram(); SharedPtr<ProgramObject> GetCurrentProgram();
// RenderState // RenderState
Uint GetRenderStateParametersVersion() const;
const RenderStateParameters& GetRenderStateParameters() const;
void SetViewport(IntVec4 viewport); // x, y, width, height void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height const IntVec4& GetViewport() const; // x, y, width, height
void SetCapability(CapabilityInput cap, Bool enabled); void SetCapability(CapabilityInput cap, Bool enabled);
Bool IsCapabilityEnabled(CapabilityInput cap) const; 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 SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const; 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); void SetDepthFunc(DepthTestFunc func);
DepthTestFunc GetDepthFunc() const; DepthTestFunc GetDepthFunc() const;
void SetDepthMask(Bool flag); void SetDepthMask(Bool flag);
@@ -12,41 +12,41 @@
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
// FramebufferAttachment // FramebufferAttachmentObject
FramebufferAttachment::FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
Int level) Int level)
: m_texture(texture), m_textureLevel(level) {} : m_texture(texture), m_textureLevel(level) {}
FramebufferAttachment::FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer) FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer)
: m_renderbuffer(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; m_isValid = IsValid;
} }
Bool FramebufferAttachment::IsTexture() const { Bool FramebufferAttachmentObject::IsTexture() const {
return m_texture != nullptr; return m_texture != nullptr;
} }
Bool FramebufferAttachment::IsRenderbuffer() const { Bool FramebufferAttachmentObject::IsRenderbuffer() const {
return m_renderbuffer != nullptr; return m_renderbuffer != nullptr;
} }
Bool FramebufferAttachment::IsEmpty() const { Bool FramebufferAttachmentObject::IsEmpty() const {
return m_texture == nullptr && m_renderbuffer == nullptr; 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; return m_texture;
} }
SharedPtr<RenderbufferObject> FramebufferAttachment::GetRenderbuffer() const { SharedPtr<RenderbufferObject> FramebufferAttachmentObject::GetRenderbuffer() const {
return m_renderbuffer; return m_renderbuffer;
} }
Int FramebufferAttachment::GetTextureLevel() const { Int FramebufferAttachmentObject::GetTextureLevel() const {
return m_textureLevel; return m_textureLevel;
} }
Bool FramebufferAttachment::IsComplete() const { Bool FramebufferAttachmentObject::IsComplete() const {
if (IsTexture()) { if (IsTexture()) {
Bool complete = m_texture->IsComplete(); Bool complete = m_texture->IsComplete();
return complete; return complete;
@@ -58,7 +58,7 @@ namespace MobileGL {
return false; return false;
} }
IntVec3 FramebufferAttachment::GetSize() const { IntVec3 FramebufferAttachmentObject::GetSize() const {
if (IsTexture()) { if (IsTexture()) {
// TODO: get correct upload target // TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()), MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
@@ -71,56 +71,55 @@ namespace MobileGL {
return {0, 0, 0}; return {0, 0, 0};
} }
Bool FramebufferAttachment::IsValid() const { Bool FramebufferAttachmentObject::IsValid() const {
return m_isValid; return m_isValid;
} }
// FramebufferObject // FramebufferObject
FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) { FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {
m_attachments.fill(FramebufferAttachment(false)); m_attachmentObjects.fill(FramebufferAttachmentObject(false));
m_drawBuffers.fill(FramebufferAttachmentType::None); m_drawBuffers.fill(FramebufferAttachmentType::None);
m_drawBuffers[0] = FramebufferAttachmentType::Color0; m_drawBuffers[0] = FramebufferAttachmentType::Color0;
m_attachmentVersions.fill(0);
} }
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture,
int level) { int level) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(std::move(texture), level); m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(std::move(texture), level);
m_drawBuffersDirty = true; BumpAttachmentVersion(type);
} }
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type, void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type,
std::shared_ptr<RenderbufferObject> renderbuffer) { std::shared_ptr<RenderbufferObject> renderbuffer) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(renderbuffer); m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer);
m_drawBuffersDirty = true; BumpAttachmentVersion(type);
} }
void FramebufferObject::Detach(FramebufferAttachmentType type) { void FramebufferObject::Detach(FramebufferAttachmentType type) {
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(false); m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false);
m_drawBuffersDirty = true; BumpAttachmentVersion(type);
} }
const FramebufferAttachment& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const { const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
return m_attachments[static_cast<SizeT>(type)]; return m_attachmentObjects[static_cast<SizeT>(type)];
} }
const Array<FramebufferAttachment, const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects() const {
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>& return m_attachmentObjects;
FramebufferObject::GetAllAttachments() const {
return m_attachments;
} }
Bool FramebufferObject::CheckCompleteness() const { Bool FramebufferObject::CheckCompleteness() const {
if (m_attachments.empty()) { if (m_attachmentObjects.empty()) {
return false; return false;
} }
Int width = -1, height = -1; Int width = -1, height = -1;
Int validAttachmentCount = 0; Int validAttachmentCount = 0;
for (SizeT i = 0; i < m_attachments.size(); ++i) { for (SizeT i = 0; i < m_attachmentObjects.size(); ++i) {
if (!m_attachments[i].IsValid()) continue; if (!m_attachmentObjects[i].IsValid()) continue;
++validAttachmentCount; ++validAttachmentCount;
const auto& attachment = m_attachments[i]; const auto& attachment = m_attachmentObjects[i];
auto attachmentSize = attachment.GetSize(); auto attachmentSize = attachment.GetSize();
Int w = attachmentSize.x(); Int w = attachmentSize.x();
Int h = attachmentSize.y(); Int h = attachmentSize.y();
@@ -143,26 +142,22 @@ namespace MobileGL {
void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) { void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
if (m_drawBuffers[index] == buffer) return; if (m_drawBuffers[index] == buffer) return;
m_drawBuffersDirty = true;
m_drawBuffers[index] = buffer; m_drawBuffers[index] = buffer;
BumpAttachmentVersion(buffer);
} }
// void FramebufferObject::SetDrawBuffers(const Vector<FramebufferAttachmentType>& buffers) { const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
// m_drawBuffers = buffers;
// m_drawBuffersDirty = true;
// }
// void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
//
// }
const Array<FramebufferAttachmentType, FramebufferObject::MAX_DRAW_BUFFERS>& FramebufferObject::
GetDrawBuffers() const {
return m_drawBuffers; return m_drawBuffers;
} }
Uint FramebufferObject::GetExternalIndex() const { Uint FramebufferObject::GetExternalIndex() const {
return m_externalIndex; return m_externalIndex;
} }
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
++m_attachmentVersions[static_cast<SizeT>(type)];
++m_objectVersion;
}
} // namespace GLState } // namespace GLState
} // namespace MG_State } // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -69,11 +69,12 @@ namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
class FramebufferAttachment { class FramebufferAttachmentObject {
public: public:
explicit FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0); explicit FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
explicit FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer); Int level = 0);
explicit FramebufferAttachment(Bool IsValid = true); explicit FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer);
explicit FramebufferAttachmentObject(Bool IsValid = true);
Bool IsTexture() const; Bool IsTexture() const;
Bool IsRenderbuffer() const; Bool IsRenderbuffer() const;
@@ -94,36 +95,51 @@ namespace MobileGL {
class FramebufferObject { class FramebufferObject {
public: public:
using TargetEnum = FramebufferTarget;
static constexpr Uint MAX_DRAW_BUFFERS = 8; 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); FramebufferObject(Uint externalIndex);
void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0); void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0);
void AttachRenderbuffer(FramebufferAttachmentType type, void AttachRenderbuffer(FramebufferAttachmentType type,
std::shared_ptr<RenderbufferObject> renderbuffer); std::shared_ptr<RenderbufferObject> renderbuffer);
void Detach(FramebufferAttachmentType type); void Detach(FramebufferAttachmentType type);
const FramebufferAttachment& GetAttachment(FramebufferAttachmentType type) const; const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
const Array<FramebufferAttachment, const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const;
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
GetAllAttachments() const;
Bool CheckCompleteness() const; Bool CheckCompleteness() const;
// aka. `buffer` as in glDrawBuffers/glReadBuffers // aka. `buffer` as in glDrawBuffers/glReadBuffers
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer); void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
bool DrawBuffersIsDirty() const { return m_drawBuffersDirty; } const FramebufferAttachmentArray& GetDrawBuffers() const;
void ClearDrawBuffersDirtyState() { m_drawBuffersDirty = false; } void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
const Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>& GetDrawBuffers() const;
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; } FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
const FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
return m_attachmentVersions;
}
Uint16 GetObjectVersion() const { return m_objectVersion; }
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
private: private:
void BumpAttachmentVersion(FramebufferAttachmentType type);
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
Array<FramebufferAttachment, FramebufferAttachmentObjectArray m_attachmentObjects;
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)> FramebufferAttachmentVersionArray m_attachmentVersions;
m_attachments;
Bool m_drawBuffersDirty = false; FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS> m_drawBuffers; FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0;
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
Uint16 m_objectVersion = 0;
}; };
} // namespace GLState } // namespace GLState
@@ -7,168 +7,246 @@
// End of Source File Header // End of Source File Header
#include "RenderState.h" #include "RenderState.h"
#include "MG_Util/Types.h"
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
RenderState::RenderState() {} RenderState::RenderState() {}
Uint RenderState::GetVersion() const {
return m_version;
}
const RenderStateParameters& RenderState::GetAllParameters() const {
return m_parameters;
}
// -------------------- Rasterization -------------------- // -------------------- Rasterization --------------------
void RenderState::SetViewport(IntVec4 viewport) { 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 { const IntVec4& RenderState::GetViewport() const {
return m_viewport; return m_parameters.Viewport;
} }
// -------------------- Capabilities -------------------- // -------------------- Capabilities --------------------
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) { 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) { switch (cap) {
case CapabilityInput::Blend: SET_CAPABILITY(DepthTest, enabled);
m_blendEnabled = enabled; SET_CAPABILITY(CullFace, enabled);
break; SET_CAPABILITY(ScissorTest, enabled);
case CapabilityInput::DepthTest: case CapabilityInput::Blend: {
m_depthTestEnabled = enabled; Bool stateChanged = false;
break; for (auto& blendState : m_parameters.BlendStates) {
case CapabilityInput::CullFace: if (blendState.Enabled == enabled) continue;
m_cullFaceEnabled = enabled; blendState.Enabled = enabled;
break; stateChanged = true;
case CapabilityInput::ScissorTest: }
m_scissorTestEnabled = enabled; if (stateChanged) ++m_version;
break; break;
}
default: // not supported currently default: // not supported currently
break; break;
} }
#undef SET_CAPABILITY
} }
Bool RenderState::IsCapabilityEnabled(CapabilityInput cap) const { Bool RenderState::IsCapabilityEnabled(CapabilityInput cap) const {
#define RETURN_CAPABILITY(capability) \
case CapabilityInput::capability: \
return m_parameters.capability##Enabled;
switch (cap) { switch (cap) {
RETURN_CAPABILITY(DepthTest);
RETURN_CAPABILITY(CullFace);
RETURN_CAPABILITY(ScissorTest);
case CapabilityInput::Blend: case CapabilityInput::Blend:
return m_blendEnabled; return m_parameters.BlendStates[0].Enabled;
case CapabilityInput::DepthTest:
return m_depthTestEnabled;
case CapabilityInput::CullFace:
return m_cullFaceEnabled;
case CapabilityInput::ScissorTest:
return m_scissorTestEnabled;
default: default:
return false; 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 -------------------- // -------------------- Blending --------------------
void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor dstAlpha) { BlendFactor dstAlpha) {
m_srcFactorRGB = srcRGB; Bool stateChanged = false;
m_dstFactorRGB = dstRGB; for (auto& blendState : m_parameters.BlendStates) {
m_srcFactorAlpha = srcAlpha; if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB &&
m_dstFactorAlpha = dstAlpha; 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, void RenderState::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const { BlendFactor& dstAlpha) const {
srcRGB = m_srcFactorRGB; srcRGB = m_parameters.BlendStates[0].SrcFactorRGB;
dstRGB = m_dstFactorRGB; dstRGB = m_parameters.BlendStates[0].DstFactorRGB;
srcAlpha = m_srcFactorAlpha; srcAlpha = m_parameters.BlendStates[0].SrcFactorAlpha;
dstAlpha = m_dstFactorAlpha; 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 -------------------- // -------------------- Depth --------------------
void RenderState::SetDepthFunc(DepthTestFunc func) { void RenderState::SetDepthFunc(DepthTestFunc func) {
m_depthFunc = func; if (m_parameters.DepthFunc == func) return;
m_parameters.DepthFunc = func;
++m_version;
} }
DepthTestFunc RenderState::GetDepthFunc() const { DepthTestFunc RenderState::GetDepthFunc() const {
return m_depthFunc; return m_parameters.DepthFunc;
} }
void RenderState::SetDepthMask(Bool flag) { void RenderState::SetDepthMask(Bool flag) {
m_depthMask = flag; if (m_parameters.DepthMask == flag) return;
m_parameters.DepthMask = flag;
++m_version;
} }
Bool RenderState::GetDepthMask() const { Bool RenderState::GetDepthMask() const {
return m_depthMask; return m_parameters.DepthMask;
} }
// -------------------- Color Mask -------------------- // -------------------- Color Mask --------------------
void RenderState::SetColorMask(BoolVec4 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 { const BoolVec4 RenderState::GetColorMask() const {
return m_colorMask; return m_parameters.ColorMask;
} }
// -------------------- Clear State -------------------- // -------------------- Clear State --------------------
void RenderState::SetClearColor(FloatVec4 color) { 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 { const FloatVec4& RenderState::GetClearColor() const {
return m_clearColor; return m_parameters.ClearColor;
} }
void RenderState::SetClearDepth(Float depth) { void RenderState::SetClearDepth(Float depth) {
m_clearDepth = depth; if (m_parameters.ClearDepth == depth) return;
m_parameters.ClearDepth = depth;
++m_version;
} }
Float RenderState::GetClearDepth() const { Float RenderState::GetClearDepth() const {
return m_clearDepth; return m_parameters.ClearDepth;
} }
// -------------------- Pixel Store -------------------- // -------------------- Pixel Store --------------------
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) { 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) { switch (param) {
case PixelStoreParam::PackAlignment: SET_PIXEL_STORE_PARAM(Pack, Alignment, value);
m_packParameters.Alignment = value; SET_PIXEL_STORE_PARAM(Pack, RowLength, value);
break; SET_PIXEL_STORE_PARAM(Pack, ImageHeight, value);
case PixelStoreParam::PackRowLength: SET_PIXEL_STORE_PARAM(Pack, SkipPixels, value);
m_packParameters.RowLength = value; SET_PIXEL_STORE_PARAM(Pack, SkipRows, value);
break; SET_PIXEL_STORE_PARAM(Pack, SkipImages, value);
case PixelStoreParam::PackImageHeight: SET_PIXEL_STORE_PARAM(Pack, SwapBytes, value != 0);
m_packParameters.ImageHeight = value; SET_PIXEL_STORE_PARAM(Pack, LSBFirst, value != 0);
break; SET_PIXEL_STORE_PARAM(Unpack, Alignment, value);
case PixelStoreParam::PackSkipPixels: SET_PIXEL_STORE_PARAM(Unpack, RowLength, value);
m_packParameters.SkipPixels = value; SET_PIXEL_STORE_PARAM(Unpack, ImageHeight, value);
break; SET_PIXEL_STORE_PARAM(Unpack, SkipPixels, value);
case PixelStoreParam::PackSkipRows: SET_PIXEL_STORE_PARAM(Unpack, SkipRows, value);
m_packParameters.SkipRows = value; SET_PIXEL_STORE_PARAM(Unpack, SkipImages, value);
break; SET_PIXEL_STORE_PARAM(Unpack, SwapBytes, value != 0);
case PixelStoreParam::PackSkipImages: SET_PIXEL_STORE_PARAM(Unpack, LSBFirst, value != 0);
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;
default: default:
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param)); MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
return; return;
@@ -176,39 +254,26 @@ namespace MobileGL {
} }
Int RenderState::GetPixelStoreParam(PixelStoreParam param) const { 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) { switch (param) {
case PixelStoreParam::PackAlignment: RETURN_PIXEL_STORE_PARAM(Pack, Alignment);
return m_packParameters.Alignment; RETURN_PIXEL_STORE_PARAM(Pack, RowLength);
case PixelStoreParam::PackRowLength: RETURN_PIXEL_STORE_PARAM(Pack, ImageHeight);
return m_packParameters.RowLength; RETURN_PIXEL_STORE_PARAM(Pack, SkipPixels);
case PixelStoreParam::PackImageHeight: RETURN_PIXEL_STORE_PARAM(Pack, SkipRows);
return m_packParameters.ImageHeight; RETURN_PIXEL_STORE_PARAM(Pack, SkipImages);
case PixelStoreParam::PackSkipPixels: RETURN_PIXEL_STORE_PARAM(Pack, SwapBytes);
return m_packParameters.SkipPixels; RETURN_PIXEL_STORE_PARAM(Pack, LSBFirst);
case PixelStoreParam::PackSkipRows: RETURN_PIXEL_STORE_PARAM(Unpack, Alignment);
return m_packParameters.SkipRows; RETURN_PIXEL_STORE_PARAM(Unpack, RowLength);
case PixelStoreParam::PackSkipImages: RETURN_PIXEL_STORE_PARAM(Unpack, ImageHeight);
return m_packParameters.SkipImages; RETURN_PIXEL_STORE_PARAM(Unpack, SkipPixels);
case PixelStoreParam::PackSwapBytes: RETURN_PIXEL_STORE_PARAM(Unpack, SkipRows);
return m_packParameters.SwapBytes ? 1 : 0; RETURN_PIXEL_STORE_PARAM(Unpack, SkipImages);
case PixelStoreParam::PackLsbFirst: RETURN_PIXEL_STORE_PARAM(Unpack, SwapBytes);
return m_packParameters.LSBFirst ? 1 : 0; RETURN_PIXEL_STORE_PARAM(Unpack, LSBFirst);
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;
default: default:
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param)); MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
return 0; return 0;
@@ -216,25 +281,31 @@ namespace MobileGL {
} }
PixelStoreParameters RenderState::GetPixelStoreParameters(Bool isUnpack) const { PixelStoreParameters RenderState::GetPixelStoreParameters(Bool isUnpack) const {
return isUnpack ? m_unpackParameters : m_packParameters; return isUnpack ? m_pixelStoreUnpackParameters : m_pixelStorePackParameters;
} }
// -------------------- Cull Face -------------------- // -------------------- Cull Face --------------------
void RenderState::SetCullFaceMode(CullFaceMode mode) { void RenderState::SetCullFaceMode(CullFaceMode mode) {
m_cullFaceMode = mode; if (m_parameters.CullFaceModeSetting == mode) return;
m_parameters.CullFaceModeSetting = mode;
++m_version;
} }
CullFaceMode RenderState::GetCullFaceMode() const { CullFaceMode RenderState::GetCullFaceMode() const {
return m_cullFaceMode; return m_parameters.CullFaceModeSetting;
} }
// --------------------- Scissor --------------------- // --------------------- Scissor ---------------------
void RenderState::SetScissorBox(IntVec4 box) { 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 { const IntVec4& RenderState::GetScissorBox() const {
return m_scissorBox; return m_parameters.ScissorBox;
} }
} // namespace GLState } // namespace GLState
} // namespace MG_State } // namespace MG_State
@@ -7,9 +7,9 @@
// End of Source File Header // End of Source File Header
#pragma once #pragma once
#include "MG_Util/Math/VectorTypes.h"
#include "MG_Util/Types.h"
#include <Includes.h> #include <Includes.h>
#include <MG_Util/Math/VectorTypes.h>
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
namespace MobileGL { namespace MobileGL {
enum class BlendFactor { enum class BlendFactor {
@@ -53,7 +53,7 @@ namespace MobileGL {
PackSkipPixels, PackSkipPixels,
PackSkipImages, PackSkipImages,
PackSwapBytes, PackSwapBytes,
PackLsbFirst, PackLSBFirst,
// Unpack Parameters // Unpack Parameters
UnpackAlignment, UnpackAlignment,
@@ -63,7 +63,7 @@ namespace MobileGL {
UnpackSkipPixels, UnpackSkipPixels,
UnpackSkipImages, UnpackSkipImages,
UnpackSwapBytes, UnpackSwapBytes,
UnpackLsbFirst, UnpackLSBFirst,
PixelStoreParamCount, PixelStoreParamCount,
Unknown = -1 Unknown = -1
@@ -128,12 +128,51 @@ namespace MobileGL {
Int Alignment = 4; 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 MG_State {
namespace GLState { namespace GLState {
class RenderState { class RenderState {
public: public:
RenderState(); RenderState();
Uint GetVersion() const;
const RenderStateParameters& GetAllParameters() const;
// Rasterization // Rasterization
void SetViewport(IntVec4 viewport); // x, y, width, height void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height const IntVec4& GetViewport() const; // x, y, width, height
@@ -141,11 +180,17 @@ namespace MobileGL {
// Capabilities // Capabilities
void SetCapability(CapabilityInput cap, Bool enabled); void SetCapability(CapabilityInput cap, Bool enabled);
Bool IsCapabilityEnabled(CapabilityInput cap) const; Bool IsCapabilityEnabled(CapabilityInput cap) const;
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
// Blending // Blending
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha); void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const; 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 // Depth
void SetDepthFunc(DepthTestFunc func); void SetDepthFunc(DepthTestFunc func);
@@ -177,39 +222,12 @@ namespace MobileGL {
const IntVec4& GetScissorBox() const; // x, y, width, height const IntVec4& GetScissorBox() const; // x, y, width, height
private: private:
// Rasterization Uint16 m_version = 0;
IntVec4 m_viewport = IntVec4(0, 0, 0, 0); // x, y, width, height RenderStateParameters m_parameters;
// 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;
// Pixel Store // Pixel Store
PixelStoreParameters m_packParameters; PixelStoreParameters m_pixelStorePackParameters;
PixelStoreParameters m_unpackParameters; PixelStoreParameters m_pixelStoreUnpackParameters;
// 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
}; };
} // namespace GLState } // namespace GLState
} // namespace MG_State } // namespace MG_State
@@ -14,47 +14,77 @@ namespace MobileGL {
SamplerObject::SamplerObject(Uint externalIndex) : m_externalIndex(externalIndex) {} SamplerObject::SamplerObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
void SamplerObject::SetWrapS(SamplerWrapMode mode) { void SamplerObject::SetWrapS(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapS) return;
m_samplerParameters.wrapS = mode; m_samplerParameters.wrapS = mode;
++m_version;
} }
void SamplerObject::SetWrapT(SamplerWrapMode mode) { void SamplerObject::SetWrapT(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapT) return;
m_samplerParameters.wrapT = mode; m_samplerParameters.wrapT = mode;
++m_version;
} }
void SamplerObject::SetWrapR(SamplerWrapMode mode) { void SamplerObject::SetWrapR(SamplerWrapMode mode) {
if (mode == m_samplerParameters.wrapR) return;
m_samplerParameters.wrapR = mode; m_samplerParameters.wrapR = mode;
++m_version;
} }
void SamplerObject::SetMinFilter(SamplerFilterMode mode) { void SamplerObject::SetMinFilter(SamplerFilterMode mode) {
if (mode == m_samplerParameters.minFilter) return;
m_samplerParameters.minFilter = mode; m_samplerParameters.minFilter = mode;
++m_version;
} }
void SamplerObject::SetMagFilter(SamplerFilterMode mode) { void SamplerObject::SetMagFilter(SamplerFilterMode mode) {
if (mode == m_samplerParameters.magFilter) return;
m_samplerParameters.magFilter = mode; m_samplerParameters.magFilter = mode;
++m_version;
} }
void SamplerObject::SetMipmapMode(SamplerMipmapMode mode) { void SamplerObject::SetMipmapMode(SamplerMipmapMode mode) {
if (mode == m_samplerParameters.mipmapMode) return;
m_samplerParameters.mipmapMode = mode; m_samplerParameters.mipmapMode = mode;
++m_version;
} }
void SamplerObject::SetLodRange(Float minLod, Float maxLod) { void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
if (minLod > maxLod) { if (minLod > maxLod) {
THROW_EXCEPTION("minLod cannot be greater than maxLod"); THROW_EXCEPTION("minLod cannot be greater than maxLod");
} }
m_samplerParameters.minLod = minLod; m_samplerParameters.minLod = minLod;
m_samplerParameters.maxLod = maxLod; m_samplerParameters.maxLod = maxLod;
++m_version;
} }
void SamplerObject::SetLodBias(Float bias) { void SamplerObject::SetLodBias(Float bias) {
if (bias == m_samplerParameters.lodBias) return;
m_samplerParameters.lodBias = bias; m_samplerParameters.lodBias = bias;
++m_version;
} }
void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) { void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) {
if (func == m_samplerParameters.compareFunc) return;
m_samplerParameters.compareFunc = func; m_samplerParameters.compareFunc = func;
++m_version;
} }
void SamplerObject::SetCompareMode(SamplerCompareMode mode) { void SamplerObject::SetCompareMode(SamplerCompareMode mode) {
if (mode == m_samplerParameters.compareMode) return;
m_samplerParameters.compareMode = mode; m_samplerParameters.compareMode = mode;
++m_version;
} }
SamplerWrapMode SamplerObject::GetWrapS() const { SamplerWrapMode SamplerObject::GetWrapS() const {
@@ -108,6 +138,10 @@ namespace MobileGL {
const SamplerParameters& SamplerObject::GetAllSamplerParameters() const { const SamplerParameters& SamplerObject::GetAllSamplerParameters() const {
return m_samplerParameters; return m_samplerParameters;
} }
Uint16 SamplerObject::GetVersion() const {
return m_version;
}
} // namespace GLState } // namespace GLState
} // namespace MG_State } // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -98,10 +98,12 @@ namespace MobileGL {
SamplerCompareMode GetCompareMode() const; SamplerCompareMode GetCompareMode() const;
SamplerCompareFunc GetSamplerCompareFunc() const; SamplerCompareFunc GetSamplerCompareFunc() const;
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
Uint16 GetVersion() const;
const SamplerParameters& GetAllSamplerParameters() const; const SamplerParameters& GetAllSamplerParameters() const;
private: private:
const Uint m_externalIndex; const Uint m_externalIndex;
Uint16 m_version = 0;
SamplerParameters m_samplerParameters; SamplerParameters m_samplerParameters;
}; };
} // namespace GLState } // namespace GLState
@@ -7,6 +7,7 @@
// End of Source File Header // End of Source File Header
#include "TextureObject.h" #include "TextureObject.h"
#include "MG_Util/Types.h"
#include <MG_Util/Metrics/TextureMetrics.h> #include <MG_Util/Metrics/TextureMetrics.h>
namespace MobileGL { namespace MobileGL {
@@ -43,7 +44,10 @@ namespace MobileGL {
} }
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) { void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
if (format == m_internalFormat) return;
m_internalFormat = format; m_internalFormat = format;
++m_textureParamsVersion;
} }
Uint TextureObjectBase::GetExternalIndex() const { Uint TextureObjectBase::GetExternalIndex() const {
@@ -55,7 +59,10 @@ namespace MobileGL {
} }
void TextureObjectBase::SetBorderColor(const FloatVec4& color) { void TextureObjectBase::SetBorderColor(const FloatVec4& color) {
if (color == m_borderColor) return;
m_borderColor = color; m_borderColor = color;
++m_textureParamsVersion;
} }
TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const { TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const {
@@ -80,6 +87,8 @@ namespace MobileGL {
} }
void TextureObjectBase::SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) { void TextureObjectBase::SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) {
if (GetSwizzleParam(param) == value) return;
switch (param) { switch (param) {
case TextureSwizzleParam::Red: case TextureSwizzleParam::Red:
m_swizzleParams.r() = value; m_swizzleParams.r() = value;
@@ -98,9 +107,14 @@ namespace MobileGL {
static_cast<Int>(param)); static_cast<Int>(param));
break; break;
} }
++m_textureParamsVersion;
} }
void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) { void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) {
if (values == m_swizzleParams) return;
m_swizzleParams = values; m_swizzleParams = values;
++m_textureParamsVersion;
} }
const UintVec2& TextureObjectBase::GetLevelRange() const { const UintVec2& TextureObjectBase::GetLevelRange() const {
@@ -108,11 +122,21 @@ namespace MobileGL {
} }
void TextureObjectBase::SetBaseLevel(Uint baseLevel) { void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
if (baseLevel == m_levelRange.x()) return;
m_levelRange.x() = baseLevel; m_levelRange.x() = baseLevel;
++m_textureParamsVersion;
} }
void TextureObjectBase::SetMaxLevel(Uint maxLevel) { void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
if (maxLevel == m_levelRange.y()) return;
m_levelRange.y() = maxLevel; m_levelRange.y() = maxLevel;
++m_textureParamsVersion;
}
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
return m_textureParamsVersion;
} }
Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const { Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const {
@@ -144,11 +168,11 @@ namespace MobileGL {
} }
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
bool dirty) { Bool dirty) {
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, 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); 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 // For some reason mojang decided to have 0x0 in last level mipmap
// Relaxing checks for that // Relaxing checks for that
bool hadZero = false; Bool hadZero = false;
for (SizeT i = 0; i < levelCount; ++i) { for (SizeT i = 0; i < levelCount; ++i) {
const auto& levelSize = m_textureStorage.GetTexelSize(0, i); const auto& levelSize = m_textureStorage.GetTexelSize(0, i);
if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) { if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) {
@@ -41,6 +41,7 @@ namespace MobileGL {
virtual const UintVec2& GetLevelRange() const = 0; virtual const UintVec2& GetLevelRange() const = 0;
virtual void SetBaseLevel(Uint baseLevel) = 0; virtual void SetBaseLevel(Uint baseLevel) = 0;
virtual void SetMaxLevel(Uint maxLevel) = 0; virtual void SetMaxLevel(Uint maxLevel) = 0;
virtual Uint16 GetTextureParamsVersion() const = 0;
protected: protected:
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0; virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
@@ -67,7 +68,7 @@ namespace MobileGL {
const UintVec2& GetLevelRange() const override; const UintVec2& GetLevelRange() const override;
void SetBaseLevel(Uint baseLevel) override; void SetBaseLevel(Uint baseLevel) override;
void SetMaxLevel(Uint maxLevel) override; void SetMaxLevel(Uint maxLevel) override;
Uint16 GetTextureParamsVersion() const override;
protected: protected:
const Uint m_externalIndex; const Uint m_externalIndex;
const TextureTarget m_target = TextureTarget::Unknown; const TextureTarget m_target = TextureTarget::Unknown;
@@ -77,6 +78,7 @@ namespace MobileGL {
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green, Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha}; TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
UintVec2 m_levelRange = {0, 1000}; UintVec2 m_levelRange = {0, 1000};
Uint16 m_textureParamsVersion = 0;
}; };
class TextureObjectMipmap : public TextureObjectBase { class TextureObjectMipmap : public TextureObjectBase {
@@ -92,8 +94,9 @@ namespace MobileGL {
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0; virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0; virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0; virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0; virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; Bool dirty = true) = 0;
virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
}; };
class TextureObjectWithOneMipmap : public TextureObjectMipmap { class TextureObjectWithOneMipmap : public TextureObjectMipmap {
@@ -108,7 +111,7 @@ namespace MobileGL {
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override; void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override; void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) 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; bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
IntVec3 GetBaseSize() const override; IntVec3 GetBaseSize() const override;
@@ -22,20 +22,26 @@ namespace MobileGL {
attr.Offset = 0; attr.Offset = 0;
attr.Buffer = nullptr; attr.Buffer = nullptr;
MarkAttributeDirty(index); BumpAttributeFormatVersion(index);
} }
} }
void VertexArrayObject::EnableAttribute(Uint index) { void VertexArrayObject::EnableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Enabled) return;
m_attributes[index].Enabled = true; m_attributes[index].Enabled = true;
MarkAttributeDirty(index); BumpAttributeSwitchVersion(index);
} }
void VertexArrayObject::DisableAttribute(Uint index) { void VertexArrayObject::DisableAttribute(Uint index) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (!m_attributes[index].Enabled) return;
m_attributes[index].Enabled = false; m_attributes[index].Enabled = false;
MarkAttributeDirty(index); BumpAttributeSwitchVersion(index);
} }
Bool VertexArrayObject::IsAttributeEnabled(Uint index) const { Bool VertexArrayObject::IsAttributeEnabled(Uint index) const {
@@ -47,6 +53,12 @@ namespace MobileGL {
SizeT offset, Bool isInteger) { SizeT offset, Bool isInteger) {
if (index >= MAX_VERTEX_ATTRIBS) return; 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) { if (size < 1 || size > 4) {
return; return;
} }
@@ -59,13 +71,16 @@ namespace MobileGL {
attr.Offset = offset; attr.Offset = offset;
attr.IsInteger = isInteger; attr.IsInteger = isInteger;
MarkAttributeDirty(index); BumpAttributeFormatVersion(index);
} }
void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) { void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Buffer == buffer) return;
m_attributes[index].Buffer = buffer; m_attributes[index].Buffer = buffer;
MarkAttributeDirty(index); BumpAttributeBufferVersion(index);
} }
BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() { BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() {
@@ -83,22 +98,6 @@ namespace MobileGL {
return m_attributes; 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 { Uint VertexArrayObject::GetExternalIndex() const {
return m_externalIndex; return m_externalIndex;
} }
@@ -107,13 +106,39 @@ namespace MobileGL {
if (index >= MAX_VERTEX_ATTRIBS) return; if (index >= MAX_VERTEX_ATTRIBS) return;
if (m_attributes[index].Divisor == divisor) return; if (m_attributes[index].Divisor == divisor) return;
m_attributes[index].Divisor = divisor; m_attributes[index].Divisor = divisor;
MarkAttributeDirty(index); BumpAttributeFormatVersion(index);
} }
Uint VertexArrayObject::GetAttributeDivisor(Uint index) const { Uint VertexArrayObject::GetAttributeDivisor(Uint index) const {
if (index >= MAX_VERTEX_ATTRIBS) return 0; if (index >= MAX_VERTEX_ATTRIBS) return 0;
return m_attributes[index].Divisor; 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 GLState
} // namespace MG_State } // namespace MG_State
} // namespace MobileGL } // namespace MobileGL
@@ -9,6 +9,7 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include "../BufferState/BufferObject.h" #include "../BufferState/BufferObject.h"
#include "MG_Util/Types.h"
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
@@ -25,6 +26,12 @@ namespace MobileGL {
SharedPtr<BufferObject> Buffer; SharedPtr<BufferObject> Buffer;
}; };
struct VertexAttributeVersion {
Uint16 FormatVersion = 0;
Uint16 BufferVersion = 0;
Uint16 SwitchVersion = 0;
};
class VertexArrayObject { class VertexArrayObject {
public: public:
static constexpr int MAX_VERTEX_ATTRIBS = 16; static constexpr int MAX_VERTEX_ATTRIBS = 16;
@@ -45,19 +52,22 @@ namespace MobileGL {
const VertexAttribute& GetAttribute(Uint index) const; const VertexAttribute& GetAttribute(Uint index) const;
const Array<VertexAttribute, MAX_VERTEX_ATTRIBS>& GetAllAttributes() const; const Array<VertexAttribute, MAX_VERTEX_ATTRIBS>& GetAllAttributes() const;
const Vector<Uint>& GetDirtyAttributeIndices() const;
void ClearDirtyAttributes();
Uint GetExternalIndex() const; Uint GetExternalIndex() const;
void SetAttributeDivisor(Uint index, Uint divisor); void SetAttributeDivisor(Uint index, Uint divisor);
Uint GetAttributeDivisor(Uint index) const; Uint GetAttributeDivisor(Uint index) const;
const VertexAttributeVersion& GetAttributeVersion(Uint index) const;
const Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS>& GetAllAttributeVersions() const;
private: private:
void MarkAttributeDirty(Uint index); void BumpAttributeFormatVersion(Uint index);
void BumpAttributeBufferVersion(Uint index);
void BumpAttributeSwitchVersion(Uint index);
const Uint m_externalIndex = 0; const Uint m_externalIndex = 0;
Array<VertexAttribute, MAX_VERTEX_ATTRIBS> m_attributes; Array<VertexAttribute, MAX_VERTEX_ATTRIBS> m_attributes;
Vector<Uint> m_dirtyAttributes; Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS> m_attributeVersions;
BindingSlot<BufferObject> m_indexBufferBindingSlot; BindingSlot<BufferObject> m_indexBufferBindingSlot;
}; };
} // namespace GLState } // namespace GLState
+18 -9
View File
@@ -72,7 +72,8 @@ TEST_F(BufferTest, PingPong) {
Vector<Int> bufdata(data.size()); Vector<Int> bufdata(data.size());
memcpy(bufdata.data(), p, byteSize); memcpy(bufdata.data(), p, byteSize);
ASSERT_EQ(data, bufdata); ASSERT_EQ(data, bufdata);
auto range = bufRead->GetDirtyRange(); ASSERT_EQ(bufRead->GetDirtyRanges().size() >= 1, true);
auto range = bufRead->GetDirtyRanges()[0];
ASSERT_EQ(range.start, 0); ASSERT_EQ(range.start, 0);
ASSERT_EQ(range.end, byteSize); ASSERT_EQ(range.end, byteSize);
} }
@@ -122,7 +123,8 @@ TEST_F(BufferTest, AcquireMemory) {
void* p = bufObj->AcquireMemory(false, true, false); void* p = bufObj->AcquireMemory(false, true, false);
memcpy(actual.data(), p, byteSize); memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 0); ASSERT_EQ(dirty.start, 0);
ASSERT_EQ(dirty.end, sizeof(Int) * 5); ASSERT_EQ(dirty.end, sizeof(Int) * 5);
@@ -150,7 +152,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithoutExplicit) {
void* p = bufObj->AcquireMemory(false, true, false); void* p = bufObj->AcquireMemory(false, true, false);
memcpy(actual.data(), p, byteSize); memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int)); ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 4); ASSERT_EQ(dirty.end, sizeof(Int) * 4);
} }
@@ -177,13 +180,15 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
mappedPtr[1] = 300; mappedPtr[1] = 300;
bufObj->FlushMemoryRange(0, sizeof(Int)); bufObj->FlushMemoryRange(0, sizeof(Int));
auto dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int)); ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2); ASSERT_EQ(dirty.end, sizeof(Int) * 2);
bufObj->ReleaseMemory(); bufObj->ReleaseMemory();
dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int)); ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2); ASSERT_EQ(dirty.end, sizeof(Int) * 2);
@@ -193,7 +198,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
memcpy(actual.data(), p, byteSize); memcpy(actual.data(), p, byteSize);
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int)); ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, sizeof(Int) * 2); ASSERT_EQ(dirty.end, sizeof(Int) * 2);
} }
@@ -235,7 +241,8 @@ TEST_F(BufferTest, CopyBufferSubData) {
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
auto dirty = dstObj->GetDirtyRange(); ASSERT_EQ(dstObj->GetDirtyRanges().size() >= 1, true);
auto dirty = dstObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 5 * sizeof(Int)); ASSERT_EQ(dirty.start, 5 * sizeof(Int));
ASSERT_EQ(dirty.end, 9 * sizeof(Int)); ASSERT_EQ(dirty.end, 9 * sizeof(Int));
} }
@@ -265,7 +272,8 @@ TEST_F(BufferTest, WriteWhileMapped) {
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, 0); ASSERT_EQ(dirty.start, 0);
ASSERT_EQ(dirty.end, byteSize); ASSERT_EQ(dirty.end, byteSize);
} }
@@ -293,7 +301,8 @@ TEST_F(BufferTest, PartialUpdate) {
ASSERT_EQ(actual, expected); ASSERT_EQ(actual, expected);
auto dirty = bufObj->GetDirtyRange(); ASSERT_EQ(bufObj->GetDirtyRanges().size() >= 1, true);
auto dirty = bufObj->GetDirtyRanges()[0];
ASSERT_EQ(dirty.start, sizeof(Int)); ASSERT_EQ(dirty.start, sizeof(Int));
ASSERT_EQ(dirty.end, 3 * sizeof(Int)); ASSERT_EQ(dirty.end, 3 * sizeof(Int));
} }
@@ -30,13 +30,22 @@ namespace MobileGL {
} }
switch (attachment) { switch (attachment) {
case GL_DEPTH_ATTACHMENT: case GL_NONE:
return FramebufferAttachmentType::Depth; return FramebufferAttachmentType::None;
case GL_STENCIL_ATTACHMENT: case GL_DEPTH_ATTACHMENT:
return FramebufferAttachmentType::Stencil; return FramebufferAttachmentType::Depth;
case GL_UNKNOWN_MGL: case GL_STENCIL_ATTACHMENT:
default: return FramebufferAttachmentType::Stencil;
return FramebufferAttachmentType::Unknown; case GL_FRONT_LEFT:
return FramebufferAttachmentType::FrontLeft;
case GL_FRONT_RIGHT:
return FramebufferAttachmentType::FrontRight;
case GL_BACK_LEFT:
return FramebufferAttachmentType::BackLeft;
case GL_BACK_RIGHT:
return FramebufferAttachmentType::BackRight;
default:
return FramebufferAttachmentType::Unknown;
} }
} }
@@ -85,7 +85,7 @@ namespace MobileGL {
case GL_PACK_SWAP_BYTES: case GL_PACK_SWAP_BYTES:
return PixelStoreParam::PackSwapBytes; return PixelStoreParam::PackSwapBytes;
case GL_PACK_LSB_FIRST: case GL_PACK_LSB_FIRST:
return PixelStoreParam::PackLsbFirst; return PixelStoreParam::PackLSBFirst;
case GL_UNPACK_ALIGNMENT: case GL_UNPACK_ALIGNMENT:
return PixelStoreParam::UnpackAlignment; return PixelStoreParam::UnpackAlignment;
case GL_UNPACK_ROW_LENGTH: case GL_UNPACK_ROW_LENGTH:
@@ -101,7 +101,7 @@ namespace MobileGL {
case GL_UNPACK_SWAP_BYTES: case GL_UNPACK_SWAP_BYTES:
return PixelStoreParam::UnpackSwapBytes; return PixelStoreParam::UnpackSwapBytes;
case GL_UNPACK_LSB_FIRST: case GL_UNPACK_LSB_FIRST:
return PixelStoreParam::UnpackLsbFirst; return PixelStoreParam::UnpackLSBFirst;
default: default:
return PixelStoreParam::Unknown; return PixelStoreParam::Unknown;
} }
@@ -29,12 +29,20 @@ namespace MobileGL {
} }
switch (type) { switch (type) {
case FramebufferAttachmentType::Depth: case FramebufferAttachmentType::Depth:
return GL_DEPTH_ATTACHMENT; return GL_DEPTH_ATTACHMENT;
case FramebufferAttachmentType::Stencil: case FramebufferAttachmentType::Stencil:
return GL_STENCIL_ATTACHMENT; return GL_STENCIL_ATTACHMENT;
default: case FramebufferAttachmentType::FrontLeft:
return GL_NONE; return GL_FRONT_LEFT;
case FramebufferAttachmentType::FrontRight:
return GL_FRONT_RIGHT;
case FramebufferAttachmentType::BackLeft:
return GL_BACK_LEFT;
case FramebufferAttachmentType::BackRight:
return GL_BACK_RIGHT;
default:
return GL_NONE;
} }
} }
@@ -85,7 +85,7 @@ namespace MobileGL {
return GL_PACK_SKIP_IMAGES; return GL_PACK_SKIP_IMAGES;
case PixelStoreParam::PackSwapBytes: case PixelStoreParam::PackSwapBytes:
return GL_PACK_SWAP_BYTES; return GL_PACK_SWAP_BYTES;
case PixelStoreParam::PackLsbFirst: case PixelStoreParam::PackLSBFirst:
return GL_PACK_LSB_FIRST; return GL_PACK_LSB_FIRST;
case PixelStoreParam::UnpackAlignment: case PixelStoreParam::UnpackAlignment:
return GL_UNPACK_ALIGNMENT; return GL_UNPACK_ALIGNMENT;
@@ -101,7 +101,7 @@ namespace MobileGL {
return GL_UNPACK_SKIP_IMAGES; return GL_UNPACK_SKIP_IMAGES;
case PixelStoreParam::UnpackSwapBytes: case PixelStoreParam::UnpackSwapBytes:
return GL_UNPACK_SWAP_BYTES; return GL_UNPACK_SWAP_BYTES;
case PixelStoreParam::UnpackLsbFirst: case PixelStoreParam::UnpackLSBFirst:
return GL_UNPACK_LSB_FIRST; return GL_UNPACK_LSB_FIRST;
default: default:
return GL_UNKNOWN_MGL; return GL_UNKNOWN_MGL;
@@ -183,6 +183,36 @@ namespace MobileGL {
return internalformat; return internalformat;
} }
} }
case TextureInternalFormat::DepthComponent: {
switch (type) {
case TexturePixelDataType::UnsignedShort:
return TextureInternalFormat::DepthComponent16;
case TexturePixelDataType::UnsignedInt:
return TextureInternalFormat::DepthComponent32;
case TexturePixelDataType::Float:
return TextureInternalFormat::DepthComponent32F;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
case TextureInternalFormat::DepthStencil: {
switch (type) {
case TexturePixelDataType::UnsignedInt248:
return TextureInternalFormat::Depth24Stencil8;
default:
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, "
"returning original.",
__func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(),
MG_Util::ConvertTextureInputFormatToString(format).c_str(),
MG_Util::ConvertTexturePixelDataTypeToString(type).c_str());
return internalformat;
}
}
default: { default: {
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning " MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning "
"original.", "original.",
@@ -193,5 +223,93 @@ namespace MobileGL {
} }
} }
} }
TextureInternalFormat ConvertInternalFormatToUnsized(TextureInternalFormat internalformat) {
switch (internalformat) {
case TextureInternalFormat::R8:
case TextureInternalFormat::R8Snorm:
case TextureInternalFormat::R16:
case TextureInternalFormat::R16Snorm:
case TextureInternalFormat::R16F:
case TextureInternalFormat::R32F:
case TextureInternalFormat::R8I:
case TextureInternalFormat::R8UI:
case TextureInternalFormat::R16I:
case TextureInternalFormat::R16UI:
case TextureInternalFormat::R32I:
case TextureInternalFormat::R32UI:
case TextureInternalFormat::Red:
return TextureInternalFormat::Red;
case TextureInternalFormat::RG8:
case TextureInternalFormat::RG8Snorm:
case TextureInternalFormat::RG16:
case TextureInternalFormat::RG16Snorm:
case TextureInternalFormat::RG16F:
case TextureInternalFormat::RG32F:
case TextureInternalFormat::RG8I:
case TextureInternalFormat::RG8UI:
case TextureInternalFormat::RG16I:
case TextureInternalFormat::RG16UI:
case TextureInternalFormat::RG32I:
case TextureInternalFormat::RG32UI:
case TextureInternalFormat::RG:
return TextureInternalFormat::RG;
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGB8:
case TextureInternalFormat::RGB8Snorm:
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGB16Snorm:
case TextureInternalFormat::RGB16F:
case TextureInternalFormat::RGB32F:
case TextureInternalFormat::R11FG11FB10F:
case TextureInternalFormat::RGB9E5:
case TextureInternalFormat::SRGB8:
case TextureInternalFormat::RGB8I:
case TextureInternalFormat::RGB8UI:
case TextureInternalFormat::RGB16I:
case TextureInternalFormat::RGB16UI:
case TextureInternalFormat::RGB32I:
case TextureInternalFormat::RGB32UI:
case TextureInternalFormat::RGB:
return TextureInternalFormat::RGB;
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
case TextureInternalFormat::RGBA8:
case TextureInternalFormat::RGBA8Snorm:
case TextureInternalFormat::RGB10A2:
case TextureInternalFormat::RGB10A2UI:
case TextureInternalFormat::RGBA12:
case TextureInternalFormat::RGBA16:
case TextureInternalFormat::SRGB8Alpha8:
case TextureInternalFormat::RGBA16F:
case TextureInternalFormat::RGBA32F:
case TextureInternalFormat::RGBA8I:
case TextureInternalFormat::RGBA8UI:
case TextureInternalFormat::RGBA16I:
case TextureInternalFormat::RGBA16UI:
case TextureInternalFormat::RGBA32I:
case TextureInternalFormat::RGBA32UI:
case TextureInternalFormat::RGBA:
return TextureInternalFormat::RGBA;
case TextureInternalFormat::DepthComponent16:
case TextureInternalFormat::DepthComponent24:
case TextureInternalFormat::DepthComponent32:
case TextureInternalFormat::DepthComponent32F:
case TextureInternalFormat::DepthComponent:
return TextureInternalFormat::DepthComponent;
case TextureInternalFormat::Depth24Stencil8:
case TextureInternalFormat::Depth32FStencil8:
case TextureInternalFormat::DepthStencil:
return TextureInternalFormat::DepthStencil;
default:
MGLOG_W("%s: Unknown or unhandled internal format %s, returning original.", __func__,
MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str());
return internalformat;
}
}
} // namespace MG_Util } // namespace MG_Util
} // namespace MobileGL } // namespace MobileGL
@@ -15,5 +15,7 @@ namespace MobileGL {
TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target); TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target);
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
TextureInputFormat format, TexturePixelDataType type); TextureInputFormat format, TexturePixelDataType type);
TextureInternalFormat ConvertInternalFormatToUnsized(TextureInternalFormat internalformat);
} // namespace MG_Util } // namespace MG_Util
} // namespace MobileGL } // namespace MobileGL
@@ -84,8 +84,8 @@ namespace MobileGL {
return "PackSkipImages"; return "PackSkipImages";
case PixelStoreParam::PackSwapBytes: case PixelStoreParam::PackSwapBytes:
return "PackSwapBytes"; return "PackSwapBytes";
case PixelStoreParam::PackLsbFirst: case PixelStoreParam::PackLSBFirst:
return "PackLsbFirst"; return "PackLSBFirst";
case PixelStoreParam::UnpackAlignment: case PixelStoreParam::UnpackAlignment:
return "UnpackAlignment"; return "UnpackAlignment";
case PixelStoreParam::UnpackRowLength: case PixelStoreParam::UnpackRowLength:
@@ -100,8 +100,8 @@ namespace MobileGL {
return "UnpackSkipImages"; return "UnpackSkipImages";
case PixelStoreParam::UnpackSwapBytes: case PixelStoreParam::UnpackSwapBytes:
return "UnpackSwapBytes"; return "UnpackSwapBytes";
case PixelStoreParam::UnpackLsbFirst: case PixelStoreParam::UnpackLSBFirst:
return "UnpackLsbFirst"; return "UnpackLSBFirst";
default: default:
return "Unknown"; return "Unknown";
} }
+134
View File
@@ -0,0 +1,134 @@
// MobileGL - MobileGL/MG_Util/Math/VectorTypes.cpp
// 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
#include "VectorTypes.h"
namespace MobileGL {
void VecRange1D::Add(const Range1D& newRange, Double ratio, SizeT* outMinStart, SizeT* outMaxEnd) {
if (this->empty()) {
this->push_back(newRange);
m_overallMaxEnd = newRange.end;
if (outMinStart) *outMinStart = this->front().start;
if (outMaxEnd) *outMaxEnd = m_overallMaxEnd;
return;
}
auto it = std::lower_bound(this->begin(), this->end(), newRange.start,
[](const Range1D& a, SizeT valueStart) { return a.start < valueStart; });
size_t pos = static_cast<size_t>(std::distance(this->begin(), it));
auto calc_gap = [](const Range1D& a, const Range1D& b) -> SizeT {
return (b.start > a.end) ? (b.start - a.end) : 0;
};
auto calc_threshold = [ratio](const Range1D& a, const Range1D& b) -> SizeT {
SizeT minStart = (a.start < b.start) ? a.start : b.start;
SizeT maxEnd = (a.end > b.end) ? a.end : b.end;
SizeT span = (maxEnd > minStart) ? (maxEnd - minStart) : 0;
return static_cast<SizeT>(static_cast<Double>(span) * ratio);
};
if (pos >= this->size()) {
Range1D& last = this->back();
SizeT gap = calc_gap(last, newRange);
SizeT threshold = calc_threshold(last, newRange);
if (gap <= threshold) {
last.end = std::max(last.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, last.end);
} else {
this->push_back(newRange);
m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end);
}
if (outMinStart) *outMinStart = this->front().start;
if (outMaxEnd) *outMaxEnd = m_overallMaxEnd;
return;
}
bool merged = false;
if (pos > 0) {
Range1D& prev = (*this)[pos - 1];
SizeT gapPrev = calc_gap(prev, newRange);
SizeT thresholdPrev = calc_threshold(prev, newRange);
if (gapPrev <= thresholdPrev) {
prev.end = std::max(prev.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, prev.end);
size_t writeIdx = pos - 1;
while (writeIdx + 1 < this->size()) {
Range1D& cur = (*this)[writeIdx];
Range1D& nxt = (*this)[writeIdx + 1];
SizeT gap = calc_gap(cur, nxt);
SizeT threshold = calc_threshold(cur, nxt);
if (gap <= threshold) {
// merge nxt into cur
cur.end = std::max(cur.end, nxt.end);
this->erase(this->begin() + (writeIdx + 1));
m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end);
} else {
break;
}
}
merged = true;
}
}
if (!merged) {
// Try to merge with the current pos interval or insert
Range1D& cur = (*this)[pos];
SizeT gapCur = calc_gap(newRange, cur); // gap between new and cur
SizeT thresholdCur = calc_threshold(newRange, cur);
if (gapCur <= thresholdCur) {
cur.start = std::min(cur.start, newRange.start);
cur.end = std::max(cur.end, newRange.end);
m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end);
size_t writeIdx = pos;
while (writeIdx + 1 < this->size()) {
Range1D& cur2 = (*this)[writeIdx];
Range1D& nxt = (*this)[writeIdx + 1];
SizeT gap = calc_gap(cur2, nxt);
SizeT threshold = calc_threshold(cur2, nxt);
if (gap <= threshold) {
cur2.end = std::max(cur2.end, nxt.end);
this->erase(this->begin() + (writeIdx + 1));
m_overallMaxEnd = std::max(m_overallMaxEnd, cur2.end);
} else {
break;
}
}
merged = true;
} else {
this->insert(this->begin() + pos, newRange);
m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end);
merged = true;
}
}
if (outMinStart) {
*outMinStart = this->front().start;
}
if (outMaxEnd) {
*outMaxEnd = m_overallMaxEnd;
}
}
SizeT VecRange1D::GetOverallMaxEnd() const {
return m_overallMaxEnd;
}
SizeT VecRange1D::GetOverallMinStart() const {
if (this->empty()) return 0;
return this->front().start;
}
} // namespace MobileGL
+11 -1
View File
@@ -11,7 +11,6 @@
#include <Includes.h> #include <Includes.h>
namespace MobileGL { namespace MobileGL {
template <typename Derived, typename T, SizeT N> template <typename Derived, typename T, SizeT N>
struct VecBase { struct VecBase {
Array<T, N> data; Array<T, N> data;
@@ -247,4 +246,15 @@ namespace MobileGL {
return incident - normal * (2.0f * incident.Dot(normal)); return incident - normal * (2.0f * incident.Dot(normal));
} }
} // namespace MG_Util } // namespace MG_Util
class VecRange1D : public Vector<Range1D> {
public:
void Add(const Range1D& newRange, Double ratio = 0.07, SizeT* outMinStart = nullptr,
SizeT* outMaxEnd = nullptr);
SizeT GetOverallMaxEnd() const;
SizeT GetOverallMinStart() const;
private:
SizeT m_overallMaxEnd;
};
} // namespace MobileGL } // namespace MobileGL
@@ -239,6 +239,12 @@ namespace MobileGL {
} }
} }
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type) {
SizeT sizedPixelFormatSize = GetSizedTexturePixelDataTypeSize(type);
if (sizedPixelFormatSize > 0) return sizedPixelFormatSize;
return GetBaseTexturePixelDataTypeSize(type);
}
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) { SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) {
SizeT sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat); SizeT sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat);
if (sizedTextureFormatSize > 0) return sizedTextureFormatSize; if (sizedTextureFormatSize > 0) return sizedTextureFormatSize;
@@ -16,6 +16,7 @@ namespace MobileGL {
SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format); SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format);
SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type); SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type);
SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type); SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type);
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type);
// This should respect internal format more // This should respect internal format more
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type); SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type);
// This should respect type more, representing data passed in // This should respect type more, representing data passed in
@@ -230,11 +230,14 @@ namespace MobileGL {
bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary, bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary,
Vector<uint32_t>& outputBinary) { Vector<uint32_t>& outputBinary) {
using namespace spvtools; using namespace spvtools;
OptimizerOptions options;
options.set_run_validator(false);
Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5); Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5);
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass()); optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary); return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary, options);
} }
Result<String> ShaderCompiler::DecompileShader(SpvcSession& session) { Result<String> ShaderCompiler::DecompileShader(SpvcSession& session) {
@@ -9,11 +9,13 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
namespace MobileGL::MG_Util::TextureFormatProcessor { namespace MobileGL {
enum class PixelFormatNormalizeOptionBit : Uint { enum class PixelFormatNormalizeOptionBit : Uint {
NoNorm16 = 1 << 0, NoNorm16 = 1 << 0,
None = 0, None = 0,
}; };
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options, namespace MG_Util::TextureFormatProcessor {
GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options,
} // namespace MobileGL::MG_Util::TextureFormatProcessor GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType);
}
} // namespace MobileGL
+7 -4
View File
@@ -145,17 +145,20 @@ namespace MobileGL {
using TargetEnum = typename ObjectType::TargetEnum; using TargetEnum = typename ObjectType::TargetEnum;
BindingSlot() : m_target((TargetEnum)0), m_boundObject(nullptr) {} BindingSlot() : m_target((TargetEnum)0), m_boundObject(nullptr) {}
explicit BindingSlot(TargetEnum target) : m_target(target), m_boundObject(nullptr) {} explicit BindingSlot(TargetEnum target) : m_target(target), m_boundObject(nullptr) {}
void Bind(SharedPtr<ObjectType> object) {
if (m_boundObject == object) return;
void Bind(SharedPtr<ObjectType> object) { m_boundObject = object; } m_boundObject = object;
++m_version;
}
SharedPtr<ObjectType> GetBoundObject() const { return m_boundObject; } SharedPtr<ObjectType> GetBoundObject() const { return m_boundObject; }
TargetEnum GetTarget() const { return m_target; } TargetEnum GetTarget() const { return m_target; }
Uint16 GetVersion() const { return m_version; }
private: private:
TargetEnum m_target; TargetEnum m_target;
Uint16 m_version = 0;
SharedPtr<ObjectType> m_boundObject; SharedPtr<ObjectType> m_boundObject;
}; };
+1 -1
View File
@@ -91,7 +91,7 @@ If you want to try the project right now, youll need to build it yourself:
## Build Options ## Build Options
| Option | Description | Default | | Option | Description | Default |
| ---------------------------- | ----------------------------------------------------- | ------- | |------------------------------| ----------------------------------------------------- | ------- |
| `MOBILEGL_BUILD_TEST` | Build MobileGL tests (requires Clang) | ON | | `MOBILEGL_BUILD_TEST` | Build MobileGL tests (requires Clang) | ON |
| `MOBILEGL_BUILD_BENCHMARK` | Build MobileGL benchmarks (requires Clang) | ON | | `MOBILEGL_BUILD_BENCHMARK` | Build MobileGL benchmarks (requires Clang) | ON |
| `MOBILEGL_FORCE_RELEASE_OPT` | Enable O3 and LTO in Debug build | ON | | `MOBILEGL_FORCE_RELEASE_OPT` | Enable O3 and LTO in Debug build | ON |
+1 -1
View File
@@ -11,7 +11,7 @@ android {
// externalNativeBuild { // externalNativeBuild {
// cmake { // cmake {
// arguments "-DTRACY_ENABLE=ON" // arguments "-DMOBILEGL_ENABLE_TRACY=ON"
// } // }
// } // }
} }