Merge branch 'Feat/Backend-Direct-GLES' into dev

This commit is contained in:
BZLZHH
2026-02-07 11:25:28 +08:00
9 changed files with 600 additions and 29 deletions
+318 -15
View File
@@ -8,8 +8,11 @@
#include "DirectGLES.h" #include "DirectGLES.h"
#include "GLES3/gl32.h" #include "GLES3/gl32.h"
#include "MG_State/GLState/ErrorState/Error.h"
#include "MG_State/GLState/RenderState/RenderState.h"
#include "MG_State/GLState/SamplerState/SamplerObject.h" #include "MG_State/GLState/SamplerState/SamplerObject.h"
#include "MG_Util/Debug/Log.h" #include "MG_Util/Debug/Log.h"
#include "MG_Util/Types.h"
#include "Utils.h" #include "Utils.h"
#include "Managers.h" #include "Managers.h"
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -882,8 +885,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) { if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) {
MOBILEGL_ASSERT(false, " Texture target %s is not supported, skipping.", MGLOG_E(" Texture target %s is not supported, skipping.",
MG_Util::ConvertTextureTargetToString(textureTarget).c_str()); MG_Util::ConvertTextureTargetToString(textureTarget).c_str());
return false; return false;
} }
@@ -909,26 +912,40 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
static GLuint s_prevDrawFBO = 0; static GLuint s_prevDrawFBO = 0;
void BindTempDrawFBO() { static GLuint s_prevReadFBO = 0;
void BindTempFBO(Bool isRead) {
MGLOG_D("%s: Binding temporary FBO for operations like CopyTexImage2D that require framebuffer binding, " MGLOG_D("%s: Binding temporary FBO for operations like CopyTexImage2D that require framebuffer binding, "
"previous draw FBO=%u", "previous draw FBO=%u, read FBO=%u",
__func__, s_prevDrawFBO); __func__, s_prevDrawFBO, s_prevReadFBO);
static GLuint tempFBO = 0; static GLuint tempFBO = 0;
if (!tempFBO) { if (!tempFBO) {
MG_External::GLES::glGenFramebuffers(1, &tempFBO); MG_External::GLES::glGenFramebuffers(1, &tempFBO);
} }
MG_External::GLES::glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&s_prevDrawFBO); if (isRead) {
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFBO); MG_External::GLES::glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (GLint*)&s_prevReadFBO);
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, tempFBO);
} else {
MG_External::GLES::glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFBO);
}
} }
void RestoreDrawFBOFromTemp() { void RestoreFBOFromTemp(Bool isRead) {
MGLOG_D("%s: Restoring previous draw FBO=%u", __func__, s_prevDrawFBO); if (isRead) {
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_prevDrawFBO); MGLOG_D("%s: Restoring previous read FBO=%u", __func__, s_prevReadFBO);
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, s_prevReadFBO);
} else {
MGLOG_D("%s: Restoring previous draw FBO=%u", __func__, s_prevDrawFBO);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_prevDrawFBO);
}
} }
class TempFBOBinder { class TempFBOBinder {
public: public:
TempFBOBinder() { BindTempDrawFBO(); } TempFBOBinder(Bool isRead) : m_isRead(isRead) { BindTempFBO(isRead); }
~TempFBOBinder() { RestoreDrawFBOFromTemp(); } ~TempFBOBinder() { RestoreFBOFromTemp(m_isRead); }
private:
const Bool m_isRead = false;
}; };
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
@@ -1001,7 +1018,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}); });
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder; TempFBOBinder tempFBOBinder(false);
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level); MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { if (MG_External::GLES::glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
@@ -1080,7 +1097,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; GLenum attachment = isStencilFormat ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
TempFBOBinder tempFBOBinder; TempFBOBinder tempFBOBinder(false);
MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level); MG_External::GLES::glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, target, currentTex, level);
errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
@@ -1136,6 +1153,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_External::GLES::glClearBufferfv(buffer, drawbuffer, value); MG_External::GLES::glClearBufferfv(buffer, drawbuffer, value);
} }
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) { void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
TextureImpl::SyncNeccessaryTextures(); TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO(); FramebufferImpl::SyncCurrentFBO();
@@ -1154,4 +1172,289 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_External::GLES::glClearBufferuiv(buffer, drawbuffer, value); MG_External::GLES::glClearBufferuiv(buffer, drawbuffer, value);
} }
} // namespace MobileGL::MG_Backend::DirectGLES class TempPixelStoreParameterSync {
public:
TempPixelStoreParameterSync(Bool isUnpack) : m_isUnpack(isUnpack) {
const auto& currentParams = MG_State::pGLContext->GetPixelStoreParameters(isUnpack);
m_prevParams = QueryCurrentGLPixelStoreParams(isUnpack);
Sync(isUnpack, currentParams);
}
~TempPixelStoreParameterSync() { Sync(m_isUnpack, m_prevParams); }
private:
const Bool m_isUnpack;
PixelStoreParameters m_prevParams;
PixelStoreParameters QueryCurrentGLPixelStoreParams(Bool isUnpack) {
PixelStoreParameters p;
if (!isUnpack) {
MG_External::GLES::glGetIntegerv(GL_PACK_ALIGNMENT, (GLint*)&p.Alignment);
MG_External::GLES::glGetIntegerv(GL_PACK_ROW_LENGTH, (GLint*)&p.RowLength);
MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_ROWS, (GLint*)&p.SkipRows);
MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
// MG_External::GLES::glGetIntegerv(GL_PACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
// MG_External::GLES::glGetIntegerv(GL_PACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
// GLint tmp;
// MG_External::GLES::glGetIntegerv(GL_PACK_SWAP_BYTES, &tmp);
// p.SwapBytes = tmp ? true : false;
// MG_External::GLES::glGetIntegerv(GL_PACK_LSB_FIRST, &tmp);
// p.LSBFirst = tmp ? true : false;
} else {
MG_External::GLES::glGetIntegerv(GL_UNPACK_ALIGNMENT, (GLint*)&p.Alignment);
MG_External::GLES::glGetIntegerv(GL_UNPACK_ROW_LENGTH, (GLint*)&p.RowLength);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_ROWS, (GLint*)&p.SkipRows);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_PIXELS, (GLint*)&p.SkipPixels);
MG_External::GLES::glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, (GLint*)&p.ImageHeight);
MG_External::GLES::glGetIntegerv(GL_UNPACK_SKIP_IMAGES, (GLint*)&p.SkipImages);
// GLint tmp;
// MG_External::GLES::glGetIntegerv(GL_UNPACK_SWAP_BYTES, &tmp);
// p.SwapBytes = tmp ? true : false;
// MG_External::GLES::glGetIntegerv(GL_UNPACK_LSB_FIRST, &tmp);
// p.LSBFirst = tmp ? true : false;
}
return p;
}
void Sync(Bool isUnpack, const PixelStoreParameters& params) {
if (!isUnpack) {
MG_External::GLES::glPixelStorei(GL_PACK_ALIGNMENT, params.Alignment);
MG_External::GLES::glPixelStorei(GL_PACK_ROW_LENGTH, params.RowLength);
MG_External::GLES::glPixelStorei(GL_PACK_SKIP_ROWS, params.SkipRows);
MG_External::GLES::glPixelStorei(GL_PACK_SKIP_PIXELS, params.SkipPixels);
// MG_External::GLES::glPixelStorei(GL_PACK_IMAGE_HEIGHT, params.ImageHeight);
// MG_External::GLES::glPixelStorei(GL_PACK_SKIP_IMAGES, params.SkipImages);
// MG_External::GLES::glPixelStorei(GL_PACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// MG_External::GLES::glPixelStorei(GL_PACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
} else {
MG_External::GLES::glPixelStorei(GL_UNPACK_ALIGNMENT, params.Alignment);
MG_External::GLES::glPixelStorei(GL_UNPACK_ROW_LENGTH, params.RowLength);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_ROWS, params.SkipRows);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_PIXELS, params.SkipPixels);
MG_External::GLES::glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, params.ImageHeight);
MG_External::GLES::glPixelStorei(GL_UNPACK_SKIP_IMAGES, params.SkipImages);
// MG_External::GLES::glPixelStorei(GL_UNPACK_SWAP_BYTES, params.SwapBytes ? GL_TRUE : GL_FALSE);
// MG_External::GLES::glPixelStorei(GL_UNPACK_LSB_FIRST, params.LSBFirst ? GL_TRUE : GL_FALSE);
}
}
};
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
MGLOG_D("ReadPixels: x=%d y=%d w=%d h=%d format=%s type=%s pixels=%p", x, y, width, height,
MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
MOBILEGL_ASSERT(format == GL_RGBA || format == GL_RGBA_INTEGER,
"Only GL_RGBA and GL_RGBA_INTEGER are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(format).c_str());
MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV ||
type == GL_INT || type == GL_FLOAT,
"Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, "
"GL_INT and GL_FLOAT are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(type).c_str());
MGLOG_D("ReadPixels: SyncNeccessaryTextures()");
TextureImpl::SyncNeccessaryTextures();
MGLOG_D("ReadPixels: SyncCurrentFBO()");
FramebufferImpl::SyncCurrentFBO();
MGLOG_D("ReadPixels: BindCurrentFBO(Read)");
BindCurrentFBO(FramebufferTarget::Read);
MGLOG_D("ReadPixels: Applying TempPixelStoreParameterSync (PACK)");
TempPixelStoreParameterSync tempPackParamsSync(false);
GLenum fbStatus = MG_External::GLES::glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
MGLOG_D("ReadPixels: GL_READ_FRAMEBUFFER status = %s", MG_Util::ConvertGLEnumToString(fbStatus).c_str());
if (fbStatus != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("ReadPixels: bound READ FBO is not complete");
return;
}
// Handle PBO
auto pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
Bool usePBO;
GLuint prevPixelPackBuffer = 0;
if (pixelPackBufferObject) {
BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject);
MGLOG_D("ReadPixels: Using PBO %u", pixelPackBufferObject->GetExternalIndex());
usePBO = true;
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject);
if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) {
MGLOG_E("ReadPixels: No backend buffer found for PBO %u.",
pixelPackBufferObject ? pixelPackBufferObject->GetExternalIndex() : 0);
return;
}
const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_PIXEL_PACK_BUFFER);
MG_External::GLES::glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
} else {
usePBO = false;
MGLOG_D("ReadPixels: Not using PBO");
}
MGLOG_D("ReadPixels: glReadPixels()");
MG_External::GLES::glReadPixels(x, y, width, height, format, type, pixels);
if (usePBO) {
// pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = MG_External::GLES::glMapBufferRange(
GL_PIXEL_PACK_BUFFER, 0, pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize();
pixelPackBufferObject->UploadSubData({pboMappedPtr, size}, 0);
pixelPackBufferObject->ClearDirty();
MGLOG_D("ReadPixels: Unmapping PBO");
MG_External::GLES::glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
} else {
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
}
MGLOG_D("ReadPixels: Restoring previous pixel pack buffer binding %u", prevPixelPackBuffer);
MG_External::GLES::glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
}
MGLOG_D("ReadPixels: finished");
}
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels) {
MGLOG_D("GetTexImage: target=%s level=%d format=%s type=%s pixels=%p",
MG_Util::ConvertGLEnumToString(target).c_str(), level, MG_Util::ConvertGLEnumToString(format).c_str(),
MG_Util::ConvertGLEnumToString(type).c_str(), pixels);
MOBILEGL_ASSERT(format == GL_RGBA || format == GL_RGBA_INTEGER,
"Only GL_RGBA and GL_RGBA_INTEGER are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(format).c_str());
MOBILEGL_ASSERT(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT_2_10_10_10_REV ||
type == GL_INT || type == GL_FLOAT,
"Only GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_2_10_10_10_REV, "
"GL_INT and GL_FLOAT are supported currently, while requested %s.",
MG_Util::ConvertGLEnumToString(type).c_str());
MGLOG_D("GetTexImage: SyncNeccessaryTextures()");
TextureImpl::SyncNeccessaryTextures();
MGLOG_D("GetTexImage: SyncCurrentFBO()");
FramebufferImpl::SyncCurrentFBO();
Uint activeTextureUnit = MG_State::pGLContext->GetActiveTextureUnit();
MGLOG_D("GetTexImage: active texture unit = %u", activeTextureUnit);
const auto& textureObject = MG_State::pGLContext->GetTextureUnitObject(activeTextureUnit)
.GetBindingSlot(MG_Util::ConvertGLEnumToTextureTarget(target))
.GetBoundObject();
MGLOG_D("GetTexImage: bound texture object = %p (name=%u)", textureObject.get(),
textureObject ? textureObject->GetExternalIndex() : 0);
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject);
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) {
MGLOG_E("GetTexImage: No backend texture found for texture %u.",
textureObject ? textureObject->GetExternalIndex() : 0);
return;
}
GLuint backendTexId = backendTextureIt->second->GetBackendTextureId();
MGLOG_D("GetTexImage: backend texture id = %u", backendTexId);
MGLOG_D("GetTexImage: Binding temporary FBO");
TempFBOBinder tempFBOBinder(true);
MGLOG_D("GetTexImage: glFramebufferTexture2D(level=%d)", level);
MG_External::GLES::glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, backendTexId,
level);
MGLOG_D("GetTexImage: glReadBuffer(GL_COLOR_ATTACHMENT0)");
MG_External::GLES::glReadBuffer(GL_COLOR_ATTACHMENT0);
GLenum fbStatus = MG_External::GLES::glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
MGLOG_D("GetTexImage: GL_READ_FRAMEBUFFER status = %s", MG_Util::ConvertGLEnumToString(fbStatus).c_str());
if (fbStatus != GL_FRAMEBUFFER_COMPLETE) {
MGLOG_E("GetTexImage: READ FBO incomplete");
MGLOG_E("GetTexImage: bound READ FBO is not complete");
return;
}
MGLOG_D("GetTexImage: Applying TempPixelStoreParameterSync (PACK)");
TempPixelStoreParameterSync tempPackParamsSync(false);
const auto& storageType = textureObject->GetStorageType();
MGLOG_D("GetTexImage: texture storage type = %d", (int)storageType);
if (storageType == TextureStorageType::Buffer) {
MGLOG_E("GetTexImage: Texture storage type Buffer is not supported.");
MGLOG_E("GetTexImage: Texture storage type Buffer is not supported.");
return;
}
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
auto levelRange = textureMipmapObject->GetLevelRange();
MGLOG_D("GetTexImage: mipmap level range = [%d, %d)", levelRange.x(), levelRange.y());
if (level < levelRange.x() || level >= levelRange.y()) {
MGLOG_E("GetTexImage: Requested level %d out of range", level);
MOBILEGL_ASSERT(false,
"GetTexImage: Requested level %d is out of range "
"(base level %d, max level %d).",
level, levelRange.x(), levelRange.y());
return;
}
auto size = textureMipmapObject->GetMipmapTexelSize(MG_Util::ConvertGLEnumToTextureUploadTarget(target), level);
MGLOG_D("GetTexImage: mip level %d size = %dx%d", level, size.x(), size.y());
// Handle PBO
auto pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
Bool usePBO;
GLuint prevPixelPackBuffer = 0;
if (pixelPackBufferObject) {
BufferImpl::CreateAndSyncBufferObject(pixelPackBufferObject);
MGLOG_D("GetTexImage: Using PBO %u", pixelPackBufferObject->GetExternalIndex());
usePBO = true;
const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(pixelPackBufferObject);
if (backendBufferIt == BufferImpl::g_backendBufferObjects.end()) {
MGLOG_E("GetTexImage: No backend buffer found for PBO %u.",
pixelPackBufferObject ? pixelPackBufferObject->GetExternalIndex() : 0);
return;
}
const auto& backendBufferObject = backendBufferIt->second;
backendBufferObject->Bind(GL_PIXEL_PACK_BUFFER);
MG_External::GLES::glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&prevPixelPackBuffer);
} else {
usePBO = false;
MGLOG_D("GetTexImage: Not using PBO");
}
MGLOG_D("GetTexImage: glReadPixels()");
MG_External::GLES::glReadPixels(0, 0, size.x(), size.y(), format, type, pixels);
if (usePBO) {
// pull back to client memory if PBO is used
MGLOG_D("ReadPixels: PBO used, mapping buffer to client memory");
GLvoid* pboMappedPtr = MG_External::GLES::glMapBufferRange(
GL_PIXEL_PACK_BUFFER, 0, pixelPackBufferObject->GetSize(), GL_MAP_READ_BIT);
if (pboMappedPtr) {
MGLOG_D("ReadPixels: Copying data from PBO to client memory");
SizeT size = pixelPackBufferObject->GetSize();
pixelPackBufferObject->UploadSubData({pboMappedPtr, size}, 0);
pixelPackBufferObject->ClearDirty();
MGLOG_D("ReadPixels: Unmapping PBO");
MG_External::GLES::glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
} else {
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
MGLOG_E("ReadPixels: glMapBufferRange returned nullptr");
}
MGLOG_D("ReadPixels: Restoring previous pixel pack buffer binding %u", prevPixelPackBuffer);
MG_External::GLES::glBindBuffer(GL_PIXEL_PACK_BUFFER, prevPixelPackBuffer);
}
MGLOG_D("GetTexImage: finished");
}
} // namespace MobileGL::MG_Backend::DirectGLES
@@ -53,4 +53,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLsizei height); GLsizei height);
void GenerateMipmap(GLenum target); void GenerateMipmap(GLenum target);
const GLubyte* GetString(GLenum name); const GLubyte* GetString(GLenum name);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
@@ -151,7 +151,7 @@ DECLARE_GL_FUNCTION_HEAD(void, LineWidth, GLfloat width) DECLARE_GL_FUNCTION_END
DECLARE_GL_FUNCTION_HEAD(void, LinkProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, LinkProgram, program) DECLARE_GL_FUNCTION_HEAD(void, LinkProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, LinkProgram, program)
DECLARE_GL_FUNCTION_HEAD(void, PixelStorei, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PixelStorei, pname, param) DECLARE_GL_FUNCTION_HEAD(void, PixelStorei, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PixelStorei, pname, param)
DECLARE_GL_FUNCTION_HEAD(void, PolygonOffset, GLfloat factor, GLfloat units) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffset, factor, units) DECLARE_GL_FUNCTION_HEAD(void, PolygonOffset, GLfloat factor, GLfloat units) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffset, factor, units)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReadPixels, x, y, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, ReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ReadPixels, x, y, width, height, format, type, pixels)
DECLARE_GL_FUNCTION_STUB_HEAD(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_HEAD(void, ReleaseShaderCompiler) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ReleaseShaderCompiler)
DECLARE_GL_FUNCTION_HEAD(void, RenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, RenderbufferStorage, target, internalformat, width, height) DECLARE_GL_FUNCTION_HEAD(void, RenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, RenderbufferStorage, target, internalformat, width, height)
DECLARE_GL_FUNCTION_HEAD(void, SampleCoverage, GLfloat value, GLboolean invert) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleCoverage, value, invert) DECLARE_GL_FUNCTION_HEAD(void, SampleCoverage, GLfloat value, GLboolean invert) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SampleCoverage, value, invert)
@@ -9,6 +9,7 @@
#include "GL_Framebuffer.h" #include "GL_Framebuffer.h"
#include "Validators.h" #include "Validators.h"
#include "Config.h" #include "Config.h"
#include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_Impl/GLImpl/Texture/Validators.h> #include <MG_Impl/GLImpl/Texture/Validators.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h> #include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
@@ -310,10 +311,10 @@ namespace MobileGL {
// ------------------- Check validity begin ------------------------ // ------------------- Check validity begin ------------------------
if (attType == FramebufferAttachmentType::Unknown) { if (attType == FramebufferAttachmentType::Unknown) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>(
std::format("`mode` = {} is not an accepted value.", "MG_Impl/GLImpl", __func__,
MG_Util::ConvertGLEnumToString(mode)))); std::format("`mode` = {} is not an accepted value.", MG_Util::ConvertGLEnumToString(mode))));
return; return;
} }
@@ -507,7 +508,142 @@ namespace MobileGL {
#endif #endif
} }
void ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels) {
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
// Check width/height
if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Width and height must be non-negative"));
return;
}
// Validate format
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
return;
}
// Validate type
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
return;
}
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No framebuffer bound to read target"));
return;
}
// Check framebuffer completeness
if (!framebufferObject->CheckCompleteness()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
return;
}
// Check for required buffers
if (textureInputFormat == TextureInputFormat::StencilIndex) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No stencil buffer for stencil index format"));
return;
}
} else if (textureInputFormat == TextureInputFormat::DepthComponent) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth buffer for depth component format"));
return;
}
} else if (textureInputFormat == TextureInputFormat::DepthStencil) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() ||
!framebufferObject->GetAttachment(FramebufferAttachmentType::Stencil).IsValid()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth/stencil buffer for depth-stencil format"));
return;
}
// Validate type for depth/stencil
if (texturePixelDataType != TexturePixelDataType::UnsignedInt248 &&
texturePixelDataType != TexturePixelDataType::Float32UnsignedInt248Rev) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Invalid type for depth-stencil format"));
return;
}
}
// Check PBO state
const auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
if (pixelPackBufferObject) {
// Check if PBO is mapped
if (pixelPackBufferObject->IsMapped()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel pack buffer is currently mapped"));
return;
}
// Check alignment
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel data not aligned for pixel pack buffer"));
return;
}
}
// Check multisampling
if (framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).IsRenderbuffer()) {
auto rbo = framebufferObject->GetAttachment(FramebufferAttachmentType::Color0).GetRenderbuffer();
if (rbo && rbo->GetSamples() > 1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"ReadPixels not supported for multisampled framebuffers"));
return;
}
}
}
void ReadPixels_Backend(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
void* pixels) {
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::ReadPixels(x, y, width, height, format, type, pixels);
#endif
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
ReadPixels_State(x, y, width, height, format, type, pixels);
ReadPixels_Backend(x, y, width, height, format, type, pixels);
}
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
ClearBufferfi_Backend(buffer, drawbuffer, depth, stencil); ClearBufferfi_Backend(buffer, drawbuffer, depth, stencil);
} }
@@ -14,6 +14,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
+129 -8
View File
@@ -1164,10 +1164,6 @@ namespace MobileGL {
} }
} }
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
// TODO: implement
}
void GetCompressedTexImage_State(GLenum target, GLint level, void* img) { void GetCompressedTexImage_State(GLenum target, GLint level, void* img) {
// TODO: implement // TODO: implement
} }
@@ -1378,7 +1374,136 @@ namespace MobileGL {
MG_State::pGLContext->SetActiveTextureUnit(texture - GL_TEXTURE0); MG_State::pGLContext->SetActiveTextureUnit(texture - GL_TEXTURE0);
} }
void GetTexImage_Backend(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
MG_Backend::DirectGLES::GetTexImage(target, level, format, type, pixels);
#endif
}
// Add to GL_Texture.cpp
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
// ======================= Converting ================================
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
// ===================== Error Checking ==============================
// Validate target
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid texture target"));
return;
}
// Validate level
if (level < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Level must be non-negative"));
return;
}
// Validate format
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid format"));
return;
}
// Validate type
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Invalid pixel data type"));
return;
}
// Get texture object
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
if (TextureImpl::IsProxyTextureTarget(textureUploadTarget)) {
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadTarget);
} else {
auto activeUnit =
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
textureObject = bindingSlot.GetBoundObject();
}
if (!TextureImpl::ValidateTextureObject(textureObject)) {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No valid texture bound to target"));
return;
}
// Check texture completeness
if (!textureObject->IsComplete()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State", "Texture is incomplete"));
return;
}
// Check PBO state
const auto& pixelPackBufferObject =
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelPack).GetBoundObject();
if (pixelPackBufferObject) {
// Check if PBO is mapped
if (pixelPackBufferObject->IsMapped()) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel pack buffer is currently mapped"));
return;
}
// Check alignment
const SizeT typeSize = MG_Util::GetTexturePixelDataTypeSize(texturePixelDataType);
if (reinterpret_cast<uintptr_t>(pixels) % typeSize != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Pixel data not aligned for pixel pack buffer"));
return;
}
}
// Special case for depth/stencil
if (textureInputFormat == TextureInputFormat::StencilIndex) {
if (textureObject->GetFormat() != TextureInternalFormat::DepthStencil &&
textureObject->GetFormat() != TextureInternalFormat::Depth24Stencil8 &&
textureObject->GetFormat() != TextureInternalFormat::Depth32FStencil8) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"No stencil buffer for stencil index format"));
return;
}
}
// Check for multisampling
if (textureObject->GetStorageType() == TextureStorageType::Mipmap) {
auto mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
if (mipmapObject->GetMipmapLevelCount() > 1) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexImage_State",
"Multisampled textures not supported for GetTexImage"));
return;
}
}
}
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
GetTexImage_State(target, level, format, type, pixels);
GetTexImage_Backend(target, level, format, type, pixels);
}
void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) {
TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
@@ -1475,10 +1600,6 @@ namespace MobileGL {
GetTexLevelParameterfv_State(target, level, pname, params); GetTexLevelParameterfv_State(target, level, pname, params);
} }
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
GetTexImage_State(target, level, format, type, pixels);
}
void GetCompressedTexImage(GLenum target, GLint level, void* img) { void GetCompressedTexImage(GLenum target, GLint level, void* img) {
GetCompressedTexImage_State(target, level, img); GetCompressedTexImage_State(target, level, img);
} }
+1 -1
View File
@@ -12,6 +12,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_Impl::GLImpl { namespace MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_DECLARATION@ */ /* @INSERTION_POINT:FUNCTION_DECLARATION@ */
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
@@ -43,7 +44,6 @@ namespace MobileGL {
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params); void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels);
void GetCompressedTexImage(GLenum target, GLint level, void* img); void GetCompressedTexImage(GLenum target, GLint level, void* img);
void GenTextures(GLsizei n, GLuint* textures); void GenTextures(GLsizei n, GLuint* textures);
void DeleteTextures(GLsizei n, const GLuint* textures); void DeleteTextures(GLsizei n, const GLuint* textures);
@@ -239,6 +239,12 @@ namespace MobileGL {
} }
} }
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type) {
SizeT sizedPixelFormatSize = GetSizedTexturePixelDataTypeSize(type);
if (sizedPixelFormatSize > 0) return sizedPixelFormatSize;
return GetBaseTexturePixelDataTypeSize(type);
}
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) { SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type) {
SizeT sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat); SizeT sizedTextureFormatSize = GetSizedInternalFormatSizeInBytes(internalformat);
if (sizedTextureFormatSize > 0) return sizedTextureFormatSize; if (sizedTextureFormatSize > 0) return sizedTextureFormatSize;
@@ -16,6 +16,7 @@ namespace MobileGL {
SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format); SizeT GetBaseInternalFormatComponentCount(TextureInternalFormat format);
SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type); SizeT GetSizedTexturePixelDataTypeSize(TexturePixelDataType type);
SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type); SizeT GetBaseTexturePixelDataTypeSize(TexturePixelDataType type);
SizeT GetTexturePixelDataTypeSize(TexturePixelDataType type);
// This should respect internal format more // This should respect internal format more
SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type); SizeT GetInternalBytesPerPixel(TextureInternalFormat internalformat, TexturePixelDataType type);
// This should respect type more, representing data passed in // This should respect type more, representing data passed in