mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
Merge branch 'dev' into Feat/Backend-Direct-Vulkan
This commit is contained in:
+51
-30
@@ -13,10 +13,32 @@ if (ANDROID)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT)
|
||||
# Check if ThinLTO or LTO is suppported
|
||||
include(CheckIPOSupported)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
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()
|
||||
|
||||
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/Math/VectorTypes.cpp
|
||||
MobileGL/MG_Util/Metrics/TextureMetrics.cpp
|
||||
|
||||
MobileGL/MG_Util/Metrics/BufferMetrics.cpp
|
||||
|
||||
MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp
|
||||
@@ -256,33 +280,35 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
${MOBILEGL_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
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
|
||||
if(NOT ANDROID)
|
||||
add_library(${CMAKE_PROJECT_NAME}_s STATIC
|
||||
${SOURCE_FILES}
|
||||
)
|
||||
else()
|
||||
set_target_properties(${CMAKE_PROJECT_NAME}_s PROPERTIES
|
||||
C_VISIBILITY_PRESET hidden
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
VISIBILITY_INLINES_HIDDEN ON
|
||||
|
||||
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
|
||||
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()
|
||||
|
||||
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)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient)
|
||||
@@ -296,11 +322,6 @@ if (ANDROID)
|
||||
log
|
||||
vulkan
|
||||
)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC
|
||||
android
|
||||
log
|
||||
vulkan
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID)
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ namespace MobileGL {
|
||||
inline const String ProjectName = "MobileGL";
|
||||
inline const String CoreName = "MobileGL Core";
|
||||
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};
|
||||
extern UniquePtr<RendererInfo> RendererInfoPtr;
|
||||
|
||||
@@ -28,4 +28,4 @@ namespace MobileGL {
|
||||
}
|
||||
} // namespace Backend
|
||||
} // namespace MG_Config
|
||||
} // namespace MobileGL
|
||||
} // namespace MobileGL
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_State/GLState/TextureState/TextureState.h>
|
||||
#include <MG_State/GLState/SamplerState/SamplerObject.h>
|
||||
|
||||
#define CallAndCheck(operation) \
|
||||
MGLOG_D("Call GLES func: %s", #operation); \
|
||||
@@ -51,4 +53,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
GLsizei height);
|
||||
void GenerateMipmap(GLenum target);
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,25 +16,26 @@
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectGLES {
|
||||
namespace BufferImpl {
|
||||
const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
|
||||
class BackendBufferObject {
|
||||
public:
|
||||
BackendBufferObject();
|
||||
void SyncToBackend(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
||||
Uint GetBackendBufferId() { return m_backendBufferId; }
|
||||
void Bind();
|
||||
void Bind(GLenum target);
|
||||
void Bind(GLenum target = TempBufferTarget);
|
||||
|
||||
private:
|
||||
void SyncToBackend_glBufferData(SharedPtr<MG_State::GLState::BufferObject>& stateBufferObject);
|
||||
void SyncToBackend_glBufferSubData(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;
|
||||
SizeT m_prevBufferSize = 0;
|
||||
Bool m_isInitialized = false;
|
||||
};
|
||||
|
||||
extern BackendBufferObject* g_boundVertexBufferObject;
|
||||
extern UnorderedMap<SharedPtr<MG_State::GLState::BufferObject>, SharedPtr<BackendBufferObject>>
|
||||
g_backendBufferObjects;
|
||||
} // namespace BufferImpl
|
||||
@@ -43,13 +44,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
class BackendVertexArrayObject {
|
||||
public:
|
||||
BackendVertexArrayObject();
|
||||
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, Bool needDivisor);
|
||||
void SyncToBackend(SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
|
||||
Uint GetBackendVertexArrayId() { return m_backendVAOId; }
|
||||
void Bind();
|
||||
|
||||
private:
|
||||
void BindAttributeBuffer(Uint index, const MG_State::GLState::VertexAttribute& attrib);
|
||||
|
||||
Uint m_backendVAOId = 0;
|
||||
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>>
|
||||
@@ -82,11 +88,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
inline const Uint TempTextureUnit = 0;
|
||||
class BackendTextureObject {
|
||||
public:
|
||||
BackendTextureObject();
|
||||
void SyncToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
|
||||
void Bind(GLenum target);
|
||||
void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
|
||||
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();
|
||||
|
||||
private:
|
||||
@@ -98,10 +107,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
FloatVec4 m_cacheBorderColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
Vec4<TextureSwizzleParam> m_cacheSwizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
||||
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>>
|
||||
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 FramebufferImpl {
|
||||
@@ -112,7 +129,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
FramebufferTarget asTarget);
|
||||
Uint GetBackendFramebufferId() { return m_backendFBOId; }
|
||||
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:
|
||||
Uint m_backendFBOId = 0;
|
||||
@@ -125,25 +146,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
*/
|
||||
FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
|
||||
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
|
||||
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
|
||||
*/
|
||||
GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};
|
||||
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>>
|
||||
g_backendFramebufferObjects;
|
||||
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
|
||||
} // namespace FramebufferImpl
|
||||
|
||||
namespace PrgramImpl {
|
||||
@@ -178,8 +196,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
Uint m_backendSamplerId = 0;
|
||||
Bool m_isInitialized = false;
|
||||
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>>
|
||||
g_backendSamplerObjects;
|
||||
} // namespace SamplerImpl
|
||||
|
||||
@@ -19,55 +19,11 @@
|
||||
#include <MG_Util/Converters/MGToGL/FramebufferEnumConverter.h>
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectGLES {
|
||||
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);
|
||||
}
|
||||
namespace BufferImpl {} // namespace BufferImpl
|
||||
|
||||
BackendBufferBindingProtector::~BackendBufferBindingProtector() {
|
||||
#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 VertexArrayImpl {} // namespace VertexArrayImpl
|
||||
|
||||
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,
|
||||
GLenum* outFormat, GLenum* outType) {
|
||||
#ifdef TRACY_ENABLE
|
||||
@@ -81,43 +37,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
} // namespace TextureImpl
|
||||
|
||||
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 FramebufferImpl {} // namespace FramebufferImpl
|
||||
|
||||
namespace PrgramImpl {
|
||||
String ProcessOutColorLocations(const String& glslCode) {
|
||||
|
||||
@@ -27,66 +27,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
};
|
||||
} // namespace DebugImpl
|
||||
|
||||
namespace BufferImpl {
|
||||
class BackendBufferBindingProtector {
|
||||
public:
|
||||
BackendBufferBindingProtector(GLenum target);
|
||||
|
||||
~BackendBufferBindingProtector();
|
||||
|
||||
private:
|
||||
GLenum m_target;
|
||||
GLint m_previousBinding = 0;
|
||||
};
|
||||
} // namespace BufferImpl
|
||||
namespace BufferImpl {} // namespace BufferImpl
|
||||
|
||||
namespace VertexArrayImpl {
|
||||
GLenum GetBindingQuery(GLenum target, bool isTexture);
|
||||
|
||||
class BackendVertexArrayBindingProtector {
|
||||
public:
|
||||
BackendVertexArrayBindingProtector();
|
||||
|
||||
~BackendVertexArrayBindingProtector();
|
||||
|
||||
private:
|
||||
GLint m_previousBinding = 0;
|
||||
};
|
||||
} // namespace VertexArrayImpl
|
||||
|
||||
namespace TextureImpl {
|
||||
class BackendTextureBindingProtector {
|
||||
public:
|
||||
BackendTextureBindingProtector(GLenum target);
|
||||
|
||||
~BackendTextureBindingProtector();
|
||||
|
||||
private:
|
||||
GLenum m_target;
|
||||
GLint m_previousBinding = 0;
|
||||
};
|
||||
|
||||
void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat,
|
||||
GLenum* outFormat, GLenum* outType);
|
||||
} // namespace TextureImpl
|
||||
|
||||
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 FramebufferImpl {} // namespace FramebufferImpl
|
||||
|
||||
namespace PrgramImpl {
|
||||
String ProcessOutColorLocations(const String& glslCode);
|
||||
|
||||
@@ -574,6 +574,7 @@ namespace MobileGL {
|
||||
return MapBuffer_State(target, access);
|
||||
}
|
||||
|
||||
// FIXME: this should be a "backend" function
|
||||
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset,
|
||||
GLsizeiptr 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, 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_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_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)
|
||||
@@ -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, 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, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_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, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Enablei, 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, 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, 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, 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, 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)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "GL_Framebuffer.h"
|
||||
#include "Validators.h"
|
||||
#include "Config.h"
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
#include <MG_Impl/GLImpl/Texture/Validators.h>
|
||||
#include <MG_State/GLState/ErrorState/Error.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) {
|
||||
if (n < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -488,7 +508,142 @@ namespace MobileGL {
|
||||
#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@ */
|
||||
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) {
|
||||
ClearBufferfi_Backend(buffer, drawbuffer, depth, stencil);
|
||||
}
|
||||
@@ -575,6 +730,10 @@ namespace MobileGL {
|
||||
DrawBuffers_State(n, bufs);
|
||||
}
|
||||
|
||||
void ReadBuffer(GLenum src) {
|
||||
ReadBuffer_State(src);
|
||||
}
|
||||
|
||||
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
|
||||
DeleteRenderbuffers_State(n, renderbuffers);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_Impl::GLImpl {
|
||||
/* @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 ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* 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 DrawBuffer(GLenum buf);
|
||||
void DrawBuffers(GLsizei n, const GLenum* bufs);
|
||||
void ReadBuffer(GLenum src);
|
||||
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
|
||||
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
|
||||
GLenum CheckFramebufferStatus(GLenum target);
|
||||
|
||||
@@ -567,7 +567,7 @@ namespace MobileGL {
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackImageHeight);
|
||||
break;
|
||||
case GL_PACK_LSB_FIRST:
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLsbFirst);
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackLSBFirst);
|
||||
break;
|
||||
case GL_PACK_ROW_LENGTH:
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::PackRowLength);
|
||||
@@ -839,7 +839,7 @@ namespace MobileGL {
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackImageHeight);
|
||||
break;
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLsbFirst);
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackLSBFirst);
|
||||
break;
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackRowLength);
|
||||
|
||||
@@ -111,13 +111,32 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
GLboolean IsEnabledi_State(GLenum target, GLuint index) {
|
||||
// TODO: implement
|
||||
return GL_FALSE;
|
||||
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target);
|
||||
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) {
|
||||
// TODO: implement
|
||||
return GL_FALSE;
|
||||
CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap);
|
||||
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) {
|
||||
@@ -241,10 +260,6 @@ namespace MobileGL {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
void ReadBuffer_State(GLenum src) {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
void ClearStencil_State(GLint s) {
|
||||
// TODO: implement
|
||||
}
|
||||
@@ -257,7 +272,67 @@ namespace MobileGL {
|
||||
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@ */
|
||||
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) {
|
||||
BlendFunc_State(sfactor, dfactor);
|
||||
}
|
||||
@@ -390,10 +465,6 @@ namespace MobileGL {
|
||||
BlendColor_State(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
void ReadBuffer(GLenum src) {
|
||||
ReadBuffer_State(src);
|
||||
}
|
||||
|
||||
void ClearStencil(GLint s) {
|
||||
ClearStencil_State(s);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_Impl::GLImpl {
|
||||
/* @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 Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
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 BlendEquation(GLenum mode);
|
||||
void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
void ReadBuffer(GLenum src);
|
||||
void ClearStencil(GLint s);
|
||||
void ClearDepth(GLclampd depth);
|
||||
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
|
||||
@@ -7,26 +7,27 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "GL_Texture.h"
|
||||
#include "GL/gl.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 "Validators.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_Util/Metrics/TextureMetrics.h>
|
||||
#include <MG_State/GLState/ErrorState/Error.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/GLToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/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 MG_Impl::GLImpl {
|
||||
@@ -714,9 +715,6 @@ namespace MobileGL {
|
||||
MGLOG_D("%s: Allocating %d bytes at mip %d", __func__, internalBytes, level);
|
||||
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) {
|
||||
MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__);
|
||||
return;
|
||||
@@ -740,6 +738,9 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -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) {
|
||||
// TODO: implement
|
||||
}
|
||||
@@ -1228,12 +1225,57 @@ namespace MobileGL {
|
||||
|
||||
void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height, GLint border) {
|
||||
GLenum outInternalFormat, format, type;
|
||||
MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format,
|
||||
&type);
|
||||
auto internalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
||||
const auto& currentReadFBO =
|
||||
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 =
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1332,7 +1374,136 @@ namespace MobileGL {
|
||||
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@ */
|
||||
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,
|
||||
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
GetCompressedTexImage_State(target, level, img);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_Impl::GLImpl {
|
||||
/* @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,
|
||||
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,
|
||||
@@ -43,7 +44,6 @@ namespace MobileGL {
|
||||
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* 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 GenTextures(GLsizei n, GLuint* textures);
|
||||
void DeleteTextures(GLsizei n, const GLuint* textures);
|
||||
|
||||
@@ -7,13 +7,12 @@
|
||||
// End of Source File Header
|
||||
|
||||
#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/ErrorState/Error.h>
|
||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
@@ -170,6 +169,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,
|
||||
TextureInternalFormat internalFormat,
|
||||
TexturePixelDataType type) {
|
||||
@@ -303,5 +303,21 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
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 MobileGL::MG_Impl::GLImpl
|
||||
} // namespace MobileGL::MG_Impl::GLImpl
|
||||
@@ -7,6 +7,7 @@
|
||||
// End of Source File Header
|
||||
|
||||
#pragma once
|
||||
#include "MG_State/GLState/TextureState/TextureEnum.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
#include <MG_State/GLState/TextureState/TextureObject.h>
|
||||
@@ -32,5 +33,6 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
TextureTarget target);
|
||||
Bool ValidateTextureSubImageOffsets(SharedPtr<MG_State::GLState::ITextureObject> textureObject, Int xoffset,
|
||||
Int width, Int yoffset = 0, Int height = 0, Int zoffset = 0, Int depth = 0);
|
||||
Bool ValidateBaseInternalFormatMatch(TextureInternalFormat format1, TextureInternalFormat format2);
|
||||
} // namespace TextureImpl
|
||||
} // namespace MobileGL::MG_Impl::GLImpl
|
||||
@@ -14,14 +14,18 @@ namespace MobileGL {
|
||||
namespace GLState {
|
||||
BufferObject::BufferObject(Uint externalIndex)
|
||||
: m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false),
|
||||
m_mappingAccess(BufferMappingAccessBit::Null), m_dirtyRange({0, 0}), m_mappedRange({0, 0}),
|
||||
m_dataPtr(MakeShared<Data>()) {}
|
||||
m_mappingAccess(BufferMappingAccessBit::Null),
|
||||
m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}),
|
||||
m_dataPtr(MakeShared<Data>()) {
|
||||
m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT);
|
||||
}
|
||||
|
||||
void BufferObject::Resize(SizeT size) {
|
||||
m_size = size;
|
||||
m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve
|
||||
m_dataPtr->resize(size);
|
||||
m_dirtyRange = {0, 0};
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::PreferReallocationBit;
|
||||
}
|
||||
|
||||
void BufferObject::UploadData(DataPtr data, SizeT atOffset) {
|
||||
@@ -30,7 +34,14 @@ namespace MobileGL {
|
||||
data.size, m_size);
|
||||
MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped.");
|
||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
|
||||
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
|
||||
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
// This function may be called by `glBufferData`, but we still set the forbid bits above,
|
||||
// because when `PreferReallocationBit` is set, those bits are ignored anyway.
|
||||
// The bits can fit the `glBufferSubData` semantics
|
||||
// (though `glBufferSubData` calls `UploadSubData` instead).
|
||||
}
|
||||
|
||||
void BufferObject::SetUsage(BufferUsage usage) {
|
||||
@@ -44,7 +55,8 @@ namespace MobileGL {
|
||||
if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly
|
||||
Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(),
|
||||
m_mappedRange.end - m_mappedRange.start);
|
||||
m_dirtyRange.UnionUpdate(m_mappedRange.start, m_mappedRange.end);
|
||||
m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
m_stagingData.clear();
|
||||
@@ -69,7 +81,8 @@ namespace MobileGL {
|
||||
"Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end);
|
||||
|
||||
Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length);
|
||||
m_dirtyRange.UnionUpdate(start, end);
|
||||
m_change.DirtyRanges.Add({start, end});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) {
|
||||
@@ -79,7 +92,10 @@ namespace MobileGL {
|
||||
atOffset, data.size, m_size);
|
||||
|
||||
Memcpy(m_dataPtr->data() + atOffset, data.data, data.size);
|
||||
m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size);
|
||||
m_change.DirtyRanges.Add({atOffset, atOffset + data.size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidInvalidationBit;
|
||||
m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit;
|
||||
}
|
||||
|
||||
void BufferObject::CopyDataFrom(const SharedPtr<BufferObject>& src, SizeT srcOffset, SizeT dstOffset,
|
||||
@@ -95,7 +111,8 @@ namespace MobileGL {
|
||||
|
||||
const Uint8* srcData = src->m_dataPtr->data() + srcOffset;
|
||||
Memcpy(m_dataPtr->data() + dstOffset, srcData, size);
|
||||
m_dirtyRange.UnionUpdate(dstOffset, dstOffset + size);
|
||||
m_change.DirtyRanges.Add({dstOffset, dstOffset + size});
|
||||
m_change.Bits |= BufferChangeBits::DirtyBit;
|
||||
}
|
||||
|
||||
void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) {
|
||||
@@ -144,6 +161,14 @@ namespace MobileGL {
|
||||
m_ownsStagingData = false;
|
||||
return m_dataPtr->data() + range.start;
|
||||
}
|
||||
|
||||
m_change.Bits |= !(access & BufferMappingAccessBit::InvalidateBuffer ||
|
||||
access & BufferMappingAccessBit::InvalidateRange)
|
||||
? BufferChangeBits::ForbidInvalidationBit
|
||||
: BufferChangeBits::None;
|
||||
m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized)
|
||||
? BufferChangeBits::ForbidUnsynchronizationBit
|
||||
: BufferChangeBits::None;
|
||||
}
|
||||
|
||||
const SharedPtr<Data> BufferObject::GetDataReadOnly() const {
|
||||
@@ -151,7 +176,8 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void BufferObject::ClearDirty() {
|
||||
m_dirtyRange = {0, 0};
|
||||
m_change.DirtyRanges.clear();
|
||||
m_change.Bits = BufferChangeBits::None;
|
||||
}
|
||||
|
||||
SizeT BufferObject::GetSize() const {
|
||||
@@ -162,8 +188,12 @@ namespace MobileGL {
|
||||
return m_usage;
|
||||
}
|
||||
|
||||
Range1D BufferObject::GetDirtyRange() const {
|
||||
return m_dirtyRange;
|
||||
const VecRange1D& BufferObject::GetDirtyRanges() const {
|
||||
return m_change.DirtyRanges;
|
||||
}
|
||||
|
||||
Flags<BufferChangeBits> BufferObject::GetChangeBits() const {
|
||||
return m_change.Bits;
|
||||
}
|
||||
|
||||
Bool BufferObject::IsMapped() const {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Math/VectorTypes.h>
|
||||
|
||||
namespace MobileGL {
|
||||
enum class BufferTarget {
|
||||
@@ -55,6 +56,23 @@ namespace MobileGL {
|
||||
Coherent = 0x80
|
||||
};
|
||||
|
||||
enum class BufferChangeBits : Uint8 {
|
||||
None = 0,
|
||||
DirtyBit = 1 << 0, // When not set, bits below are ignored and nothing should be synced to backend
|
||||
PreferReallocationBit =
|
||||
1 << 1, // <=> `glBufferData`; When set, ForbidInvalidationBit and ForbidUnsynchronizationBit are ignored
|
||||
ForbidInvalidationBit = 1 << 2, // Indidate that invalidation flags were not used during mapping, else we're
|
||||
// allowed to act as `GL_MAP_INVALIDATE_*` in backend
|
||||
ForbidUnsynchronizationBit = 1 << 3, // (the same description as above, but for unsynchronization)
|
||||
};
|
||||
|
||||
struct BufferChange {
|
||||
static constexpr int DEFAULT_RESERVED_DIRTY_RANGES_COUNT = 50;
|
||||
|
||||
Flags<BufferChangeBits> Bits = BufferChangeBits::None;
|
||||
VecRange1D DirtyRanges;
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class BufferObject {
|
||||
@@ -77,11 +95,12 @@ namespace MobileGL {
|
||||
Bool IsMapped() const;
|
||||
SizeT GetSize() const;
|
||||
BufferUsage GetUsage() const;
|
||||
Range1D GetDirtyRange() const;
|
||||
Range1D GetMappedRange() const;
|
||||
const SharedPtr<Data> GetDataReadOnly() const;
|
||||
Flags<BufferMappingAccessBit> GetMappingAccess() const;
|
||||
Uint GetExternalIndex() const;
|
||||
const VecRange1D& GetDirtyRanges() const;
|
||||
Flags<BufferChangeBits> GetChangeBits() const;
|
||||
|
||||
private:
|
||||
const Uint m_externalIndex = 0;
|
||||
@@ -90,7 +109,7 @@ namespace MobileGL {
|
||||
SharedPtr<Data> m_dataPtr;
|
||||
Bool m_isMapped;
|
||||
Flags<BufferMappingAccessBit> m_mappingAccess;
|
||||
Range1D m_dirtyRange;
|
||||
BufferChange m_change;
|
||||
Range1D m_mappedRange;
|
||||
Vector<Uint8> m_stagingData;
|
||||
Bool m_ownsStagingData;
|
||||
|
||||
@@ -220,6 +220,14 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
// RenderState
|
||||
Uint GLContext::GetRenderStateParametersVersion() const {
|
||||
return m_renderState.GetVersion();
|
||||
}
|
||||
|
||||
const RenderStateParameters& GLContext::GetRenderStateParameters() const {
|
||||
return m_renderState.GetAllParameters();
|
||||
}
|
||||
|
||||
void GLContext::SetViewport(IntVec4 viewport) {
|
||||
m_renderState.SetViewport(viewport);
|
||||
}
|
||||
@@ -236,6 +244,14 @@ namespace MobileGL {
|
||||
return m_renderState.IsCapabilityEnabled(cap);
|
||||
}
|
||||
|
||||
void GLContext::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) {
|
||||
m_renderState.SetCapabilityIndexed(cap, index, enabled);
|
||||
}
|
||||
|
||||
Bool GLContext::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const {
|
||||
return m_renderState.IsCapabilityEnabledIndexed(cap, index);
|
||||
}
|
||||
|
||||
void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha) {
|
||||
m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
@@ -246,6 +262,16 @@ namespace MobileGL {
|
||||
m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB,
|
||||
BlendFactor srcAlpha, BlendFactor dstAlpha) {
|
||||
m_renderState.SetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB,
|
||||
BlendFactor& srcAlpha, BlendFactor& dstAlpha) const {
|
||||
m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
void GLContext::SetDepthFunc(DepthTestFunc func) {
|
||||
m_renderState.SetDepthFunc(func);
|
||||
}
|
||||
|
||||
@@ -86,13 +86,21 @@ namespace MobileGL {
|
||||
SharedPtr<ProgramObject> GetCurrentProgram();
|
||||
|
||||
// RenderState
|
||||
Uint GetRenderStateParametersVersion() const;
|
||||
const RenderStateParameters& GetRenderStateParameters() const;
|
||||
void SetViewport(IntVec4 viewport); // x, y, width, height
|
||||
const IntVec4& GetViewport() const; // x, y, width, height
|
||||
void SetCapability(CapabilityInput cap, Bool enabled);
|
||||
Bool IsCapabilityEnabled(CapabilityInput cap) const;
|
||||
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
|
||||
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
|
||||
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
|
||||
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha);
|
||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
DepthTestFunc GetDepthFunc() const;
|
||||
void SetDepthMask(Bool flag);
|
||||
|
||||
@@ -12,41 +12,41 @@
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
// FramebufferAttachment
|
||||
FramebufferAttachment::FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level)
|
||||
// FramebufferAttachmentObject
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level)
|
||||
: m_texture(texture), m_textureLevel(level) {}
|
||||
FramebufferAttachment::FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer)
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer)
|
||||
: m_renderbuffer(renderbuffer) {}
|
||||
FramebufferAttachment::FramebufferAttachment(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
|
||||
FramebufferAttachmentObject::FramebufferAttachmentObject(Bool IsValid) : m_texture(nullptr), m_renderbuffer(nullptr) {
|
||||
m_isValid = IsValid;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsTexture() const {
|
||||
Bool FramebufferAttachmentObject::IsTexture() const {
|
||||
return m_texture != nullptr;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsRenderbuffer() const {
|
||||
Bool FramebufferAttachmentObject::IsRenderbuffer() const {
|
||||
return m_renderbuffer != nullptr;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsEmpty() const {
|
||||
Bool FramebufferAttachmentObject::IsEmpty() const {
|
||||
return m_texture == nullptr && m_renderbuffer == nullptr;
|
||||
}
|
||||
|
||||
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachment::GetTexture() const {
|
||||
SharedPtr<MG_State::GLState::ITextureObject> FramebufferAttachmentObject::GetTexture() const {
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
SharedPtr<RenderbufferObject> FramebufferAttachment::GetRenderbuffer() const {
|
||||
SharedPtr<RenderbufferObject> FramebufferAttachmentObject::GetRenderbuffer() const {
|
||||
return m_renderbuffer;
|
||||
}
|
||||
|
||||
Int FramebufferAttachment::GetTextureLevel() const {
|
||||
Int FramebufferAttachmentObject::GetTextureLevel() const {
|
||||
return m_textureLevel;
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsComplete() const {
|
||||
Bool FramebufferAttachmentObject::IsComplete() const {
|
||||
if (IsTexture()) {
|
||||
Bool complete = m_texture->IsComplete();
|
||||
return complete;
|
||||
@@ -58,7 +58,7 @@ namespace MobileGL {
|
||||
return false;
|
||||
}
|
||||
|
||||
IntVec3 FramebufferAttachment::GetSize() const {
|
||||
IntVec3 FramebufferAttachmentObject::GetSize() const {
|
||||
if (IsTexture()) {
|
||||
// TODO: get correct upload target
|
||||
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()),
|
||||
@@ -71,56 +71,55 @@ namespace MobileGL {
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
Bool FramebufferAttachment::IsValid() const {
|
||||
Bool FramebufferAttachmentObject::IsValid() const {
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
// FramebufferObject
|
||||
FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) {
|
||||
m_attachments.fill(FramebufferAttachment(false));
|
||||
m_attachmentObjects.fill(FramebufferAttachmentObject(false));
|
||||
m_drawBuffers.fill(FramebufferAttachmentType::None);
|
||||
m_drawBuffers[0] = FramebufferAttachmentType::Color0;
|
||||
m_attachmentVersions.fill(0);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture,
|
||||
int level) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(std::move(texture), level);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(std::move(texture), level);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type,
|
||||
std::shared_ptr<RenderbufferObject> renderbuffer) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(renderbuffer);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(renderbuffer);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
void FramebufferObject::Detach(FramebufferAttachmentType type) {
|
||||
m_attachments[static_cast<SizeT>(type)] = FramebufferAttachment(false);
|
||||
m_drawBuffersDirty = true;
|
||||
m_attachmentObjects[static_cast<SizeT>(type)] = FramebufferAttachmentObject(false);
|
||||
BumpAttachmentVersion(type);
|
||||
}
|
||||
|
||||
const FramebufferAttachment& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
|
||||
return m_attachments[static_cast<SizeT>(type)];
|
||||
const FramebufferAttachmentObject& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const {
|
||||
return m_attachmentObjects[static_cast<SizeT>(type)];
|
||||
}
|
||||
|
||||
const Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
|
||||
FramebufferObject::GetAllAttachments() const {
|
||||
return m_attachments;
|
||||
const FramebufferObject::FramebufferAttachmentObjectArray& FramebufferObject::GetAllAttachmentObjects() const {
|
||||
return m_attachmentObjects;
|
||||
}
|
||||
|
||||
Bool FramebufferObject::CheckCompleteness() const {
|
||||
if (m_attachments.empty()) {
|
||||
if (m_attachmentObjects.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Int width = -1, height = -1;
|
||||
Int validAttachmentCount = 0;
|
||||
for (SizeT i = 0; i < m_attachments.size(); ++i) {
|
||||
if (!m_attachments[i].IsValid()) continue;
|
||||
for (SizeT i = 0; i < m_attachmentObjects.size(); ++i) {
|
||||
if (!m_attachmentObjects[i].IsValid()) continue;
|
||||
|
||||
++validAttachmentCount;
|
||||
const auto& attachment = m_attachments[i];
|
||||
const auto& attachment = m_attachmentObjects[i];
|
||||
auto attachmentSize = attachment.GetSize();
|
||||
Int w = attachmentSize.x();
|
||||
Int h = attachmentSize.y();
|
||||
@@ -143,26 +142,22 @@ namespace MobileGL {
|
||||
|
||||
void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
|
||||
if (m_drawBuffers[index] == buffer) return;
|
||||
m_drawBuffersDirty = true;
|
||||
m_drawBuffers[index] = buffer;
|
||||
BumpAttachmentVersion(buffer);
|
||||
}
|
||||
|
||||
// void FramebufferObject::SetDrawBuffers(const Vector<FramebufferAttachmentType>& buffers) {
|
||||
// m_drawBuffers = buffers;
|
||||
// m_drawBuffersDirty = true;
|
||||
// }
|
||||
// void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) {
|
||||
//
|
||||
// }
|
||||
|
||||
const Array<FramebufferAttachmentType, FramebufferObject::MAX_DRAW_BUFFERS>& FramebufferObject::
|
||||
GetDrawBuffers() const {
|
||||
const FramebufferObject::FramebufferAttachmentArray& FramebufferObject::GetDrawBuffers() const {
|
||||
return m_drawBuffers;
|
||||
}
|
||||
|
||||
Uint FramebufferObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
}
|
||||
|
||||
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
|
||||
++m_attachmentVersions[static_cast<SizeT>(type)];
|
||||
++m_objectVersion;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -69,11 +69,12 @@ namespace MobileGL {
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class FramebufferAttachment {
|
||||
class FramebufferAttachmentObject {
|
||||
public:
|
||||
explicit FramebufferAttachment(SharedPtr<MG_State::GLState::ITextureObject> texture, Int level = 0);
|
||||
explicit FramebufferAttachment(SharedPtr<RenderbufferObject> renderbuffer);
|
||||
explicit FramebufferAttachment(Bool IsValid = true);
|
||||
explicit FramebufferAttachmentObject(SharedPtr<MG_State::GLState::ITextureObject> texture,
|
||||
Int level = 0);
|
||||
explicit FramebufferAttachmentObject(SharedPtr<RenderbufferObject> renderbuffer);
|
||||
explicit FramebufferAttachmentObject(Bool IsValid = true);
|
||||
|
||||
Bool IsTexture() const;
|
||||
Bool IsRenderbuffer() const;
|
||||
@@ -94,36 +95,51 @@ namespace MobileGL {
|
||||
|
||||
class FramebufferObject {
|
||||
public:
|
||||
using TargetEnum = FramebufferTarget;
|
||||
static constexpr Uint MAX_DRAW_BUFFERS = 8;
|
||||
|
||||
using TargetEnum = FramebufferTarget;
|
||||
using FramebufferAttachmentObjectArray =
|
||||
Array<FramebufferAttachmentObject,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
|
||||
using FramebufferAttachmentArray = Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>;
|
||||
using FramebufferAttachmentVersionArray =
|
||||
Array<Uint16, static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>;
|
||||
|
||||
FramebufferObject(Uint externalIndex);
|
||||
|
||||
void AttachTexture(FramebufferAttachmentType type, SharedPtr<ITextureObject> texture, int level = 0);
|
||||
void AttachRenderbuffer(FramebufferAttachmentType type,
|
||||
std::shared_ptr<RenderbufferObject> renderbuffer);
|
||||
void Detach(FramebufferAttachmentType type);
|
||||
const FramebufferAttachment& GetAttachment(FramebufferAttachmentType type) const;
|
||||
const Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>&
|
||||
GetAllAttachments() const;
|
||||
const FramebufferAttachmentObject& GetAttachment(FramebufferAttachmentType type) const;
|
||||
const FramebufferAttachmentObjectArray& GetAllAttachmentObjects() const;
|
||||
Bool CheckCompleteness() const;
|
||||
// aka. `buffer` as in glDrawBuffers/glReadBuffers
|
||||
void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer);
|
||||
bool DrawBuffersIsDirty() const { return m_drawBuffersDirty; }
|
||||
void ClearDrawBuffersDirtyState() { m_drawBuffersDirty = false; }
|
||||
const Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS>& GetDrawBuffers() const;
|
||||
const FramebufferAttachmentArray& GetDrawBuffers() const;
|
||||
void SetReadBuffer(FramebufferAttachmentType buf) { m_readBuffer = buf; }
|
||||
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
|
||||
|
||||
const FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
|
||||
return m_attachmentVersions;
|
||||
}
|
||||
|
||||
Uint16 GetObjectVersion() const { return m_objectVersion; }
|
||||
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
private:
|
||||
void BumpAttachmentVersion(FramebufferAttachmentType type);
|
||||
|
||||
const Uint m_externalIndex = 0;
|
||||
Array<FramebufferAttachment,
|
||||
static_cast<SizeT>(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>
|
||||
m_attachments;
|
||||
Bool m_drawBuffersDirty = false;
|
||||
Array<FramebufferAttachmentType, MAX_DRAW_BUFFERS> m_drawBuffers;
|
||||
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0;
|
||||
FramebufferAttachmentObjectArray m_attachmentObjects;
|
||||
FramebufferAttachmentVersionArray m_attachmentVersions;
|
||||
|
||||
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
|
||||
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::Color0; // ditto
|
||||
|
||||
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
|
||||
Uint16 m_objectVersion = 0;
|
||||
};
|
||||
|
||||
} // namespace GLState
|
||||
|
||||
@@ -7,168 +7,246 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "RenderState.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
RenderState::RenderState() {}
|
||||
|
||||
Uint RenderState::GetVersion() const {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
const RenderStateParameters& RenderState::GetAllParameters() const {
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
// -------------------- Rasterization --------------------
|
||||
void RenderState::SetViewport(IntVec4 viewport) {
|
||||
m_viewport = viewport;
|
||||
if (m_parameters.Viewport == viewport) return;
|
||||
|
||||
m_parameters.Viewport = viewport;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const IntVec4& RenderState::GetViewport() const {
|
||||
return m_viewport;
|
||||
return m_parameters.Viewport;
|
||||
}
|
||||
|
||||
// -------------------- Capabilities --------------------
|
||||
void RenderState::SetCapability(CapabilityInput cap, Bool enabled) {
|
||||
#define SET_CAPABILITY(capability, flag) \
|
||||
case CapabilityInput::capability: \
|
||||
if (m_parameters.capability##Enabled == flag) break; \
|
||||
m_parameters.capability##Enabled = flag; \
|
||||
++m_version; \
|
||||
break;
|
||||
|
||||
switch (cap) {
|
||||
case CapabilityInput::Blend:
|
||||
m_blendEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::DepthTest:
|
||||
m_depthTestEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::CullFace:
|
||||
m_cullFaceEnabled = enabled;
|
||||
break;
|
||||
case CapabilityInput::ScissorTest:
|
||||
m_scissorTestEnabled = enabled;
|
||||
SET_CAPABILITY(DepthTest, enabled);
|
||||
SET_CAPABILITY(CullFace, enabled);
|
||||
SET_CAPABILITY(ScissorTest, enabled);
|
||||
case CapabilityInput::Blend: {
|
||||
Bool stateChanged = false;
|
||||
for (auto& blendState : m_parameters.BlendStates) {
|
||||
if (blendState.Enabled == enabled) continue;
|
||||
blendState.Enabled = enabled;
|
||||
stateChanged = true;
|
||||
}
|
||||
if (stateChanged) ++m_version;
|
||||
break;
|
||||
}
|
||||
default: // not supported currently
|
||||
break;
|
||||
}
|
||||
#undef SET_CAPABILITY
|
||||
}
|
||||
|
||||
Bool RenderState::IsCapabilityEnabled(CapabilityInput cap) const {
|
||||
#define RETURN_CAPABILITY(capability) \
|
||||
case CapabilityInput::capability: \
|
||||
return m_parameters.capability##Enabled;
|
||||
switch (cap) {
|
||||
RETURN_CAPABILITY(DepthTest);
|
||||
RETURN_CAPABILITY(CullFace);
|
||||
RETURN_CAPABILITY(ScissorTest);
|
||||
case CapabilityInput::Blend:
|
||||
return m_blendEnabled;
|
||||
case CapabilityInput::DepthTest:
|
||||
return m_depthTestEnabled;
|
||||
case CapabilityInput::CullFace:
|
||||
return m_cullFaceEnabled;
|
||||
case CapabilityInput::ScissorTest:
|
||||
return m_scissorTestEnabled;
|
||||
return m_parameters.BlendStates[0].Enabled;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderState::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) {
|
||||
// Only for BlendState currently
|
||||
if (cap != CapabilityInput::Blend) {
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
return;
|
||||
}
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
if (m_parameters.BlendStates[index].Enabled == enabled) return;
|
||||
|
||||
m_parameters.BlendStates[index].Enabled = enabled;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Bool RenderState::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const {
|
||||
// Only for BlendState currently
|
||||
if (cap != CapabilityInput::Blend) {
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
return false;
|
||||
}
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index);
|
||||
return false;
|
||||
}
|
||||
return m_parameters.BlendStates[index].Enabled;
|
||||
}
|
||||
|
||||
// -------------------- Blending --------------------
|
||||
void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha) {
|
||||
m_srcFactorRGB = srcRGB;
|
||||
m_dstFactorRGB = dstRGB;
|
||||
m_srcFactorAlpha = srcAlpha;
|
||||
m_dstFactorAlpha = dstAlpha;
|
||||
Bool stateChanged = false;
|
||||
for (auto& blendState : m_parameters.BlendStates) {
|
||||
if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB &&
|
||||
blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) {
|
||||
continue;
|
||||
}
|
||||
blendState.SrcFactorRGB = srcRGB;
|
||||
blendState.DstFactorRGB = dstRGB;
|
||||
blendState.SrcFactorAlpha = srcAlpha;
|
||||
blendState.DstFactorAlpha = dstAlpha;
|
||||
stateChanged = true;
|
||||
}
|
||||
if (!stateChanged) return;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void RenderState::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const {
|
||||
srcRGB = m_srcFactorRGB;
|
||||
dstRGB = m_dstFactorRGB;
|
||||
srcAlpha = m_srcFactorAlpha;
|
||||
dstAlpha = m_dstFactorAlpha;
|
||||
srcRGB = m_parameters.BlendStates[0].SrcFactorRGB;
|
||||
dstRGB = m_parameters.BlendStates[0].DstFactorRGB;
|
||||
srcAlpha = m_parameters.BlendStates[0].SrcFactorAlpha;
|
||||
dstAlpha = m_parameters.BlendStates[0].DstFactorAlpha;
|
||||
}
|
||||
|
||||
void RenderState::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB,
|
||||
BlendFactor srcAlpha, BlendFactor dstAlpha) {
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
PerBufferBlendState& blendState = m_parameters.BlendStates[index];
|
||||
if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB &&
|
||||
blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) {
|
||||
return;
|
||||
}
|
||||
blendState.SrcFactorRGB = srcRGB;
|
||||
blendState.DstFactorRGB = dstRGB;
|
||||
blendState.SrcFactorAlpha = srcAlpha;
|
||||
blendState.DstFactorAlpha = dstAlpha;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void RenderState::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB,
|
||||
BlendFactor& srcAlpha, BlendFactor& dstAlpha) const {
|
||||
if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index);
|
||||
return;
|
||||
}
|
||||
srcRGB = m_parameters.BlendStates[index].SrcFactorRGB;
|
||||
dstRGB = m_parameters.BlendStates[index].DstFactorRGB;
|
||||
srcAlpha = m_parameters.BlendStates[index].SrcFactorAlpha;
|
||||
dstAlpha = m_parameters.BlendStates[index].DstFactorAlpha;
|
||||
}
|
||||
|
||||
// -------------------- Depth --------------------
|
||||
void RenderState::SetDepthFunc(DepthTestFunc func) {
|
||||
m_depthFunc = func;
|
||||
if (m_parameters.DepthFunc == func) return;
|
||||
|
||||
m_parameters.DepthFunc = func;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
DepthTestFunc RenderState::GetDepthFunc() const {
|
||||
return m_depthFunc;
|
||||
return m_parameters.DepthFunc;
|
||||
}
|
||||
|
||||
void RenderState::SetDepthMask(Bool flag) {
|
||||
m_depthMask = flag;
|
||||
if (m_parameters.DepthMask == flag) return;
|
||||
|
||||
m_parameters.DepthMask = flag;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Bool RenderState::GetDepthMask() const {
|
||||
return m_depthMask;
|
||||
return m_parameters.DepthMask;
|
||||
}
|
||||
|
||||
// -------------------- Color Mask --------------------
|
||||
void RenderState::SetColorMask(BoolVec4 mask) {
|
||||
m_colorMask = mask;
|
||||
if (m_parameters.ColorMask == mask) return;
|
||||
|
||||
m_parameters.ColorMask = mask;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const BoolVec4 RenderState::GetColorMask() const {
|
||||
return m_colorMask;
|
||||
return m_parameters.ColorMask;
|
||||
}
|
||||
|
||||
// -------------------- Clear State --------------------
|
||||
void RenderState::SetClearColor(FloatVec4 color) {
|
||||
m_clearColor = color;
|
||||
if (m_parameters.ClearColor == color) return;
|
||||
|
||||
m_parameters.ClearColor = color;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const FloatVec4& RenderState::GetClearColor() const {
|
||||
return m_clearColor;
|
||||
return m_parameters.ClearColor;
|
||||
}
|
||||
|
||||
void RenderState::SetClearDepth(Float depth) {
|
||||
m_clearDepth = depth;
|
||||
if (m_parameters.ClearDepth == depth) return;
|
||||
|
||||
m_parameters.ClearDepth = depth;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Float RenderState::GetClearDepth() const {
|
||||
return m_clearDepth;
|
||||
return m_parameters.ClearDepth;
|
||||
}
|
||||
|
||||
// -------------------- Pixel Store --------------------
|
||||
void RenderState::SetPixelStoreParam(PixelStoreParam param, Int value) {
|
||||
#define SET_PIXEL_STORE_PARAM(paramNameHead, paramNameTail, val) \
|
||||
case PixelStoreParam::paramNameHead##paramNameTail: \
|
||||
if (m_pixelStore##paramNameHead##Parameters.paramNameTail == val) break; \
|
||||
m_pixelStore##paramNameHead##Parameters.paramNameTail = val; \
|
||||
break;
|
||||
|
||||
switch (param) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
m_packParameters.Alignment = value;
|
||||
break;
|
||||
case PixelStoreParam::PackRowLength:
|
||||
m_packParameters.RowLength = value;
|
||||
break;
|
||||
case PixelStoreParam::PackImageHeight:
|
||||
m_packParameters.ImageHeight = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipPixels:
|
||||
m_packParameters.SkipPixels = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipRows:
|
||||
m_packParameters.SkipRows = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSkipImages:
|
||||
m_packParameters.SkipImages = value;
|
||||
break;
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
m_packParameters.SwapBytes = value != 0;
|
||||
break;
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
m_packParameters.LSBFirst = value != 0;
|
||||
break;
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
m_unpackParameters.Alignment = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackRowLength:
|
||||
m_unpackParameters.RowLength = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackImageHeight:
|
||||
m_unpackParameters.ImageHeight = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipPixels:
|
||||
m_unpackParameters.SkipPixels = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipRows:
|
||||
m_unpackParameters.SkipRows = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSkipImages:
|
||||
m_unpackParameters.SkipImages = value;
|
||||
break;
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
m_unpackParameters.SwapBytes = value != 0;
|
||||
MGLOG_D("%s: SwapBytes = %s", __func__, value ? "true" : "false");
|
||||
break;
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
m_unpackParameters.LSBFirst = value != 0;
|
||||
break;
|
||||
SET_PIXEL_STORE_PARAM(Pack, Alignment, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, RowLength, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, ImageHeight, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipPixels, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipRows, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SkipImages, value);
|
||||
SET_PIXEL_STORE_PARAM(Pack, SwapBytes, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Pack, LSBFirst, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, Alignment, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, RowLength, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, ImageHeight, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipPixels, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipRows, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SkipImages, value);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, SwapBytes, value != 0);
|
||||
SET_PIXEL_STORE_PARAM(Unpack, LSBFirst, value != 0);
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
|
||||
return;
|
||||
@@ -176,39 +254,26 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
Int RenderState::GetPixelStoreParam(PixelStoreParam param) const {
|
||||
#define RETURN_PIXEL_STORE_PARAM(paramNameHead, paramNameTail) \
|
||||
case PixelStoreParam::paramNameHead##paramNameTail: \
|
||||
return m_pixelStore##paramNameHead##Parameters.paramNameTail;
|
||||
switch (param) {
|
||||
case PixelStoreParam::PackAlignment:
|
||||
return m_packParameters.Alignment;
|
||||
case PixelStoreParam::PackRowLength:
|
||||
return m_packParameters.RowLength;
|
||||
case PixelStoreParam::PackImageHeight:
|
||||
return m_packParameters.ImageHeight;
|
||||
case PixelStoreParam::PackSkipPixels:
|
||||
return m_packParameters.SkipPixels;
|
||||
case PixelStoreParam::PackSkipRows:
|
||||
return m_packParameters.SkipRows;
|
||||
case PixelStoreParam::PackSkipImages:
|
||||
return m_packParameters.SkipImages;
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
return m_packParameters.SwapBytes ? 1 : 0;
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
return m_packParameters.LSBFirst ? 1 : 0;
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
return m_unpackParameters.Alignment;
|
||||
case PixelStoreParam::UnpackRowLength:
|
||||
return m_unpackParameters.RowLength;
|
||||
case PixelStoreParam::UnpackImageHeight:
|
||||
return m_unpackParameters.ImageHeight;
|
||||
case PixelStoreParam::UnpackSkipPixels:
|
||||
return m_unpackParameters.SkipPixels;
|
||||
case PixelStoreParam::UnpackSkipRows:
|
||||
return m_unpackParameters.SkipRows;
|
||||
case PixelStoreParam::UnpackSkipImages:
|
||||
return m_unpackParameters.SkipImages;
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
return m_unpackParameters.SwapBytes ? 1 : 0;
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
return m_unpackParameters.LSBFirst ? 1 : 0;
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, Alignment);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, RowLength);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, ImageHeight);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipPixels);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipRows);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SkipImages);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, SwapBytes);
|
||||
RETURN_PIXEL_STORE_PARAM(Pack, LSBFirst);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, Alignment);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, RowLength);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, ImageHeight);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipPixels);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipRows);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SkipImages);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, SwapBytes);
|
||||
RETURN_PIXEL_STORE_PARAM(Unpack, LSBFirst);
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Invalid PixelStoreParam enum: %d", static_cast<int>(param));
|
||||
return 0;
|
||||
@@ -216,25 +281,31 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
PixelStoreParameters RenderState::GetPixelStoreParameters(Bool isUnpack) const {
|
||||
return isUnpack ? m_unpackParameters : m_packParameters;
|
||||
return isUnpack ? m_pixelStoreUnpackParameters : m_pixelStorePackParameters;
|
||||
}
|
||||
|
||||
// -------------------- Cull Face --------------------
|
||||
void RenderState::SetCullFaceMode(CullFaceMode mode) {
|
||||
m_cullFaceMode = mode;
|
||||
if (m_parameters.CullFaceModeSetting == mode) return;
|
||||
|
||||
m_parameters.CullFaceModeSetting = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
CullFaceMode RenderState::GetCullFaceMode() const {
|
||||
return m_cullFaceMode;
|
||||
return m_parameters.CullFaceModeSetting;
|
||||
}
|
||||
|
||||
// --------------------- Scissor ---------------------
|
||||
void RenderState::SetScissorBox(IntVec4 box) {
|
||||
m_scissorBox = box;
|
||||
if (m_parameters.ScissorBox == box) return;
|
||||
|
||||
m_parameters.ScissorBox = box;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
const IntVec4& RenderState::GetScissorBox() const {
|
||||
return m_scissorBox;
|
||||
return m_parameters.ScissorBox;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
// End of Source File Header
|
||||
|
||||
#pragma once
|
||||
#include "MG_Util/Math/VectorTypes.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <Includes.h>
|
||||
#include <MG_Util/Math/VectorTypes.h>
|
||||
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
|
||||
|
||||
namespace MobileGL {
|
||||
enum class BlendFactor {
|
||||
@@ -53,7 +53,7 @@ namespace MobileGL {
|
||||
PackSkipPixels,
|
||||
PackSkipImages,
|
||||
PackSwapBytes,
|
||||
PackLsbFirst,
|
||||
PackLSBFirst,
|
||||
|
||||
// Unpack Parameters
|
||||
UnpackAlignment,
|
||||
@@ -63,7 +63,7 @@ namespace MobileGL {
|
||||
UnpackSkipPixels,
|
||||
UnpackSkipImages,
|
||||
UnpackSwapBytes,
|
||||
UnpackLsbFirst,
|
||||
UnpackLSBFirst,
|
||||
|
||||
PixelStoreParamCount,
|
||||
Unknown = -1
|
||||
@@ -128,12 +128,51 @@ namespace MobileGL {
|
||||
Int Alignment = 4;
|
||||
};
|
||||
|
||||
struct PerBufferBlendState {
|
||||
Bool Enabled = false;
|
||||
BlendFactor SrcFactorRGB = BlendFactor::One;
|
||||
BlendFactor DstFactorRGB = BlendFactor::Zero;
|
||||
BlendFactor SrcFactorAlpha = BlendFactor::One;
|
||||
BlendFactor DstFactorAlpha = BlendFactor::Zero;
|
||||
};
|
||||
|
||||
struct RenderStateParameters {
|
||||
// Rasterization
|
||||
IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
|
||||
// Blending
|
||||
Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates;
|
||||
|
||||
// Depth
|
||||
Bool DepthTestEnabled = false;
|
||||
DepthTestFunc DepthFunc = DepthTestFunc::Less;
|
||||
Bool DepthMask = true;
|
||||
|
||||
// Color Mask
|
||||
BoolVec4 ColorMask = BoolVec4(true, true, true, true);
|
||||
|
||||
// Clear State
|
||||
FloatVec4 ClearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Float ClearDepth = 1.0f;
|
||||
|
||||
// Cull Face
|
||||
Bool CullFaceEnabled = false;
|
||||
CullFaceMode CullFaceModeSetting = CullFaceMode::Back;
|
||||
|
||||
// Scissor
|
||||
Bool ScissorTestEnabled = false;
|
||||
IntVec4 ScissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
class RenderState {
|
||||
public:
|
||||
RenderState();
|
||||
|
||||
Uint GetVersion() const;
|
||||
const RenderStateParameters& GetAllParameters() const;
|
||||
|
||||
// Rasterization
|
||||
void SetViewport(IntVec4 viewport); // x, y, width, height
|
||||
const IntVec4& GetViewport() const; // x, y, width, height
|
||||
@@ -141,11 +180,17 @@ namespace MobileGL {
|
||||
// Capabilities
|
||||
void SetCapability(CapabilityInput cap, Bool enabled);
|
||||
Bool IsCapabilityEnabled(CapabilityInput cap) const;
|
||||
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
|
||||
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
|
||||
|
||||
// Blending
|
||||
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
|
||||
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
|
||||
BlendFactor dstAlpha);
|
||||
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
|
||||
BlendFactor& dstAlpha) const;
|
||||
|
||||
// Depth
|
||||
void SetDepthFunc(DepthTestFunc func);
|
||||
@@ -177,39 +222,12 @@ namespace MobileGL {
|
||||
const IntVec4& GetScissorBox() const; // x, y, width, height
|
||||
|
||||
private:
|
||||
// Rasterization
|
||||
IntVec4 m_viewport = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
|
||||
// Blending
|
||||
Bool m_blendEnabled = false;
|
||||
BlendFactor m_srcFactorRGB = BlendFactor::One;
|
||||
BlendFactor m_dstFactorRGB = BlendFactor::Zero;
|
||||
BlendFactor m_srcFactorAlpha = BlendFactor::One;
|
||||
BlendFactor m_dstFactorAlpha = BlendFactor::Zero;
|
||||
|
||||
// Depth
|
||||
Bool m_depthTestEnabled = false;
|
||||
DepthTestFunc m_depthFunc = DepthTestFunc::Less;
|
||||
Bool m_depthMask = true;
|
||||
|
||||
// Color Mask
|
||||
BoolVec4 m_colorMask = BoolVec4(true, true, true, true);
|
||||
|
||||
// Clear State
|
||||
FloatVec4 m_clearColor = FloatVec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Float m_clearDepth = 1.0f;
|
||||
Uint16 m_version = 0;
|
||||
RenderStateParameters m_parameters;
|
||||
|
||||
// Pixel Store
|
||||
PixelStoreParameters m_packParameters;
|
||||
PixelStoreParameters m_unpackParameters;
|
||||
|
||||
// Cull Face
|
||||
Bool m_cullFaceEnabled = false;
|
||||
CullFaceMode m_cullFaceMode = CullFaceMode::Back;
|
||||
|
||||
// Scissor
|
||||
Bool m_scissorTestEnabled = false;
|
||||
IntVec4 m_scissorBox = IntVec4(0, 0, 0, 0); // x, y, width, height
|
||||
PixelStoreParameters m_pixelStorePackParameters;
|
||||
PixelStoreParameters m_pixelStoreUnpackParameters;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -14,47 +14,77 @@ namespace MobileGL {
|
||||
SamplerObject::SamplerObject(Uint externalIndex) : m_externalIndex(externalIndex) {}
|
||||
|
||||
void SamplerObject::SetWrapS(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapS) return;
|
||||
|
||||
m_samplerParameters.wrapS = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetWrapT(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapT) return;
|
||||
|
||||
m_samplerParameters.wrapT = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetWrapR(SamplerWrapMode mode) {
|
||||
if (mode == m_samplerParameters.wrapR) return;
|
||||
|
||||
m_samplerParameters.wrapR = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMinFilter(SamplerFilterMode mode) {
|
||||
if (mode == m_samplerParameters.minFilter) return;
|
||||
|
||||
m_samplerParameters.minFilter = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMagFilter(SamplerFilterMode mode) {
|
||||
if (mode == m_samplerParameters.magFilter) return;
|
||||
|
||||
m_samplerParameters.magFilter = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetMipmapMode(SamplerMipmapMode mode) {
|
||||
if (mode == m_samplerParameters.mipmapMode) return;
|
||||
|
||||
m_samplerParameters.mipmapMode = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetLodRange(Float minLod, Float maxLod) {
|
||||
if (minLod == m_samplerParameters.minLod && maxLod == m_samplerParameters.maxLod) return;
|
||||
|
||||
if (minLod > maxLod) {
|
||||
THROW_EXCEPTION("minLod cannot be greater than maxLod");
|
||||
}
|
||||
m_samplerParameters.minLod = minLod;
|
||||
m_samplerParameters.maxLod = maxLod;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetLodBias(Float bias) {
|
||||
if (bias == m_samplerParameters.lodBias) return;
|
||||
|
||||
m_samplerParameters.lodBias = bias;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetSamplerCompareFunc(SamplerCompareFunc func) {
|
||||
if (func == m_samplerParameters.compareFunc) return;
|
||||
|
||||
m_samplerParameters.compareFunc = func;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
void SamplerObject::SetCompareMode(SamplerCompareMode mode) {
|
||||
if (mode == m_samplerParameters.compareMode) return;
|
||||
|
||||
m_samplerParameters.compareMode = mode;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
SamplerWrapMode SamplerObject::GetWrapS() const {
|
||||
@@ -108,6 +138,10 @@ namespace MobileGL {
|
||||
const SamplerParameters& SamplerObject::GetAllSamplerParameters() const {
|
||||
return m_samplerParameters;
|
||||
}
|
||||
|
||||
Uint16 SamplerObject::GetVersion() const {
|
||||
return m_version;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -98,10 +98,12 @@ namespace MobileGL {
|
||||
SamplerCompareMode GetCompareMode() const;
|
||||
SamplerCompareFunc GetSamplerCompareFunc() const;
|
||||
Uint GetExternalIndex() const;
|
||||
Uint16 GetVersion() const;
|
||||
const SamplerParameters& GetAllSamplerParameters() const;
|
||||
|
||||
private:
|
||||
const Uint m_externalIndex;
|
||||
Uint16 m_version = 0;
|
||||
SamplerParameters m_samplerParameters;
|
||||
};
|
||||
} // namespace GLState
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "TextureObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
|
||||
namespace MobileGL {
|
||||
@@ -43,7 +44,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetInternalFormat(TextureInternalFormat format) {
|
||||
if (format == m_internalFormat) return;
|
||||
|
||||
m_internalFormat = format;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint TextureObjectBase::GetExternalIndex() const {
|
||||
@@ -55,7 +59,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetBorderColor(const FloatVec4& color) {
|
||||
if (color == m_borderColor) return;
|
||||
|
||||
m_borderColor = color;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const {
|
||||
@@ -80,6 +87,8 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) {
|
||||
if (GetSwizzleParam(param) == value) return;
|
||||
|
||||
switch (param) {
|
||||
case TextureSwizzleParam::Red:
|
||||
m_swizzleParams.r() = value;
|
||||
@@ -98,9 +107,14 @@ namespace MobileGL {
|
||||
static_cast<Int>(param));
|
||||
break;
|
||||
}
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) {
|
||||
if (values == m_swizzleParams) return;
|
||||
|
||||
m_swizzleParams = values;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
const UintVec2& TextureObjectBase::GetLevelRange() const {
|
||||
@@ -108,11 +122,21 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetBaseLevel(Uint baseLevel) {
|
||||
if (baseLevel == m_levelRange.x()) return;
|
||||
|
||||
m_levelRange.x() = baseLevel;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
void TextureObjectBase::SetMaxLevel(Uint maxLevel) {
|
||||
if (maxLevel == m_levelRange.y()) return;
|
||||
|
||||
m_levelRange.y() = maxLevel;
|
||||
++m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint16 TextureObjectBase::GetTextureParamsVersion() const {
|
||||
return m_textureParamsVersion;
|
||||
}
|
||||
|
||||
Uint TextureObjectWithOneMipmap::GetMipmapLevelCount() const {
|
||||
@@ -144,11 +168,11 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void TextureObjectWithOneMipmap::MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
bool dirty) {
|
||||
Bool dirty) {
|
||||
m_textureStorage.MarkDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel, dirty);
|
||||
}
|
||||
|
||||
bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
Bool TextureObjectWithOneMipmap::IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const {
|
||||
return m_textureStorage.IsDirty(GetIndexOfTextureUploadTarget(uploadTarget), mipmapLevel);
|
||||
}
|
||||
|
||||
@@ -170,7 +194,7 @@ namespace MobileGL {
|
||||
|
||||
// For some reason mojang decided to have 0x0 in last level mipmap
|
||||
// Relaxing checks for that
|
||||
bool hadZero = false;
|
||||
Bool hadZero = false;
|
||||
for (SizeT i = 0; i < levelCount; ++i) {
|
||||
const auto& levelSize = m_textureStorage.GetTexelSize(0, i);
|
||||
if (levelSize.x() <= 0 || levelSize.y() <= 0 || levelSize.z() <= 0) {
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace MobileGL {
|
||||
virtual const UintVec2& GetLevelRange() const = 0;
|
||||
virtual void SetBaseLevel(Uint baseLevel) = 0;
|
||||
virtual void SetMaxLevel(Uint maxLevel) = 0;
|
||||
virtual Uint16 GetTextureParamsVersion() const = 0;
|
||||
|
||||
protected:
|
||||
virtual Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const = 0;
|
||||
@@ -67,7 +68,7 @@ namespace MobileGL {
|
||||
const UintVec2& GetLevelRange() const override;
|
||||
void SetBaseLevel(Uint baseLevel) override;
|
||||
void SetMaxLevel(Uint maxLevel) override;
|
||||
|
||||
Uint16 GetTextureParamsVersion() const override;
|
||||
protected:
|
||||
const Uint m_externalIndex;
|
||||
const TextureTarget m_target = TextureTarget::Unknown;
|
||||
@@ -77,6 +78,7 @@ namespace MobileGL {
|
||||
Vec4<TextureSwizzleParam> m_swizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green,
|
||||
TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};
|
||||
UintVec2 m_levelRange = {0, 1000};
|
||||
Uint16 m_textureParamsVersion = 0;
|
||||
};
|
||||
|
||||
class TextureObjectMipmap : public TextureObjectBase {
|
||||
@@ -92,8 +94,9 @@ namespace MobileGL {
|
||||
virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0;
|
||||
virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0;
|
||||
virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0;
|
||||
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0;
|
||||
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
|
||||
virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel,
|
||||
Bool dirty = true) = 0;
|
||||
virtual Bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
|
||||
};
|
||||
|
||||
class TextureObjectWithOneMipmap : public TextureObjectMipmap {
|
||||
@@ -108,7 +111,7 @@ namespace MobileGL {
|
||||
void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) override;
|
||||
void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) override;
|
||||
void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) override;
|
||||
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) override;
|
||||
void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, Bool dirty) override;
|
||||
bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const override;
|
||||
|
||||
IntVec3 GetBaseSize() const override;
|
||||
|
||||
@@ -22,20 +22,26 @@ namespace MobileGL {
|
||||
attr.Offset = 0;
|
||||
attr.Buffer = nullptr;
|
||||
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexArrayObject::EnableAttribute(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Enabled) return;
|
||||
|
||||
m_attributes[index].Enabled = true;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeSwitchVersion(index);
|
||||
}
|
||||
|
||||
void VertexArrayObject::DisableAttribute(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (!m_attributes[index].Enabled) return;
|
||||
|
||||
m_attributes[index].Enabled = false;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeSwitchVersion(index);
|
||||
}
|
||||
|
||||
Bool VertexArrayObject::IsAttributeEnabled(Uint index) const {
|
||||
@@ -47,6 +53,12 @@ namespace MobileGL {
|
||||
SizeT offset, Bool isInteger) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Size == size && m_attributes[index].Type == type &&
|
||||
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride &&
|
||||
m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < 1 || size > 4) {
|
||||
return;
|
||||
}
|
||||
@@ -59,13 +71,16 @@ namespace MobileGL {
|
||||
attr.Offset = offset;
|
||||
attr.IsInteger = isInteger;
|
||||
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
|
||||
void VertexArrayObject::BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
|
||||
if (m_attributes[index].Buffer == buffer) return;
|
||||
|
||||
m_attributes[index].Buffer = buffer;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeBufferVersion(index);
|
||||
}
|
||||
|
||||
BindingSlot<BufferObject>& VertexArrayObject::GetIndexBufferBindingSlot() {
|
||||
@@ -83,22 +98,6 @@ namespace MobileGL {
|
||||
return m_attributes;
|
||||
}
|
||||
|
||||
void VertexArrayObject::MarkAttributeDirty(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
if (std::find(m_dirtyAttributes.begin(), m_dirtyAttributes.end(), index) != m_dirtyAttributes.end()) {
|
||||
return;
|
||||
}
|
||||
m_dirtyAttributes.push_back(index);
|
||||
}
|
||||
|
||||
const Vector<Uint>& VertexArrayObject::GetDirtyAttributeIndices() const {
|
||||
return m_dirtyAttributes;
|
||||
}
|
||||
|
||||
void VertexArrayObject::ClearDirtyAttributes() {
|
||||
m_dirtyAttributes.clear();
|
||||
}
|
||||
|
||||
Uint VertexArrayObject::GetExternalIndex() const {
|
||||
return m_externalIndex;
|
||||
}
|
||||
@@ -107,13 +106,39 @@ namespace MobileGL {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
if (m_attributes[index].Divisor == divisor) return;
|
||||
m_attributes[index].Divisor = divisor;
|
||||
MarkAttributeDirty(index);
|
||||
BumpAttributeFormatVersion(index);
|
||||
}
|
||||
|
||||
Uint VertexArrayObject::GetAttributeDivisor(Uint index) const {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return 0;
|
||||
return m_attributes[index].Divisor;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeFormatVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].FormatVersion;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeBufferVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].BufferVersion;
|
||||
}
|
||||
|
||||
void VertexArrayObject::BumpAttributeSwitchVersion(Uint index) {
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return;
|
||||
++m_attributeVersions[index].SwitchVersion;
|
||||
}
|
||||
|
||||
const VertexAttributeVersion& VertexArrayObject::GetAttributeVersion(Uint index) const {
|
||||
static VertexAttributeVersion emptyVersion;
|
||||
if (index >= MAX_VERTEX_ATTRIBS) return emptyVersion;
|
||||
return m_attributeVersions[index];
|
||||
}
|
||||
|
||||
const Array<VertexAttributeVersion, VertexArrayObject::MAX_VERTEX_ATTRIBS>& VertexArrayObject::
|
||||
GetAllAttributeVersions() const {
|
||||
return m_attributeVersions;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include "../BufferState/BufferObject.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
@@ -25,6 +26,12 @@ namespace MobileGL {
|
||||
SharedPtr<BufferObject> Buffer;
|
||||
};
|
||||
|
||||
struct VertexAttributeVersion {
|
||||
Uint16 FormatVersion = 0;
|
||||
Uint16 BufferVersion = 0;
|
||||
Uint16 SwitchVersion = 0;
|
||||
};
|
||||
|
||||
class VertexArrayObject {
|
||||
public:
|
||||
static constexpr int MAX_VERTEX_ATTRIBS = 16;
|
||||
@@ -45,19 +52,22 @@ namespace MobileGL {
|
||||
const VertexAttribute& GetAttribute(Uint index) const;
|
||||
const Array<VertexAttribute, MAX_VERTEX_ATTRIBS>& GetAllAttributes() const;
|
||||
|
||||
const Vector<Uint>& GetDirtyAttributeIndices() const;
|
||||
void ClearDirtyAttributes();
|
||||
Uint GetExternalIndex() const;
|
||||
|
||||
void SetAttributeDivisor(Uint index, Uint divisor);
|
||||
Uint GetAttributeDivisor(Uint index) const;
|
||||
|
||||
const VertexAttributeVersion& GetAttributeVersion(Uint index) const;
|
||||
const Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS>& GetAllAttributeVersions() const;
|
||||
|
||||
private:
|
||||
void MarkAttributeDirty(Uint index);
|
||||
void BumpAttributeFormatVersion(Uint index);
|
||||
void BumpAttributeBufferVersion(Uint index);
|
||||
void BumpAttributeSwitchVersion(Uint index);
|
||||
|
||||
const Uint m_externalIndex = 0;
|
||||
Array<VertexAttribute, MAX_VERTEX_ATTRIBS> m_attributes;
|
||||
Vector<Uint> m_dirtyAttributes;
|
||||
Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS> m_attributeVersions;
|
||||
BindingSlot<BufferObject> m_indexBufferBindingSlot;
|
||||
};
|
||||
} // namespace GLState
|
||||
|
||||
@@ -72,7 +72,8 @@ TEST_F(BufferTest, PingPong) {
|
||||
Vector<Int> bufdata(data.size());
|
||||
memcpy(bufdata.data(), p, byteSize);
|
||||
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.end, byteSize);
|
||||
}
|
||||
@@ -122,7 +123,8 @@ TEST_F(BufferTest, AcquireMemory) {
|
||||
void* p = bufObj->AcquireMemory(false, true, false);
|
||||
memcpy(actual.data(), p, byteSize);
|
||||
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.end, sizeof(Int) * 5);
|
||||
@@ -150,7 +152,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithoutExplicit) {
|
||||
void* p = bufObj->AcquireMemory(false, true, false);
|
||||
memcpy(actual.data(), p, byteSize);
|
||||
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.end, sizeof(Int) * 4);
|
||||
}
|
||||
@@ -177,13 +180,15 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
|
||||
mappedPtr[1] = 300;
|
||||
|
||||
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.end, sizeof(Int) * 2);
|
||||
|
||||
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.end, sizeof(Int) * 2);
|
||||
|
||||
@@ -193,7 +198,8 @@ TEST_F(BufferTest, AcquireMemoryRangeWithExplicit) {
|
||||
memcpy(actual.data(), p, byteSize);
|
||||
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.end, sizeof(Int) * 2);
|
||||
}
|
||||
@@ -235,7 +241,8 @@ TEST_F(BufferTest, CopyBufferSubData) {
|
||||
|
||||
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.end, 9 * sizeof(Int));
|
||||
}
|
||||
@@ -265,7 +272,8 @@ TEST_F(BufferTest, WriteWhileMapped) {
|
||||
|
||||
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.end, byteSize);
|
||||
}
|
||||
@@ -293,7 +301,8 @@ TEST_F(BufferTest, PartialUpdate) {
|
||||
|
||||
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.end, 3 * sizeof(Int));
|
||||
}
|
||||
|
||||
@@ -30,13 +30,22 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
switch (attachment) {
|
||||
case GL_DEPTH_ATTACHMENT:
|
||||
return FramebufferAttachmentType::Depth;
|
||||
case GL_STENCIL_ATTACHMENT:
|
||||
return FramebufferAttachmentType::Stencil;
|
||||
case GL_UNKNOWN_MGL:
|
||||
default:
|
||||
return FramebufferAttachmentType::Unknown;
|
||||
case GL_NONE:
|
||||
return FramebufferAttachmentType::None;
|
||||
case GL_DEPTH_ATTACHMENT:
|
||||
return FramebufferAttachmentType::Depth;
|
||||
case GL_STENCIL_ATTACHMENT:
|
||||
return FramebufferAttachmentType::Stencil;
|
||||
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:
|
||||
return PixelStoreParam::PackSwapBytes;
|
||||
case GL_PACK_LSB_FIRST:
|
||||
return PixelStoreParam::PackLsbFirst;
|
||||
return PixelStoreParam::PackLSBFirst;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
return PixelStoreParam::UnpackAlignment;
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
@@ -101,7 +101,7 @@ namespace MobileGL {
|
||||
case GL_UNPACK_SWAP_BYTES:
|
||||
return PixelStoreParam::UnpackSwapBytes;
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
return PixelStoreParam::UnpackLsbFirst;
|
||||
return PixelStoreParam::UnpackLSBFirst;
|
||||
default:
|
||||
return PixelStoreParam::Unknown;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,20 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FramebufferAttachmentType::Depth:
|
||||
return GL_DEPTH_ATTACHMENT;
|
||||
case FramebufferAttachmentType::Stencil:
|
||||
return GL_STENCIL_ATTACHMENT;
|
||||
default:
|
||||
return GL_NONE;
|
||||
case FramebufferAttachmentType::Depth:
|
||||
return GL_DEPTH_ATTACHMENT;
|
||||
case FramebufferAttachmentType::Stencil:
|
||||
return GL_STENCIL_ATTACHMENT;
|
||||
case FramebufferAttachmentType::FrontLeft:
|
||||
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;
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
return GL_PACK_SWAP_BYTES;
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
case PixelStoreParam::PackLSBFirst:
|
||||
return GL_PACK_LSB_FIRST;
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
return GL_UNPACK_ALIGNMENT;
|
||||
@@ -101,7 +101,7 @@ namespace MobileGL {
|
||||
return GL_UNPACK_SKIP_IMAGES;
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
return GL_UNPACK_SWAP_BYTES;
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
case PixelStoreParam::UnpackLSBFirst:
|
||||
return GL_UNPACK_LSB_FIRST;
|
||||
default:
|
||||
return GL_UNKNOWN_MGL;
|
||||
|
||||
@@ -183,6 +183,36 @@ namespace MobileGL {
|
||||
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: {
|
||||
MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning "
|
||||
"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 MobileGL
|
||||
@@ -15,5 +15,7 @@ namespace MobileGL {
|
||||
TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target);
|
||||
TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat,
|
||||
TextureInputFormat format, TexturePixelDataType type);
|
||||
TextureInternalFormat ConvertInternalFormatToUnsized(TextureInternalFormat internalformat);
|
||||
|
||||
} // namespace MG_Util
|
||||
} // namespace MobileGL
|
||||
@@ -84,8 +84,8 @@ namespace MobileGL {
|
||||
return "PackSkipImages";
|
||||
case PixelStoreParam::PackSwapBytes:
|
||||
return "PackSwapBytes";
|
||||
case PixelStoreParam::PackLsbFirst:
|
||||
return "PackLsbFirst";
|
||||
case PixelStoreParam::PackLSBFirst:
|
||||
return "PackLSBFirst";
|
||||
case PixelStoreParam::UnpackAlignment:
|
||||
return "UnpackAlignment";
|
||||
case PixelStoreParam::UnpackRowLength:
|
||||
@@ -100,8 +100,8 @@ namespace MobileGL {
|
||||
return "UnpackSkipImages";
|
||||
case PixelStoreParam::UnpackSwapBytes:
|
||||
return "UnpackSwapBytes";
|
||||
case PixelStoreParam::UnpackLsbFirst:
|
||||
return "UnpackLsbFirst";
|
||||
case PixelStoreParam::UnpackLSBFirst:
|
||||
return "UnpackLSBFirst";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
@@ -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,7 +11,6 @@
|
||||
#include <Includes.h>
|
||||
|
||||
namespace MobileGL {
|
||||
|
||||
template <typename Derived, typename T, SizeT N>
|
||||
struct VecBase {
|
||||
Array<T, N> data;
|
||||
@@ -247,4 +246,15 @@ namespace MobileGL {
|
||||
return incident - normal * (2.0f * incident.Dot(normal));
|
||||
}
|
||||
} // 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
|
||||
@@ -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 sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat);
|
||||
if (sizedTextureFormatSize > 0) return sizedTextureFormatSize;
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace MobileGL {
|
||||
SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format);
|
||||
SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type);
|
||||
SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type);
|
||||
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type);
|
||||
// This should respect internal format more
|
||||
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type);
|
||||
// This should respect type more, representing data passed in
|
||||
|
||||
@@ -230,11 +230,14 @@ namespace MobileGL {
|
||||
bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector<Uint32>& inputBinary,
|
||||
Vector<uint32_t>& outputBinary) {
|
||||
using namespace spvtools;
|
||||
OptimizerOptions options;
|
||||
options.set_run_validator(false);
|
||||
|
||||
Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5);
|
||||
|
||||
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) {
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
|
||||
namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
namespace MobileGL {
|
||||
enum class PixelFormatNormalizeOptionBit : Uint {
|
||||
NoNorm16 = 1 << 0,
|
||||
None = 0,
|
||||
};
|
||||
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options,
|
||||
GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType);
|
||||
} // namespace MobileGL::MG_Util::TextureFormatProcessor
|
||||
namespace MG_Util::TextureFormatProcessor {
|
||||
void NormalizePixelFormat(GLenum internalFormat, Flags<PixelFormatNormalizeOptionBit> options,
|
||||
GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType);
|
||||
}
|
||||
} // namespace MobileGL
|
||||
@@ -145,17 +145,20 @@ namespace MobileGL {
|
||||
using TargetEnum = typename ObjectType::TargetEnum;
|
||||
|
||||
BindingSlot() : m_target((TargetEnum)0), 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; }
|
||||
|
||||
TargetEnum GetTarget() const { return m_target; }
|
||||
Uint16 GetVersion() const { return m_version; }
|
||||
|
||||
private:
|
||||
TargetEnum m_target;
|
||||
Uint16 m_version = 0;
|
||||
SharedPtr<ObjectType> m_boundObject;
|
||||
};
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ If you want to try the project right now, you’ll need to build it yourself:
|
||||
## Build Options
|
||||
|
||||
| Option | Description | Default |
|
||||
| ---------------------------- | ----------------------------------------------------- | ------- |
|
||||
|------------------------------| ----------------------------------------------------- | ------- |
|
||||
| `MOBILEGL_BUILD_TEST` | Build MobileGL tests (requires Clang) | ON |
|
||||
| `MOBILEGL_BUILD_BENCHMARK` | Build MobileGL benchmarks (requires Clang) | ON |
|
||||
| `MOBILEGL_FORCE_RELEASE_OPT` | Enable O3 and LTO in Debug build | ON |
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ android {
|
||||
|
||||
// externalNativeBuild {
|
||||
// cmake {
|
||||
// arguments "-DTRACY_ENABLE=ON"
|
||||
// arguments "-DMOBILEGL_ENABLE_TRACY=ON"
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user