mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (...): Add global OpenGL state. Add gl texture state (almost complete for Minecraft) and implementation gl texture functions that Minecraft would use. Add gl error state.
This commit is contained in:
@@ -44,6 +44,11 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
MG/MG_GL/GL/Texture/GL_Texture.cpp
|
||||
|
||||
MG/MG_GL/GL/VertexArray/GL_VertexArray.cpp
|
||||
|
||||
# MG_GL/State
|
||||
MG/MG_GL/State/Core/GLState.cpp
|
||||
|
||||
MG/MG_GL/State/Texture/TextureState.cpp
|
||||
|
||||
# MG_GL/GLX
|
||||
MG/MG_GL/GLX/LookUp/LookUp.cpp
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#endif
|
||||
#define MG_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include <array>
|
||||
#include <unordered_set>
|
||||
#include <GL/gl.h>
|
||||
|
||||
namespace MG_Constants {
|
||||
namespace Common {
|
||||
inline const int LOG_LEVEL_DEBUG = 0x0010;
|
||||
@@ -18,6 +22,58 @@ namespace MG_Constants {
|
||||
inline const int LOG_LEVEL_INFO = 0x0013;
|
||||
inline const int LOG_LEVEL_FATAL = 0x0014;
|
||||
}
|
||||
|
||||
namespace Texture {
|
||||
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 = {
|
||||
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 = {
|
||||
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 = {
|
||||
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,
|
||||
GL_R11F_G11F_B10F, GL_RG32F, GL_RG32I, GL_RG32UI, GL_RG16, GL_RG16F, GL_RGB16I,
|
||||
GL_RGB16UI, GL_RG8, GL_RG8I, GL_RG8UI, GL_R32F, GL_R32I, GL_R32UI, GL_R16F,
|
||||
GL_R16I, GL_R16UI, GL_R8, GL_R8I, GL_R8UI, GL_RGBA16_SNORM, GL_RGBA8_SNORM,
|
||||
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
|
||||
}; // OpenGL 3
|
||||
|
||||
inline const std::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,
|
||||
GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8,
|
||||
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 = {
|
||||
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 = {
|
||||
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
|
||||
}; // OpenGL 3
|
||||
}
|
||||
|
||||
namespace Backend {
|
||||
#define BACKEND_VULKAN 0x0015
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
#ifndef MOBILEGL_GL_VERTEXARRAY_H
|
||||
#include "MG_GL/GL/VertexArray/GL_VertexArray.h"
|
||||
#endif
|
||||
#ifndef MOBILEGL_GLSTATE_H
|
||||
#include "MG_GL/State/Core/GLState.h"
|
||||
#endif
|
||||
#ifndef MOBILEGL_TEXTURESTATE_H
|
||||
#include "MG_GL/State/Texture/TextureState.h"
|
||||
#endif
|
||||
#ifndef MOBILEGL_LOOKUP_H
|
||||
#include "MG_GL/GLX/LookUp/LookUp.h"
|
||||
#endif
|
||||
@@ -64,6 +70,7 @@
|
||||
#include <array>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <glslang/Include/Types.h>
|
||||
|
||||
@@ -7,4 +7,10 @@
|
||||
__attribute__((constructor)) void MG_Initialize() {
|
||||
MG_Util::Debug::LogInit();
|
||||
MG_Util::Debug::LogI("MobileGL Initializing...");
|
||||
MG_State::Init();
|
||||
}
|
||||
|
||||
__attribute__((destructor)) void MG_Destroy() {
|
||||
MG_Util::Debug::LogI("MobileGL Exiting...");
|
||||
MG_State::Destroy();
|
||||
}
|
||||
@@ -110,8 +110,9 @@ namespace MG_GL::GL {
|
||||
}
|
||||
|
||||
GLenum GetError() {
|
||||
MG_Util::Debug::LogD("glGetError");
|
||||
return GL_NO_ERROR;
|
||||
GLenum error = MG_State::GetError();
|
||||
MG_Util::Debug::LogD("glGetError -> %s", MG_Util::Debug::GLEnumToString(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
void GetIntegerv(GLenum pname, GLint *params) {
|
||||
@@ -153,8 +154,4 @@ namespace MG_GL::GL {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ namespace MG_GL::GL {
|
||||
const ::GLubyte* GetStringi(GLenum name, GLuint index);
|
||||
::GLenum GetError();
|
||||
void GetIntegerv(GLenum pname, GLint *params);
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GL_GETTER_H
|
||||
|
||||
@@ -5,5 +5,89 @@
|
||||
#include "GL_Texture.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
|
||||
void ActiveTexture(GLenum texture) {
|
||||
MG_Util::Debug::LogD("glActiveTexture, texture: %d", texture);
|
||||
GLenum result = MG_State::BindTextureUnit(texture);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void BindTexture(GLenum target, GLuint texture) {
|
||||
MG_Util::Debug::LogD("glBindTexture, target: %d, texture: %d", target, texture);
|
||||
GLenum result = MG_State::BindTexture(target, texture);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void DeleteTextures(GLsizei n, const GLuint* textures) {
|
||||
MG_Util::Debug::LogD("glDeleteTextures, n: %d, textures: %p", n, textures);
|
||||
GLenum result = MG_State::DeleteTextures(n, textures);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void GenTextures(GLsizei n, GLuint* textures) {
|
||||
MG_Util::Debug::LogD("glGenTextures, n: %d, textures: %p", n, textures);
|
||||
GLenum result = MG_State::CreateTextures(n, textures);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border,
|
||||
GLenum format, GLenum type, const void* data) {
|
||||
MG_Util::Debug::LogD("glTexImage2D, target: %d, level: %d, internalFormat: %d, width: %d, height: %d, format: %d, type: %d, data: %p",
|
||||
target, level, internalFormat, width, height, format, type, data);
|
||||
GLenum result = MG_State::UploadTexture2D(target, level, internalFormat, width, height, border, format, type, data);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
||||
MG_Util::Debug::LogD("glTexParameterf, target: %d, pname: %d, param: %f", target, pname, param);
|
||||
GLenum result = MG_State::SetTexturePropertyFloat(target, pname, param);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
MG_Util::Debug::LogD("glTexParameteri, target: %d, pname: %d, param: %d", target, pname, param);
|
||||
GLenum result = MG_State::SetTexturePropertyInt(target, pname, param);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
||||
GLsizei height, GLenum format, GLenum type, const void* pixels) {
|
||||
MG_Util::Debug::LogD("glTexSubImage2D, target: %d, level: %d, xoffset: %d, yoffset: %d, width: %d, height: %d, format: %d, type: %d, pixels: %p",
|
||||
target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
GLenum result = MG_State::UpdateTextureRegion2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
if (result == GL_NO_ERROR)
|
||||
return;
|
||||
MG_State::SetError(result);
|
||||
MG_Util::Debug::LogE("Error from MG State: %s", MG_Util::Debug::GLEnumToString(result));
|
||||
}
|
||||
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
|
||||
MG_Util::Debug::LogD("glGetTexLevelParameteriv, target: %d, level: %d, pname: %d, params: %p",
|
||||
target, level, pname, params);
|
||||
GLenum result = MG_State::GetTextureLevelPropertyIntVector(target, level, pname, params);
|
||||
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,7 +8,15 @@
|
||||
#include "../../../Includes.h"
|
||||
|
||||
namespace MG_GL::GL {
|
||||
|
||||
void ActiveTexture(GLenum texture);
|
||||
void BindTexture(GLenum target, GLuint texture);
|
||||
void DeleteTextures(GLsizei n, const GLuint* textures);
|
||||
void GenTextures(GLsizei n, GLuint* textures);
|
||||
void TexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data);
|
||||
void TexParameterf(GLenum target, GLenum pname, GLfloat param);
|
||||
void TexParameteri(GLenum target, GLenum pname, GLint param);
|
||||
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
|
||||
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_GL_TEXTURE_H
|
||||
|
||||
+11
-11
@@ -20,12 +20,12 @@ extern "C" MG_EXPORT type gl##name(__VA_ARGS__) {
|
||||
extern "C" MG_EXPORT type gl##name(__VA_ARGS__) {
|
||||
|
||||
#define DECLARE_GL_FUNCTION_END(type,name,...) \
|
||||
MG_Util::Debug::LogD("Emulating function: %s(...)", __FUNCTION__); \
|
||||
MG_Util::Debug::LogD("Implementing function: %s(...)", __FUNCTION__); \
|
||||
return MG_GL::GL::name(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \
|
||||
MG_Util::Debug::LogD("Emulating function: %s(...)", __FUNCTION__); \
|
||||
MG_Util::Debug::LogD("Implementing function: %s(...)", __FUNCTION__); \
|
||||
MG_GL::GL::name(__VA_ARGS__); \
|
||||
}
|
||||
|
||||
@@ -33,13 +33,13 @@ DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetStringi, GLenum name, GLuint index)
|
||||
DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetString, GLenum name) DECLARE_GL_FUNCTION_END(const GLubyte*, GetString, name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void*, MapBuffer, GLenum target, GLenum access) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void*, MapBuffer, target, access)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClearDepth, GLclampd depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearDepth, depth)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ActiveTexture, GLenum texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ActiveTexture, texture)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ActiveTexture, GLenum texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ActiveTexture, texture)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, AttachShader, GLuint program, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, AttachShader, program,shader)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindAttribLocation, GLuint program, GLuint index, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindAttribLocation, program,index,name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBuffer, GLenum target, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBuffer, target,buffer)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindFramebuffer, GLenum target, GLuint framebuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindFramebuffer, target,framebuffer)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindRenderbuffer, GLenum target, GLuint renderbuffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindRenderbuffer, target,renderbuffer)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindTexture, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindTexture, target,texture)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BindTexture, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTexture, target,texture)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendColor, red,green,blue,alpha)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquation, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquation, mode)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparate, modeRGB,modeAlpha)
|
||||
@@ -66,7 +66,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteFramebuffers, GLsizei n, const GLuint
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteProgram, GLuint program) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteProgram, program)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteRenderbuffers, GLsizei n, const GLuint *renderbuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteRenderbuffers, n,renderbuffers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteShader, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteShader, shader)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DeleteTextures, GLsizei n, const GLuint *textures) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DeleteTextures, n,textures)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, DeleteTextures, GLsizei n, const GLuint *textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DeleteTextures, n,textures)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthFunc, GLenum func) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthFunc, func)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthMask, GLboolean flag) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthMask, flag)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangef, GLfloat n, GLfloat f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangef, n,f)
|
||||
@@ -86,7 +86,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GenBuffers, GLsizei n, GLuint *buffers) DECL
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateMipmap, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateMipmap, target)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenFramebuffers, GLsizei n, GLuint *framebuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenFramebuffers, n,framebuffers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenRenderbuffers, GLsizei n, GLuint *renderbuffers) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenRenderbuffers, n,renderbuffers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GenTextures, GLsizei n, GLuint *textures) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenTextures, n,textures)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GenTextures, GLsizei n, GLuint *textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenTextures, n,textures)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveAttrib, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveAttrib, program,index,bufSize,length,size,type,name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniform, program,index,bufSize,length,size,type,name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetAttachedShaders, program,maxCount,count,shaders)
|
||||
@@ -137,12 +137,12 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, StencilMask, GLuint mask) DECLARE_GL_FUNCTIO
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, StencilMaskSeparate, GLenum face, GLuint mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, StencilMaskSeparate, face,mask)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, StencilOp, GLenum fail, GLenum zfail, GLenum zpass) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, StencilOp, fail,zfail,zpass)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, StencilOpSeparate, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, StencilOpSeparate, face,sfail,dpfail,dppass)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage2D, target,level,internalformat,width,height,border,format,type,pixels)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterf, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameterf, target,pname,param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage2D, target,level,internalformat,width,height,border,format,type,pixels)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexParameterf, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameterf, target,pname,param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterfv, GLenum target, GLenum pname, const GLfloat *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameterfv, target,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameteri, target,pname,param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameteri, target,pname,param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameteriv, GLenum target, GLenum pname, const GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameteriv, target,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexSubImage2D, target,level,xoffset,yoffset,width,height,format,type,pixels)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexSubImage2D, target,level,xoffset,yoffset,width,height,format,type,pixels)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1f, GLint location, GLfloat v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1f, location,v0)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1fv, location,count,value)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1i, GLint location, GLint v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1i, location,v0)
|
||||
@@ -337,7 +337,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, MemoryBarrierByRegion, GLbitfield barriers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage2DMultisample, target,samples,internalformat,width,height,fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultisamplefv, GLenum pname, GLuint index, GLfloat *val) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultisamplefv, pname,index,val)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, SampleMaski, GLuint maskNumber, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SampleMaski, maskNumber,mask)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTexLevelParameteriv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexLevelParameteriv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTexLevelParameterfv, target,level,pname,params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindVertexBuffer, bindingindex,buffer,offset,stride)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribFormat, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribFormat, attribindex,size,type,normalized,relativeoffset)
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/4/4.
|
||||
//
|
||||
|
||||
#include "GLState.h"
|
||||
|
||||
TextureState* MG_State_T::textureState;
|
||||
std::queue<GLenum> MG_State_T::glErrorQueue;
|
||||
|
||||
namespace MG_State {
|
||||
MG_State_T* MG_State_O;
|
||||
|
||||
void Init() {
|
||||
MG_State_O = new MG_State_T();
|
||||
MG_State_T::textureState = new TextureState();
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
delete MG_State_O;
|
||||
}
|
||||
|
||||
void SetError(GLenum error) {
|
||||
if (error == GL_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
MG_State_T::glErrorQueue.push(error);
|
||||
}
|
||||
|
||||
GLenum GetError() {
|
||||
if (MG_State_T::glErrorQueue.empty()) {
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
GLenum error = MG_State_T::glErrorQueue.front();
|
||||
MG_State_T::glErrorQueue.pop();
|
||||
return error;
|
||||
}
|
||||
|
||||
// Texture
|
||||
GLenum BindTextureUnit(GLenum textureUnit) {
|
||||
return MG_State_T::textureState->BindUnit(textureUnit);
|
||||
}
|
||||
|
||||
GLenum CreateTexture(GLuint* texture) {
|
||||
return MG_State_T::textureState->Create(texture);
|
||||
}
|
||||
|
||||
GLenum CreateTextures(GLsizei n, GLuint* textures) {
|
||||
return MG_State_T::textureState->CreateN(n, textures);
|
||||
}
|
||||
|
||||
GLenum BindTexture(GLenum target, GLuint texture) {
|
||||
return MG_State_T::textureState->Bind(target, texture);
|
||||
}
|
||||
|
||||
GLenum UploadTexture2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data) {
|
||||
return MG_State_T::textureState->Upload2D(target, level, internalFormat, width, height, border, format, type, data);
|
||||
}
|
||||
|
||||
GLenum UpdateTextureRegion2D(GLenum target, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const GLvoid* data) {
|
||||
return MG_State_T::textureState->UpdateRegion2D(target, level, xoffset, yoffset, width, height, format, type, data);
|
||||
}
|
||||
|
||||
GLenum SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) {
|
||||
return MG_State_T::textureState->SetTexturePropertyInt(target, pname, param);
|
||||
}
|
||||
|
||||
GLenum SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) {
|
||||
return MG_State_T::textureState->SetTexturePropertyFloat(target, pname, param);
|
||||
}
|
||||
|
||||
GLenum DeleteTexture(GLuint texture) {
|
||||
return MG_State_T::textureState->Delete(texture);
|
||||
}
|
||||
|
||||
GLenum DeleteTextures(GLsizei n, const GLuint* textures) {
|
||||
return MG_State_T::textureState->DeleteN(n, textures);
|
||||
}
|
||||
|
||||
GLenum GetTextureLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) {
|
||||
return MG_State_T::textureState->GetLevelPropertyIntVector(target, level, pname, params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/4/4.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGL_GLSTATE_H
|
||||
#define MOBILEGL_GLSTATE_H
|
||||
|
||||
#include "../../../Includes.h"
|
||||
|
||||
struct MG_State_T {
|
||||
static std::queue<GLenum> glErrorQueue;
|
||||
static TextureState* textureState;
|
||||
};
|
||||
|
||||
namespace MG_State {
|
||||
extern MG_State_T* MG_State_O;
|
||||
|
||||
void Init();
|
||||
void Destroy();
|
||||
void SetError(GLenum error);
|
||||
GLenum GetError();
|
||||
|
||||
//Texture
|
||||
GLenum BindTextureUnit(GLenum textureUnit);
|
||||
GLenum CreateTexture(GLuint* texture);
|
||||
GLenum CreateTextures(GLsizei n, GLuint* textures);
|
||||
GLenum BindTexture(GLenum target, GLuint texture);
|
||||
GLenum UploadTexture2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data);
|
||||
GLenum UpdateTextureRegion2D(GLenum target, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const GLvoid* data);
|
||||
GLenum SetTexturePropertyInt(GLenum target, GLenum pname, GLint param);
|
||||
GLenum SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param);
|
||||
GLenum DeleteTexture(GLuint texture);
|
||||
GLenum DeleteTextures(GLsizei n, const GLuint* textures);
|
||||
GLenum GetTextureLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params);
|
||||
}
|
||||
|
||||
|
||||
#endif //MOBILEGL_GLSTATE_H
|
||||
@@ -0,0 +1,935 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/4/4.
|
||||
//
|
||||
|
||||
#include "TextureState.h"
|
||||
|
||||
// TextureObject
|
||||
|
||||
bool TextureObject::IsImmutable() const {
|
||||
bool immutable = params.texPropertiesInt.count(GL_TEXTURE_IMMUTABLE_FORMAT);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: TextureObject::IsImmutable returns %d", immutable);
|
||||
return immutable;
|
||||
}
|
||||
|
||||
// TextureUnitState
|
||||
|
||||
void TextureUnitState::Bind(GLenum target, GLuint texture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: TextureUnitState::Bind target=0x%x texture=%u", target, texture);
|
||||
boundTextures[target] = texture;
|
||||
}
|
||||
|
||||
GLuint TextureUnitState::GetBoundTexture(GLenum target) {
|
||||
auto it = boundTextures.find(target);
|
||||
GLuint tex = (it != boundTextures.end()) ? it->second : 0;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: TextureUnitState::GetBoundTexture target=0x%x returns %u", target, tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
// TextureState
|
||||
|
||||
TextureState::TextureState() {
|
||||
textureUnits.resize(MG_Constants::Texture::MAX_TEXTURE_UNITS);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: TextureState constructor, textureUnits=%zu", textureUnits.size());
|
||||
}
|
||||
|
||||
TextureState &TextureState::GetInstance() {
|
||||
static TextureState instance;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetInstance called");
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool TextureState::IsTextureGenerated(GLuint texture) {
|
||||
bool isValidTextureNumber = texture != 0;
|
||||
bool isValidTexture;
|
||||
bool generated = false;
|
||||
if (!isValidTextureNumber) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture == 0");
|
||||
} else {
|
||||
isValidTexture = textures.find(texture) != textures.end();
|
||||
if (!isValidTexture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
||||
} else {
|
||||
generated = textures.at(texture).generated;
|
||||
if (!generated) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture %d not generated", texture, generated);
|
||||
}
|
||||
}
|
||||
}
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture=%u returns %d", texture, generated);
|
||||
return generated;
|
||||
}
|
||||
|
||||
bool TextureState::IsTexture(GLuint texture) {
|
||||
bool isTex = texture != 0 && textures.find(texture) != textures.end();
|
||||
MG_Util::Debug::LogD("MG_State: Texture: IsTexture texture=%u returns %d", texture, isTex);
|
||||
return isTex;
|
||||
}
|
||||
|
||||
GLenum TextureState::BindUnit(GLenum textureUnit) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: BindUnit textureUnit=0x%x", textureUnit);
|
||||
GLuint unitIndex = textureUnit - GL_TEXTURE0;
|
||||
if (unitIndex < textureUnits.size()) {
|
||||
activeTextureUnit = unitIndex;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: BindUnit set activeTextureUnit=%u", activeTextureUnit);
|
||||
} else {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: BindUnit invalid texture unit 0x%x", textureUnit);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::Create(GLuint* texture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Create called");
|
||||
if (!texture) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Create received null pointer");
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
return CreateN(1, texture);
|
||||
}
|
||||
|
||||
GLenum TextureState::CreateN(GLsizei n, GLuint* textures) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN called with n=%d", n);
|
||||
if (n < 1) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CreateN invalid n=%d", n);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
for (GLsizei i = 0; i < n; ++i) {
|
||||
GLuint id = 0;
|
||||
if (!freeIDs.empty()) {
|
||||
id = *freeIDs.begin();
|
||||
freeIDs.erase(freeIDs.begin());
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
||||
} else {
|
||||
id = ++lastUsedID;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
||||
}
|
||||
TextureObject obj;
|
||||
obj.generated = true;
|
||||
this->textures[id] = obj;
|
||||
textures[i] = id;
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::Bind(GLenum target, GLuint texture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Bind called with target=0x%x, texture=%u", target, texture);
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Bind invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (texture == 0) {
|
||||
TextureUnitState& unit = textureUnits[activeTextureUnit];
|
||||
unit.Bind(target, 0);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Bind unbind succeeded for target=0x%x", target);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
if (!IsTextureGenerated(texture)) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Bind texture %u not generated", texture);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto texObjIt = textures.find(texture);
|
||||
if(texObjIt != textures.end()){
|
||||
if (texObjIt->second.target != target && texObjIt->second.target != GL_NONE) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Bind texture %u bound to different target 0x%x", texture, texObjIt->second.target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextureUnitState& unit = textureUnits[activeTextureUnit];
|
||||
TextureObject* texObj = nullptr;
|
||||
auto it = this->textures.find(texture);
|
||||
if (it == this->textures.end()) {
|
||||
MG_Util::Debug::LogW("MG_State: Texture: Bind texture %u not found, creating new (non-generated)", texture);
|
||||
TextureObject newObj;
|
||||
newObj.generated = false;
|
||||
this->textures[texture] = newObj;
|
||||
texObj = &this->textures[texture];
|
||||
} else {
|
||||
texObj = &it->second;
|
||||
}
|
||||
|
||||
if (texObj->target == GL_NONE) {
|
||||
texObj->target = target;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Bind setting target=0x%x for texture %u", target, texture);
|
||||
} else if (texObj->target != target) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Bind mismatch target for texture %u, expected 0x%x, got 0x%x", texture, texObj->target, target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
unit.Bind(target, texture);
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Bind succeeded for texture %u on target=0x%x", texture, target);
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
size_t TextureState::CalculatePixelDataSize(GLenum format, GLenum type, GLsizei width, GLsizei height) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CalculatePixelDataSize called format=0x%x, type=0x%x, width=%d, height=%d", format, type, width, height);
|
||||
size_t bytesPerPixel = 0;
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE_3_3_2:
|
||||
case GL_UNSIGNED_BYTE_2_3_3_REV:
|
||||
bytesPerPixel = 1;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
|
||||
case GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
bytesPerPixel = 2;
|
||||
break;
|
||||
case GL_UNSIGNED_INT_8_8_8_8:
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_INT_10_10_10_2:
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||
bytesPerPixel = 4;
|
||||
default: {
|
||||
int components = 0;
|
||||
switch (format) {
|
||||
case GL_RED: components = 1; break;
|
||||
case GL_RG: components = 2; break;
|
||||
case GL_RGB:
|
||||
case GL_BGR: components = 3; break;
|
||||
case GL_RGBA:
|
||||
case GL_BGRA: components = 4; break;
|
||||
case GL_DEPTH_COMPONENT: components = 1; break;
|
||||
case GL_DEPTH_STENCIL: components = 2; break;
|
||||
default: components = 0; break;
|
||||
}
|
||||
size_t typeSize = 0;
|
||||
switch (type) {
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE: typeSize = 1; break;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT: typeSize = 2; break;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
case GL_FLOAT: typeSize = 4; break;
|
||||
default: typeSize = 0; break;
|
||||
}
|
||||
bytesPerPixel = components * typeSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t totalSize = static_cast<size_t>(width) * static_cast<size_t>(height) * bytesPerPixel;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CalculatePixelDataSize returns %zu", totalSize);
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D called target=0x%x, level=%d, width=%d, height=%d", target, level, width, height);
|
||||
GLenum validity = CheckUploadingTexture2DValidity(target, level, internalFormat, width, height, border, format, type, data);
|
||||
if (validity != GL_NO_ERROR) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Upload2D CheckUploadingTexture2DValidity failed with error 0x%x", validity);
|
||||
return validity;
|
||||
}
|
||||
|
||||
bool isProxyTexture = (target == GL_PROXY_TEXTURE_1D || target == GL_PROXY_TEXTURE_2D ||
|
||||
target == GL_PROXY_TEXTURE_3D || target == GL_PROXY_TEXTURE_CUBE_MAP ||
|
||||
target == GL_PROXY_TEXTURE_1D_ARRAY || target == GL_PROXY_TEXTURE_2D_ARRAY ||
|
||||
target == GL_PROXY_TEXTURE_RECTANGLE || target == GL_PROXY_TEXTURE_2D_MULTISAMPLE ||
|
||||
target == GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
|
||||
if (isProxyTexture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D proxy texture detected");
|
||||
TextureObject& proxyTex = proxyTextures[target];
|
||||
TextureParams::MipmapLevel mip{};
|
||||
mip.width = width;
|
||||
mip.height = height;
|
||||
mip.internalFormat = internalFormat;
|
||||
mip.format = format;
|
||||
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{};
|
||||
mip.width = width;
|
||||
mip.height = height;
|
||||
mip.internalFormat = internalFormat;
|
||||
mip.format = format;
|
||||
mip.type = type;
|
||||
if (data != nullptr) {
|
||||
size_t dataSize = CalculatePixelDataSize(format, type, width, height);
|
||||
mip.pixelData.resize(dataSize);
|
||||
memcpy(mip.pixelData.data(), data, dataSize);
|
||||
mip.hasData = true;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D uploaded data size=%zu", dataSize);
|
||||
} else {
|
||||
mip.hasData = false;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D data pointer is null");
|
||||
}
|
||||
tex.data = data;
|
||||
tex.params.mipmapData[level] = mip;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D succeeded for level=%d", level);
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const GLvoid* data) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D called target=0x%x, level=%d, x=%d, y=%d, w=%d, h=%d",
|
||||
target, level, xoffset, yoffset, width, height);
|
||||
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (level < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D invalid level=%d", level);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (xoffset < 0 || yoffset < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D negative offset x=%d, y=%d", xoffset, yoffset);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D negative dimensions w=%d, h=%d", width, height);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
// TODO: need to impl PBO and then impl here
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D data pointer is null");
|
||||
return GL_INVALID_OPERATION ;
|
||||
}
|
||||
|
||||
GLuint boundTex = textureUnits[activeTextureUnit].GetBoundTexture(target);
|
||||
if (boundTex == 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D no texture bound for target=0x%x", target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (!IsTextureGenerated(boundTex)) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D texture %u not generated", boundTex);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto tex = textures[boundTex];
|
||||
|
||||
if (tex.IsImmutable()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D texture is immutable");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto mipIt = tex.params.mipmapData.find(level);
|
||||
if (mipIt == tex.params.mipmapData.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D no mipmap level %d", level);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
TextureParams::MipmapLevel& mip = mipIt->second;
|
||||
|
||||
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D invalid format=0x%x", format);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D invalid type=0x%x", type);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
bool typeNeedsRGB = (type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_BYTE_2_3_3_REV ||
|
||||
type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV);
|
||||
if (typeNeedsRGB && format != GL_RGB) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D type requires RGB format");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
bool typeNeedsRGBA = (type == GL_UNSIGNED_SHORT_4_4_4_4 || type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
|
||||
type == GL_UNSIGNED_SHORT_5_5_5_1 || type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
|
||||
type == GL_UNSIGNED_INT_8_8_8_8 || type == GL_UNSIGNED_INT_8_8_8_8_REV ||
|
||||
type == GL_UNSIGNED_INT_10_10_10_2 || type == GL_UNSIGNED_INT_2_10_10_10_REV);
|
||||
if (typeNeedsRGBA && format != GL_RGBA && format != GL_BGRA) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D type requires RGBA/BGRA format");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (xoffset + width > mip.width || yoffset + height > mip.height) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D region out of bounds: "
|
||||
"x=%d+%d > %d or y=%d+%d > %d",
|
||||
xoffset, width, mip.width, yoffset, height, mip.height);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
bool isDepthInternal = (mip.internalFormat == GL_DEPTH_COMPONENT ||
|
||||
mip.internalFormat == GL_DEPTH_COMPONENT16 ||
|
||||
mip.internalFormat == GL_DEPTH_COMPONENT24 ||
|
||||
mip.internalFormat == GL_DEPTH_COMPONENT32F ||
|
||||
mip.internalFormat == GL_DEPTH_STENCIL ||
|
||||
mip.internalFormat == GL_DEPTH24_STENCIL8 ||
|
||||
mip.internalFormat == GL_DEPTH32F_STENCIL8);
|
||||
|
||||
bool isDepthFormat = (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL);
|
||||
if (isDepthInternal != isDepthFormat) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: UpdateRegion2D format mismatch with internal format");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
mip.hasData = true;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D validated subimage update");
|
||||
|
||||
tex.data = data;
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
GLenum TextureState::SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat called target=0x%x, pname=0x%x, param=%f", target, pname, param);
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid pname=0x%x", pname);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_BORDER_COLOR:
|
||||
break;
|
||||
case GL_TEXTURE_MIN_LOD:
|
||||
if(param < -1000.0f){
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat param for GL_TEXTURE_MIN_LOD too low: %f", param);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_MAX_LOD:
|
||||
if(param > 1000.0f){
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat param for GL_TEXTURE_MAX_LOD too high: %f", param);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_LOD_BIAS:
|
||||
if(param < -1000.0f || param > 1000.0f) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat param for GL_TEXTURE_LOD_BIAS out of range: %f", param);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_R:
|
||||
case GL_TEXTURE_SWIZZLE_G:
|
||||
case GL_TEXTURE_SWIZZLE_B:
|
||||
case GL_TEXTURE_SWIZZLE_A:
|
||||
if (param != GL_ZERO && param != GL_ONE && param != GL_RED && param != GL_GREEN && param != GL_BLUE && param != GL_ALPHA) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyFloat invalid swizzle param=%f", param);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GLuint boundTex = textureUnits[activeTextureUnit].GetBoundTexture(target);
|
||||
TextureObject& tex = textures[boundTex];
|
||||
tex.params.texPropertiesFloat[pname] = param;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyFloat succeeded for texture %u", boundTex);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::SetTexturePropertyInt(GLenum target, GLenum pname, GLint param) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt called target=0x%x, pname=0x%x, param=%d", target, pname, param);
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_TEXTURE_PARAM_NAMES.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid pname=0x%x", pname);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
if (param != GL_NEAREST && param != GL_LINEAR && param != GL_NEAREST_MIPMAP_NEAREST &&
|
||||
param != GL_LINEAR_MIPMAP_NEAREST && param != GL_NEAREST_MIPMAP_LINEAR &&
|
||||
param != GL_LINEAR_MIPMAP_LINEAR) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid filter param=%d", param);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
case GL_TEXTURE_WRAP_R:
|
||||
if (param != GL_CLAMP_TO_EDGE && param != GL_CLAMP_TO_BORDER &&
|
||||
param != GL_MIRRORED_REPEAT && param != GL_REPEAT) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid wrap param=%d", param);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_SWIZZLE_R:
|
||||
case GL_TEXTURE_SWIZZLE_G:
|
||||
case GL_TEXTURE_SWIZZLE_B:
|
||||
case GL_TEXTURE_SWIZZLE_A:
|
||||
if(param != GL_ZERO && param != GL_ONE && param != GL_RED && param != GL_GREEN && param != GL_BLUE && param != GL_ALPHA){
|
||||
MG_Util::Debug::LogE("MG_State: Texture: SetTexturePropertyInt invalid swizzle param=%d", param);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint boundTex = textureUnits[activeTextureUnit].GetBoundTexture(target);
|
||||
TextureObject& tex = textures[boundTex];
|
||||
tex.params.texPropertiesInt[pname] = param;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: SetTexturePropertyInt succeeded for texture %u", boundTex);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::Delete(GLuint texture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: Delete called for texture=%u", texture);
|
||||
if (!texture) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: Delete received texture 0");
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
auto it = this->textures.find(texture);
|
||||
if (it != this->textures.end()) {
|
||||
InvalidateTextureInAllUnits(texture);
|
||||
this->textures.erase(it);
|
||||
freeIDs.insert(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);
|
||||
}
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: DeleteN called with n=%d", n);
|
||||
if (n < 1) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: DeleteN invalid n=%d", n);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
for (GLsizei i = 0; i < n; ++i) {
|
||||
GLuint id = textures[i];
|
||||
if (id == 0) continue;
|
||||
auto it = this->textures.find(id);
|
||||
if (it != this->textures.end()) {
|
||||
InvalidateTextureInAllUnits(id);
|
||||
this->textures.erase(it);
|
||||
freeIDs.insert(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);
|
||||
}
|
||||
}
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
GLenum TextureState::GetLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetLevelPropertyIntVector called target=0x%x, level=%d, pname=0x%x", target, level, pname);
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (level < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector invalid level=%d", level);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.find(pname) == MG_Constants::Texture::VALID_QUERY_LEVEL_PROPERTY_PARAM_NAMES.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector invalid pname=0x%x", pname);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if ((target == GL_TEXTURE_RECTANGLE || target == GL_PROXY_TEXTURE_RECTANGLE) && level != 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector invalid level for rectangle texture");
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLuint activeUnit = activeTextureUnit;
|
||||
if (activeUnit >= textureUnits.size()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector active texture unit out of range");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
bool isProxyTexture = (target == GL_PROXY_TEXTURE_1D || target == GL_PROXY_TEXTURE_2D ||
|
||||
target == GL_PROXY_TEXTURE_3D || target == GL_PROXY_TEXTURE_CUBE_MAP ||
|
||||
target == GL_PROXY_TEXTURE_1D_ARRAY || target == GL_PROXY_TEXTURE_2D_ARRAY ||
|
||||
target == GL_PROXY_TEXTURE_RECTANGLE || target == GL_PROXY_TEXTURE_2D_MULTISAMPLE ||
|
||||
target == GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
|
||||
|
||||
TextureUnitState& unit = textureUnits[activeUnit];
|
||||
GLuint boundTexture = unit.GetBoundTexture(target);
|
||||
|
||||
if (!isProxyTexture && boundTexture == 0) {
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector no texture bound for compressed image size");
|
||||
return GL_INVALID_OPERATION;
|
||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||
*params = GL_NONE;
|
||||
break;
|
||||
case GL_TEXTURE_COMPRESSED:
|
||||
*params = GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
*params = 0;
|
||||
break;
|
||||
}
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetLevelPropertyIntVector returns default value for unbound texture");
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
std::unordered_map<GLuint, TextureObject>::iterator texIt;
|
||||
|
||||
if (!isProxyTexture) {
|
||||
texIt = textures.find(boundTexture);
|
||||
if (texIt == textures.end()) {
|
||||
*params = 0;
|
||||
MG_Util::Debug::LogW(
|
||||
"MG_State: Texture: GetLevelPropertyIntVector texture %u not found",
|
||||
boundTexture);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
TextureObject& tex = isProxyTexture ? proxyTextures[target] : texIt->second;
|
||||
|
||||
if (!isProxyTexture && tex.target != target && tex.target != GL_NONE) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector texture target mismatch: texture target=0x%x, expected=0x%x", tex.target, target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto mipIt = tex.params.mipmapData.find(level);
|
||||
if (mipIt == tex.params.mipmapData.end()) {
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector no mipmap level %d for compressed image size", level);
|
||||
return GL_INVALID_OPERATION;
|
||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||
*params = GL_NONE;
|
||||
break;
|
||||
case GL_TEXTURE_COMPRESSED:
|
||||
*params = GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
*params = 0;
|
||||
break;
|
||||
}
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetLevelPropertyIntVector returns default value for missing mipmap level");
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
const TextureParams::MipmapLevel& mip = mipIt->second;
|
||||
ComponentSizes sizes = GetComponentSizes(mip.internalFormat);
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_WIDTH:
|
||||
*params = mip.width;
|
||||
break;
|
||||
case GL_TEXTURE_HEIGHT:
|
||||
*params = mip.height;
|
||||
break;
|
||||
case GL_TEXTURE_DEPTH:
|
||||
*params = 1; // Assuming 2D Texture
|
||||
break;
|
||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
||||
*params = mip.internalFormat;
|
||||
break;
|
||||
case GL_TEXTURE_RED_SIZE:
|
||||
case GL_TEXTURE_GREEN_SIZE:
|
||||
case GL_TEXTURE_BLUE_SIZE:
|
||||
case GL_TEXTURE_ALPHA_SIZE:
|
||||
case GL_TEXTURE_DEPTH_SIZE:
|
||||
case GL_TEXTURE_STENCIL_SIZE:
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_RED_SIZE: *params = sizes.red; break;
|
||||
case GL_TEXTURE_GREEN_SIZE: *params = sizes.green; break;
|
||||
case GL_TEXTURE_BLUE_SIZE: *params = sizes.blue; break;
|
||||
case GL_TEXTURE_ALPHA_SIZE: *params = sizes.alpha; break;
|
||||
case GL_TEXTURE_DEPTH_SIZE: *params = sizes.depth; break;
|
||||
case GL_TEXTURE_STENCIL_SIZE: *params = sizes.stencil; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_COMPRESSED:
|
||||
*params = sizes.isCompressed ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
|
||||
if (!sizes.isCompressed) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector texture is not compressed");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
*params = static_cast<GLint>(mip.pixelData.size());
|
||||
break;
|
||||
default:
|
||||
MG_Util::Debug::LogE("MG_State: Texture: GetLevelPropertyIntVector invalid pname=0x%x", pname);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetLevelPropertyIntVector returns %d for pname=0x%x", *params, pname);
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
void TextureState::InvalidateTextureInAllUnits(GLuint texture) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: InvalidateTextureInAllUnits called for texture=%u", texture);
|
||||
for (auto& unit : textureUnits) {
|
||||
for (auto& [target, tex] : unit.boundTextures) {
|
||||
if (tex == texture) {
|
||||
tex = 0;
|
||||
MG_Util::Debug::LogD("MG_State: Texture: InvalidateTextureInAllUnits unset texture for target=0x%x", target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLenum TextureState::CheckUploadingTexture2DValidity(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity called target=0x%x, level=%d", target, level);
|
||||
if (MG_Constants::Texture::VALID_TARGETS.find(target) == MG_Constants::Texture::VALID_TARGETS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid target=0x%x", target);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (level < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid level=%d", level);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if ((target == GL_TEXTURE_RECTANGLE || target == GL_PROXY_TEXTURE_RECTANGLE) && level != 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid level for rectangle texture");
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid dimensions width=%d, height=%d", width, height);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if ((target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) && width != height) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity cube map requires equal width and height");
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (width > MG_Constants::Texture::MAX_TEXTURE_SIZE) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity width exceeds maximum: %d", width);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (target == GL_TEXTURE_1D_ARRAY || target == GL_PROXY_TEXTURE_1D_ARRAY) {
|
||||
if (height > MG_Constants::Texture::MAX_ARRAY_LAYERS) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity height exceeds MAX_ARRAY_LAYERS: %d", height);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
} else if (height > MG_Constants::Texture::MAX_TEXTURE_SIZE) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity height exceeds maximum: %d", height);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_INTERNAL_FORMATS.find(internalFormat) == MG_Constants::Texture::VALID_INTERNAL_FORMATS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid internalFormat=0x%x", internalFormat);
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_FORMATS.find(format) == MG_Constants::Texture::VALID_FORMATS.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid format=0x%x", format);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
if (MG_Constants::Texture::VALID_TYPES.find(type) == MG_Constants::Texture::VALID_TYPES.end()) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid type=0x%x", type);
|
||||
return GL_INVALID_ENUM;
|
||||
}
|
||||
|
||||
bool typeNeedsRGB = (type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_SHORT_5_6_5);
|
||||
if (typeNeedsRGB && format != GL_RGB) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity type requires RGB but format=0x%x", format);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
bool typeNeedsRGBA = (type == GL_UNSIGNED_SHORT_4_4_4_4 || type == GL_UNSIGNED_INT_8_8_8_8);
|
||||
if (typeNeedsRGBA && format != GL_RGBA && format != GL_BGRA) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity type requires RGBA but format=0x%x", format);
|
||||
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 isDepthFormat = (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL);
|
||||
if (isDepthInternal != isDepthFormat) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity depth internal/format mismatch");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (isDepthInternal && (target != GL_TEXTURE_2D && target != GL_PROXY_TEXTURE_2D &&
|
||||
target != GL_TEXTURE_RECTANGLE && target != GL_PROXY_TEXTURE_RECTANGLE)) {
|
||||
MG_Util::Debug::LogE("MG_State: Texture: CheckUploadingTexture2DValidity invalid target for depth texture");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
bool isProxyTexture = (target == GL_PROXY_TEXTURE_1D || target == GL_PROXY_TEXTURE_2D ||
|
||||
target == GL_PROXY_TEXTURE_3D || target == GL_PROXY_TEXTURE_CUBE_MAP ||
|
||||
target == GL_PROXY_TEXTURE_1D_ARRAY || target == GL_PROXY_TEXTURE_2D_ARRAY ||
|
||||
target == GL_PROXY_TEXTURE_RECTANGLE || target == GL_PROXY_TEXTURE_2D_MULTISAMPLE ||
|
||||
target == GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
|
||||
if (!isProxyTexture) {
|
||||
GLuint boundTex = textureUnits[activeTextureUnit].GetBoundTexture(target);
|
||||
if (boundTex == 0) {
|
||||
MG_Util::Debug::LogE(
|
||||
"MG_State: Texture: CheckUploadingTexture2DValidity no texture bound for target=0x%x",
|
||||
target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
TextureObject &tex = textures[boundTex];
|
||||
if (tex.target != target) {
|
||||
MG_Util::Debug::LogE(
|
||||
"MG_State: Texture: CheckUploadingTexture2DValidity texture target mismatch: texture target=0x%x, expected=0x%x",
|
||||
tex.target, target);
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
if (tex.IsImmutable()) {
|
||||
MG_Util::Debug::LogE(
|
||||
"MG_State: Texture: CheckUploadingTexture2DValidity texture is immutable");
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
}
|
||||
|
||||
MG_Util::Debug::LogD("MG_State: Texture: CheckUploadingTexture2DValidity succeeded");
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
ComponentSizes TextureState::GetComponentSizes(GLenum internalFormat) {
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetComponentSizes called for internalFormat=0x%x", internalFormat);
|
||||
ComponentSizes sizes = {0};
|
||||
switch (internalFormat) {
|
||||
// Base formats
|
||||
case GL_R8:
|
||||
case GL_R8_SNORM: sizes.red = 8; break;
|
||||
case GL_R16:
|
||||
case GL_R16_SNORM:
|
||||
case GL_R16F: sizes.red = 16; break;
|
||||
case GL_R32F: sizes.red = 32; break;
|
||||
case GL_R8I:
|
||||
case GL_R8UI: sizes.red = 8; break;
|
||||
case GL_R16I:
|
||||
case GL_R16UI: sizes.red = 16; break;
|
||||
case GL_R32I:
|
||||
case GL_R32UI: sizes.red = 32; break;
|
||||
|
||||
case GL_RG8:
|
||||
case GL_RG8_SNORM: sizes.red = 8; sizes.green = 8; break;
|
||||
case GL_RG16:
|
||||
case GL_RG16_SNORM:
|
||||
case GL_RG16F: sizes.red = 16; sizes.green = 16; break;
|
||||
case GL_RG32F: sizes.red = 32; sizes.green = 32; break;
|
||||
case GL_RG8I:
|
||||
case GL_RG8UI: sizes.red = 8; sizes.green = 8; break;
|
||||
case GL_RG16I:
|
||||
case GL_RG16UI: sizes.red = 16; sizes.green = 16; break;
|
||||
case GL_RG32I:
|
||||
case GL_RG32UI: sizes.red = 32; sizes.green = 32; break;
|
||||
|
||||
case GL_RGB8:
|
||||
case GL_RGB8_SNORM: sizes.red = 8; sizes.green = 8; sizes.blue = 8; break;
|
||||
case GL_RGB16:
|
||||
case GL_RGB16_SNORM:
|
||||
case GL_RGB16F: sizes.red = 16; sizes.green = 16; sizes.blue = 16; break;
|
||||
case GL_RGB32F: sizes.red = 32; sizes.green = 32; sizes.blue = 32; break;
|
||||
case GL_RGB8I:
|
||||
case GL_RGB8UI: sizes.red = 8; sizes.green = 8; sizes.blue = 8; break;
|
||||
case GL_RGB16I:
|
||||
case GL_RGB16UI: sizes.red = 16; sizes.green = 16; sizes.blue = 16; break;
|
||||
case GL_RGB32I:
|
||||
case GL_RGB32UI: sizes.red = 32; sizes.green = 32; sizes.blue = 32; break;
|
||||
|
||||
case GL_RGBA8:
|
||||
case GL_RGBA8_SNORM: sizes.red = 8; sizes.green = 8; sizes.blue = 8; sizes.alpha = 8; break;
|
||||
case GL_RGBA16:
|
||||
case GL_RGBA16_SNORM:
|
||||
case GL_RGBA16F: sizes.red = 16; sizes.green = 16; sizes.blue = 16; sizes.alpha = 16; break;
|
||||
case GL_RGBA32F: sizes.red = 32; sizes.green = 32; sizes.blue = 32; sizes.alpha = 32; break;
|
||||
case GL_RGBA8I:
|
||||
case GL_RGBA8UI: sizes.red = 8; sizes.green = 8; sizes.blue = 8; sizes.alpha = 8; break;
|
||||
case GL_RGBA16I:
|
||||
case GL_RGBA16UI: sizes.red = 16; sizes.green = 16; sizes.blue = 16; sizes.alpha = 16; break;
|
||||
case GL_RGBA32I:
|
||||
case GL_RGBA32UI: sizes.red = 32; sizes.green = 32; sizes.blue = 32; sizes.alpha = 32; break;
|
||||
|
||||
// Packed formats
|
||||
case GL_RGB565: sizes.red = 5; sizes.green = 6; sizes.blue = 5; break;
|
||||
case GL_RGBA4: sizes.red = 4; sizes.green = 4; sizes.blue = 4; sizes.alpha = 4; break;
|
||||
case GL_RGB5_A1: sizes.red = 5; sizes.green = 5; sizes.blue = 5; sizes.alpha = 1; break;
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGB10_A2UI: sizes.red = 10; sizes.green = 10; sizes.blue = 10; sizes.alpha = 2; break;
|
||||
case GL_R11F_G11F_B10F: sizes.red = 11; sizes.green = 11; sizes.blue = 10; break;
|
||||
case GL_RGB9_E5: sizes.red = 9; sizes.green = 9; sizes.blue = 9; break; // shared exponent
|
||||
|
||||
// sRGB formats
|
||||
case GL_SRGB8: sizes.red = 8; sizes.green = 8; sizes.blue = 8; break;
|
||||
case GL_SRGB8_ALPHA8: sizes.red = 8; sizes.green = 8; sizes.blue = 8; sizes.alpha = 8; break;
|
||||
|
||||
// Depth/stencil formats
|
||||
case GL_DEPTH_COMPONENT16: sizes.depth = 16; break;
|
||||
case GL_DEPTH_COMPONENT24: sizes.depth = 24; break;
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
case GL_DEPTH_COMPONENT32F: sizes.depth = 32; break;
|
||||
case GL_DEPTH24_STENCIL8: sizes.depth = 24; sizes.stencil = 8; break;
|
||||
case GL_DEPTH32F_STENCIL8: sizes.depth = 32; sizes.stencil = 8; break;
|
||||
|
||||
// Compressed formats
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
sizes.isCompressed = true;
|
||||
sizes.red = 5; sizes.green = 6; sizes.blue = 5;
|
||||
if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) sizes.alpha = 1;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_RG_RGTC2:
|
||||
case GL_COMPRESSED_SIGNED_RG_RGTC2:
|
||||
case GL_COMPRESSED_RED_RGTC1:
|
||||
case GL_COMPRESSED_SIGNED_RED_RGTC1:
|
||||
sizes.isCompressed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (internalFormat == GL_RGBA || internalFormat == GL_BGRA ||
|
||||
internalFormat == GL_RGBA_INTEGER || internalFormat == GL_BGRA_INTEGER) {
|
||||
// Typically matches RGBA8 when no size is specified
|
||||
sizes.red = 8; sizes.green = 8; sizes.blue = 8; sizes.alpha = 8;
|
||||
} else if (internalFormat == GL_RGB || internalFormat == GL_BGR ||
|
||||
internalFormat == GL_RGB_INTEGER || internalFormat == GL_BGR_INTEGER) {
|
||||
sizes.red = 8; sizes.green = 8; sizes.blue = 8;
|
||||
} else if (internalFormat == GL_RG || internalFormat == GL_RG_INTEGER) {
|
||||
sizes.red = 8; sizes.green = 8;
|
||||
} else if (internalFormat == GL_RED || internalFormat == GL_RED_INTEGER) {
|
||||
sizes.red = 8;
|
||||
} else if (internalFormat == GL_DEPTH_COMPONENT) {
|
||||
sizes.depth = 32; // Common default
|
||||
} else if (internalFormat == GL_DEPTH_STENCIL) {
|
||||
sizes.depth = 32; sizes.stencil = 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
MG_Util::Debug::LogD("MG_State: Texture: GetComponentSizes returns (red=%d, green=%d, blue=%d, alpha=%d, depth=%d, stencil=%d, isCompressed=%d)",
|
||||
sizes.red, sizes.green, sizes.blue, sizes.alpha, sizes.depth, sizes.stencil, sizes.isCompressed);
|
||||
return sizes;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// Created by BZLZHH on 2025/4/4.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGL_TEXTURESTATE_H
|
||||
#define MOBILEGL_TEXTURESTATE_H
|
||||
#define MOBILEGL_GLSTATE_H
|
||||
|
||||
#include "../../../Includes.h"
|
||||
|
||||
struct ComponentSizes {
|
||||
GLint red = 0;
|
||||
GLint green = 0;
|
||||
GLint blue = 0;
|
||||
GLint alpha = 0;
|
||||
GLint depth = 0;
|
||||
GLint stencil = 0;
|
||||
bool isCompressed = false;
|
||||
};
|
||||
|
||||
struct TextureParams {
|
||||
std::unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||
std::unordered_map<GLenum, GLint> texPropertiesInt;
|
||||
struct MipmapLevel {
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
GLenum format = GL_RGBA;
|
||||
GLenum internalFormat = GL_RGBA;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
std::vector<GLubyte> pixelData;
|
||||
bool hasData = false;
|
||||
};
|
||||
std::unordered_map<GLint, MipmapLevel> mipmapData;
|
||||
};
|
||||
|
||||
class TextureObject {
|
||||
public:
|
||||
bool generated = false;
|
||||
GLenum target = GL_NONE;
|
||||
TextureParams params;
|
||||
const void* data = nullptr;
|
||||
bool IsImmutable() const;
|
||||
};
|
||||
|
||||
class TextureUnitState {
|
||||
private:
|
||||
GLenum activeTarget = GL_TEXTURE_2D;
|
||||
|
||||
public:
|
||||
std::unordered_map<GLenum, GLuint> boundTextures;
|
||||
void Bind(GLenum target, GLuint texture);
|
||||
GLuint GetBoundTexture(GLenum target);
|
||||
};
|
||||
|
||||
class TextureState {
|
||||
private:
|
||||
std::vector<TextureUnitState> textureUnits;
|
||||
GLuint activeTextureUnit = 0;
|
||||
|
||||
GLuint lastUsedID = 0;
|
||||
std::set<GLuint> freeIDs;
|
||||
|
||||
std::unordered_map<GLuint, TextureObject> textures;
|
||||
std::unordered_map<GLenum, TextureObject> proxyTextures;
|
||||
public:
|
||||
TextureState();
|
||||
|
||||
static TextureState& GetInstance();
|
||||
bool IsTextureGenerated(GLuint texture);
|
||||
bool IsTexture(GLuint texture);
|
||||
|
||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||
GLenum BindUnit(GLenum textureUnit);
|
||||
GLenum Create(GLuint* texture);
|
||||
GLenum CreateN(GLsizei n, GLuint* textures);
|
||||
GLenum Bind(GLenum target, GLuint texture);
|
||||
GLenum Upload2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data);
|
||||
GLenum UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const GLvoid* data);
|
||||
GLenum SetTexturePropertyInt(GLenum target, GLenum pname, GLint param);
|
||||
GLenum SetTexturePropertyFloat(GLenum target, GLenum pname, GLfloat param);
|
||||
GLenum Delete(GLuint texture);
|
||||
GLenum DeleteN(GLsizei n, const GLuint* textures);
|
||||
GLenum GetLevelPropertyIntVector(GLenum target, GLint level, GLenum pname, GLint* params);
|
||||
|
||||
private:
|
||||
static static size_t CalculatePixelDataSize(GLenum format, GLenum type, GLsizei width, GLsizei height);
|
||||
void InvalidateTextureInAllUnits(GLuint texture);
|
||||
static ComponentSizes GetComponentSizes(GLenum internalFormat);
|
||||
GLenum CheckUploadingTexture2DValidity(GLenum target, GLint level, GLint internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const void* data);
|
||||
};
|
||||
|
||||
#endif //MOBILEGL_TEXTURESTATE_H
|
||||
Reference in New Issue
Block a user