mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
Merge branch 'Feat/dev-es-shittily-draw' into dev-es without ShittilyDraw
# Conflict: # MG/Includes.h # Changes: # Remove ShittilyDraw, ready to implement MG_RHI... # Update progress.
This commit is contained in:
+2
-2
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
+33
-24
@@ -5,6 +5,12 @@
|
||||
#ifndef MOBILEGL_CONSTANTS_H
|
||||
#define MOBILEGL_CONSTANTS_H
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <GL/gl.h>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define __ANDROID_API__ 26
|
||||
#endif
|
||||
@@ -15,10 +21,13 @@
|
||||
#define MG_EXPORT extern "C" __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <GL/gl.h>
|
||||
namespace ankerl {
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
|
||||
template <typename T>
|
||||
using unordered_set = ankerl::unordered_dense::set<T>;
|
||||
}
|
||||
|
||||
namespace MG_Constants {
|
||||
namespace Common {
|
||||
@@ -30,7 +39,7 @@ namespace MG_Constants {
|
||||
}
|
||||
|
||||
namespace Blend {
|
||||
static const std::unordered_set<GLenum> VALID_FACTORS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_FACTORS = {
|
||||
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
|
||||
@@ -39,51 +48,51 @@ namespace MG_Constants {
|
||||
}
|
||||
|
||||
namespace Depth {
|
||||
static const std::unordered_set<GLenum> VALID_FUNCS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_FUNCS = {
|
||||
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
|
||||
}; // OpenGL 3
|
||||
}
|
||||
|
||||
namespace CommonState {
|
||||
static const std::unordered_set<GLenum> VALID_CAPS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_CAPS = {
|
||||
GL_BLEND, GL_DEPTH_TEST, GL_STENCIL_TEST, GL_SCISSOR_TEST, GL_CULL_FACE,
|
||||
GL_POLYGON_OFFSET_FILL, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_SAMPLE_COVERAGE
|
||||
}; // OpenGL 3
|
||||
}
|
||||
|
||||
namespace Framebuffer {
|
||||
static const std::unordered_set<GLenum> VALID_ATTACHMENTS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_ATTACHMENTS = {
|
||||
GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
|
||||
GL_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHMENT
|
||||
}; // OpenGL 3
|
||||
|
||||
static const std::unordered_set<GLenum> VALID_TARGETS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
||||
GL_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER
|
||||
}; // OpenGL 3
|
||||
|
||||
static const std::unordered_set<GLenum> VALID_ACCESS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
|
||||
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||
}; // OpenGL 3
|
||||
}
|
||||
|
||||
namespace Buffer {
|
||||
static const std::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
||||
GL_BUFFER_ACCESS, GL_BUFFER_MAPPED, GL_BUFFER_SIZE, GL_BUFFER_USAGE
|
||||
}; // OpenGL 3
|
||||
|
||||
static const std::unordered_set<GLenum> VALID_TARGETS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
||||
GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
GL_PIXEL_PACK_BUFFER, GL_PIXEL_UNPACK_BUFFER, GL_TEXTURE_BUFFER,
|
||||
GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER
|
||||
}; // OpenGL 3
|
||||
|
||||
static const std::unordered_set<GLenum> VALID_ACCESS = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_ACCESS = {
|
||||
GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||
}; // OpenGL 3
|
||||
}
|
||||
|
||||
namespace PixelStore {
|
||||
static const std::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = {
|
||||
static const ankerl::unordered_map<GLenum, GLint> DEFAULT_VALUES_MAP = {
|
||||
{GL_PACK_SWAP_BYTES, GL_FALSE},
|
||||
{GL_PACK_LSB_FIRST, GL_FALSE},
|
||||
{GL_PACK_ROW_LENGTH, 0},
|
||||
@@ -102,7 +111,7 @@ namespace MG_Constants {
|
||||
{GL_UNPACK_ALIGNMENT, 4}
|
||||
}; // OpenGL 3
|
||||
|
||||
static const std::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
||||
static const ankerl::unordered_set<GLenum> VALID_PARAM_NAMES = {
|
||||
GL_PACK_SWAP_BYTES, GL_PACK_LSB_FIRST, GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT,
|
||||
GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_IMAGES, GL_PACK_ALIGNMENT,
|
||||
GL_UNPACK_SWAP_BYTES, GL_UNPACK_LSB_FIRST, GL_UNPACK_ROW_LENGTH,
|
||||
@@ -116,18 +125,18 @@ namespace MG_Constants {
|
||||
inline const GLuint MAX_TEXTURE_UNITS = 80;
|
||||
const GLsizei MAX_TEXTURE_SIZE = 32768;
|
||||
const GLsizei MAX_ARRAY_LAYERS = 256;
|
||||
inline const std::unordered_set<GLenum> VALID_TARGETS = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_TARGETS = {
|
||||
GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D, GL_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_1D_ARRAY,
|
||||
GL_TEXTURE_RECTANGLE, GL_PROXY_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_PROXY_TEXTURE_CUBE_MAP
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::unordered_set<GLenum> VALID_FORMATS = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_FORMATS = {
|
||||
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::unordered_set<GLenum> VALID_INTERNAL_FORMATS = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_INTERNAL_FORMATS = {
|
||||
GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
|
||||
GL_RGBA32F, GL_RGBA32I, GL_RGBA32UI, GL_RGBA16, GL_RGBA16F, GL_RGBA16I,
|
||||
GL_RGBA16UI, GL_RGBA8, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2, GL_RGB10_A2UI,
|
||||
@@ -137,12 +146,12 @@ namespace MG_Constants {
|
||||
GL_RGB32F, GL_RGB32I, GL_RGB32UI, GL_RGB16_SNORM, GL_RGB16F, GL_RGB16I, GL_RGB16UI,
|
||||
GL_RGB16, GL_RGB8_SNORM, GL_RGB8, GL_RGB8I, GL_RGB8UI, GL_SRGB8, GL_RGB9_E5,
|
||||
GL_RG16_SNORM, GL_RG8_SNORM, GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_SIGNED_RG_RGTC2,
|
||||
GL_R16_SNORM, GL_R8_SNORM, GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_SIGNED_RED_RGTC1,
|
||||
GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, GL_DEPTH32F_STENCIL8,
|
||||
GL_DEPTH24_STENCIL8
|
||||
GL_R16_SNORM, GL_R8_SNORM, GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_SIGNED_RED_RGTC1,
|
||||
GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
|
||||
GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::unordered_set<GLenum> VALID_TYPES = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_TYPES = {
|
||||
GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
|
||||
GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5,
|
||||
GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
|
||||
@@ -150,14 +159,14 @@ namespace MG_Constants {
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_TEXTURE_PARAM_NAMES = {
|
||||
GL_TEXTURE_BASE_LEVEL, GL_TEXTURE_COMPARE_FUNC, GL_TEXTURE_COMPARE_MODE, GL_TEXTURE_MIN_FILTER,
|
||||
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MAX_LEVEL, GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G,
|
||||
GL_TEXTURE_SWIZZLE_B, GL_TEXTURE_SWIZZLE_A, GL_TEXTURE_SWIZZLE_RGBA, GL_TEXTURE_WRAP_S,
|
||||
GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R, GL_TEXTURE_LOD_BIAS, GL_TEXTURE_MIN_LOD, GL_TEXTURE_MAX_LOD, GL_TEXTURE_BORDER_COLOR
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
|
||||
inline const ankerl::unordered_set<GLenum> VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES = {
|
||||
GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH, GL_TEXTURE_INTERNAL_FORMAT,
|
||||
GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE,
|
||||
GL_TEXTURE_DEPTH_SIZE, GL_TEXTURE_COMPRESSED, GL_TEXTURE_COMPRESSED_IMAGE_SIZE
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ namespace MG_Global {
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
inline const int LogLevel = MG_Constants::Common::LOG_LEVEL_DEBUG;
|
||||
inline constexpr int LogLevel = MG_Constants::Common::LOG_LEVEL_INFO;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
inline const char* LOG_FILE_PATH = "/sdcard/MG/latest.log";
|
||||
|
||||
+3
-1
@@ -100,6 +100,7 @@
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <format>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <glslang/Include/Types.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
@@ -107,7 +108,8 @@
|
||||
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include "GLES3/gl32.h"
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include <GLES3/gl32.h>
|
||||
|
||||
#include "MG_Include/UncertainBool.hpp"
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ std::atomic<uintptr_t> g_nextSurfaceId{1};
|
||||
EGLenum g_currentAPI = EGL_OPENGL_ES_API;
|
||||
|
||||
std::mutex g_globalMutex;
|
||||
std::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||
std::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||
std::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||
ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||
ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||
ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||
EGLint g_lastError = EGL_SUCCESS;
|
||||
|
||||
thread_local EGLContext tls_currentContext = EGL_NO_CONTEXT;
|
||||
|
||||
@@ -69,9 +69,9 @@ extern std::atomic<uintptr_t> g_nextSurfaceId;
|
||||
extern EGLenum g_currentAPI;
|
||||
|
||||
extern std::mutex g_globalMutex;
|
||||
extern std::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||
extern std::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||
extern std::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||
extern ankerl::unordered_map<EGLDisplay, VulkanDisplay> g_displays;
|
||||
extern ankerl::unordered_map<EGLSurface, VulkanSurface> g_surfaces;
|
||||
extern ankerl::unordered_map<EGLContext, VulkanContext> g_contexts;
|
||||
extern EGLint g_lastError;
|
||||
|
||||
extern thread_local EGLContext tls_currentContext;
|
||||
|
||||
@@ -5,41 +5,98 @@
|
||||
#include "GL_Buffer.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
|
||||
GLbitfield access) {
|
||||
MG_Util::Debug::LogD("glMapBufferRange, target: %s, offset: %lld, length: %lld, access: 0x%X",
|
||||
MG_Util::Debug::GLEnumToString(target),
|
||||
static_cast<long long>(offset),
|
||||
static_cast<long long>(length),
|
||||
access);
|
||||
void* mappedPointer = nullptr;
|
||||
GLenum result = MG_State::AcquireBufferMemoryRange(target, offset, length, access, &mappedPointer);
|
||||
|
||||
if (result == GL_NO_ERROR) {
|
||||
MG_Util::Debug::LogD("Mapped pointer: %p", mappedPointer);
|
||||
return mappedPointer;
|
||||
}
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error mapping buffer range: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
|
||||
MG_Util::Debug::LogD("glFlushMappedBufferRange, target: %s, offset: %lld, length: %lld",
|
||||
MG_Util::Debug::GLEnumToString(target),
|
||||
static_cast<long long>(offset),
|
||||
static_cast<long long>(length));
|
||||
GLenum result = MG_State::SyncBufferMemory(target, offset, length);
|
||||
if (result == GL_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error flushing mapped buffer range: %s",
|
||||
MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
|
||||
GLintptr readOffset, GLintptr writeOffset,
|
||||
GLsizeiptr size) {
|
||||
MG_Util::Debug::LogD("glCopyBufferSubData, readTarget: %s, writeTarget: %s, "
|
||||
"readOffset: %lld, writeOffset: %lld, size: %lld",
|
||||
MG_Util::Debug::GLEnumToString(readTarget),
|
||||
MG_Util::Debug::GLEnumToString(writeTarget),
|
||||
static_cast<long long>(readOffset),
|
||||
static_cast<long long>(writeOffset),
|
||||
static_cast<long long>(size));
|
||||
GLenum result = MG_State::CopyBufferRange(readTarget, writeTarget, readOffset, writeOffset, size);
|
||||
if (result == GL_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error copying buffer subdata: %s",
|
||||
MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void* MapBuffer(GLenum target, GLenum access) {
|
||||
MG_Util::Debug::LogD("glMapBuffer(target=0x%x, access=0x%x)", target, access);
|
||||
|
||||
void* mappedPtr = nullptr;
|
||||
GLenum err = MG_State::AcquireBufferMemory(target, access, &mappedPtr);
|
||||
|
||||
if (err != GL_NO_ERROR) {
|
||||
MG_State::SetError(err);
|
||||
MG_Util::Debug::LogE("glMapBuffer failed: %s",
|
||||
MG_Util::Debug::GLEnumToString(err));
|
||||
MG_Util::Debug::LogE("glMapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MG_Util::Debug::LogD("glMapBuffer returns %p", mappedPtr);
|
||||
return mappedPtr;
|
||||
}
|
||||
|
||||
GLboolean UnmapBuffer(GLenum target) {
|
||||
MG_Util::Debug::LogD("glUnmapBuffer(target=0x%x)", target);
|
||||
|
||||
GLenum err = MG_State::ReleaseBufferMemory(target);
|
||||
if (err != GL_NO_ERROR) {
|
||||
MG_State::SetError(err);
|
||||
MG_Util::Debug::LogE("glUnmapBuffer failed: %s",
|
||||
MG_Util::Debug::GLEnumToString(err));
|
||||
MG_Util::Debug::LogE("glUnmapBuffer failed: %s", MG_Util::Debug::GLEnumToString(err));
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
MG_Util::Debug::LogD("glUnmapBuffer succeeded");
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
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 +109,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 +137,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 +157,32 @@ 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 BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
|
||||
MG_Util::Debug::LogD("glBufferSubData, target: %s, offset: %lld, size: %lld, data: %p",
|
||||
MG_Util::Debug::GLEnumToString(target),
|
||||
static_cast<long long>(offset),
|
||||
static_cast<long long>(size),
|
||||
data);
|
||||
GLenum result = MG_State::CommitBufferStorageRegion(target, offset, size, data);
|
||||
if (result != GL_NO_ERROR) {
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,17 @@
|
||||
#include "../../../../Includes.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
void* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
void* MapBuffer(GLenum target, GLenum access);
|
||||
GLboolean UnmapBuffer(GLenum target);
|
||||
void BindBuffer(GLenum target, GLuint buffer);
|
||||
void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||
void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
#include "GL_Common.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
void Clear(GLbitfield mask) {
|
||||
MG_Util::Debug::LogD("glClear, mask: 0x%X", mask);
|
||||
GLenum result = MG_State::glClear(mask);
|
||||
if (result == GL_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error clearing buffers: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void Enable(GLenum cap) {
|
||||
MG_Util::Debug::LogD("glEnable, cap: %s", MG_Util::Debug::GLEnumToString(cap));
|
||||
GLenum result = MG_State::glEnable(cap);
|
||||
@@ -43,14 +53,6 @@ namespace MG_GL::GL {
|
||||
MG_Util::Debug::LogE("Error setting separate blend func: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void Clear(GLbitfield mask) {
|
||||
MG_Util::Debug::LogD("glClear, mask: 0x%X", mask);
|
||||
GLenum result = MG_State::glClear(mask);
|
||||
if (result == GL_NO_ERROR) return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error clearing buffers: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
MG_Util::Debug::LogD("glClearColor, rgba: [%.2f, %.2f, %.2f, %.2f]", red, green, blue, alpha);
|
||||
GLenum result = MG_State::glClearColor(red, green, blue, alpha);
|
||||
|
||||
@@ -5,13 +5,27 @@
|
||||
#include "GL_Drawing.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
// This is a test function that directly draws textures.
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) {
|
||||
::GLES::glViewport(0,0,3200,1440);
|
||||
MG_RHI::GLES::Test::DrawAllTextures();
|
||||
};
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
::GLES::glViewport(0,0,3200,1440);
|
||||
MG_RHI::GLES::Test::DrawAllTextures();
|
||||
};
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawBuffer(GLenum buf) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,15 @@
|
||||
|
||||
#ifndef MOBILEGL_GL_DRAWING_H
|
||||
#define MOBILEGL_GL_DRAWING_H
|
||||
|
||||
#include "../../../../Includes.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
|
||||
void MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount);
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei drawcount, const GLint *basevertex);
|
||||
void DrawBuffer(GLenum buf);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GL_DRAWING_H
|
||||
|
||||
@@ -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));
|
||||
@@ -64,4 +65,9 @@ namespace MG_GL::GL {
|
||||
MG_Util::Debug::GLEnumToString(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -46,7 +46,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparate, GLenum modeRGB, GLenu
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BlendFunc, GLenum sfactor, GLenum dfactor) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFunc, sfactor,dfactor)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFuncSeparate, sfactorRGB,dfactorRGB,sfactorAlpha,dfactorAlpha)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BufferData, target,size,data,usage)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BufferSubData, target,offset,size,data)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BufferSubData, target,offset,size,data)
|
||||
DECLARE_GL_FUNCTION_HEAD(GLenum, CheckFramebufferStatus, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckFramebufferStatus, target)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, Clear, GLbitfield mask) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Clear, mask)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearColor, red,green,blue,alpha)
|
||||
@@ -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,10 +197,11 @@ 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)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, FlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length) DECLARE_GL_FUNCTION_END_NO_RETURN(void, FlushMappedBufferRange, target,offset,length)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BindVertexArray, GLuint array) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindVertexArray, array)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteVertexArrays, GLsizei n, const GLuint *arrays) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteVertexArrays, n,arrays)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GenVertexArrays, GLsizei n, GLuint *arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenVertexArrays, n,arrays)
|
||||
@@ -233,7 +234,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferiv, GLenum buffer, GLint drawbuff
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferuiv, buffer,drawbuffer,value)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferfv, buffer,drawbuffer,value)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferfi, buffer,drawbuffer,depth,stencil)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyBufferSubData, readTarget,writeTarget,readOffset,writeOffset,size)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, CopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyBufferSubData, readTarget,writeTarget,readOffset,writeOffset,size)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformIndices, program,uniformCount,uniformNames,uniformIndices)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformsiv, program,uniformCount,uniformIndices,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLuint, GetUniformBlockIndex, GLuint program, const GLchar *uniformBlockName) DECLARE_GL_FUNCTION_STUB_END(GLuint, GetUniformBlockIndex, program,uniformBlockName)
|
||||
@@ -365,7 +366,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunci, GLuint buf, GLenum src, GLenum d
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf,srcRGB,dstRGB,srcAlpha,dstAlpha)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMaski, index,r,g,b,a)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, IsEnabledi, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_END(GLboolean, IsEnabledi, target,index)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawElementsBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawElementsBaseVertex, mode,count,type,indices,basevertex)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, DrawElementsBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawElementsBaseVertex, mode,count,type,indices,basevertex)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawRangeElementsBaseVertex, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawRangeElementsBaseVertex, mode,start,end,count,type,indices,basevertex)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawElementsInstancedBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawElementsInstancedBaseVertex, mode,count,type,indices,instancecount,basevertex)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTexture, GLenum target, GLenum attachment, GLuint texture, GLint level) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTexture, target,attachment,texture,level)
|
||||
@@ -388,7 +389,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetSamplerParameterIuiv, GLuint sampler, GLe
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexBuffer, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexBuffer, target,internalformat,buffer)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexBufferRange, target,internalformat,buffer,offset,size)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3DMultisample, target,samples,internalformat,width,height,depth,fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void*, MapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) DECLARE_GL_FUNCTION_STUB_END(void*, MapBufferRange, target,offset,length,access)
|
||||
DECLARE_GL_FUNCTION_HEAD(void*, MapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) DECLARE_GL_FUNCTION_END(void*, MapBufferRange, target,offset,length,access)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearIndex, GLfloat c ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearIndex,c)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, IndexMask, GLuint mask ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, IndexMask,mask)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, AlphaFunc, GLenum func, GLclampf ref ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, AlphaFunc,func,ref)
|
||||
@@ -402,7 +403,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, EdgeFlag, GLboolean flag ) DECLARE_GL_FUNCTI
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, EdgeFlagv, const GLboolean *flag ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EdgeFlagv,flag)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClipPlane, GLenum plane, const GLdouble *equation ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClipPlane,plane,equation)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetClipPlane, GLenum plane, GLdouble *equation ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetClipPlane,plane,equation)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffer, GLenum mode ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffer,mode)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, DrawBuffer, GLenum mode ) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawBuffer,mode)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, EnableClientState, GLenum cap ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EnableClientState,cap)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DisableClientState, GLenum cap ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DisableClientState,cap)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetDoublev, GLenum pname, GLdouble *params ) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetDoublev,pname,params)
|
||||
@@ -738,7 +739,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, LoadTransposeMatrixd,const GLdouble* m) DECL
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultTransposeMatrixf,const GLfloat* m) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultTransposeMatrixf,m)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultTransposeMatrixd,const GLdouble* m) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultTransposeMatrixd,m)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiDrawArrays, GLenum mode, const GLint* first, const GLsizei* count, GLsizei drawcount) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiDrawArrays,mode,first,count,drawcount)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiDrawElements, GLenum mode, const GLsizei* count, GLenum type, const void* const*indices, GLsizei drawcount) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiDrawElements,mode,count,type,indices,drawcount)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElements, GLenum mode, const GLsizei* count, GLenum type, const void* const*indices, GLsizei drawcount) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElements,mode,count,type,indices,drawcount)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PointParameterf, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PointParameterf,pname,param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PointParameterfv, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PointParameterfv,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PointParameteri, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PointParameteri,pname,param)
|
||||
@@ -814,7 +815,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4uiv, GLuint index, const GLuint
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4usv,index,v)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PrimitiveRestartIndex, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrimitiveRestartIndex,index)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformName, GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformName,program,uniformIndex,bufSize,length,uniformName)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiDrawElementsBaseVertex, GLenum mode, const GLsizei* count, GLenum type, const void* const*indices, GLsizei drawcount, const GLint* basevertex) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiDrawElementsBaseVertex,mode,count,type,indices,drawcount,basevertex)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsBaseVertex, GLenum mode, const GLsizei* count, GLenum type, const void* const*indices, GLsizei drawcount, const GLint* basevertex) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsBaseVertex,mode,count,type,indices,drawcount,basevertex)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProvokingVertex,mode)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage2DMultisample,target,samples,internalformat,width,height,fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3DMultisample,target,samples,internalformat,width,height,depth,fixedsamplelocations)
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace MG_GL::GL {
|
||||
}
|
||||
return (const GLubyte *)rendererString.c_str();
|
||||
*/
|
||||
return (const GLubyte *)(MG_GL::Getter::GetMGName() + "(MobileGL Core) Renderer").c_str();
|
||||
return (const GLubyte *)(MG_GL::Getter::GetMGName() + " (MobileGL Core) Renderer").c_str();
|
||||
}
|
||||
case GL_SHADING_LANGUAGE_VERSION:
|
||||
return (const GLubyte *) "4.50 MobileGL with glslang";
|
||||
@@ -114,37 +114,181 @@ namespace MG_GL::GL {
|
||||
|
||||
void GetIntegerv(GLenum pname, GLint *params) {
|
||||
MG_Util::Debug::LogD("glGetIntegerv, pname: %s", MG_Util::Debug::GLEnumToString(pname));
|
||||
if (!params) {
|
||||
MG_State::SetError(GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL_CONTEXT_PROFILE_MASK:
|
||||
(*params) = GL_CONTEXT_CORE_PROFILE_BIT;
|
||||
// Viewport and scissor
|
||||
case GL_VIEWPORT:
|
||||
memcpy(params, MG_State_T::commonState->viewport, 4 * sizeof(GLint));
|
||||
break;
|
||||
case GL_NUM_EXTENSIONS:
|
||||
static GLint num_extensions = -1;
|
||||
if (num_extensions == -1) {
|
||||
const GLubyte* ext_str = MG_GL::GL::GetString(GL_EXTENSIONS);
|
||||
char *copy = strdup((const char *) ext_str);
|
||||
char *token = strtok(copy, " ");
|
||||
num_extensions = 0;
|
||||
while (token) {
|
||||
num_extensions++;
|
||||
token = strtok(nullptr, " ");
|
||||
}
|
||||
free(copy);
|
||||
}
|
||||
(*params) = num_extensions;
|
||||
case GL_SCISSOR_BOX:
|
||||
// TODO: memcpy(params, MG_State_T::commonState->scissorBox, 4 * sizeof(GLint));
|
||||
break;
|
||||
case GL_MAJOR_VERSION:
|
||||
(*params) = MG_Global::GL::GLVersionMajor;
|
||||
case GL_MAX_VIEWPORT_DIMS: {
|
||||
static const GLint maxDims[2] = {16384, 16384};
|
||||
memcpy(params, maxDims, sizeof(maxDims));
|
||||
break;
|
||||
case GL_MINOR_VERSION:
|
||||
(*params) = MG_Global::GL::GLVersionMinor;
|
||||
}
|
||||
|
||||
// Buffer bindings
|
||||
case GL_ARRAY_BUFFER_BINDING:
|
||||
params[0] = static_cast<GLint>(MG_State_T::bufferState->GetCurrentBinding(GL_ARRAY_BUFFER));
|
||||
break;
|
||||
|
||||
case GL_ELEMENT_ARRAY_BUFFER_BINDING:
|
||||
params[0] = static_cast<GLint>(MG_State_T::vertexArrayState->GetBoundElementBuffer());
|
||||
break;
|
||||
case GL_DRAW_FRAMEBUFFER_BINDING:
|
||||
params[0] = static_cast<GLint>(MG_State_T::framebufferState->currentBindings_[GL_DRAW_FRAMEBUFFER]);
|
||||
break;
|
||||
case GL_READ_FRAMEBUFFER_BINDING:
|
||||
params[0] = static_cast<GLint>(MG_State_T::framebufferState->currentBindings_[GL_READ_FRAMEBUFFER]);
|
||||
break;
|
||||
case GL_RENDERBUFFER_BINDING:
|
||||
// TODO: params[0] = static_cast<GLint>(MG_State_T::framebufferState->currentRenderbuffer_);
|
||||
break;
|
||||
|
||||
// Program state
|
||||
case GL_CURRENT_PROGRAM:
|
||||
params[0] = static_cast<GLint>(MG_State_T::programState->currentProgram_);
|
||||
break;
|
||||
case GL_MAX_VERTEX_ATTRIBS:
|
||||
// TODO: Check the real value
|
||||
params[0] = 64;
|
||||
break;
|
||||
|
||||
// Texture state
|
||||
case GL_TEXTURE_BINDING_2D: {
|
||||
GLuint unit = MG_State_T::textureState->activeTextureUnit_;
|
||||
auto& textures = MG_State_T::textureState->textureUnits_[unit].boundTextures;
|
||||
params[0] = textures.count(GL_TEXTURE_2D) ? static_cast<GLint>(textures[GL_TEXTURE_2D]) : 0;
|
||||
break;
|
||||
}
|
||||
case GL_ACTIVE_TEXTURE:
|
||||
params[0] = GL_TEXTURE0 + MG_State_T::textureState->activeTextureUnit_;
|
||||
break;
|
||||
case GL_MAX_TEXTURE_SIZE:
|
||||
// TODO: Get real GL_MAX_TEXTURE_SIZE.
|
||||
(*params) = 32768;
|
||||
params[0] = 8192;
|
||||
break;
|
||||
|
||||
// Blend state
|
||||
case GL_BLEND_SRC_RGB:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->blendSrcRGB);
|
||||
break;
|
||||
case GL_BLEND_DST_RGB:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->blendDstRGB);
|
||||
break;
|
||||
case GL_BLEND_SRC_ALPHA:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->blendSrcAlpha);
|
||||
break;
|
||||
case GL_BLEND_DST_ALPHA:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->blendDstAlpha);
|
||||
break;
|
||||
|
||||
// Depth and stencil
|
||||
case GL_DEPTH_FUNC:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->depthFunc);
|
||||
break;
|
||||
case GL_DEPTH_WRITEMASK:
|
||||
params[0] = static_cast<GLint>(MG_State_T::commonState->depthMask);
|
||||
break;
|
||||
case GL_STENCIL_REF:
|
||||
// TODO: params[0] = MG_State_T::commonState->stencilRef;
|
||||
break;
|
||||
|
||||
// Capability enables
|
||||
case GL_BLEND:
|
||||
params[0] = MG_State_T::commonState->capabilities[GL_BLEND] ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
case GL_DEPTH_TEST:
|
||||
params[0] = MG_State_T::commonState->capabilities[GL_DEPTH_TEST] ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
case GL_SCISSOR_TEST:
|
||||
params[0] = MG_State_T::commonState->capabilities[GL_SCISSOR_TEST] ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
|
||||
// Pixel operations
|
||||
case GL_PACK_ALIGNMENT:
|
||||
params[0] = MG_State_T::commonState->QueryPixelStoreInt(GL_PACK_ALIGNMENT);
|
||||
break;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
params[0] = MG_State_T::commonState->QueryPixelStoreInt(GL_UNPACK_ALIGNMENT);
|
||||
break;
|
||||
|
||||
// Hardware limits, TODO: Check the real values
|
||||
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
|
||||
params[0] = 32;
|
||||
break;
|
||||
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
|
||||
params[0] = 32;
|
||||
break;
|
||||
case GL_MAX_TEXTURE_IMAGE_UNITS:
|
||||
params[0] = 32;
|
||||
break;
|
||||
case GL_MAX_RENDERBUFFER_SIZE:
|
||||
params[0] = 65537;
|
||||
break;
|
||||
case GL_MAX_DRAW_BUFFERS:
|
||||
params[0] = 32;
|
||||
break;
|
||||
case GL_MAX_COLOR_ATTACHMENTS:
|
||||
params[0] = 32;
|
||||
break;
|
||||
|
||||
// Color state
|
||||
case GL_COLOR_CLEAR_VALUE: {
|
||||
const auto& c = MG_State_T::commonState->clearColor;
|
||||
params[0] = static_cast<GLint>(c[0] * 0x7FFF);
|
||||
params[1] = static_cast<GLint>(c[1] * 0x7FFF);
|
||||
params[2] = static_cast<GLint>(c[2] * 0x7FFF);
|
||||
params[3] = static_cast<GLint>(c[3] * 0x7FFF);
|
||||
break;
|
||||
}
|
||||
case GL_COLOR_WRITEMASK:
|
||||
params[0] = MG_State_T::commonState->colorMask[0];
|
||||
params[1] = MG_State_T::commonState->colorMask[1];
|
||||
params[2] = MG_State_T::commonState->colorMask[2];
|
||||
params[3] = MG_State_T::commonState->colorMask[3];
|
||||
break;
|
||||
|
||||
// Stencil operations
|
||||
case GL_STENCIL_CLEAR_VALUE:
|
||||
// TODO: params[0] = MG_State_T::commonState->stencilClearValue;
|
||||
break;
|
||||
case GL_STENCIL_BITS:
|
||||
// TODO: Check the real value
|
||||
params[0] = 8;
|
||||
break;
|
||||
|
||||
// Implementation limits
|
||||
case GL_SUBPIXEL_BITS:
|
||||
// TODO: Check the real value
|
||||
params[0] = 4;
|
||||
break;
|
||||
case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
|
||||
// TODO: params[0] = static_cast<GLint>(MG_State_T::textureState->compressedFormats_.size());
|
||||
break;
|
||||
case GL_COMPRESSED_TEXTURE_FORMATS:
|
||||
// TODO: Implement GL_COMPRESSED_TEXTURE_FORMATS
|
||||
break;
|
||||
|
||||
// Polygon state
|
||||
case GL_POLYGON_OFFSET_FACTOR:
|
||||
// TODO: params[0] = static_cast<GLint>(MG_State_T::commonState->polygonOffsetFactor);
|
||||
break;
|
||||
case GL_POLYGON_OFFSET_UNITS:
|
||||
// TODO: params[0] = static_cast<GLint>(MG_State_T::commonState->polygonOffsetUnits);
|
||||
break;
|
||||
|
||||
// Others...
|
||||
default:
|
||||
MG_Util::Debug::LogE("glGetIntegerv: Invalid enum %s (0x%X)", MG_Util::Debug::GLEnumToString(pname), pname);
|
||||
MG_State::SetError(GL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,58 +6,60 @@
|
||||
|
||||
#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::Create(GLuint buffer) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Create called");
|
||||
if (!buffer)
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
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::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=0x%x, buffer=%u", target, buffer);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=%s, buffer=%u", MG_Util::Debug::GLEnumToString(target), buffer);
|
||||
currentBindings_[target] = buffer;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target);
|
||||
return GL_NO_ERROR;
|
||||
@@ -73,68 +75,190 @@ 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;
|
||||
}
|
||||
|
||||
GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer) {
|
||||
GLenum BufferState::CommitStorageRegion(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData called on target 0x%x, offset=%ld, size=%ld", target, offset, size);
|
||||
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
||||
if (MG_Constants::Buffer::VALID_ACCESS.find(access) == MG_Constants::Buffer::VALID_ACCESS.end()) {
|
||||
return GL_INVALID_ENUM;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemory buffer at target 0x%x acquired mapped memory, access mode = 0x%x", target, access);
|
||||
}
|
||||
|
||||
if (offset < 0 || size < 0) return GL_INVALID_VALUE;
|
||||
|
||||
auto it = currentBindings_.find(target);
|
||||
if (it == currentBindings_.end() || it->second == 0)
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
BufferObject& obj = buffers_[it->second];
|
||||
if (obj.isMapped) return GL_INVALID_OPERATION;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: BufferSubData get buffer object %u at target 0x%x", it->second, target);
|
||||
|
||||
obj.isMapped = true;
|
||||
*mappedPointer = obj.data.data();
|
||||
obj.isMapped = true;
|
||||
obj.accessMode = access;
|
||||
if (static_cast<size_t>(offset + size) > obj.data.size()) return GL_INVALID_VALUE;
|
||||
|
||||
if (data) {
|
||||
memcpy(obj.data.data() + offset, data, size);
|
||||
obj.dirty = true;
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum BufferState::AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void** mappedPointer) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange called with target=0x%x, offset=%ld, length=%ld, access=0x%x", target, offset, length, access);
|
||||
if (!IsValidTarget_(target)) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: invalid target 0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
if (offset < 0 || length <= 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: invalid offset %ld or length %ld", offset, length);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto it = currentBindings_.find(target);
|
||||
if (it == currentBindings_.end() || it->second == 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: no buffer bound to target 0x%x", target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
BufferObject& obj = buffers_[it->second];
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange operating on buffer %u", it->second);
|
||||
if (obj.isMapped) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: buffer %u is already mapped", it->second);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
const GLbitfield validFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ;
|
||||
if ((access & ~validFlags) != 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: invalid access flags 0x%x", access);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (static_cast<size_t>(offset + length) > obj.data.size()) {
|
||||
MG_Util::Debug::LogE("MG_State: Buffer: AcquireBufferMemoryRange failed: requested range [%ld, %ld) exceeds buffer size %zu", offset, offset + length, obj.data.size());
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
obj.isMapped = true;
|
||||
obj.mapOffset = offset;
|
||||
obj.mapLength = length;
|
||||
obj.mapAccessFlags = access;
|
||||
obj.dirty = true;
|
||||
*mappedPointer = obj.data.data() + offset;
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: AcquireBufferMemoryRange succeeded for buffer %u. Mapped pointer: %p", it->second, *mappedPointer);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum BufferState::SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr length) {
|
||||
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
||||
if (offset < 0 || length <= 0) return GL_INVALID_VALUE;
|
||||
|
||||
auto it = currentBindings_.find(target);
|
||||
if (it == currentBindings_.end() || it->second == 0)
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
BufferObject& obj = buffers_[it->second];
|
||||
if (!obj.isMapped || !(obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT))
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
if (offset < obj.mapOffset || offset + length > obj.mapOffset + obj.mapLength)
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
// TODO: Add support for flush range.
|
||||
// Now only mark it as dirty.
|
||||
obj.dirty = true;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum BufferState::CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
|
||||
if (!IsValidTarget_(readTarget) || !IsValidTarget_(writeTarget))
|
||||
return GL_INVALID_ENUM;
|
||||
if (readOffset < 0 || writeOffset < 0 || size < 0)
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
GLuint readBuffer = currentBindings_[readTarget];
|
||||
GLuint writeBuffer = currentBindings_[writeTarget];
|
||||
if (readBuffer == 0 || writeBuffer == 0 || readBuffer == writeBuffer)
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
BufferObject& src = buffers_[readBuffer];
|
||||
BufferObject& dst = buffers_[writeBuffer];
|
||||
|
||||
if (static_cast<size_t>(readOffset + size) > src.data.size() ||
|
||||
static_cast<size_t>(writeOffset + size) > dst.data.size())
|
||||
return GL_INVALID_VALUE;
|
||||
|
||||
memcpy(dst.data.data() + writeOffset, src.data.data() + readOffset, size);
|
||||
dst.dirty = true;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum BufferState::AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer) {
|
||||
return AcquireBufferMemoryRange(target, 0, buffers_[currentBindings_[target]].data.size(), access, mappedPointer);
|
||||
}
|
||||
|
||||
GLenum BufferState::ReleaseBufferMemory(GLenum target) {
|
||||
MG_Util::Debug::LogD("MG_State: Buffer: ReleaseBufferMemory called on target 0x%x",target);
|
||||
if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
|
||||
if (!IsValidTarget_(target))
|
||||
return GL_INVALID_ENUM;
|
||||
|
||||
|
||||
auto it = currentBindings_.find(target);
|
||||
if (it == currentBindings_.end() || it->second == 0)
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
BufferObject& obj = buffers_[it->second];
|
||||
if (!obj.isMapped) return GL_INVALID_OPERATION;
|
||||
if (!obj.isMapped)
|
||||
return GL_INVALID_OPERATION;
|
||||
|
||||
if ((obj.mapAccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
|
||||
obj.dirty = true;
|
||||
}
|
||||
|
||||
obj.isMapped = false;
|
||||
obj.mapOffset = 0;
|
||||
obj.mapLength = 0;
|
||||
obj.mapAccessFlags = 0;
|
||||
obj.accessMode = GL_READ_WRITE;
|
||||
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))
|
||||
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend.
|
||||
//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 +303,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,48 @@
|
||||
#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;
|
||||
GLintptr mapOffset = 0;
|
||||
GLsizeiptr mapLength = 0;
|
||||
GLbitfield mapAccessFlags = 0;
|
||||
};
|
||||
|
||||
// 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 Bind(GLenum target, GLuint buffer);
|
||||
GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
|
||||
GLenum CommitStorageRegion(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
|
||||
GLenum AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void** mappedPointer);
|
||||
GLenum SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
GLenum CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer);
|
||||
GLenum ReleaseBufferMemory(GLenum target);
|
||||
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const;
|
||||
GLenum DeleteN(GLsizei n, const GLuint* buffers);
|
||||
|
||||
bool ValidateHandle(GLuint buffer);
|
||||
bool ValidateAllocatedHandle(GLuint buffer);
|
||||
bool ValidateGeneratedName(GLuint buffer);
|
||||
void Delete(GLuint buffer);
|
||||
GLuint GetCurrentBinding(GLenum target) const;
|
||||
|
||||
unordered_map<GLenum, GLuint> currentBindings_;
|
||||
unordered_map<GLuint, BufferObject> buffers_;
|
||||
private:
|
||||
std::unordered_map<GLuint, BufferObject> buffers_;
|
||||
std::set<GLuint> freeIds_;
|
||||
GLuint lastId_ = 0;
|
||||
std::unordered_map<GLenum, GLuint> currentBindings_;
|
||||
std::vector<GLuint> freeId_;
|
||||
GLuint lastId_ = 1;
|
||||
|
||||
static bool IsValidTarget_(GLenum target);
|
||||
};
|
||||
|
||||
@@ -107,6 +107,7 @@ GLenum CommonState::Clear(GLbitfield mask) {
|
||||
if ((mask & ~validBits) != 0) {
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
clearMask = mask;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,17 @@
|
||||
#include "../../../Includes.h"
|
||||
|
||||
class CommonState {
|
||||
private:
|
||||
template <typename K, typename V>
|
||||
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||
public:
|
||||
// Viewport
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
|
||||
// Color mask
|
||||
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;
|
||||
@@ -22,21 +30,15 @@ private:
|
||||
// Clear state
|
||||
GLfloat clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GLfloat clearDepth = 1.0f;
|
||||
|
||||
// Color mask
|
||||
GLboolean colorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
|
||||
|
||||
GLenum clearMask;
|
||||
|
||||
// Depth state
|
||||
GLenum depthFunc = GL_LESS;
|
||||
GLboolean depthMask = GL_TRUE;
|
||||
|
||||
// Viewport
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
|
||||
|
||||
// Capability enables
|
||||
std::unordered_map<GLenum, bool> capabilities;
|
||||
unordered_map<GLenum, bool> capabilities;
|
||||
|
||||
public:
|
||||
CommonState();
|
||||
|
||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||
@@ -57,6 +59,7 @@ public:
|
||||
GLenum Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
GLint QueryPixelStoreInt(GLenum pname);
|
||||
|
||||
};
|
||||
|
||||
#endif //MOBILEGL_COMMONSTATE_H
|
||||
|
||||
@@ -155,17 +155,30 @@ namespace MG_State {
|
||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr) {
|
||||
return MG_State_T::bufferState->AcquireBufferMemory(target, access, mappedPtr);
|
||||
}
|
||||
|
||||
GLenum AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void** mappedPointer) {
|
||||
return MG_State_T::bufferState->AcquireBufferMemoryRange(target, offset, length, access, mappedPointer);
|
||||
}
|
||||
|
||||
GLenum SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr length) {
|
||||
return MG_State_T::bufferState->SyncBufferMemory(target, offset, length);
|
||||
}
|
||||
|
||||
GLenum CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
|
||||
return MG_State_T::bufferState->CopyBufferRange(readTarget, writeTarget, readOffset,
|
||||
writeOffset, size);
|
||||
}
|
||||
|
||||
GLenum ReleaseBufferMemory(GLenum target) {
|
||||
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 GenBufferNames(GLsizei n, GLuint* buffers) {
|
||||
return MG_State_T::bufferState->GenNameN(n, buffers);
|
||||
}
|
||||
|
||||
GLenum BindBuffer(GLenum target, GLuint buffer) {
|
||||
@@ -173,6 +186,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 +195,26 @@ namespace MG_State {
|
||||
return MG_State_T::bufferState->CommitStorage(target, size, data, usage);
|
||||
}
|
||||
|
||||
bool ValidateBufferHandle(GLuint buffer) {
|
||||
return MG_State_T::bufferState->ValidateHandle(buffer);
|
||||
GLenum CommitBufferStorageRegion(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
|
||||
return MG_State_T::bufferState->CommitStorageRegion(target, offset, size, data);
|
||||
}
|
||||
|
||||
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 +232,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);
|
||||
}
|
||||
@@ -367,11 +397,11 @@ void UpdateProgramUniformMatrix##suffix##Vector(GLint location, GLsizei count, G
|
||||
|
||||
GLenum MG_State::AttachTexture2DToFramebuffer(GLenum target, GLenum attachment, GLenum textarget,
|
||||
GLuint texture, GLint level) {
|
||||
return MG_State_T::framebufferState->glAttachTexture2D(target, attachment, textarget,
|
||||
texture, level);
|
||||
return MG_State_T::framebufferState->AttachTexture2D(target, attachment, textarget,
|
||||
texture, level);
|
||||
}
|
||||
|
||||
GLenum MG_State::ValidateFramebufferCompleteness(GLenum target) {
|
||||
return MG_State_T::framebufferState->glValidateCompleteness(target);
|
||||
return MG_State_T::framebufferState->ValidateCompleteness(target);
|
||||
}
|
||||
}
|
||||
@@ -57,18 +57,25 @@ namespace MG_State {
|
||||
|
||||
// Buffer
|
||||
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr);
|
||||
GLenum AcquireBufferMemoryRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void** mappedPointer);
|
||||
GLenum SyncBufferMemory(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
GLenum CopyBufferRange(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
GLenum ReleaseBufferMemory(GLenum target);
|
||||
GLenum CreateBuffer(GLuint* buffer);
|
||||
GLenum CreateBuffers(GLsizei n, GLuint* buffers);
|
||||
GLenum CreateBuffer(GLuint buffer);
|
||||
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);
|
||||
GLenum CommitBufferStorageRegion(GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
|
||||
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);
|
||||
|
||||
@@ -32,7 +32,8 @@ GLenum FramebufferState::Delete(GLuint framebuffer) {
|
||||
if (framebuffer == 0) return GL_INVALID_VALUE;
|
||||
|
||||
if (framebuffers_.erase(framebuffer)) {
|
||||
freeIds_.insert(framebuffer);
|
||||
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend.
|
||||
//freeIds_.insert(framebuffer);
|
||||
for (auto& [target, id] : currentBindings_) {
|
||||
if (id == framebuffer) id = 0;
|
||||
}
|
||||
@@ -48,18 +49,18 @@ GLenum FramebufferState::Bind(GLenum target, GLuint framebuffer) {
|
||||
if (target == GL_FRAMEBUFFER) {
|
||||
currentBindings_[GL_READ_FRAMEBUFFER] = framebuffer;
|
||||
currentBindings_[GL_DRAW_FRAMEBUFFER] = framebuffer;
|
||||
currentBindings_[GL_FRAMEBUFFER] = framebuffer;
|
||||
} else {
|
||||
currentBindings_[target] = framebuffer;
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum FramebufferState::glAttachTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level) {
|
||||
GLenum FramebufferState::AttachTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level) {
|
||||
if (MG_Constants::Framebuffer::VALID_ATTACHMENTS.find(attachment) == MG_Constants::Framebuffer::VALID_ATTACHMENTS.end() ||
|
||||
MG_Constants::Texture::VALID_TARGETS.find(textarget) == MG_Constants::Texture::VALID_TARGETS.end())
|
||||
return GL_INVALID_ENUM;
|
||||
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
|
||||
FramebufferObject* fbo = GetCurrentFBO(target);
|
||||
if (!fbo) return GL_INVALID_OPERATION;
|
||||
if (texture != 0 && !MG_State_T::textureState->IsTexture(texture))
|
||||
@@ -83,7 +84,8 @@ GLenum FramebufferState::glAttachTexture2D(GLenum target, GLenum attachment,
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum FramebufferState::glValidateCompleteness(GLenum target) {
|
||||
GLenum FramebufferState::ValidateCompleteness(GLenum target) {
|
||||
if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER;
|
||||
FramebufferObject* fbo = GetCurrentFBO(target);
|
||||
if (!fbo) return GL_INVALID_OPERATION;
|
||||
return fbo->status;
|
||||
|
||||
@@ -17,7 +17,7 @@ struct FramebufferAttachment {
|
||||
|
||||
struct FramebufferObject {
|
||||
bool generated = false;
|
||||
std::unordered_map<GLenum, FramebufferAttachment> attachments;
|
||||
ankerl::unordered_map<GLenum, FramebufferAttachment> attachments;
|
||||
GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
@@ -30,14 +30,15 @@ public:
|
||||
GLenum CreateN(GLsizei n, GLuint* framebuffers);
|
||||
GLenum Delete(GLuint framebuffer);
|
||||
GLenum Bind(GLenum target, GLuint framebuffer);
|
||||
GLenum glAttachTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level);
|
||||
GLenum glValidateCompleteness(GLenum target);
|
||||
GLenum AttachTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level);
|
||||
GLenum ValidateCompleteness(GLenum target);
|
||||
FramebufferObject* GetCurrentFBO(GLenum target);
|
||||
|
||||
ankerl::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW
|
||||
|
||||
private:
|
||||
std::unordered_map<GLuint, FramebufferObject> framebuffers_;
|
||||
std::unordered_map<GLenum, GLuint> currentBindings_; // READ/DRAW/FRAMEBUFFER
|
||||
ankerl::unordered_map<GLuint, FramebufferObject> framebuffers_;
|
||||
std::set<GLuint> freeIds_;
|
||||
GLuint lastId_ = 0;
|
||||
bool ValidateHandle(GLuint framebuffer);
|
||||
|
||||
@@ -48,7 +48,7 @@ GLenum ProgramState::DeleteProgram(GLuint program) {
|
||||
}
|
||||
|
||||
programs_.erase(program);
|
||||
freeProgramIds_.insert(program);
|
||||
//freeProgramIds_.insert(program);
|
||||
if (currentProgram_ == program)
|
||||
currentProgram_ = 0;
|
||||
MG_Util::Debug::LogD("MG_State: Program: DeleteProgram success, id=%u", program);
|
||||
@@ -261,6 +261,7 @@ GLenum ProgramState::SetUniform(GLuint program, GLint location, GLsizei count, c
|
||||
}
|
||||
|
||||
UniformValue& uniform = prog.uniformValues[uniformName];
|
||||
|
||||
uniform.setData(type, count, value);
|
||||
MG_Util::Debug::LogD("MG_State: Program: SetUniform success: %s set", uniformName.c_str());
|
||||
return GL_NO_ERROR;
|
||||
@@ -303,7 +304,7 @@ GLenum ProgramState::SetUniformMatrix(GLuint program, GLint location, GLsizei co
|
||||
}
|
||||
|
||||
UniformValue& uniform = prog.uniformValues[uniformName];
|
||||
uniform.setData(matrixType, count * MG_Util::Program::GetMatrixElementCount(matrixType), value);
|
||||
uniform.setData(matrixType, count, value);
|
||||
MG_Util::Debug::LogD("MG_State: Program: SetUniformMatrix success: %s set", uniformName.c_str());
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
@@ -334,15 +335,15 @@ void ProgramState::UpdateUniform##suffix##Vector1(GLint location, GLsizei count,
|
||||
} \
|
||||
void ProgramState::UpdateUniform##suffix##Vector2(GLint location, GLsizei count, const type* value) { \
|
||||
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector2 called, location=%d, count=%d", location, count); \
|
||||
SetUniform<type>(currentProgram_, location, count * 2, value, vecType); \
|
||||
SetUniform<type>(currentProgram_, location, count, value, vecType); \
|
||||
} \
|
||||
void ProgramState::UpdateUniform##suffix##Vector3(GLint location, GLsizei count, const type* value) { \
|
||||
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector3 called, location=%d, count=%d", location, count); \
|
||||
SetUniform<type>(currentProgram_, location, count * 3, value, vecType); \
|
||||
SetUniform<type>(currentProgram_, location, count, value, vecType); \
|
||||
} \
|
||||
void ProgramState::UpdateUniform##suffix##Vector4(GLint location, GLsizei count, const type* value) { \
|
||||
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector4 called, location=%d, count=%d", location, count); \
|
||||
SetUniform<type>(currentProgram_, location, count * 4, value, vecType); \
|
||||
SetUniform<type>(currentProgram_, location, count, value, vecType); \
|
||||
}
|
||||
|
||||
IMPLEMENT_UNIFORM_FUNCTIONS(GLfloat, Float, GL_FLOAT_VEC4)
|
||||
@@ -462,16 +463,62 @@ void ProgramState::CleanupShaders_() {
|
||||
|
||||
// UniformValue
|
||||
template<typename T>
|
||||
void UniformValue::setData(GLenum uniformType, GLsizei numElements, const T* values) {
|
||||
MG_Util::Debug::LogD("MG_State: Program: UniformValue::setData called, type=0x%X, count=%d", uniformType, numElements);
|
||||
void UniformValue::setData(GLenum uniformType, GLsizei count_, const T* values) {
|
||||
MG_Util::Debug::LogD("MG_State: Program: UniformValue::setData called, type=0x%X, count=%d", uniformType, count_);
|
||||
//type = uniformType;
|
||||
count = numElements;
|
||||
count = count_;
|
||||
|
||||
floatData.clear();
|
||||
intData.clear();
|
||||
uintData.clear();
|
||||
boolData.clear();
|
||||
|
||||
switch (type) {
|
||||
case GL_FLOAT: numElements = count_ * 1; break;
|
||||
case GL_FLOAT_VEC2: numElements = count_ * 2; break;
|
||||
case GL_FLOAT_VEC3: numElements = count_ * 3; break;
|
||||
case GL_FLOAT_VEC4: numElements = count_ * 4; break;
|
||||
case GL_INT: numElements = count_ * 1; break;
|
||||
case GL_INT_VEC2: numElements = count_ * 2; break;
|
||||
case GL_INT_VEC3: numElements = count_ * 3; break;
|
||||
case GL_INT_VEC4: numElements = count_ * 4; break;
|
||||
case GL_UNSIGNED_INT: numElements = count_ * 1; break;
|
||||
case GL_UNSIGNED_INT_VEC2: numElements = count_ * 2; break;
|
||||
case GL_UNSIGNED_INT_VEC3: numElements = count_ * 3; break;
|
||||
case GL_UNSIGNED_INT_VEC4: numElements = count_ * 4; break;
|
||||
case GL_BOOL: numElements = count_ * 1; break;
|
||||
case GL_BOOL_VEC2: numElements = count_ * 2; break;
|
||||
case GL_BOOL_VEC3: numElements = count_ * 3; break;
|
||||
case GL_BOOL_VEC4: numElements = count_ * 4; break;
|
||||
case GL_FLOAT_MAT2: numElements = count_ * 4; break; // 2x2
|
||||
case GL_FLOAT_MAT3: numElements = count_ * 9; break; // 3x3
|
||||
case GL_FLOAT_MAT4: numElements = count_ * 16; break; // 4x4
|
||||
case GL_FLOAT_MAT2x3: numElements = count_ * 6; break; // 2x3
|
||||
case GL_FLOAT_MAT2x4: numElements = count_ * 8; break; // 2x4
|
||||
case GL_FLOAT_MAT3x2: numElements = count_ * 6; break; // 3x2
|
||||
case GL_FLOAT_MAT3x4: numElements = count_ * 12; break; // 3x4
|
||||
case GL_FLOAT_MAT4x2: numElements = count_ * 8; break; // 4x2
|
||||
case GL_FLOAT_MAT4x3: numElements = count_ * 12; break; // 4x3
|
||||
case GL_SAMPLER_1D:
|
||||
case GL_SAMPLER_2D:
|
||||
case GL_SAMPLER_3D:
|
||||
case GL_SAMPLER_CUBE:
|
||||
case GL_SAMPLER_1D_SHADOW:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
case GL_SAMPLER_CUBE_SHADOW:
|
||||
case GL_SAMPLER_1D_ARRAY:
|
||||
case GL_SAMPLER_2D_ARRAY:
|
||||
case GL_SAMPLER_1D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_BUFFER:
|
||||
case GL_SAMPLER_2D_MULTISAMPLE:
|
||||
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: numElements = count_ * 1; break;
|
||||
default:
|
||||
MG_Util::Debug::LogW("MG_State: Program: UniformValue::setData warning: unsupported type 0x%X for numElements", uniformType);
|
||||
numElements = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (GLsizei i = 0; i < numElements; ++i) {
|
||||
switch (uniformType) {
|
||||
case GL_FLOAT:
|
||||
|
||||
@@ -27,36 +27,37 @@ struct UniformValue {
|
||||
std::vector<GLuint> uintData;
|
||||
std::vector<GLboolean> boolData;
|
||||
GLsizei count;
|
||||
GLsizei numElements;
|
||||
|
||||
UniformValue() : type(0), count(0) {}
|
||||
|
||||
template<typename T>
|
||||
void setData(GLenum uniformType, GLsizei numElements, const T* values);
|
||||
void setData(GLenum uniformType, GLsizei count_, const T* values);
|
||||
};
|
||||
|
||||
struct ProgramObject {
|
||||
std::vector<GLuint> attachedShaders;
|
||||
UncertainBool linked;
|
||||
bool dirty;
|
||||
GLint linkStatus;
|
||||
std::string infoLog;
|
||||
std::unordered_map<std::string, GLint> attribBindings;
|
||||
std::unordered_map<std::string, GLint> attribLocations;
|
||||
std::unordered_map<std::string, GLint> uniformLocations;
|
||||
std::unordered_map<std::string, UniformValue> uniformValues;
|
||||
ankerl::unordered_map<std::string, GLint> attribBindings;
|
||||
ankerl::unordered_map<std::string, GLint> attribLocations;
|
||||
ankerl::unordered_map<std::string, GLint> uniformLocations;
|
||||
ankerl::unordered_map<std::string, UniformValue> uniformValues;
|
||||
bool markedForDeletion;
|
||||
};
|
||||
|
||||
class ProgramState {
|
||||
private:
|
||||
std::unordered_map<GLuint, ShaderObject> shaders_;
|
||||
std::unordered_map<GLuint, ProgramObject> programs_;
|
||||
public:
|
||||
ankerl::unordered_map<GLuint, ShaderObject> shaders_;
|
||||
ankerl::unordered_map<GLuint, ProgramObject> programs_;
|
||||
std::set<GLuint> freeShaderIds_;
|
||||
std::set<GLuint> freeProgramIds_;
|
||||
GLuint lastShaderId_ = 0;
|
||||
GLuint lastProgramId_ = 0;
|
||||
GLuint currentProgram_ = 0;
|
||||
|
||||
public:
|
||||
ProgramState();
|
||||
~ProgramState();
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ GLenum ProgramState::DeleteShader(GLuint shader) {
|
||||
MG_Util::Debug::LogD("MG_State: Program: DeleteShader info: shader %u marked for deferred deletion (in use)", shader);
|
||||
} else {
|
||||
shaders_.erase(shader);
|
||||
freeShaderIds_.insert(shader);
|
||||
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend.
|
||||
//freeShaderIds_.insert(shader);
|
||||
MG_Util::Debug::LogD("MG_State: Program: DeleteShader success: shader %u deleted immediately", shader);
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
|
||||
@@ -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,8 @@ GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
|
||||
if (it != this->textures.end()) {
|
||||
InvalidateTextureInAllUnits_(id);
|
||||
this->textures.erase(it);
|
||||
freeIDs_.insert(id);
|
||||
// TODO: Prevent the object that uses a freeId from conflicting with legacy object in the backend.
|
||||
//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 +700,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);
|
||||
@@ -803,10 +873,10 @@ GLenum TextureState::CheckUploadingTexture2DValidity_(GLenum target, GLint level
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
bool isDepthInternal = (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH_COMPONENT24
|
||||
|| internalFormat == GL_DEPTH_COMPONENT16 || internalFormat == GL_DEPTH32F_STENCIL8
|
||||
|| internalFormat == GL_DEPTH24_STENCIL8 || internalFormat == GL_DEPTH_COMPONENT
|
||||
|| internalFormat == GL_DEPTH_STENCIL);
|
||||
bool isDepthInternal = (internalFormat == GL_DEPTH_COMPONENT32 || internalFormat == GL_DEPTH_COMPONENT32F ||
|
||||
internalFormat == GL_DEPTH_COMPONENT24 || internalFormat == GL_DEPTH_COMPONENT16 ||
|
||||
internalFormat == GL_DEPTH32F_STENCIL8 || internalFormat == GL_DEPTH24_STENCIL8 ||
|
||||
internalFormat == GL_DEPTH_COMPONENT || internalFormat == GL_DEPTH_STENCIL);
|
||||
bool isDepthFormat = (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL);
|
||||
if (isDepthInternal != isDepthFormat) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity_ depth internal/format mismatch");
|
||||
@@ -895,7 +965,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 +1004,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,24 +47,27 @@ 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:
|
||||
std::vector<TextureUnitState> textureUnits_;
|
||||
GLuint activeTextureUnit_ = 0;
|
||||
|
||||
GLuint lastUsedID_ = 0;
|
||||
std::set<GLuint> freeIDs_;
|
||||
GLuint lastUsedID_ = 1;
|
||||
// ankerl::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:
|
||||
@@ -69,7 +75,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);
|
||||
@@ -88,6 +94,8 @@ public:
|
||||
GLenum DeleteN(GLsizei n, const GLuint* textures);
|
||||
GLenum QueryLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params);
|
||||
|
||||
std::vector<TextureUnitState> textureUnits_;
|
||||
GLuint activeTextureUnit_ = 0;
|
||||
private:
|
||||
size_t CalculatePixelDataSize_(GLenum format, GLenum type, GLsizei width, GLsizei height);
|
||||
void InvalidateTextureInAllUnits_(GLuint texture);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "../../../Includes.h"
|
||||
|
||||
struct VertexAttribState {
|
||||
bool enabled = false;
|
||||
bool enabled;
|
||||
GLint size = 4;
|
||||
GLenum type = GL_FLOAT;
|
||||
GLboolean normalized = GL_FALSE;
|
||||
@@ -21,8 +21,10 @@ struct VertexAttribState {
|
||||
|
||||
struct VertexArrayObject {
|
||||
bool generated = false;
|
||||
bool attribDirty = false;
|
||||
bool eboDirty = false;
|
||||
GLuint elementBuffer = 0;
|
||||
std::unordered_map<GLuint, VertexAttribState> attribs;
|
||||
ankerl::unordered_map<GLuint, VertexAttribState> attribs;
|
||||
};
|
||||
|
||||
class VertexArrayState {
|
||||
@@ -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,12 +46,14 @@ public:
|
||||
|
||||
GLuint GetBoundElementBuffer();
|
||||
VertexArrayObject* GetCurrentVAO();
|
||||
bool ValidateGeneratedName(GLuint array);
|
||||
bool ValidateAllocatedHandle(GLuint array);
|
||||
|
||||
GLuint currentVao_ = 0;
|
||||
ankerl::unordered_map<GLuint, VertexArrayObject> vaos_;
|
||||
private:
|
||||
std::unordered_map<GLuint, VertexArrayObject> vaos_;
|
||||
std::set<GLuint> freeIds_;
|
||||
GLuint lastId_ = 0;
|
||||
GLuint currentVao_ = 0;
|
||||
};
|
||||
|
||||
#endif //MOBILEGL_VERTEXARRAYSTATE_H
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace MG_RHI::GLES::Test {
|
||||
GLuint quadVBO = 0;
|
||||
GLint uTexLoc = -1;
|
||||
GLint uMVPLoc = -1;
|
||||
std::unordered_map<GLuint, GLuint> textureCache;
|
||||
std::unordered_map<GLuint, bool> textureDirty;
|
||||
ankerl::unordered_map<GLuint, GLuint> textureCache;
|
||||
ankerl::unordered_map<GLuint, bool> textureDirty;
|
||||
};
|
||||
|
||||
static ScreenResources sRes;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace MG_Util::Program {
|
||||
std::ostringstream ss;
|
||||
ss << "[";
|
||||
|
||||
const size_t elemCount = std::min<size_t>(value.count, 16); // 限制最大显示元素
|
||||
const size_t elemCount = std::min<size_t>(value.count, 16);
|
||||
|
||||
switch(value.type) {
|
||||
case GL_FLOAT:
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace MG_Util::Program {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_set<GLint> used_locations;
|
||||
ankerl::unordered_set<GLint> used_locations;
|
||||
GLint auto_location = 0;
|
||||
for (auto spirv: allSpirv) {
|
||||
spvc_parsed_ir ir = nullptr;
|
||||
@@ -395,11 +395,44 @@ namespace MG_Util::Program {
|
||||
prog.uniformLocations[name] = final_location;
|
||||
UniformValue uniformValue;
|
||||
uniformValue.type = gl_type;
|
||||
uniformValue.count = spvc_type_get_array_dimension(type, 0) > 0 ?
|
||||
spvc_type_get_array_dimension(type, 0) : 1;
|
||||
prog.uniformValues[name] = uniformValue;
|
||||
}
|
||||
}
|
||||
spvc_context_destroy(context);
|
||||
}
|
||||
|
||||
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES) {
|
||||
spvc_context context = nullptr;
|
||||
spvc_parsed_ir ir = nullptr;
|
||||
spvc_compiler compiler_glsl = nullptr;
|
||||
spvc_compiler_options options = nullptr;
|
||||
spvc_resources resources = nullptr;
|
||||
const spvc_reflected_resource *list = nullptr;
|
||||
const char *result = nullptr;
|
||||
size_t count;
|
||||
|
||||
const SpvId *p_spirv = spirv.data();
|
||||
size_t word_count = spirv.size();
|
||||
|
||||
spvc_context_create(&context);
|
||||
spvc_context_parse_spirv(context, p_spirv, word_count, &ir);
|
||||
spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir, SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler_glsl);
|
||||
spvc_compiler_create_shader_resources(compiler_glsl, &resources);
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
|
||||
spvc_compiler_create_compiler_options(compiler_glsl, &options);
|
||||
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, glslVersion);
|
||||
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, isES ? SPVC_TRUE : SPVC_FALSE);
|
||||
spvc_compiler_install_compiler_options(compiler_glsl, options);
|
||||
spvc_compiler_compile(compiler_glsl, &result);
|
||||
|
||||
if (!result) {
|
||||
return{};
|
||||
}
|
||||
|
||||
std::string essl = result;
|
||||
|
||||
spvc_context_destroy(context);
|
||||
|
||||
return essl;
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,7 @@ namespace MG_Util::Program {
|
||||
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader);
|
||||
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog);
|
||||
void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog);
|
||||
std::string CompileSPIRVToGLSL(std::vector<unsigned int> spirv, uint glslVersion, bool isES);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GLSLTOOL_H
|
||||
|
||||
+20
-11
@@ -4,7 +4,7 @@
|
||||
- [x] glGetAttribLocation
|
||||
- [x] glGetBufferParameteriv
|
||||
- [x] glGetError
|
||||
- [ ] glGetIntegerv
|
||||
- [x] glGetIntegerv
|
||||
- [x] glGetProgramiv
|
||||
- [x] glGetShaderiv
|
||||
- [x] glGetString
|
||||
@@ -33,6 +33,8 @@
|
||||
- [x] glFramebufferTexture2D
|
||||
- [x] glGenFramebuffers
|
||||
|
||||
~~glBlitFramebuffer~~
|
||||
|
||||
---
|
||||
|
||||
### **4. Shader & Program Management**
|
||||
@@ -60,6 +62,10 @@
|
||||
- [x] glUnmapBuffer
|
||||
- [x] glVertexAttribIPointer
|
||||
- [x] glVertexAttribPointer
|
||||
- [x] glBufferSubData
|
||||
- [x] glMapBufferRange
|
||||
- [x] glFlushMappedBufferRange
|
||||
- [x] glCopyBufferSubData
|
||||
|
||||
---
|
||||
|
||||
@@ -90,28 +96,27 @@
|
||||
---
|
||||
|
||||
### **8. Drawing Commands**
|
||||
- [ ] glDrawElements
|
||||
- [ ] glDrawArrays
|
||||
~~glDrawElements~~
|
||||
|
||||
## Abstraction Layer (MG_RHI)
|
||||
|
||||
### **1. Initialization & Query Functions**
|
||||
|
||||
glGetAttribLocation~~
|
||||
~~glGetAttribLocation~~
|
||||
|
||||
glGetBufferParameteriv~~
|
||||
~~glGetBufferParameteriv~~
|
||||
|
||||
glGetError~~
|
||||
~~glGetError~~
|
||||
|
||||
- [ ] glGetIntegerv
|
||||
~~glGetIntegerv~~
|
||||
- [ ] glGetProgramiv
|
||||
- [ ] glGetShaderiv
|
||||
- [ ] glGetString
|
||||
- [ ] glGetStringi
|
||||
|
||||
glGetTexLevelParameteriv~~
|
||||
~~glGetTexLevelParameteriv~~
|
||||
|
||||
glGetUniformLocation~~
|
||||
~~glGetUniformLocation~~
|
||||
|
||||
---
|
||||
|
||||
@@ -133,6 +138,7 @@ glGetUniformLocation~~
|
||||
- [ ] glDeleteFramebuffers
|
||||
- [ ] glFramebufferTexture2D
|
||||
- [ ] glGenFramebuffers
|
||||
- [ ] glBlitFramebuffer
|
||||
|
||||
---
|
||||
|
||||
@@ -161,6 +167,10 @@ glGetUniformLocation~~
|
||||
- [ ] glUnmapBuffer
|
||||
- [ ] glVertexAttribIPointer
|
||||
- [ ] glVertexAttribPointer
|
||||
- [ ] glBufferSubData
|
||||
- [ ] glMapBufferRange
|
||||
- [ ] glFlushMappedBufferRange
|
||||
- [ ] glCopyBufferSubData
|
||||
|
||||
---
|
||||
|
||||
@@ -191,5 +201,4 @@ glGetUniformLocation~~
|
||||
---
|
||||
|
||||
### **8. Drawing Commands**
|
||||
- [ ] glDrawElements
|
||||
- [ ] glDrawArrays
|
||||
- [ ] glDrawElements
|
||||
@@ -6,7 +6,11 @@
|
||||
|
||||
**glslang** by **KhronosGroup**: [github](https://github.com/KhronosGroup/glslang)
|
||||
|
||||
**GlslOptimizerV2** by **aiekick**: [github](https://github.com/aiekick/GlslOptimizerV2)
|
||||
*(Unused Currently)* **GlslOptimizerV2** by **aiekick**: [github](https://github.com/aiekick/GlslOptimizerV2)
|
||||
|
||||
**unordered_dense** by **Martin Leitner-Ankerl**: [github](https://github.com/martinus/unordered_dense)
|
||||
|
||||
**OpenGL Mathematics (*GLM*)** by **G-Truc Creation**: [github](https://github.com/g-truc/glm)
|
||||
|
||||
## Progress
|
||||
|
||||
@@ -21,12 +25,12 @@
|
||||
|
||||
---
|
||||
|
||||
**Target**: **OpenGL implementation compatible with Minecraft 1.17 to 1.21.1**
|
||||
**Target**: **OpenGL implementation compatible with Minecraft 1.17 to 1.21.5**
|
||||
|
||||
| Component | Development Progress\* |
|
||||
|--------------------------------|------------------------|
|
||||
| **OpenGL State Manager** | **59 / 62** |
|
||||
| **Abstraction Layer (MG_RHI)** | **0 / 57** |
|
||||
| **OpenGL State Manager** | **65 / 65** |
|
||||
| **Abstraction Layer (MG_RHI)** | **0 / 61** |
|
||||
| **OpenGL ES Backend** | **N/A** (of MG_RHI) |
|
||||
| **Vulkan Backend** | **planned** |
|
||||
|
||||
|
||||
@@ -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