mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
Merge branch 'feat/dev-es-renaming' into feat/dev-es-shittily-draw
This commit is contained in:
+3
-3
@@ -4,7 +4,7 @@ project("MobileGL")
|
|||||||
|
|
||||||
enable_language(CXX)
|
enable_language(CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
|
|||||||
|
|
||||||
set(CMAKE_ANDROID_STL_TYPE c++_static)
|
set(CMAKE_ANDROID_STL_TYPE c++_static)
|
||||||
|
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
#set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
set(PROFILING OFF)
|
set(PROFILING OFF)
|
||||||
|
|
||||||
@@ -118,4 +118,4 @@ if (PROFILING)
|
|||||||
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
|
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
|
||||||
target_link_libraries(MobileGL perfetto ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(MobileGL perfetto ${CMAKE_THREAD_LIBS_INIT})
|
||||||
target_compile_definitions(MobileGL PUBLIC PROFILING=1)
|
target_compile_definitions(MobileGL PUBLIC PROFILING=1)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ namespace MG_Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
inline const int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
inline constexpr int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
|
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
|
||||||
|
|||||||
@@ -102,6 +102,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <format>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
#include <glslang/Include/Types.h>
|
#include <glslang/Include/Types.h>
|
||||||
@@ -110,6 +111,7 @@
|
|||||||
#include <glslang/SPIRV/GlslangToSpv.h>
|
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
#include "GLES/gl32.h"
|
#include "GLES/gl32.h"
|
||||||
|
|
||||||
#include "MG_Include/UncertainBool.hpp"
|
#include "MG_Include/UncertainBool.hpp"
|
||||||
|
|||||||
@@ -38,8 +38,20 @@ namespace MG_GL::GL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BindBuffer(GLenum target, GLuint buffer) {
|
void BindBuffer(GLenum target, GLuint buffer) {
|
||||||
MG_Util::Debug::LogD("glBindBuffer, target: %d, buffer: %d", target, buffer);
|
MG_Util::Debug::LogD("glBindBuffer, target: %s, buffer: %d", MG_Util::Debug::GLEnumToString(target), buffer);
|
||||||
if (buffer != 0 && !MG_State::ValidateBufferHandle(buffer)) {
|
if (buffer != 0 &&
|
||||||
|
MG_State::ValidateGeneratedName(buffer) &&
|
||||||
|
!MG_State::ValidateAllocatedBufferHandle(buffer)) {
|
||||||
|
MG_Util::Debug::LogD("Actually creating buffer: %u", buffer);
|
||||||
|
GLenum result = MG_State::CreateBuffer(buffer);
|
||||||
|
if (result != GL_NO_ERROR) {
|
||||||
|
MG_State::SetError(result);
|
||||||
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != 0 && !MG_State::ValidateAllocatedBufferHandle(buffer)) {
|
||||||
MG_State::SetError(GL_INVALID_VALUE);
|
MG_State::SetError(GL_INVALID_VALUE);
|
||||||
MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer);
|
MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer);
|
||||||
return;
|
return;
|
||||||
@@ -52,8 +64,8 @@ namespace MG_GL::GL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
|
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
|
||||||
MG_Util::Debug::LogD("glBufferData, target: %d, size: %zd, data: %p, usage: %d",
|
MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s",
|
||||||
target, size, data, usage);
|
MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage));
|
||||||
GLenum result = MG_State::CommitBufferStorage(target, size, data, usage);
|
GLenum result = MG_State::CommitBufferStorage(target, size, data, usage);
|
||||||
if (result == GL_NO_ERROR)
|
if (result == GL_NO_ERROR)
|
||||||
return;
|
return;
|
||||||
@@ -80,9 +92,9 @@ namespace MG_GL::GL {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum result = MG_State::CreateBuffers(n, buffers);
|
GLenum result = MG_State::GenBufferNames(n, buffers);
|
||||||
if (result == GL_NO_ERROR) {
|
if (result == GL_NO_ERROR) {
|
||||||
MG_Util::Debug::LogD("Generated buffers:");
|
MG_Util::Debug::LogD("Generated buffer names:");
|
||||||
for (GLsizei i = 0; i < n; ++i) {
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
|
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
|
||||||
}
|
}
|
||||||
@@ -100,9 +112,20 @@ namespace MG_GL::GL {
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid = MG_State::ValidateBufferHandle(buffer);
|
bool isValid = MG_State::ValidateAllocatedBufferHandle(buffer);
|
||||||
// Should we report gl error here or in MG_State?
|
// Should we report gl error here or in MG_State?
|
||||||
MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid");
|
MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid");
|
||||||
return isValid ? GL_TRUE : GL_FALSE;
|
return isValid ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteBuffers(GLsizei n, const GLuint *buffers) {
|
||||||
|
MG_Util::Debug::LogD("glDeleteBuffers, n: %d, buffers: %p", n, buffers);
|
||||||
|
|
||||||
|
GLenum result = MG_State::DeleteBuffers(n, buffers);
|
||||||
|
if (result == GL_NO_ERROR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MG_State::SetError(result);
|
||||||
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ namespace MG_GL::GL {
|
|||||||
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||||
void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
|
void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
|
||||||
void GenBuffers(GLsizei n, GLuint* buffers);
|
void GenBuffers(GLsizei n, GLuint* buffers);
|
||||||
|
void DeleteBuffers(GLsizei n, const GLuint *buffers);
|
||||||
GLboolean IsBuffer(GLuint buffer);
|
GLboolean IsBuffer(GLuint buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ namespace MG_GL::GL {
|
|||||||
GLenum result = MG_State::AttachTexture2DToFramebuffer(
|
GLenum result = MG_State::AttachTexture2DToFramebuffer(
|
||||||
target, attachment, textarget, texture, level
|
target, attachment, textarget, texture, level
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Texture attachment failed: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace MG_GL::GL {
|
|||||||
void BindFramebuffer(GLenum target, GLuint framebuffer);
|
void BindFramebuffer(GLenum target, GLuint framebuffer);
|
||||||
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
GLenum CheckFramebufferStatus(GLenum target);
|
GLenum CheckFramebufferStatus(GLenum target);
|
||||||
|
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_FRAMEBUFFER_H
|
#endif //MOBILEGL_GL_FRAMEBUFFER_H
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexSubImage2D, GLenum target, GLint leve
|
|||||||
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram)
|
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateProgram) DECLARE_GL_FUNCTION_END(GLuint, CreateProgram)
|
||||||
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type)
|
DECLARE_GL_FUNCTION_HEAD(GLuint, CreateShader, GLenum type) DECLARE_GL_FUNCTION_END(GLuint, CreateShader, type)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CullFace, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CullFace, mode)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteBuffers, GLsizei n, const GLuint *buffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteBuffers, n,buffers)
|
DECLARE_GL_FUNCTION_HEAD(void, DeleteBuffers, GLsizei n, const GLuint *buffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteBuffers, n,buffers)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, DeleteFramebuffers, GLsizei n, const GLuint *framebuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteFramebuffers, n,framebuffers)
|
DECLARE_GL_FUNCTION_HEAD(void, DeleteFramebuffers, GLsizei n, const GLuint *framebuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteFramebuffers, n,framebuffers)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, DeleteProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteProgram, program)
|
DECLARE_GL_FUNCTION_HEAD(void, DeleteProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteProgram, program)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteRenderbuffers, GLsizei n, const GLuint *renderbuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteRenderbuffers, n,renderbuffers)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteRenderbuffers, GLsizei n, const GLuint *renderbuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteRenderbuffers, n,renderbuffers)
|
||||||
@@ -197,7 +197,8 @@ DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count
|
|||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x2fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x2fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x4fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x4fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x3fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x3fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter)
|
DECLARE_GL_FUNCTION_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter)
|
||||||
|
//DECLARE_GL_FUNCTION_STUB_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RenderbufferStorageMultisample, target,samples,internalformat,width,height)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RenderbufferStorageMultisample, target,samples,internalformat,width,height)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTextureLayer, target,attachment,texture,level,layer)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTextureLayer, target,attachment,texture,level,layer)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, FlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FlushMappedBufferRange, target,offset,length)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, FlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FlushMappedBufferRange, target,offset,length)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace MG_GL::GL {
|
namespace MG_GL::GL {
|
||||||
void GenVertexArrays(GLsizei n, GLuint* arrays) {
|
void GenVertexArrays(GLsizei n, GLuint* arrays) {
|
||||||
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
|
MG_Util::Debug::LogD("glGenVertexArrays, n: %d, arrays: %p", n, arrays);
|
||||||
GLenum result = MG_State::CreateVertexArrays(n, arrays);
|
GLenum result = MG_State::GenVertexArraysNames(n, arrays);
|
||||||
if (result == GL_NO_ERROR) return;
|
if (result == GL_NO_ERROR) return;
|
||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
|
|||||||
@@ -6,57 +6,80 @@
|
|||||||
|
|
||||||
#include "BufferState.h"
|
#include "BufferState.h"
|
||||||
|
|
||||||
GLenum BufferState::Create(GLuint* buffer) {
|
GLenum BufferState::GenName(GLuint *buffer) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Create called");
|
MG_Util::Debug::LogD("MG_State: Buffer: GenName");
|
||||||
if (!buffer) return GL_INVALID_VALUE;
|
if (!buffer)
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
if (!freeIds_.empty()) {
|
if (freeId_.empty()) {
|
||||||
id = *freeIds_.begin();
|
id = lastId_++;
|
||||||
freeIds_.erase(freeIds_.begin());
|
|
||||||
} else {
|
} else {
|
||||||
id = ++lastId_;
|
id = freeId_.back();
|
||||||
|
freeId_.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
*buffer = id;
|
*buffer = id;
|
||||||
BufferObject& obj = buffers_[id];
|
MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", id);
|
|
||||||
obj.generated = true;
|
|
||||||
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) {
|
GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n);
|
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n);
|
||||||
if (n < 0) return GL_INVALID_VALUE;
|
if (n < 0) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
for (GLsizei i = 0; i < n; ++i) {
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
GLenum result = Create(&buffers[i]);
|
GLenum result = GenName(&buffers[i]);
|
||||||
if (result != GL_NO_ERROR) {
|
if (result != GL_NO_ERROR) {
|
||||||
MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result);
|
MG_Util::Debug::LogE("MG_State: Buffer: GenNameN failed with error 0x%x", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully");
|
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully");
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BufferState::Bind(GLenum target, GLuint buffer) {
|
GLenum BufferState::Create(GLuint buffer) {
|
||||||
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
MG_Util::Debug::LogD("MG_State: Buffer: Create called");
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=0x%x, buffer=%u", target, buffer);
|
if (!buffer)
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
|
||||||
if (buffer != 0) {
|
if (ValidateAllocatedHandle(buffer))
|
||||||
auto it = buffers_.find(buffer);
|
return GL_INVALID_VALUE;
|
||||||
if (it == buffers_.end()) {
|
|
||||||
buffers_[buffer];
|
BufferObject& obj = buffers_[buffer];
|
||||||
} else {
|
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer);
|
||||||
BufferObject& obj = it->second;
|
obj.generated = true;
|
||||||
if (obj.target != 0 && obj.target != target) {
|
obj.dirty = true;
|
||||||
MG_Util::Debug::LogE("MG_State: Buffer: Bind can not bind a buffer to different target 0x%x, current bind target is 0x%x", target, obj.target);
|
|
||||||
return GL_INVALID_OPERATION;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
buffers_[buffer].target = target;
|
//GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) {
|
||||||
}
|
// MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n);
|
||||||
|
// if (n < 0) return GL_INVALID_VALUE;
|
||||||
|
//
|
||||||
|
// for (GLsizei i = 0; i < n; ++i) {
|
||||||
|
// GLenum result = Create(&buffers[i]);
|
||||||
|
// if (result != GL_NO_ERROR) {
|
||||||
|
// MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result);
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully");
|
||||||
|
// return GL_NO_ERROR;
|
||||||
|
//}
|
||||||
|
|
||||||
|
GLenum BufferState::Bind(GLenum target, GLuint buffer) {
|
||||||
|
// We don't handle unallocated buffer names here, just plain bind
|
||||||
|
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=%s, buffer=%u", MG_Util::Debug::GLEnumToString(target), buffer);
|
||||||
|
|
||||||
|
// if (buffer != 0 && !ValidateAllocatedHandle(buffer)) {
|
||||||
|
// MG_Util::Debug::LogE("MG_State: Buffer: Binding invalid buffer %d to %s", buffer, MG_Util::Debug::GLEnumToString(target));
|
||||||
|
// return GL_INVALID_OPERATION;
|
||||||
|
// }
|
||||||
|
|
||||||
currentBindings_[target] = buffer;
|
currentBindings_[target] = buffer;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target);
|
MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target);
|
||||||
@@ -73,7 +96,11 @@ GLenum BufferState::CommitStorage(GLenum target, GLsizeiptr size, const void* da
|
|||||||
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target);
|
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage get buffer object %u at target 0x%x",it->second,target);
|
||||||
obj.usage = usage;
|
obj.usage = usage;
|
||||||
obj.data.resize(size);
|
obj.data.resize(size);
|
||||||
if (data) memcpy(obj.data.data(), data, size);
|
if (data) {
|
||||||
|
memcpy(obj.data.data(), data, size);
|
||||||
|
obj.dataValid = true;
|
||||||
|
}
|
||||||
|
obj.dirty = true;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage buffer at target 0x%x committed storage, size = %zu, usage=0x%x", target, size, usage);
|
MG_Util::Debug::LogD("MG_State: Buffer: CommitStorage buffer at target 0x%x committed storage, size = %zu, usage=0x%x", target, size, usage);
|
||||||
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
@@ -95,8 +122,8 @@ GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** map
|
|||||||
|
|
||||||
obj.isMapped = true;
|
obj.isMapped = true;
|
||||||
*mappedPointer = obj.data.data();
|
*mappedPointer = obj.data.data();
|
||||||
obj.isMapped = true;
|
|
||||||
obj.accessMode = access;
|
obj.accessMode = access;
|
||||||
|
obj.dirty = true;
|
||||||
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -115,26 +142,45 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
|||||||
|
|
||||||
obj.isMapped = false;
|
obj.isMapped = false;
|
||||||
obj.accessMode = GL_READ_WRITE;
|
obj.accessMode = GL_READ_WRITE;
|
||||||
|
obj.dirty = true;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: ReleaseBufferMemory buffer at target 0x%x released mapped memory", target);
|
MG_Util::Debug::LogD("MG_State: Buffer: ReleaseBufferMemory buffer at target 0x%x released mapped memory", target);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferState::ValidateHandle(GLuint buffer) {
|
bool BufferState::ValidateAllocatedHandle(GLuint buffer) {
|
||||||
bool isvalid = buffers_.count(buffer) > 0;
|
bool isValid = buffers_.find(buffer) != buffers_.end();
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: ValidateHandle called on buffer %u returns %d", buffer, isvalid);
|
MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid);
|
||||||
return isvalid;
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BufferState::ValidateGeneratedName(GLuint buffer) {
|
||||||
|
bool inFreeList = std::find(freeId_.begin(), freeId_.end(), buffer) != freeId_.end();
|
||||||
|
bool lessThanLast = buffer < lastId_; // lastId_ is not generated yet
|
||||||
|
MG_Util::Debug::LogD("MG_State: Buffer: ValidateGeneratedName called on buffer %u returns %d", buffer, lessThanLast && !inFreeList);
|
||||||
|
return lessThanLast && !inFreeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferState::Delete(GLuint buffer) {
|
void BufferState::Delete(GLuint buffer) {
|
||||||
if (buffers_.erase(buffer)) {
|
buffers_.erase(buffer);
|
||||||
freeIds_.insert(buffer);
|
if (ValidateGeneratedName(buffer))
|
||||||
for (auto& [target, id] : currentBindings_) {
|
freeId_.emplace_back(buffer);
|
||||||
if (id == buffer) id = 0;
|
for (auto& [target, id] : currentBindings_) {
|
||||||
}
|
if (id == buffer) id = 0;
|
||||||
}
|
}
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer);
|
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum BufferState::DeleteN(GLsizei n, const GLuint* buffers) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Buffer: DeleteN called with n=%d", n);
|
||||||
|
if (n < 0) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
|
Delete(buffers[i]);
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Buffer: DeleteN deleted buffers successfully");
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
bool BufferState::IsValidTarget_(GLenum target) {
|
bool BufferState::IsValidTarget_(GLenum target) {
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end()));
|
MG_Util::Debug::LogD("MG_State: Buffer: IsValidTarget_ called with target=0x%x,result=%d", target, !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end()));
|
||||||
return !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end());
|
return !(MG_Constants::Buffer::VALID_TARGETS.find(target) == MG_Constants::Buffer::VALID_TARGETS.end());
|
||||||
@@ -179,7 +225,7 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
|
|||||||
case GL_BUFFER_USAGE:
|
case GL_BUFFER_USAGE:
|
||||||
*params = static_cast<GLint>(buffer.usage);
|
*params = static_cast<GLint>(buffer.usage);
|
||||||
break;
|
break;
|
||||||
MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector Query info about buffer %u succeed",buffer.target);
|
MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector Query info about buffer %u succeed", target);
|
||||||
default:
|
default:
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,34 +9,42 @@
|
|||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
class BufferState {
|
class BufferState {
|
||||||
|
template <typename K, typename V>
|
||||||
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct BufferObject {
|
struct BufferObject {
|
||||||
GLenum target = 0;
|
|
||||||
GLenum usage = GL_STATIC_DRAW;
|
GLenum usage = GL_STATIC_DRAW;
|
||||||
std::vector<GLubyte> data;
|
std::vector<GLubyte> data;
|
||||||
|
bool dataValid = false;
|
||||||
|
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
||||||
bool isMapped = false;
|
bool isMapped = false;
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
GLenum accessMode = GL_READ_WRITE;
|
GLenum accessMode = GL_READ_WRITE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
GLenum Create(GLuint* buffer);
|
GLenum GenName(GLuint* buffer);
|
||||||
GLenum CreateN(GLsizei n, GLuint* buffers);
|
GLenum GenNameN(GLsizei n, GLuint* buffers);
|
||||||
|
GLenum Create(GLuint buffer);
|
||||||
|
// GLenum CreateN(GLsizei n, GLuint* buffers);
|
||||||
GLenum Bind(GLenum target, GLuint buffer);
|
GLenum Bind(GLenum target, GLuint buffer);
|
||||||
GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer);
|
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer);
|
||||||
GLenum ReleaseBufferMemory(GLenum target);
|
GLenum ReleaseBufferMemory(GLenum target);
|
||||||
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
|
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
|
||||||
|
|
||||||
bool ValidateHandle(GLuint buffer);
|
bool ValidateAllocatedHandle(GLuint buffer);
|
||||||
|
bool ValidateGeneratedName(GLuint buffer);
|
||||||
void Delete(GLuint buffer);
|
void Delete(GLuint buffer);
|
||||||
|
GLenum DeleteN(GLsizei n, const GLuint* buffers);
|
||||||
GLuint GetCurrentBinding(GLenum target) const;
|
GLuint GetCurrentBinding(GLenum target) const;
|
||||||
|
|
||||||
std::unordered_map<GLenum, GLuint> currentBindings_;
|
unordered_map<GLenum, GLuint> currentBindings_;
|
||||||
std::unordered_map<GLuint, BufferObject> buffers_;
|
unordered_map<GLuint, BufferObject> buffers_;
|
||||||
private:
|
private:
|
||||||
std::set<GLuint> freeIds_;
|
std::vector<GLuint> freeId_;
|
||||||
GLuint lastId_ = 0;
|
GLuint lastId_ = 1;
|
||||||
|
|
||||||
static bool IsValidTarget_(GLenum target);
|
static bool IsValidTarget_(GLenum target);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
class CommonState {
|
class CommonState {
|
||||||
|
template <typename K, typename V>
|
||||||
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
public:
|
public:
|
||||||
// Viewport
|
// Viewport
|
||||||
GLint viewport[4] = {0, 0, 0, 0};
|
GLint viewport[4] = {0, 0, 0, 0};
|
||||||
@@ -17,7 +19,7 @@ public:
|
|||||||
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
||||||
|
|
||||||
// Pixel storage parameters
|
// Pixel storage parameters
|
||||||
std::unordered_map<GLenum, GLint> pixelStoreParams;
|
unordered_map<GLenum, GLint> pixelStoreParams;
|
||||||
|
|
||||||
// Blend state
|
// Blend state
|
||||||
GLenum blendSrcRGB = GL_ONE;
|
GLenum blendSrcRGB = GL_ONE;
|
||||||
@@ -35,7 +37,7 @@ public:
|
|||||||
GLboolean depthMask = GL_TRUE;
|
GLboolean depthMask = GL_TRUE;
|
||||||
|
|
||||||
// Capability enables
|
// Capability enables
|
||||||
std::unordered_map<GLenum, bool> capabilities;
|
unordered_map<GLenum, bool> capabilities;
|
||||||
|
|
||||||
CommonState();
|
CommonState();
|
||||||
|
|
||||||
|
|||||||
@@ -160,12 +160,16 @@ namespace MG_State {
|
|||||||
return MG_State_T::bufferState->ReleaseBufferMemory(target);
|
return MG_State_T::bufferState->ReleaseBufferMemory(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum CreateBuffer(GLuint* buffer) {
|
GLenum CreateBuffer(GLuint buffer) {
|
||||||
return MG_State_T::bufferState->Create(buffer);
|
return MG_State_T::bufferState->Create(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum CreateBuffers(GLsizei n, GLuint* buffers) {
|
// GLenum CreateBuffers(GLsizei n, GLuint* buffers) {
|
||||||
return MG_State_T::bufferState->CreateN(n, buffers);
|
// return MG_State_T::bufferState->CreateN(n, buffers);
|
||||||
|
// }
|
||||||
|
|
||||||
|
GLenum GenBufferNames(GLsizei n, GLuint* buffers) {
|
||||||
|
return MG_State_T::bufferState->GenNameN(n, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum BindBuffer(GLenum target, GLuint buffer) {
|
GLenum BindBuffer(GLenum target, GLuint buffer) {
|
||||||
@@ -173,6 +177,7 @@ namespace MG_State {
|
|||||||
auto* vao = MG_State_T::vertexArrayState->GetCurrentVAO();
|
auto* vao = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||||
if (!vao) return GL_INVALID_OPERATION;
|
if (!vao) return GL_INVALID_OPERATION;
|
||||||
vao->elementBuffer = (GLuint)buffer;
|
vao->elementBuffer = (GLuint)buffer;
|
||||||
|
vao->eboDirty = true;
|
||||||
}
|
}
|
||||||
return MG_State_T::bufferState->Bind(target, buffer);
|
return MG_State_T::bufferState->Bind(target, buffer);
|
||||||
}
|
}
|
||||||
@@ -181,14 +186,22 @@ namespace MG_State {
|
|||||||
return MG_State_T::bufferState->CommitStorage(target, size, data, usage);
|
return MG_State_T::bufferState->CommitStorage(target, size, data, usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidateBufferHandle(GLuint buffer) {
|
bool ValidateAllocatedBufferHandle(GLuint buffer) {
|
||||||
return MG_State_T::bufferState->ValidateHandle(buffer);
|
return MG_State_T::bufferState->ValidateAllocatedHandle(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValidateGeneratedName(GLuint buffer) {
|
||||||
|
return MG_State_T::bufferState->ValidateGeneratedName(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteBuffer(GLuint buffer) {
|
void DeleteBuffer(GLuint buffer) {
|
||||||
return MG_State_T::bufferState->Delete(buffer);
|
return MG_State_T::bufferState->Delete(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum DeleteBuffers(GLsizei n, const GLuint* buffers) {
|
||||||
|
return MG_State_T::bufferState->DeleteN(n, buffers);
|
||||||
|
}
|
||||||
|
|
||||||
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params) {
|
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params) {
|
||||||
return MG_State_T::bufferState->QueryPropertyIntVector(target, pname, params);
|
return MG_State_T::bufferState->QueryPropertyIntVector(target, pname, params);
|
||||||
}
|
}
|
||||||
@@ -206,6 +219,10 @@ namespace MG_State {
|
|||||||
return MG_State_T::vertexArrayState->CreateN(n, arrays);
|
return MG_State_T::vertexArrayState->CreateN(n, arrays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum GenVertexArraysNames(GLsizei n, GLuint* arrays) {
|
||||||
|
return MG_State_T::vertexArrayState->GenNameN(n, arrays);
|
||||||
|
}
|
||||||
|
|
||||||
GLenum EnableVertexAttribArray(GLuint index) {
|
GLenum EnableVertexAttribArray(GLuint index) {
|
||||||
return MG_State_T::vertexArrayState->EnableAttrib(index);
|
return MG_State_T::vertexArrayState->EnableAttrib(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,17 +58,21 @@ namespace MG_State {
|
|||||||
// Buffer
|
// Buffer
|
||||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr);
|
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr);
|
||||||
GLenum ReleaseBufferMemory(GLenum target);
|
GLenum ReleaseBufferMemory(GLenum target);
|
||||||
GLenum CreateBuffer(GLuint* buffer);
|
GLenum CreateBuffer(GLuint buffer);
|
||||||
GLenum CreateBuffers(GLsizei n, GLuint* buffers);
|
// GLenum CreateBuffers(GLsizei n, GLuint* buffers);
|
||||||
|
GLenum GenBufferNames(GLsizei n, GLuint* buffers);
|
||||||
GLenum BindBuffer(GLenum target, GLuint buffer);
|
GLenum BindBuffer(GLenum target, GLuint buffer);
|
||||||
GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||||
bool ValidateBufferHandle(GLuint buffer);
|
bool ValidateAllocatedBufferHandle(GLuint buffer);
|
||||||
|
bool ValidateGeneratedName(GLuint buffer);
|
||||||
void DeleteBuffer(GLuint buffer);
|
void DeleteBuffer(GLuint buffer);
|
||||||
|
GLenum DeleteBuffers(GLsizei n, const GLuint* buffers);
|
||||||
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params);
|
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params);
|
||||||
|
|
||||||
// VertexArray
|
// VertexArray
|
||||||
GLenum CreateVertexArray(GLuint* array);
|
GLenum CreateVertexArray(GLuint* array);
|
||||||
GLenum CreateVertexArrays(GLsizei n, GLuint* arrays);
|
GLenum CreateVertexArrays(GLsizei n, GLuint* arrays);
|
||||||
|
GLenum GenVertexArraysNames(GLsizei n, GLuint* arrays);
|
||||||
GLenum BindVertexArray(GLuint array);
|
GLenum BindVertexArray(GLuint array);
|
||||||
GLenum EnableVertexAttribArray(GLuint index);
|
GLenum EnableVertexAttribArray(GLuint index);
|
||||||
GLenum DisableVertexAttribArray(GLuint index);
|
GLenum DisableVertexAttribArray(GLuint index);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// TextureObject
|
// TextureObject
|
||||||
|
|
||||||
bool TextureObject::IsImmutable() const {
|
bool TextureObject::IsImmutable() const {
|
||||||
bool immutable = params.texPropertiesInt.count(GL_TEXTURE_IMMUTABLE_FORMAT);
|
bool immutable = params.texPropertiesInt.find(GL_TEXTURE_IMMUTABLE_FORMAT) != params.texPropertiesInt.end();
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: TextureObject::IsImmutable returns %d", immutable);
|
MG_Util::Debug::LogD("MG_State: Texture: TextureObject::IsImmutable returns %d", immutable);
|
||||||
return immutable;
|
return immutable;
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ bool TextureState::IsTextureGenerated(GLuint texture) {
|
|||||||
if (!isValidTexture) {
|
if (!isValidTexture) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
||||||
} else {
|
} else {
|
||||||
generated = textures.at(texture).generated;
|
generated = textures[texture].generated;
|
||||||
if (!generated) {
|
if (!generated) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture %d not generated", texture, generated);
|
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture %d not generated", texture, generated);
|
||||||
}
|
}
|
||||||
@@ -101,12 +101,12 @@ GLenum TextureState::CreateN(GLsizei n, GLuint* textures) {
|
|||||||
|
|
||||||
for (GLsizei i = 0; i < n; ++i) {
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
if (!freeIDs_.empty()) {
|
if (!freeID_.empty()) {
|
||||||
id = *freeIDs_.begin();
|
id = freeID_.back();
|
||||||
freeIDs_.erase(freeIDs_.begin());
|
freeID_.pop_back();
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
||||||
} else {
|
} else {
|
||||||
id = ++lastUsedID_;
|
id = lastUsedID_++;
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
||||||
}
|
}
|
||||||
TextureObject obj;
|
TextureObject obj;
|
||||||
@@ -258,7 +258,7 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
if (isProxyTexture) {
|
if (isProxyTexture) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D proxy texture detected");
|
MG_Util::Debug::LogD("MG_State: Texture: Upload2D proxy texture detected");
|
||||||
TextureObject& proxyTex = proxyTextures_[target];
|
TextureObject& proxyTex = proxyTextures_[target];
|
||||||
TextureParams::MipmapLevel mip{};
|
auto& mip = proxyTex.params.mipmapData[level];
|
||||||
mip.width = width;
|
mip.width = width;
|
||||||
mip.height = height;
|
mip.height = height;
|
||||||
mip.internalFormat = internalFormat;
|
mip.internalFormat = internalFormat;
|
||||||
@@ -266,19 +266,25 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
mip.type = type;
|
mip.type = type;
|
||||||
proxyTex.generated = true;
|
proxyTex.generated = true;
|
||||||
proxyTex.target = target;
|
proxyTex.target = target;
|
||||||
proxyTex.params.mipmapData[level] = mip;
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint boundTex = textureUnits_[activeTextureUnit_].GetBoundTexture(target);
|
GLuint boundTex = textureUnits_[activeTextureUnit_].GetBoundTexture(target);
|
||||||
TextureObject& tex = textures[boundTex];
|
TextureObject& tex = textures[boundTex];
|
||||||
TextureParams::MipmapLevel mip{};
|
// TextureParams::MipmapLevel mip{};
|
||||||
|
|
||||||
|
auto& mip = tex.params.mipmapData[level];
|
||||||
mip.width = width;
|
mip.width = width;
|
||||||
mip.height = height;
|
mip.height = height;
|
||||||
mip.internalFormat = internalFormat;
|
mip.internalFormat = internalFormat;
|
||||||
mip.format = format;
|
mip.format = format;
|
||||||
mip.type = type;
|
mip.type = type;
|
||||||
if (data != nullptr) {
|
mip.dirty = true;
|
||||||
|
|
||||||
|
if (data == nullptr) {
|
||||||
|
mip.hasData = false;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Texture: Upload2D data pointer is null");
|
||||||
|
} else {
|
||||||
GLint unpackSwapBytes = GetUnpackParam_(GL_UNPACK_SWAP_BYTES);
|
GLint unpackSwapBytes = GetUnpackParam_(GL_UNPACK_SWAP_BYTES);
|
||||||
GLint unpackLSBFirst = GetUnpackParam_(GL_UNPACK_LSB_FIRST);
|
GLint unpackLSBFirst = GetUnpackParam_(GL_UNPACK_LSB_FIRST);
|
||||||
GLint unpackSkipPixels = GetUnpackParam_(GL_UNPACK_SKIP_PIXELS);
|
GLint unpackSkipPixels = GetUnpackParam_(GL_UNPACK_SKIP_PIXELS);
|
||||||
@@ -288,47 +294,69 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
GLint unpackImageHeight = GetUnpackParam_(GL_UNPACK_IMAGE_HEIGHT);
|
GLint unpackImageHeight = GetUnpackParam_(GL_UNPACK_IMAGE_HEIGHT);
|
||||||
GLint unpackSkipImages = GetUnpackParam_(GL_UNPACK_SKIP_IMAGES);
|
GLint unpackSkipImages = GetUnpackParam_(GL_UNPACK_SKIP_IMAGES);
|
||||||
|
|
||||||
GLsizei rowLength = (unpackRowLength > 0) ? unpackRowLength : width;
|
bool isDefaultUnpack = (unpackSwapBytes == 0) && (unpackLSBFirst == 0) &&
|
||||||
|
(unpackSkipPixels == 0) && (unpackSkipRows == 0) &&
|
||||||
|
(unpackRowLength == 0) && (unpackAlignment == 4) &&
|
||||||
|
(unpackImageHeight == 0) && (unpackSkipImages == 0);
|
||||||
|
|
||||||
size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
||||||
size_t componentSize = GetComponentSize_(type);
|
size_t componentSize = GetComponentSize_(type);
|
||||||
|
|
||||||
size_t srcRowSize = rowLength * bytesPerPixel;
|
|
||||||
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
|
||||||
size_t srcImageStride = (unpackImageHeight > 0) ?
|
|
||||||
srcRowStride * unpackImageHeight :
|
|
||||||
srcRowStride * height;
|
|
||||||
|
|
||||||
const GLubyte* srcData = static_cast<const GLubyte*>(data);
|
|
||||||
srcData += unpackSkipImages * srcImageStride;
|
|
||||||
srcData += unpackSkipRows * srcRowStride;
|
|
||||||
srcData += unpackSkipPixels * bytesPerPixel;
|
|
||||||
|
|
||||||
size_t dstRowStride = width * bytesPerPixel;
|
size_t dstRowStride = width * bytesPerPixel;
|
||||||
size_t dstSize = dstRowStride * height;
|
size_t dstSize = dstRowStride * height;
|
||||||
mip.pixelData.resize(dstSize);
|
mip.pixelData.resize(dstSize);
|
||||||
GLubyte* dstData = mip.pixelData.data();
|
GLubyte *dstData = mip.pixelData.data();
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; ++y) {
|
if (isDefaultUnpack) {
|
||||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
const GLubyte *srcData = static_cast<const GLubyte *>(data);
|
||||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
size_t srcRowSize = width * bytesPerPixel;
|
||||||
|
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
||||||
|
|
||||||
if (unpackSwapBytes) {
|
if (srcRowStride == dstRowStride) {
|
||||||
SwapBytesForTexture_(format, type, srcRow, dstRow, width);
|
memcpy(dstData, srcData, dstSize);
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with fast path - block memcpy", dstSize);
|
||||||
|
} else {
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte *srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte *dstRow = dstData + y * dstRowStride;
|
||||||
|
memcpy(dstRow, srcRow, srcRowSize);
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with fast path - row memcpy", dstSize);
|
||||||
}
|
}
|
||||||
else if (unpackLSBFirst && componentSize == 1) {
|
} else {
|
||||||
ReverseBitOrder_(srcRow, dstRow, width * bytesPerPixel);
|
GLsizei rowLength = (unpackRowLength > 0) ? unpackRowLength : width;
|
||||||
}
|
|
||||||
else {
|
size_t srcRowSize = rowLength * bytesPerPixel;
|
||||||
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
||||||
|
size_t srcImageStride = (unpackImageHeight > 0) ?
|
||||||
|
srcRowStride * unpackImageHeight :
|
||||||
|
srcRowStride * height;
|
||||||
|
|
||||||
|
const GLubyte *srcData = static_cast<const GLubyte *>(data);
|
||||||
|
srcData += unpackSkipImages * srcImageStride;
|
||||||
|
srcData += unpackSkipRows * srcRowStride;
|
||||||
|
srcData += unpackSkipPixels * bytesPerPixel;
|
||||||
|
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte *srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte *dstRow = dstData + y * dstRowStride;
|
||||||
|
|
||||||
|
if (unpackSwapBytes) {
|
||||||
|
SwapBytesForTexture_(format, type, srcRow, dstRow, width);
|
||||||
|
} else if (unpackLSBFirst && componentSize == 1) {
|
||||||
|
ReverseBitOrder_(srcRow, dstRow, width * bytesPerPixel);
|
||||||
|
} else {
|
||||||
|
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mip.hasData = true;
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with unpack params", dstSize);
|
||||||
}
|
}
|
||||||
mip.hasData = true;
|
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D uploaded %zu bytes with unpack params", dstSize);
|
|
||||||
} else {
|
|
||||||
mip.hasData = false;
|
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D data pointer is null");
|
|
||||||
}
|
}
|
||||||
tex.params.mipmapData[level] = mip;
|
// tex.params.mipmapData[level] = mip;
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +392,7 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
|||||||
|
|
||||||
const size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
const size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
||||||
const size_t srcSize = CalculatePixelDataSize_(format, type, width, height);
|
const size_t srcSize = CalculatePixelDataSize_(format, type, width, height);
|
||||||
|
|
||||||
if (bytesPerPixel == 0) {
|
if (bytesPerPixel == 0) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: Invalid format/type combination");
|
MG_Util::Debug::LogE("MG_State: Texture: Invalid format/type combination");
|
||||||
return GL_INVALID_ENUM;
|
return GL_INVALID_ENUM;
|
||||||
@@ -402,27 +430,68 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
|||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D srcData=%p, dstData=%p", srcData, dstData);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D srcData=%p, dstData=%p", srcData, dstData);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D bytesPerPixel=%zu", bytesPerPixel);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D bytesPerPixel=%zu", bytesPerPixel);
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; ++y) {
|
// Check if fast path is applicable
|
||||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
const bool isDefaultUnpack = (unpackSwapBytes == 0) && (unpackLSBFirst == 0) &&
|
||||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
(unpackRowLength == 0) && (unpackAlignment == 4) &&
|
||||||
|
(unpackSkipPixels == 0) && (unpackSkipRows == 0) &&
|
||||||
|
(unpackImageHeight == 0) && (unpackSkipImages == 0);
|
||||||
|
|
||||||
if (unpackSwapBytes) {
|
if (isDefaultUnpack) {
|
||||||
for (GLsizei x = 0; x < width; ++x) {
|
const size_t copySize = width * bytesPerPixel;
|
||||||
const GLubyte* srcPixel = srcRow + x * bytesPerPixel;
|
|
||||||
GLubyte* dstPixel = dstRow + x * bytesPerPixel;
|
if (srcRowStride == dstRowStride) {
|
||||||
SwapPixelBytes_(format, type, srcPixel, dstPixel);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D block memcpy(dst=%p, src=%p, size=%zu) called.", dstData, srcData, width * bytesPerPixel);
|
||||||
}
|
memcpy(dstData, srcData, copySize * height);
|
||||||
} else if (unpackLSBFirst && GetComponentSize_(type) == 1) {
|
|
||||||
for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
|
||||||
dstRow[i] = ReverseBits_(srcRow[i]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
memcpy(dstRow, srcRow, copySize);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D row memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const size_t componentSize = GetComponentSize_(type);
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
|
||||||
|
if (unpackSwapBytes) {
|
||||||
|
for (GLsizei x = 0; x < width; ++x) {
|
||||||
|
SwapPixelBytes_(format, type, srcRow + x*bytesPerPixel, dstRow + x*bytesPerPixel);
|
||||||
|
}
|
||||||
|
} else if (unpackLSBFirst && componentSize == 1) {
|
||||||
|
for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
||||||
|
dstRow[i] = ReverseBits_(srcRow[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
// const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
// GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
//
|
||||||
|
// if (unpackSwapBytes) {
|
||||||
|
// for (GLsizei x = 0; x < width; ++x) {
|
||||||
|
// const GLubyte* srcPixel = srcRow + x * bytesPerPixel;
|
||||||
|
// GLubyte* dstPixel = dstRow + x * bytesPerPixel;
|
||||||
|
// SwapPixelBytes_(format, type, srcPixel, dstPixel);
|
||||||
|
// }
|
||||||
|
// } else if (unpackLSBFirst && GetComponentSize_(type) == 1) {
|
||||||
|
// for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
||||||
|
// dstRow[i] = ReverseBits_(srcRow[i]);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
// memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
mip.hasData = true;
|
mip.hasData = true;
|
||||||
|
mip.dirty = true;
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D succeeded");
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D succeeded");
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -541,7 +610,7 @@ GLenum TextureState::Delete(GLuint texture) {
|
|||||||
if (it != this->textures.end()) {
|
if (it != this->textures.end()) {
|
||||||
InvalidateTextureInAllUnits_(texture);
|
InvalidateTextureInAllUnits_(texture);
|
||||||
this->textures.erase(it);
|
this->textures.erase(it);
|
||||||
freeIDs_.insert(texture);
|
freeID_.emplace_back(texture);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Delete succeeded for texture=%u", texture);
|
MG_Util::Debug::LogD("MG_State: Texture: Delete succeeded for texture=%u", texture);
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogW("MG_State: Texture: Delete texture %u not found", texture);
|
MG_Util::Debug::LogW("MG_State: Texture: Delete texture %u not found", texture);
|
||||||
@@ -563,7 +632,7 @@ GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
|
|||||||
if (it != this->textures.end()) {
|
if (it != this->textures.end()) {
|
||||||
InvalidateTextureInAllUnits_(id);
|
InvalidateTextureInAllUnits_(id);
|
||||||
this->textures.erase(it);
|
this->textures.erase(it);
|
||||||
freeIDs_.insert(id);
|
freeID_.emplace_back(id);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: DeleteN deleted texture=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: DeleteN deleted texture=%u", id);
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogW("MG_State: Texture: DeleteN texture %u not found", id);
|
MG_Util::Debug::LogW("MG_State: Texture: DeleteN texture %u not found", id);
|
||||||
@@ -630,7 +699,7 @@ GLenum TextureState::QueryLevelPropertyIntVector(GLenum target, GLint level, GLe
|
|||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<GLuint, TextureObject>::iterator texIt;
|
unordered_map<GLuint, TextureObject>::iterator texIt;
|
||||||
|
|
||||||
if (!isProxyTexture) {
|
if (!isProxyTexture) {
|
||||||
texIt = textures.find(boundTexture);
|
texIt = textures.find(boundTexture);
|
||||||
@@ -895,7 +964,7 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tex = textures[boundTex];
|
const auto& tex = textures[boundTex];
|
||||||
|
|
||||||
if (tex.IsImmutable()) {
|
if (tex.IsImmutable()) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ texture is immutable");
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ texture is immutable");
|
||||||
@@ -934,7 +1003,7 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
|
|||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureParams::MipmapLevel& mip = mipIt->second;
|
const auto& mip = mipIt->second;
|
||||||
if (xoffset + width > mip.width || yoffset + height > mip.height) {
|
if (xoffset + width > mip.width || yoffset + height > mip.height) {
|
||||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ region out of bounds: "
|
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ region out of bounds: "
|
||||||
"x=%d+%d > %d or y=%d+%d > %d",
|
"x=%d+%d > %d or y=%d+%d > %d",
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ struct ComponentSizes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TextureParams {
|
struct TextureParams {
|
||||||
std::unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
template <typename K, typename V>
|
||||||
std::unordered_map<GLenum, GLint> texPropertiesInt;
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
|
unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||||
|
unordered_map<GLenum, GLint> texPropertiesInt;
|
||||||
struct MipmapLevel {
|
struct MipmapLevel {
|
||||||
GLsizei width = 0;
|
GLsizei width = 0;
|
||||||
GLsizei height = 0;
|
GLsizei height = 0;
|
||||||
@@ -29,8 +31,9 @@ struct TextureParams {
|
|||||||
GLenum type = GL_UNSIGNED_BYTE;
|
GLenum type = GL_UNSIGNED_BYTE;
|
||||||
std::vector<GLubyte> pixelData;
|
std::vector<GLubyte> pixelData;
|
||||||
bool hasData = false;
|
bool hasData = false;
|
||||||
|
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
||||||
};
|
};
|
||||||
std::unordered_map<GLint, MipmapLevel> mipmapData;
|
unordered_map<GLint, MipmapLevel> mipmapData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureObject {
|
class TextureObject {
|
||||||
@@ -44,23 +47,28 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class TextureUnitState {
|
class TextureUnitState {
|
||||||
|
template <typename K, typename V>
|
||||||
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
private:
|
private:
|
||||||
GLenum activeTarget = GL_TEXTURE_2D;
|
GLenum activeTarget = GL_TEXTURE_2D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::unordered_map<GLenum, GLuint> boundTextures;
|
unordered_map<GLenum, GLuint> boundTextures;
|
||||||
void Bind(GLenum target, GLuint texture);
|
void Bind(GLenum target, GLuint texture);
|
||||||
GLuint GetBoundTexture(GLenum target);
|
GLuint GetBoundTexture(GLenum target);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureState {
|
class TextureState {
|
||||||
|
template <typename K, typename V>
|
||||||
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
private:
|
private:
|
||||||
GLuint activeTextureUnit_ = 0;
|
GLuint activeTextureUnit_ = 0;
|
||||||
|
|
||||||
GLuint lastUsedID_ = 0;
|
GLuint lastUsedID_ = 1;
|
||||||
std::set<GLuint> freeIDs_;
|
// std::unordered_set<GLuint> freeIDs_;
|
||||||
|
std::vector<GLuint> freeID_;
|
||||||
|
|
||||||
std::unordered_map<GLenum, TextureObject> proxyTextures_;
|
unordered_map<GLenum, TextureObject> proxyTextures_;
|
||||||
|
|
||||||
static GLint GetUnpackParam_(GLenum pname);
|
static GLint GetUnpackParam_(GLenum pname);
|
||||||
public:
|
public:
|
||||||
@@ -68,7 +76,7 @@ public:
|
|||||||
|
|
||||||
bool IsTextureGenerated(GLuint texture);
|
bool IsTextureGenerated(GLuint texture);
|
||||||
bool IsTexture(GLuint texture);
|
bool IsTexture(GLuint texture);
|
||||||
std::unordered_map<GLuint, TextureObject> textures;
|
unordered_map<GLuint, TextureObject> textures;
|
||||||
|
|
||||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
GLenum BindUnit(GLenum textureUnit);
|
GLenum BindUnit(GLenum textureUnit);
|
||||||
|
|||||||
@@ -10,6 +10,37 @@ VertexArrayState::VertexArrayState() {
|
|||||||
vaos_[0];
|
vaos_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum VertexArrayState::GenName(GLuint *array) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: GenName");
|
||||||
|
if (!array)
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
GLuint id;
|
||||||
|
if (freeIds_.empty()) {
|
||||||
|
id = ++lastId_;
|
||||||
|
} else {
|
||||||
|
id = *freeIds_.begin();
|
||||||
|
freeIds_.erase(freeIds_.begin());
|
||||||
|
}
|
||||||
|
*array = id;
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: Generated new name %d", id);
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum VertexArrayState::GenNameN(GLsizei n, GLuint* arrays) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: GenNameN called with n=%d", n);
|
||||||
|
if (n < 0)
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
|
GLenum result = GenName(&arrays[i]);
|
||||||
|
if (result != GL_NO_ERROR) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: VAO: GenNameN failed at index %d with error 0x%x", i, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: GenNameN created %d names", n);
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum VertexArrayState::Create(GLuint* array) {
|
GLenum VertexArrayState::Create(GLuint* array) {
|
||||||
if (array == nullptr) return GL_INVALID_VALUE;
|
if (array == nullptr) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
@@ -41,24 +72,57 @@ GLenum VertexArrayState::CreateN(GLsizei n, GLuint* arrays) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLenum VertexArrayState::Bind(GLuint array) {
|
GLenum VertexArrayState::Bind(GLuint array) {
|
||||||
if (array != 0 && !vaos_.count(array)) return GL_INVALID_OPERATION;
|
MG_Util::Debug::LogD("MG_State: VAO: Bind called for %u", array);
|
||||||
|
if (array != 0) {
|
||||||
|
if (!ValidateGeneratedName(array)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: VAO: Bind invalid name %u", array);
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
auto& vao = vaos_[array];
|
||||||
|
if (!vao.generated) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: Creating VAO %u during bind", array);
|
||||||
|
vao.generated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
currentVao_ = array;
|
currentVao_ = array;
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: Bound to %u", array);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VertexArrayState::ValidateGeneratedName(GLuint array) {
|
||||||
|
if (array == 0)
|
||||||
|
return true;
|
||||||
|
bool inFreeList = freeIds_.count(array) > 0;
|
||||||
|
bool valid = (array <= lastId_) && !inFreeList;
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: ValidateGeneratedName %u: %d", array, valid);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VertexArrayState::ValidateAllocatedHandle(GLuint array) {
|
||||||
|
bool exists = vaos_.count(array) && vaos_[array].generated;
|
||||||
|
MG_Util::Debug::LogD("MG_State: VAO: ValidateAllocatedHandle %u: %d", array, exists);
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum VertexArrayState::EnableAttrib(GLuint index) {
|
GLenum VertexArrayState::EnableAttrib(GLuint index) {
|
||||||
if (currentVao_ == 0) return GL_INVALID_OPERATION;
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
GetCurrentVAO()->attribs[index].enabled = true;
|
GetCurrentVAO()->attribs[index].enabled = true;
|
||||||
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
||||||
|
|
||||||
|
GetCurrentVAO()->attribDirty = true;
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum VertexArrayState::DisableAttrib(GLuint index) {
|
GLenum VertexArrayState::DisableAttrib(GLuint index) {
|
||||||
if (currentVao_ == 0) return GL_INVALID_OPERATION;
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
GetCurrentVAO()->attribs[index].enabled = false;
|
GetCurrentVAO()->attribs[index].enabled = false;
|
||||||
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
MG_Util::Debug::LogD("Attrib vaos_[%u].attribs[%u].enabled = %d", currentVao_, index, vaos_[currentVao_].attribs[index].enabled);
|
||||||
|
|
||||||
|
GetCurrentVAO()->attribDirty = true;
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +130,8 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
|||||||
GLboolean normalized, GLsizei stride,
|
GLboolean normalized, GLsizei stride,
|
||||||
const void* pointer, bool isInteger,
|
const void* pointer, bool isInteger,
|
||||||
GLuint currentArrayBuffer) {
|
GLuint currentArrayBuffer) {
|
||||||
if (currentVao_ == 0) return GL_INVALID_OPERATION;
|
if (!ValidateAllocatedHandle(currentVao_))
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||||
|
|
||||||
VertexAttribState state;
|
VertexAttribState state;
|
||||||
@@ -81,6 +146,8 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
|||||||
state.enabled = true;
|
state.enabled = true;
|
||||||
|
|
||||||
vaos_[currentVao_].attribs[index] = state;
|
vaos_[currentVao_].attribs[index] = state;
|
||||||
|
|
||||||
|
GetCurrentVAO()->attribDirty = true;
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ struct VertexAttribState {
|
|||||||
|
|
||||||
struct VertexArrayObject {
|
struct VertexArrayObject {
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
|
bool attribDirty = false;
|
||||||
|
bool eboDirty = false;
|
||||||
GLuint elementBuffer = 0;
|
GLuint elementBuffer = 0;
|
||||||
std::unordered_map<GLuint, VertexAttribState> attribs;
|
std::unordered_map<GLuint, VertexAttribState> attribs;
|
||||||
};
|
};
|
||||||
@@ -30,6 +32,8 @@ public:
|
|||||||
VertexArrayState();
|
VertexArrayState();
|
||||||
|
|
||||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
|
GLenum GenName(GLuint* array);
|
||||||
|
GLenum GenNameN(GLsizei n, GLuint* arrays);
|
||||||
GLenum Create(GLuint* array);
|
GLenum Create(GLuint* array);
|
||||||
GLenum CreateN(GLsizei n, GLuint* arrays);
|
GLenum CreateN(GLsizei n, GLuint* arrays);
|
||||||
GLenum Bind(GLuint array);
|
GLenum Bind(GLuint array);
|
||||||
@@ -42,6 +46,8 @@ public:
|
|||||||
|
|
||||||
GLuint GetBoundElementBuffer();
|
GLuint GetBoundElementBuffer();
|
||||||
VertexArrayObject* GetCurrentVAO();
|
VertexArrayObject* GetCurrentVAO();
|
||||||
|
bool ValidateGeneratedName(GLuint array);
|
||||||
|
bool ValidateAllocatedHandle(GLuint array);
|
||||||
|
|
||||||
GLuint currentVao_ = 0;
|
GLuint currentVao_ = 0;
|
||||||
std::unordered_map<GLuint, VertexArrayObject> vaos_;
|
std::unordered_map<GLuint, VertexArrayObject> vaos_;
|
||||||
|
|||||||
@@ -1206,6 +1206,15 @@ void Log##name(const char* format, ...) { \
|
|||||||
CASE(GL_DOT3_RGBA)
|
CASE(GL_DOT3_RGBA)
|
||||||
/* texture_border_clamp */
|
/* texture_border_clamp */
|
||||||
CASE(GL_CLAMP_TO_BORDER)
|
CASE(GL_CLAMP_TO_BORDER)
|
||||||
|
/* framebuffer_status */
|
||||||
|
CASE(GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
CASE(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
|
||||||
|
CASE(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
|
||||||
|
CASE(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
|
||||||
|
CASE(GL_FRAMEBUFFER_UNSUPPORTED)
|
||||||
|
CASE(GL_COLOR_ATTACHMENT0)
|
||||||
|
CASE(GL_DEPTH_ATTACHMENT)
|
||||||
|
CASE(GL_STENCIL_ATTACHMENT)
|
||||||
/*
|
/*
|
||||||
* Miscellaneous
|
* Miscellaneous
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace 'top.mobilegl.mobilegl'
|
||||||
|
compileSdk 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk 26
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
}
|
||||||
|
proguard {
|
||||||
|
minifyEnabled true
|
||||||
|
initWith debug
|
||||||
|
}
|
||||||
|
fordebug {
|
||||||
|
debuggable true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path "CMakeLists.txt"
|
||||||
|
version "3.22.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
ndkVersion '27.2.12479018'
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user