mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +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)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
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_BUILD_TYPE Release)
|
||||
#set(CMAKE_BUILD_TYPE Release)
|
||||
|
||||
set(PROFILING OFF)
|
||||
|
||||
@@ -118,4 +118,4 @@ if (PROFILING)
|
||||
add_library(perfetto STATIC ${CMAKE_SOURCE_DIR}/3rdparty/perfetto/sdk/perfetto.cc)
|
||||
target_link_libraries(MobileGL perfetto ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_compile_definitions(MobileGL PUBLIC PROFILING=1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ namespace MG_Global {
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
inline const int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
||||
inline constexpr int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <format>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <glslang/Include/Types.h>
|
||||
@@ -110,6 +111,7 @@
|
||||
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include "GLES/gl32.h"
|
||||
|
||||
#include "MG_Include/UncertainBool.hpp"
|
||||
|
||||
@@ -38,8 +38,20 @@ namespace MG_GL::GL {
|
||||
}
|
||||
|
||||
void BindBuffer(GLenum target, GLuint buffer) {
|
||||
MG_Util::Debug::LogD("glBindBuffer, target: %d, buffer: %d", target, buffer);
|
||||
if (buffer != 0 && !MG_State::ValidateBufferHandle(buffer)) {
|
||||
MG_Util::Debug::LogD("glBindBuffer, target: %s, buffer: %d", MG_Util::Debug::GLEnumToString(target), 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_Util::Debug::LogE("Invalid buffer handle: %u", buffer);
|
||||
return;
|
||||
@@ -52,8 +64,8 @@ namespace MG_GL::GL {
|
||||
}
|
||||
|
||||
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
|
||||
MG_Util::Debug::LogD("glBufferData, target: %d, size: %zd, data: %p, usage: %d",
|
||||
target, size, data, usage);
|
||||
MG_Util::Debug::LogD("glBufferData, target: %s, size: %zd, data: %p, usage: %s",
|
||||
MG_Util::Debug::GLEnumToString(target), size, data, MG_Util::Debug::GLEnumToString(usage));
|
||||
GLenum result = MG_State::CommitBufferStorage(target, size, data, usage);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
@@ -80,9 +92,9 @@ namespace MG_GL::GL {
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum result = MG_State::CreateBuffers(n, buffers);
|
||||
GLenum result = MG_State::GenBufferNames(n, buffers);
|
||||
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) {
|
||||
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
|
||||
}
|
||||
@@ -100,9 +112,20 @@ namespace MG_GL::GL {
|
||||
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?
|
||||
MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid");
|
||||
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 GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
|
||||
void GenBuffers(GLsizei n, GLuint* buffers);
|
||||
void DeleteBuffers(GLsizei n, const GLuint *buffers);
|
||||
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(
|
||||
target, attachment, textarget, texture, level
|
||||
);
|
||||
|
||||
if (result == GL_NO_ERROR) return;
|
||||
MG_State::SetError(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 FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
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
|
||||
|
||||
@@ -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, 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, 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, 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)
|
||||
@@ -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, 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_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, 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)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace MG_GL::GL {
|
||||
void GenVertexArrays(GLsizei n, GLuint* 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;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
|
||||
@@ -6,57 +6,80 @@
|
||||
|
||||
#include "BufferState.h"
|
||||
|
||||
GLenum BufferState::Create(GLuint* buffer) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Create called");
|
||||
if (!buffer) return GL_INVALID_VALUE;
|
||||
GLenum BufferState::GenName(GLuint *buffer) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: GenName");
|
||||
if (!buffer)
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
GLuint id = 0;
|
||||
if (!freeIds_.empty()) {
|
||||
id = *freeIds_.begin();
|
||||
freeIds_.erase(freeIds_.begin());
|
||||
if (freeId_.empty()) {
|
||||
id = lastId_++;
|
||||
} else {
|
||||
id = ++lastId_;
|
||||
id = freeId_.back();
|
||||
freeId_.pop_back();
|
||||
}
|
||||
|
||||
*buffer = id;
|
||||
BufferObject& obj = buffers_[id];
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", id);
|
||||
obj.generated = true;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n);
|
||||
GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n);
|
||||
if (n < 0) return GL_INVALID_VALUE;
|
||||
|
||||
for (GLsizei i = 0; i < n; ++i) {
|
||||
GLenum result = Create(&buffers[i]);
|
||||
GLenum result = GenName(&buffers[i]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
GLenum BufferState::Bind(GLenum target, GLuint buffer) {
|
||||
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=0x%x, buffer=%u", target, buffer);
|
||||
GLenum BufferState::Create(GLuint buffer) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Create called");
|
||||
if (!buffer)
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
if (buffer != 0) {
|
||||
auto it = buffers_.find(buffer);
|
||||
if (it == buffers_.end()) {
|
||||
buffers_[buffer];
|
||||
} else {
|
||||
BufferObject& obj = it->second;
|
||||
if (obj.target != 0 && obj.target != target) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
buffers_[buffer].target = target;
|
||||
}
|
||||
if (ValidateAllocatedHandle(buffer))
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
BufferObject& obj = buffers_[buffer];
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer);
|
||||
obj.generated = true;
|
||||
obj.dirty = true;
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
//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;
|
||||
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);
|
||||
obj.usage = usage;
|
||||
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);
|
||||
|
||||
return GL_NO_ERROR;
|
||||
@@ -95,8 +122,8 @@ GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** map
|
||||
|
||||
obj.isMapped = true;
|
||||
*mappedPointer = obj.data.data();
|
||||
obj.isMapped = true;
|
||||
obj.accessMode = access;
|
||||
obj.dirty = true;
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
@@ -115,26 +142,45 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
||||
|
||||
obj.isMapped = false;
|
||||
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);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
bool BufferState::ValidateHandle(GLuint buffer) {
|
||||
bool isvalid = buffers_.count(buffer) > 0;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: ValidateHandle called on buffer %u returns %d", buffer, isvalid);
|
||||
return isvalid;
|
||||
bool BufferState::ValidateAllocatedHandle(GLuint buffer) {
|
||||
bool isValid = buffers_.find(buffer) != buffers_.end();
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, 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) {
|
||||
if (buffers_.erase(buffer)) {
|
||||
freeIds_.insert(buffer);
|
||||
for (auto& [target, id] : currentBindings_) {
|
||||
if (id == buffer) id = 0;
|
||||
}
|
||||
buffers_.erase(buffer);
|
||||
if (ValidateGeneratedName(buffer))
|
||||
freeId_.emplace_back(buffer);
|
||||
for (auto& [target, id] : currentBindings_) {
|
||||
if (id == buffer) id = 0;
|
||||
}
|
||||
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) {
|
||||
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());
|
||||
@@ -179,7 +225,7 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p
|
||||
case GL_BUFFER_USAGE:
|
||||
*params = static_cast<GLint>(buffer.usage);
|
||||
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:
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
@@ -9,34 +9,42 @@
|
||||
#include "../../../Includes.h"
|
||||
|
||||
class BufferState {
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
|
||||
public:
|
||||
struct BufferObject {
|
||||
GLenum target = 0;
|
||||
GLenum usage = GL_STATIC_DRAW;
|
||||
std::vector<GLubyte> data;
|
||||
bool dataValid = false;
|
||||
bool dirty = false; // TODO: encapsulate this with an public API to RHI
|
||||
bool isMapped = false;
|
||||
bool generated = false;
|
||||
GLenum accessMode = GL_READ_WRITE;
|
||||
};
|
||||
|
||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||
GLenum Create(GLuint* buffer);
|
||||
GLenum CreateN(GLsizei n, GLuint* buffers);
|
||||
GLenum GenName(GLuint* buffer);
|
||||
GLenum GenNameN(GLsizei n, GLuint* buffers);
|
||||
GLenum Create(GLuint buffer);
|
||||
// GLenum CreateN(GLsizei n, GLuint* buffers);
|
||||
GLenum Bind(GLenum target, GLuint buffer);
|
||||
GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer);
|
||||
GLenum ReleaseBufferMemory(GLenum target);
|
||||
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);
|
||||
GLenum DeleteN(GLsizei n, const GLuint* buffers);
|
||||
GLuint GetCurrentBinding(GLenum target) const;
|
||||
|
||||
std::unordered_map<GLenum, GLuint> currentBindings_;
|
||||
std::unordered_map<GLuint, BufferObject> buffers_;
|
||||
unordered_map<GLenum, GLuint> currentBindings_;
|
||||
unordered_map<GLuint, BufferObject> buffers_;
|
||||
private:
|
||||
std::set<GLuint> freeIds_;
|
||||
GLuint lastId_ = 0;
|
||||
std::vector<GLuint> freeId_;
|
||||
GLuint lastId_ = 1;
|
||||
|
||||
static bool IsValidTarget_(GLenum target);
|
||||
};
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "../../../Includes.h"
|
||||
|
||||
class CommonState {
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
public:
|
||||
// Viewport
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
@@ -17,7 +19,7 @@ public:
|
||||
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
||||
|
||||
// Pixel storage parameters
|
||||
std::unordered_map<GLenum, GLint> pixelStoreParams;
|
||||
unordered_map<GLenum, GLint> pixelStoreParams;
|
||||
|
||||
// Blend state
|
||||
GLenum blendSrcRGB = GL_ONE;
|
||||
@@ -35,7 +37,7 @@ public:
|
||||
GLboolean depthMask = GL_TRUE;
|
||||
|
||||
// Capability enables
|
||||
std::unordered_map<GLenum, bool> capabilities;
|
||||
unordered_map<GLenum, bool> capabilities;
|
||||
|
||||
CommonState();
|
||||
|
||||
|
||||
@@ -160,12 +160,16 @@ namespace MG_State {
|
||||
return MG_State_T::bufferState->ReleaseBufferMemory(target);
|
||||
}
|
||||
|
||||
GLenum CreateBuffer(GLuint* buffer) {
|
||||
GLenum CreateBuffer(GLuint buffer) {
|
||||
return MG_State_T::bufferState->Create(buffer);
|
||||
}
|
||||
|
||||
GLenum CreateBuffers(GLsizei n, GLuint* buffers) {
|
||||
return MG_State_T::bufferState->CreateN(n, buffers);
|
||||
// GLenum CreateBuffers(GLsizei n, GLuint* 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) {
|
||||
@@ -173,6 +177,7 @@ namespace MG_State {
|
||||
auto* vao = MG_State_T::vertexArrayState->GetCurrentVAO();
|
||||
if (!vao) return GL_INVALID_OPERATION;
|
||||
vao->elementBuffer = (GLuint)buffer;
|
||||
vao->eboDirty = true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
bool ValidateBufferHandle(GLuint buffer) {
|
||||
return MG_State_T::bufferState->ValidateHandle(buffer);
|
||||
bool ValidateAllocatedBufferHandle(GLuint buffer) {
|
||||
return MG_State_T::bufferState->ValidateAllocatedHandle(buffer);
|
||||
}
|
||||
|
||||
bool ValidateGeneratedName(GLuint buffer) {
|
||||
return MG_State_T::bufferState->ValidateGeneratedName(buffer);
|
||||
}
|
||||
|
||||
void DeleteBuffer(GLuint 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) {
|
||||
return MG_State_T::bufferState->QueryPropertyIntVector(target, pname, params);
|
||||
}
|
||||
@@ -206,6 +219,10 @@ namespace MG_State {
|
||||
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) {
|
||||
return MG_State_T::vertexArrayState->EnableAttrib(index);
|
||||
}
|
||||
|
||||
@@ -58,17 +58,21 @@ namespace MG_State {
|
||||
// Buffer
|
||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr);
|
||||
GLenum ReleaseBufferMemory(GLenum target);
|
||||
GLenum CreateBuffer(GLuint* buffer);
|
||||
GLenum CreateBuffers(GLsizei n, GLuint* buffers);
|
||||
GLenum CreateBuffer(GLuint buffer);
|
||||
// GLenum CreateBuffers(GLsizei n, GLuint* buffers);
|
||||
GLenum GenBufferNames(GLsizei n, GLuint* buffers);
|
||||
GLenum BindBuffer(GLenum target, GLuint buffer);
|
||||
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);
|
||||
GLenum DeleteBuffers(GLsizei n, const GLuint* buffers);
|
||||
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params);
|
||||
|
||||
// VertexArray
|
||||
GLenum CreateVertexArray(GLuint* array);
|
||||
GLenum CreateVertexArrays(GLsizei n, GLuint* arrays);
|
||||
GLenum GenVertexArraysNames(GLsizei n, GLuint* arrays);
|
||||
GLenum BindVertexArray(GLuint array);
|
||||
GLenum EnableVertexAttribArray(GLuint index);
|
||||
GLenum DisableVertexAttribArray(GLuint index);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// TextureObject
|
||||
|
||||
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);
|
||||
return immutable;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ bool TextureState::IsTextureGenerated(GLuint texture) {
|
||||
if (!isValidTexture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
||||
} else {
|
||||
generated = textures.at(texture).generated;
|
||||
generated = textures[texture].generated;
|
||||
if (!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) {
|
||||
GLuint id = 0;
|
||||
if (!freeIDs_.empty()) {
|
||||
id = *freeIDs_.begin();
|
||||
freeIDs_.erase(freeIDs_.begin());
|
||||
if (!freeID_.empty()) {
|
||||
id = freeID_.back();
|
||||
freeID_.pop_back();
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
||||
} else {
|
||||
id = ++lastUsedID_;
|
||||
id = lastUsedID_++;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
||||
}
|
||||
TextureObject obj;
|
||||
@@ -258,7 +258,7 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
||||
if (isProxyTexture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D proxy texture detected");
|
||||
TextureObject& proxyTex = proxyTextures_[target];
|
||||
TextureParams::MipmapLevel mip{};
|
||||
auto& mip = proxyTex.params.mipmapData[level];
|
||||
mip.width = width;
|
||||
mip.height = height;
|
||||
mip.internalFormat = internalFormat;
|
||||
@@ -266,19 +266,25 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
||||
mip.type = type;
|
||||
proxyTex.generated = true;
|
||||
proxyTex.target = target;
|
||||
proxyTex.params.mipmapData[level] = mip;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLuint boundTex = textureUnits_[activeTextureUnit_].GetBoundTexture(target);
|
||||
TextureObject& tex = textures[boundTex];
|
||||
TextureParams::MipmapLevel mip{};
|
||||
// TextureParams::MipmapLevel mip{};
|
||||
|
||||
auto& mip = tex.params.mipmapData[level];
|
||||
mip.width = width;
|
||||
mip.height = height;
|
||||
mip.internalFormat = internalFormat;
|
||||
mip.format = format;
|
||||
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 unpackLSBFirst = GetUnpackParam_(GL_UNPACK_LSB_FIRST);
|
||||
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 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 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 dstSize = dstRowStride * height;
|
||||
mip.pixelData.resize(dstSize);
|
||||
GLubyte* dstData = mip.pixelData.data();
|
||||
GLubyte *dstData = mip.pixelData.data();
|
||||
|
||||
for (GLsizei y = 0; y < height; ++y) {
|
||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||
if (isDefaultUnpack) {
|
||||
const GLubyte *srcData = static_cast<const GLubyte *>(data);
|
||||
size_t srcRowSize = width * bytesPerPixel;
|
||||
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
||||
|
||||
if (unpackSwapBytes) {
|
||||
SwapBytesForTexture_(format, type, srcRow, dstRow, width);
|
||||
if (srcRowStride == dstRowStride) {
|
||||
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) {
|
||||
ReverseBitOrder_(srcRow, dstRow, width * bytesPerPixel);
|
||||
}
|
||||
else {
|
||||
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||
} else {
|
||||
GLsizei rowLength = (unpackRowLength > 0) ? unpackRowLength : width;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -364,7 +392,7 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
||||
|
||||
const size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
||||
const size_t srcSize = CalculatePixelDataSize_(format, type, width, height);
|
||||
|
||||
|
||||
if (bytesPerPixel == 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Invalid format/type combination");
|
||||
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 bytesPerPixel=%zu", bytesPerPixel);
|
||||
|
||||
for (GLsizei y = 0; y < height; ++y) {
|
||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||
// Check if fast path is applicable
|
||||
const bool isDefaultUnpack = (unpackSwapBytes == 0) && (unpackLSBFirst == 0) &&
|
||||
(unpackRowLength == 0) && (unpackAlignment == 4) &&
|
||||
(unpackSkipPixels == 0) && (unpackSkipRows == 0) &&
|
||||
(unpackImageHeight == 0) && (unpackSkipImages == 0);
|
||||
|
||||
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]);
|
||||
}
|
||||
if (isDefaultUnpack) {
|
||||
const size_t copySize = width * bytesPerPixel;
|
||||
|
||||
if (srcRowStride == dstRowStride) {
|
||||
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 {
|
||||
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);
|
||||
for (GLsizei y = 0; y < height; ++y) {
|
||||
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.dirty = true;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D succeeded");
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
@@ -541,7 +610,7 @@ GLenum TextureState::Delete(GLuint texture) {
|
||||
if (it != this->textures.end()) {
|
||||
InvalidateTextureInAllUnits_(texture);
|
||||
this->textures.erase(it);
|
||||
freeIDs_.insert(texture);
|
||||
freeID_.emplace_back(texture);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Delete succeeded for texture=%u", texture);
|
||||
} else {
|
||||
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()) {
|
||||
InvalidateTextureInAllUnits_(id);
|
||||
this->textures.erase(it);
|
||||
freeIDs_.insert(id);
|
||||
freeID_.emplace_back(id);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: DeleteN deleted texture=%u", id);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
std::unordered_map<GLuint, TextureObject>::iterator texIt;
|
||||
unordered_map<GLuint, TextureObject>::iterator texIt;
|
||||
|
||||
if (!isProxyTexture) {
|
||||
texIt = textures.find(boundTexture);
|
||||
@@ -895,7 +964,7 @@ GLenum TextureState::CheckUpdatingTextureRegion2DValidity_(GLenum target, GLint
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto tex = textures[boundTex];
|
||||
const auto& tex = textures[boundTex];
|
||||
|
||||
if (tex.IsImmutable()) {
|
||||
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;
|
||||
}
|
||||
|
||||
TextureParams::MipmapLevel& mip = mipIt->second;
|
||||
const auto& mip = mipIt->second;
|
||||
if (xoffset + width > mip.width || yoffset + height > mip.height) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUpdatingTextureRegion2DValidity_ region out of bounds: "
|
||||
"x=%d+%d > %d or y=%d+%d > %d",
|
||||
|
||||
@@ -19,8 +19,10 @@ struct ComponentSizes {
|
||||
};
|
||||
|
||||
struct TextureParams {
|
||||
std::unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||
std::unordered_map<GLenum, GLint> texPropertiesInt;
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||
unordered_map<GLenum, GLint> texPropertiesInt;
|
||||
struct MipmapLevel {
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
@@ -29,8 +31,9 @@ struct TextureParams {
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
std::vector<GLubyte> pixelData;
|
||||
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 {
|
||||
@@ -44,23 +47,28 @@ public:
|
||||
};
|
||||
|
||||
class TextureUnitState {
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
private:
|
||||
GLenum activeTarget = GL_TEXTURE_2D;
|
||||
|
||||
public:
|
||||
std::unordered_map<GLenum, GLuint> boundTextures;
|
||||
unordered_map<GLenum, GLuint> boundTextures;
|
||||
void Bind(GLenum target, GLuint texture);
|
||||
GLuint GetBoundTexture(GLenum target);
|
||||
};
|
||||
|
||||
class TextureState {
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
private:
|
||||
GLuint activeTextureUnit_ = 0;
|
||||
|
||||
GLuint lastUsedID_ = 0;
|
||||
std::set<GLuint> freeIDs_;
|
||||
GLuint lastUsedID_ = 1;
|
||||
// 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);
|
||||
public:
|
||||
@@ -68,7 +76,7 @@ public:
|
||||
|
||||
bool IsTextureGenerated(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
|
||||
GLenum BindUnit(GLenum textureUnit);
|
||||
|
||||
@@ -10,6 +10,37 @@ VertexArrayState::VertexArrayState() {
|
||||
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) {
|
||||
if (array == nullptr) return GL_INVALID_VALUE;
|
||||
|
||||
@@ -41,24 +72,57 @@ GLenum VertexArrayState::CreateN(GLsizei n, GLuint* arrays) {
|
||||
}
|
||||
|
||||
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;
|
||||
MG_Util::Debug::LogD("MG_State: VAO: Bound to %u", array);
|
||||
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) {
|
||||
if (currentVao_ == 0) return GL_INVALID_OPERATION;
|
||||
if (!ValidateAllocatedHandle(currentVao_))
|
||||
return GL_INVALID_OPERATION;
|
||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
||||
GetCurrentVAO()->attribs[index].enabled = true;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
GetCurrentVAO()->attribs[index].enabled = false;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -66,7 +130,8 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
GLboolean normalized, GLsizei stride,
|
||||
const void* pointer, bool isInteger,
|
||||
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;
|
||||
|
||||
VertexAttribState state;
|
||||
@@ -81,6 +146,8 @@ GLenum VertexArrayState::SetAttribPointer(GLuint index, GLint size, GLenum type,
|
||||
state.enabled = true;
|
||||
|
||||
vaos_[currentVao_].attribs[index] = state;
|
||||
|
||||
GetCurrentVAO()->attribDirty = true;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ struct VertexAttribState {
|
||||
|
||||
struct VertexArrayObject {
|
||||
bool generated = false;
|
||||
bool attribDirty = false;
|
||||
bool eboDirty = false;
|
||||
GLuint elementBuffer = 0;
|
||||
std::unordered_map<GLuint, VertexAttribState> attribs;
|
||||
};
|
||||
@@ -30,6 +32,8 @@ public:
|
||||
VertexArrayState();
|
||||
|
||||
// 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 CreateN(GLsizei n, GLuint* arrays);
|
||||
GLenum Bind(GLuint array);
|
||||
@@ -42,6 +46,8 @@ public:
|
||||
|
||||
GLuint GetBoundElementBuffer();
|
||||
VertexArrayObject* GetCurrentVAO();
|
||||
bool ValidateGeneratedName(GLuint array);
|
||||
bool ValidateAllocatedHandle(GLuint array);
|
||||
|
||||
GLuint currentVao_ = 0;
|
||||
std::unordered_map<GLuint, VertexArrayObject> vaos_;
|
||||
|
||||
@@ -1206,6 +1206,15 @@ void Log##name(const char* format, ...) { \
|
||||
CASE(GL_DOT3_RGBA)
|
||||
/* texture_border_clamp */
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -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