diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index d6ad277d..0651103a 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -39,6 +39,21 @@ namespace MobileGL::MG_Backend::DirectVulkan { GLint computeWorkGroupSize[3] = {1, 1, 1}; }; + struct DrawElementsIndirectCommand { + Uint32 count = 0; + Uint32 instanceCount = 0; + Uint32 firstIndex = 0; + Int32 baseVertex = 0; + Uint32 baseInstance = 0; + }; + + struct DrawArraysIndirectCommand { + Uint32 count = 0; + Uint32 instanceCount = 0; + Uint32 first = 0; + Uint32 baseInstance = 0; + }; + UnorderedMap g_programResourceCaches; String NormalizeDescriptorName(const SpvReflectDescriptorBinding& binding) { @@ -193,6 +208,122 @@ namespace MobileGL::MG_Backend::DirectVulkan { name[copyLength] = '\0'; } } + + const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) { + auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); + if (drawBuffer) { + drawBuffer->MarkPersistentMappedRangeDirty(); + const auto drawData = drawBuffer->GetDataReadOnly(); + const SizeT commandOffset = reinterpret_cast(indirect); + if (!drawData || commandOffset + requiredBytes > drawData->size()) { + MGLOG_E("%s skipped: invalid GL_DRAW_INDIRECT_BUFFER binding or range", label); + return nullptr; + } + return drawData->data() + commandOffset; + } + + if (!indirect) { + MGLOG_E("%s skipped: indirect pointer is null", label); + return nullptr; + } + + return reinterpret_cast(indirect); + } + + Vector GetUniformBlockActiveVariables(const MG_State::GLState::ProgramObject& program, + GLuint blockIndex) { + Vector activeVariables; + const Uint uniformCount = program.GetUniformCount(); + activeVariables.reserve(uniformCount); + for (Uint uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) { + if (program.GetActiveUniformBlockIndex(uniformIndex) == static_cast(blockIndex)) { + activeVariables.push_back(uniformIndex); + } + } + return activeVariables; + } + + GLuint FindProgramInputIndex(const MG_State::GLState::ProgramObject& program, const String& name) { + const Int activeCount = program.GetActiveAttributesCount(); + for (Int index = 0; index < activeCount; ++index) { + if (program.GetActiveAttribName(index) == name) { + return static_cast(index); + } + } + return GL_INVALID_INDEX; + } + + GLuint FindProgramOutputIndex(const MG_State::GLState::ProgramObject& program, const String& name) { + const Int activeCount = program.GetActiveFragmentOutputCount(); + for (Int index = 0; index < activeCount; ++index) { + if (program.GetActiveFragmentOutputName(index) == name) { + return static_cast(index); + } + } + return GL_INVALID_INDEX; + } + + GLint GetProgramOutputLocation(const MG_State::GLState::ProgramObject& program, const String& name) { + const Int activeCount = program.GetActiveFragmentOutputCount(); + for (Int index = 0; index < activeCount; ++index) { + if (program.GetActiveFragmentOutputName(index) == name) { + return program.GetFragmentOutputLocation(index); + } + } + return -1; + } + + GLint GetProgramResourceActiveCount(const MG_State::GLState::ProgramObject& program, GLenum programInterface, + const ProgramResourceCache& cache) { + switch (programInterface) { + case GL_SHADER_STORAGE_BLOCK: + return static_cast(cache.storageBlocks.size()); + case GL_BUFFER_VARIABLE: + return static_cast(cache.bufferVariables.size()); + case GL_UNIFORM_BLOCK: + return program.GetActiveUniformBlocksCount(); + case GL_UNIFORM: + return static_cast(program.GetUniformCount()); + case GL_PROGRAM_INPUT: + return program.GetActiveAttributesCount(); + case GL_PROGRAM_OUTPUT: + return program.GetActiveFragmentOutputCount(); + default: + return 0; + } + } + + GLint GetProgramResourceMaxNameLength(const MG_State::GLState::ProgramObject& program, GLenum programInterface, + const ProgramResourceCache& cache) { + switch (programInterface) { + case GL_SHADER_STORAGE_BLOCK: { + SizeT maxLength = 0; + for (const auto& block : cache.storageBlocks) maxLength = std::max(maxLength, block.name.size() + 1); + return static_cast(maxLength); + } + case GL_BUFFER_VARIABLE: { + SizeT maxLength = 0; + for (const auto& var : cache.bufferVariables) maxLength = std::max(maxLength, var.name.size() + 1); + return static_cast(maxLength); + } + case GL_UNIFORM_BLOCK: + return program.GetActiveUniformBlocksMaxNameLength() + 1; + case GL_UNIFORM: + return program.GetUniformMaxLength() + 1; + case GL_PROGRAM_INPUT: + return program.GetActiveAttributesMaxLength() + 1; + case GL_PROGRAM_OUTPUT: { + SizeT maxLength = 0; + const Int activeCount = program.GetActiveFragmentOutputCount(); + for (Int index = 0; index < activeCount; ++index) { + maxLength = std::max(maxLength, program.GetActiveFragmentOutputName(index).size() + 1); + } + return static_cast(maxLength); + } + default: + return 0; + } + } } // namespace GLuint GetShaderStorageBlockIndex(const MG_State::GLState::ProgramObject& program, const String& name) { @@ -256,7 +387,44 @@ namespace MobileGL::MG_Backend::DirectVulkan { pVulkanRenderer->MultiDrawElementsIndirectCount(mode, type, indirect, 0, drawcount, stride); } void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { - MGLOG_W("DirectVulkan::MultiDrawArraysIndirect is not implemented yet (drawcount=%d)", drawcount); + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirect called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawArraysIndirect called with null GL context"); + + if (drawcount <= 0) { + return; + } + if (stride == 0) { + stride = sizeof(DrawArraysIndirectCommand); + } + if (stride < static_cast(sizeof(DrawArraysIndirectCommand))) { + MGLOG_E("MultiDrawArraysIndirect skipped: stride %d is smaller than command size %zu", + stride, sizeof(DrawArraysIndirectCommand)); + return; + } + + const auto* commandBytes = ResolveIndirectCommandBytes( + indirect, + static_cast(stride) * static_cast(drawcount - 1) + sizeof(DrawArraysIndirectCommand), + "MultiDrawArraysIndirect"); + if (!commandBytes) { + return; + } + + for (GLsizei i = 0; i < drawcount; ++i) { + DrawArraysIndirectCommand cmd{}; + std::memcpy(&cmd, commandBytes + static_cast(i) * stride, sizeof(cmd)); + if (cmd.count == 0 || cmd.instanceCount == 0) { + continue; + } + + DrawCmd payload{}; + payload.mode = mode; + payload.params.vertexCount = cmd.count; + payload.params.instanceCount = cmd.instanceCount; + payload.params.firstVertex = cmd.first; + payload.params.firstInstance = cmd.baseInstance; + pVulkanRenderer->DrawArrays(payload); + } } void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { @@ -266,23 +434,152 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void MultiDrawArraysIndirectCount(GLenum mode, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) { - MGLOG_W("DirectVulkan::MultiDrawArraysIndirectCount is not implemented yet (maxdrawcount=%d)", maxdrawcount); + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::MultiDrawArraysIndirectCount called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::MultiDrawArraysIndirectCount called with null GL context"); + + if (maxdrawcount <= 0) { + return; + } + if (stride == 0) { + stride = sizeof(DrawArraysIndirectCommand); + } + if (stride < static_cast(sizeof(DrawArraysIndirectCommand))) { + MGLOG_E("MultiDrawArraysIndirectCount skipped: stride %d is smaller than command size %zu", + stride, sizeof(DrawArraysIndirectCommand)); + return; + } + + auto parameterBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Parameter).GetBoundObject(); + if (!parameterBuffer || drawcount < 0 || static_cast(drawcount) + sizeof(Uint32) > parameterBuffer->GetSize()) { + MGLOG_E("MultiDrawArraysIndirectCount skipped: invalid GL_PARAMETER_BUFFER binding or range"); + return; + } + + parameterBuffer->MarkPersistentMappedRangeDirty(); + const auto parameterData = parameterBuffer->GetDataReadOnly(); + if (!parameterData) { + MGLOG_E("MultiDrawArraysIndirectCount skipped: CPU fallback cannot read parameter buffer"); + return; + } + + Uint32 actualDrawCount = 0; + std::memcpy(&actualDrawCount, parameterData->data() + drawcount, sizeof(actualDrawCount)); + actualDrawCount = std::min(actualDrawCount, static_cast(maxdrawcount)); + MultiDrawArraysIndirect(mode, indirect, static_cast(actualDrawCount), stride); } void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, - const void* indices, GLint basevertex) {} - void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) {} + const void* indices, GLint basevertex) { + (void)start; + (void)end; + DrawElementsBaseVertex(mode, count, type, indices, basevertex); + } + void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) { + (void)start; + (void)end; + DrawElements(mode, count, type, indices); + } void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, - GLsizei instancecount, GLint basevertex, GLuint baseinstance) {} + GLsizei instancecount, GLint basevertex, GLuint baseinstance) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsInstancedBaseVertexBaseInstance called with null GL context"); + + DrawIndexedCmd payload{}; + payload.mode = mode; + payload.indexBufferView.indexType = type; + payload.indexBufferView.indexByteOffset = reinterpret_cast(indices); + payload.indexBufferView.indexByteSize = count * MG_Util::GetGLTypeSize(type); + payload.params.indexCount = count; + payload.params.instanceCount = instancecount; + payload.params.firstIndex = 0; + payload.params.vertexOffset = basevertex; + payload.params.firstInstance = static_cast(baseinstance); + pVulkanRenderer->DrawElements(payload); + } void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, - GLsizei instancecount, GLint basevertex) {} + GLsizei instancecount, GLint basevertex) { + DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, basevertex, 0); + } void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, - GLsizei instancecount, GLuint baseinstance) {} - void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) {} - void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) {} + GLsizei instancecount, GLuint baseinstance) { + DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, 0, baseinstance); + } + void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) { + DrawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instancecount, 0, 0); + } + void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawElementsIndirect called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawElementsIndirect called with null GL context"); + + const SizeT indexSize = MG_Util::GetGLTypeSize(type); + if (indexSize == 0) { + MGLOG_E("DrawElementsIndirect skipped: unsupported index type 0x%x", type); + return; + } + + const auto* commandBytes = + ResolveIndirectCommandBytes(indirect, sizeof(DrawElementsIndirectCommand), "DrawElementsIndirect"); + if (!commandBytes) { + return; + } + + DrawElementsIndirectCommand cmd{}; + std::memcpy(&cmd, commandBytes, sizeof(cmd)); + if (cmd.count == 0 || cmd.instanceCount == 0) { + return; + } + + DrawIndexedCmd payload{}; + payload.mode = mode; + payload.indexBufferView.indexType = type; + payload.indexBufferView.indexByteOffset = static_cast(cmd.firstIndex) * indexSize; + payload.indexBufferView.indexByteSize = static_cast(cmd.count) * indexSize; + payload.params.indexCount = cmd.count; + payload.params.instanceCount = cmd.instanceCount; + payload.params.firstIndex = 0; + payload.params.vertexOffset = cmd.baseVertex; + payload.params.firstInstance = static_cast(cmd.baseInstance); + pVulkanRenderer->DrawElements(payload); + } void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, - GLuint baseinstance) {} - void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {} - void DrawArraysIndirect(GLenum mode, const void* indirect) {} + GLuint baseinstance) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysInstancedBaseInstance called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArraysInstancedBaseInstance called with null GL context"); + + DrawCmd payload{}; + payload.mode = mode; + payload.params.vertexCount = count; + payload.params.instanceCount = instancecount; + payload.params.firstVertex = first; + payload.params.firstInstance = baseinstance; + pVulkanRenderer->DrawArrays(payload); + } + void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { + DrawArraysInstancedBaseInstance(mode, first, count, instancecount, 0); + } + void DrawArraysIndirect(GLenum mode, const void* indirect) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::DrawArraysIndirect called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::DrawArraysIndirect called with null GL context"); + + const auto* commandBytes = + ResolveIndirectCommandBytes(indirect, sizeof(DrawArraysIndirectCommand), "DrawArraysIndirect"); + if (!commandBytes) { + return; + } + + DrawArraysIndirectCommand cmd{}; + std::memcpy(&cmd, commandBytes, sizeof(cmd)); + if (cmd.count == 0 || cmd.instanceCount == 0) { + return; + } + + DrawCmd payload{}; + payload.mode = mode; + payload.params.vertexCount = cmd.count; + payload.params.instanceCount = cmd.instanceCount; + payload.params.firstVertex = cmd.first; + payload.params.firstInstance = cmd.baseInstance; + pVulkanRenderer->DrawArrays(payload); + } void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::CopyTexImage2D called with null VulkanRenderer"); @@ -461,31 +758,35 @@ namespace MobileGL::MG_Backend::DirectVulkan { auto* programObject = TryGetDirectVulkanProgram(program); if (!programObject) return; auto& cache = GetProgramResourceCache(*programObject); - if (programInterface == GL_SHADER_STORAGE_BLOCK) { - if (pname == GL_ACTIVE_RESOURCES) { - *params = static_cast(cache.storageBlocks.size()); - } else if (pname == GL_MAX_NAME_LENGTH) { - SizeT maxLength = 0; - for (const auto& block : cache.storageBlocks) maxLength = std::max(maxLength, block.name.size() + 1); - *params = static_cast(maxLength); + switch (pname) { + case GL_ACTIVE_RESOURCES: + *params = GetProgramResourceActiveCount(*programObject, programInterface, cache); + return; + case GL_MAX_NAME_LENGTH: + *params = GetProgramResourceMaxNameLength(*programObject, programInterface, cache); + return; + case GL_MAX_NUM_ACTIVE_VARIABLES: + if (programInterface == GL_SHADER_STORAGE_BLOCK) { + SizeT maxCount = 0; + for (const auto& block : cache.storageBlocks) { + maxCount = std::max(maxCount, block.activeVariables.size()); + } + *params = static_cast(maxCount); + } else if (programInterface == GL_UNIFORM_BLOCK) { + GLint maxCount = 0; + const Int activeBlocks = programObject->GetActiveUniformBlocksCount(); + for (Int index = 0; index < activeBlocks; ++index) { + maxCount = std::max(maxCount, programObject->GetUniformBlockActiveUniformCount(index)); + } + *params = maxCount; } else { *params = 0; } return; - } - if (programInterface == GL_BUFFER_VARIABLE) { - if (pname == GL_ACTIVE_RESOURCES) { - *params = static_cast(cache.bufferVariables.size()); - } else if (pname == GL_MAX_NAME_LENGTH) { - SizeT maxLength = 0; - for (const auto& var : cache.bufferVariables) maxLength = std::max(maxLength, var.name.size() + 1); - *params = static_cast(maxLength); - } else { - *params = 0; - } + default: + *params = 0; return; } - *params = 0; } GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name) { @@ -493,17 +794,30 @@ namespace MobileGL::MG_Backend::DirectVulkan { auto* programObject = TryGetDirectVulkanProgram(program); if (!programObject) return GL_INVALID_INDEX; auto& cache = GetProgramResourceCache(*programObject); + const String resourceName = name; if (programInterface == GL_SHADER_STORAGE_BLOCK) { return GetShaderStorageBlockIndex(*programObject, name); } if (programInterface == GL_BUFFER_VARIABLE) { - const String resourceName = name; const auto it = std::find_if(cache.bufferVariables.begin(), cache.bufferVariables.end(), [&](const BufferVariableResource& var) { return var.name == resourceName; }); return it == cache.bufferVariables.end() ? GL_INVALID_INDEX : static_cast(std::distance(cache.bufferVariables.begin(), it)); } + if (programInterface == GL_UNIFORM_BLOCK) { + return programObject->GetUniformBlockIndex(name); + } + if (programInterface == GL_UNIFORM) { + const Int activeUniformIndex = programObject->GetActiveUniformIndex(resourceName); + return activeUniformIndex >= 0 ? static_cast(activeUniformIndex) : GL_INVALID_INDEX; + } + if (programInterface == GL_PROGRAM_INPUT) { + return FindProgramInputIndex(*programObject, resourceName); + } + if (programInterface == GL_PROGRAM_OUTPUT) { + return FindProgramOutputIndex(*programObject, resourceName); + } return GL_INVALID_INDEX; } @@ -520,6 +834,23 @@ namespace MobileGL::MG_Backend::DirectVulkan { CopyResourceName(cache.bufferVariables[index].name, bufSize, length, name); return; } + if (programInterface == GL_UNIFORM_BLOCK && programObject->IsActiveUniformBlock(index)) { + CopyResourceName(programObject->GetUniformBlockName(index), bufSize, length, name); + return; + } + if (programInterface == GL_UNIFORM && index < programObject->GetUniformCount()) { + CopyResourceName(programObject->GetActiveUniformName(index), bufSize, length, name); + return; + } + if (programInterface == GL_PROGRAM_INPUT && index < static_cast(programObject->GetActiveAttributesCount())) { + CopyResourceName(programObject->GetActiveAttribName(index), bufSize, length, name); + return; + } + if (programInterface == GL_PROGRAM_OUTPUT && + index < static_cast(programObject->GetActiveFragmentOutputCount())) { + CopyResourceName(programObject->GetActiveFragmentOutputName(index), bufSize, length, name); + return; + } if (length) *length = 0; if (name && bufSize > 0) name[0] = '\0'; } @@ -589,6 +920,155 @@ namespace MobileGL::MG_Backend::DirectVulkan { writeValue(0); break; } + } else if (programInterface == GL_UNIFORM_BLOCK && + programObject->IsActiveUniformBlock(index)) { + const auto activeVariables = GetUniformBlockActiveVariables(*programObject, index); + switch (prop) { + case GL_NAME_LENGTH: + writeValue(static_cast(programObject->GetUniformBlockName(index).size() + 1)); + break; + case GL_BUFFER_BINDING: + writeValue(static_cast(programObject->GetUniformBlockBinding(index))); + break; + case GL_BUFFER_DATA_SIZE: + writeValue(static_cast(programObject->GetUBOSizeAt(index))); + break; + case GL_NUM_ACTIVE_VARIABLES: + writeValue(static_cast(activeVariables.size())); + break; + case GL_ACTIVE_VARIABLES: + for (const GLuint variableIndex : activeVariables) { + writeValue(static_cast(variableIndex)); + } + break; + case GL_REFERENCED_BY_VERTEX_SHADER: + writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangVertex) ? GL_TRUE + : GL_FALSE); + break; + case GL_REFERENCED_BY_FRAGMENT_SHADER: + writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangFragment) ? GL_TRUE + : GL_FALSE); + break; + case GL_REFERENCED_BY_COMPUTE_SHADER: + writeValue(programObject->IsUniformBlockReferencedByStage(index, EShLangCompute) ? GL_TRUE + : GL_FALSE); + break; + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + writeValue(GL_FALSE); + break; + default: + writeValue(0); + break; + } + } else if (programInterface == GL_UNIFORM && index < programObject->GetUniformCount()) { + const auto& uniformName = programObject->GetActiveUniformName(index); + const GLint location = programObject->GetUniformLocation(uniformName); + switch (prop) { + case GL_NAME_LENGTH: + writeValue(static_cast(uniformName.size() + 1)); + break; + case GL_TYPE: + writeValue(static_cast(programObject->GetActiveUniformType(index))); + break; + case GL_ARRAY_SIZE: + writeValue(programObject->GetActiveUniformArraySize(index)); + break; + case GL_BLOCK_INDEX: + writeValue(programObject->GetActiveUniformBlockIndex(index)); + break; + case GL_LOCATION: + writeValue(location); + break; + case GL_OFFSET: + writeValue(location >= 0 && programObject->IsValidUniformLocation(location) + ? static_cast(programObject->GetUniformOffset(location)) + : 0); + break; + case GL_ARRAY_STRIDE: + case GL_MATRIX_STRIDE: + case GL_IS_ROW_MAJOR: + case GL_TOP_LEVEL_ARRAY_SIZE: + case GL_TOP_LEVEL_ARRAY_STRIDE: + case GL_REFERENCED_BY_VERTEX_SHADER: + case GL_REFERENCED_BY_FRAGMENT_SHADER: + case GL_REFERENCED_BY_COMPUTE_SHADER: + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + writeValue(0); + break; + default: + writeValue(0); + break; + } + } else if (programInterface == GL_PROGRAM_INPUT && + index < static_cast(programObject->GetActiveAttributesCount())) { + const auto& resourceName = programObject->GetActiveAttribName(index); + switch (prop) { + case GL_NAME_LENGTH: + writeValue(static_cast(resourceName.size() + 1)); + break; + case GL_TYPE: + writeValue(static_cast(programObject->GetActiveAttribType(index))); + break; + case GL_ARRAY_SIZE: + writeValue(programObject->GetActiveAttribArraySize(index)); + break; + case GL_LOCATION: + writeValue(programObject->GetAttributeLocation(resourceName)); + break; + case GL_REFERENCED_BY_VERTEX_SHADER: + writeValue(GL_TRUE); + break; + case GL_REFERENCED_BY_FRAGMENT_SHADER: + case GL_REFERENCED_BY_COMPUTE_SHADER: + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + case GL_IS_PER_PATCH: + case GL_LOCATION_INDEX: + writeValue(0); + break; + default: + writeValue(0); + break; + } + } else if (programInterface == GL_PROGRAM_OUTPUT && + index < static_cast(programObject->GetActiveFragmentOutputCount())) { + const auto& resourceName = programObject->GetActiveFragmentOutputName(index); + switch (prop) { + case GL_NAME_LENGTH: + writeValue(static_cast(resourceName.size() + 1)); + break; + case GL_TYPE: + writeValue(static_cast(programObject->GetFragmentOutputType(index))); + break; + case GL_ARRAY_SIZE: + writeValue(programObject->GetActiveFragmentOutputArraySize(index)); + break; + case GL_LOCATION: + writeValue(programObject->GetFragmentOutputLocation(index)); + break; + case GL_LOCATION_INDEX: + writeValue(0); + break; + case GL_REFERENCED_BY_FRAGMENT_SHADER: + writeValue(GL_TRUE); + break; + case GL_REFERENCED_BY_VERTEX_SHADER: + case GL_REFERENCED_BY_COMPUTE_SHADER: + case GL_REFERENCED_BY_GEOMETRY_SHADER: + case GL_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_REFERENCED_BY_TESS_EVALUATION_SHADER: + case GL_IS_PER_PATCH: + writeValue(0); + break; + default: + writeValue(0); + break; + } } else { writeValue(0); } @@ -602,13 +1082,21 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (programInterface == GL_UNIFORM) { return programObject->GetUniformLocation(name); } + if (programInterface == GL_PROGRAM_INPUT) { + return programObject->GetAttributeLocation(name); + } + if (programInterface == GL_PROGRAM_OUTPUT) { + return GetProgramOutputLocation(*programObject, name); + } return -1; } GLint GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, const GLchar* name) { - (void)program; - (void)programInterface; - (void)name; + auto* programObject = TryGetDirectVulkanProgram(program); + if (!programObject || !name) return -1; + if (programInterface == GL_PROGRAM_OUTPUT) { + return GetProgramOutputLocation(*programObject, name) >= 0 ? 0 : -1; + } return -1; } diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index a69f0cbb..9cd6f11a 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -302,8 +302,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramParameteri, GLuint program, GLenum pn DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateFramebuffer, target, numAttachments, attachments) DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateSubFramebuffer, target, numAttachments, attachments, x, y, width, height) DECLARE_GL_FUNCTION_HEAD(void, TexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage2D, target, levels, internalformat, width, height) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage3D, target, levels, internalformat, width, height, depth) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetInternalformativ, target, internalformat, pname, bufSize, params) +DECLARE_GL_FUNCTION_HEAD(void, TexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage3D, target, levels, internalformat, width, height, depth) +DECLARE_GL_FUNCTION_HEAD(void, GetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetInternalformativ, target, internalformat, pname, bufSize, params) DECLARE_GL_FUNCTION_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchCompute, num_groups_x, num_groups_y, num_groups_z) DECLARE_GL_FUNCTION_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchComputeIndirect, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawArraysIndirect, GLenum mode, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysIndirect, mode, indirect) @@ -1035,14 +1035,14 @@ DECLARE_GL_FUNCTION_HEAD(void, GetNamedRenderbufferParameteriv, GLuint renderbuf DECLARE_GL_FUNCTION_HEAD(void, CreateTextures, GLenum target, GLsizei n, GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateTextures, target, n, textures) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBuffer, GLuint texture, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBuffer, texture, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRange, GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRange, texture, internalformat, buffer, offset, size) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage1D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3D, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisample, texture, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisample, GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisample, texture, samples, internalformat, width, height, depth, fixedsamplelocations) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels) +DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) +DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage1D, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage1D, texture, level, xoffset, width, format, imageSize, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, imageSize, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) @@ -1050,20 +1050,20 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage1D, GLuint texture, GLint DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2D, texture, level, xoffset, yoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3D, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3D, texture, level, xoffset, yoffset, zoffset, x, y, width, height) DECLARE_GL_FUNCTION_HEAD(void, TextureParameterf, GLuint texture, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterf, texture, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfv, GLuint texture, GLenum pname, const GLfloat* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfv, texture, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfv, GLuint texture, GLenum pname, const GLfloat* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterfv, texture, pname, param) DECLARE_GL_FUNCTION_HEAD(void, TextureParameteri, GLuint texture, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteri, texture, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIiv, GLuint texture, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIuiv, GLuint texture, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIiv, GLuint texture, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIuiv, GLuint texture, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriv, GLuint texture, GLenum pname, const GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteriv, texture, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateTextureMipmap, texture) +DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmap, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture) DECLARE_GL_FUNCTION_HEAD(void, BindTextureUnit, GLuint unit, GLuint texture) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindTextureUnit, unit, texture) DECLARE_GL_FUNCTION_HEAD(void, GetTextureImage, GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureImage, texture, level, format, type, bufSize, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetCompressedTextureImage, GLuint texture, GLint level, GLsizei bufSize, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetCompressedTextureImage, texture, level, bufSize, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfv, GLuint texture, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameteriv, GLuint texture, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIiv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIuiv, GLuint texture, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfv, GLuint texture, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIiv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIuiv, GLuint texture, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameteriv, GLuint texture, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameteriv, texture, pname, params) DECLARE_GL_FUNCTION_HEAD(void, CreateVertexArrays, GLsizei n, GLuint* arrays) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateVertexArrays, n, arrays) DECLARE_GL_FUNCTION_HEAD(void, DisableVertexArrayAttrib, GLuint vaobj, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DisableVertexArrayAttrib, vaobj, index) @@ -1761,25 +1761,25 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, MatrixPopEXT, GLenum mode) DECLARE_GL_FUNCTI DECLARE_GL_FUNCTION_STUB_HEAD(void, MatrixPushEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MatrixPushEXT, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, ClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClientAttribDefaultEXT, mask) DECLARE_GL_FUNCTION_STUB_HEAD(void, PushClientAttribDefaultEXT, GLbitfield mask) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PushClientAttribDefaultEXT, mask) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfEXT, GLuint texture, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfEXT, texture, target, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterfvEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameteriEXT, GLuint texture, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameteriEXT, texture, target, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterivEXT, texture, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfEXT, GLuint texture, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterf, texture, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterfv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameteriEXT, GLuint texture, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteri, texture, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameteriv, texture, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage1DEXT, texture, target, level, internalformat, width, border, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage2DEXT, GLuint texture, 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, TextureImage2DEXT, texture, target, level, internalformat, width, height, border, format, type, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage1DEXT, texture, target, level, xoffset, width, format, type, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage2DEXT, GLuint texture, 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, TextureSubImage2DEXT, texture, target, level, xoffset, yoffset, width, height, format, type, pixels) +DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage1D, texture, level, xoffset, width, format, type, pixels) +DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage2DEXT, GLuint texture, 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, TextureSubImage2D, texture, level, xoffset, yoffset, width, height, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage1DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage1DEXT, texture, target, level, internalformat, x, y, width, border) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureImage2DEXT, GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureImage2DEXT, texture, target, level, internalformat, x, y, width, height, border) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage1DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage1DEXT, texture, target, level, xoffset, x, y, width) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage2DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage2DEXT, texture, target, level, xoffset, yoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureImageEXT, GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureImageEXT, texture, target, level, format, type, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterfvEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterivEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterfvEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterfvEXT, texture, target, level, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureLevelParameterivEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureLevelParameterivEXT, texture, target, level, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterfvEXT, GLuint texture, GLenum target, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterfv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameteriv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterfvEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameterfv, texture, level, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureLevelParameterivEXT, GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureLevelParameteriv, texture, level, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage3DEXT, GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage3DEXT, texture, target, level, internalformat, width, height, depth, border, format, type, pixels) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureSubImage3DEXT, texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) +DECLARE_GL_FUNCTION_HEAD(void, TextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureSubImage3D, texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTextureSubImage3DEXT, GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTextureSubImage3DEXT, texture, target, level, xoffset, yoffset, zoffset, x, y, width, height) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindMultiTextureEXT, GLenum texunit, GLenum target, GLuint texture) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindMultiTextureEXT, texunit, target, texture) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexCoordPointerEXT, GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexCoordPointerEXT, texunit, size, type, stride, pointer) @@ -1854,10 +1854,10 @@ DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferPointervEXT, GLuint buffer, GLenum DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedBufferSubDataEXT, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedBufferSubDataEXT, buffer, offset, size, data) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferEXT, texture, target, internalformat, buffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexBufferEXT, GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexBufferEXT, texunit, target, internalformat, buffer) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIivEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureParameterIuivEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIivEXT, texture, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetTextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetTextureParameterIuivEXT, texture, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureParameterIuiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIivEXT, GLuint texture, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIiv, texture, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetTextureParameterIuivEXT, GLuint texture, GLenum target, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTextureParameterIuiv, texture, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIivEXT, texunit, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, MultiTexParameterIuivEXT, GLenum texunit, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MultiTexParameterIuivEXT, texunit, target, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetMultiTexParameterIivEXT, GLenum texunit, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetMultiTexParameterIivEXT, texunit, target, pname, params) @@ -1895,7 +1895,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture2DEXT, GLuint framebu DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferTexture3DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferTexture3DEXT, framebuffer, attachment, textarget, texture, level, zoffset) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferRenderbufferEXT, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferRenderbuffer, framebuffer, attachment, renderbuffertarget, renderbuffer) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferAttachmentParameterivEXT, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameterivEXT, framebuffer, attachment, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateTextureMipmapEXT, GLuint texture, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateTextureMipmapEXT, texture, target) +DECLARE_GL_FUNCTION_HEAD(void, GenerateTextureMipmapEXT, GLuint texture, GLenum target) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GenerateTextureMipmap, texture) DECLARE_GL_FUNCTION_STUB_HEAD(void, GenerateMultiTexMipmapEXT, GLenum texunit, GLenum target) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GenerateMultiTexMipmapEXT, texunit, target) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBufferEXT, GLuint framebuffer, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBufferEXT, framebuffer, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferDrawBuffersEXT, GLuint framebuffer, GLsizei n, const GLenum* bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferDrawBuffersEXT, framebuffer, n, bufs) @@ -1949,9 +1949,9 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix3x4dvEXT, GLuint program DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x2dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x2dvEXT, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, ProgramUniformMatrix4x3dvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ProgramUniformMatrix4x3dvEXT, program, location, count, transpose, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBufferRangeEXT, GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBufferRangeEXT, texture, target, internalformat, buffer, offset, size) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage1DEXT, texture, target, levels, internalformat, width) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DEXT, texture, target, levels, internalformat, width, height) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DEXT, texture, target, levels, internalformat, width, height, depth) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage1D, texture, levels, internalformat, width) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage2D, texture, levels, internalformat, width, height) +DECLARE_GL_FUNCTION_HEAD(void, TextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureStorage3D, texture, levels, internalformat, width, height, depth) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage2DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage2DMultisampleEXT, texture, target, samples, internalformat, width, height, fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureStorage3DMultisampleEXT, GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureStorage3DMultisampleEXT, texture, target, samples, internalformat, width, height, depth, fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayBindVertexBufferEXT, GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayBindVertexBufferEXT, vaobj, bindingindex, buffer, offset, stride) @@ -2087,7 +2087,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearColorIuiEXT, GLuint red, GLuint green, DECLARE_GL_FUNCTION_STUB_HEAD(GLboolean, AreTexturesResidentEXT, GLsizei n, const GLuint* textures, GLboolean* residences) DECLARE_GL_FUNCTION_STUB_END(GLboolean, AreTexturesResidentEXT, n, textures, residences) DECLARE_GL_FUNCTION_STUB_HEAD(void, PrioritizeTexturesEXT, GLsizei n, const GLuint* textures, const GLclampf* priorities) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrioritizeTexturesEXT, n, textures, priorities) DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureNormalEXT, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureNormalEXT, mode) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexStorage1DEXT, target, levels, internalformat, width) +DECLARE_GL_FUNCTION_HEAD(void, TexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexStorage1D, target, levels, internalformat, width) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjecti64vEXT, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetQueryObjectui64vEXT, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, BindBufferOffsetEXT, GLenum target, GLuint index, GLuint buffer, GLintptr offset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindBufferOffsetEXT, target, index, buffer, offset) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 3d67ae43..4f31724e 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -44,6 +44,47 @@ namespace MobileGL::MG_Impl::GLImpl { textureObject->SetBorderColor(FloatVec4(static_cast(params[0]), static_cast(params[1]), static_cast(params[2]), static_cast(params[3]))); } + + Bool SetTextureSwizzleParamsFromInts(const SharedPtr& textureObject, + const GLint* params, const char* caller) { + Vec4 swizzleParams; + for (int i = 0; i < 4; ++i) { + swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(params[i]); + if (TextureSwizzleParam::Unknown == swizzleParams[i]) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", caller, "`params` is not valid.")); + return false; + } + } + textureObject->SetSwizzleParamRGBA(swizzleParams); + return true; + } + + template + void WithTemporarilyBoundNamedTexture(const SharedPtr& textureObject, + Fn&& fn) { + if (!textureObject) return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureObject->GetTarget()); + const auto previousBinding = bindingSlot.GetBoundObject(); + bindingSlot.Bind(textureObject); + fn(MG_Util::ConvertTextureTargetToGLEnum(textureObject->GetTarget())); + bindingSlot.Bind(previousBinding); + } + + SizeT ComputeTextureStorageByteSize(TextureInternalFormat textureInternalFormat, GLsizei width, GLsizei height, + GLsizei depth) { + GLenum realInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(textureInternalFormat); + GLenum realFormat = GL_RGBA; + GLenum realType = GL_UNSIGNED_BYTE; + MG_Util::TextureFormatProcessor::NormalizePixelFormat( + realInternalFormat, PixelFormatNormalizeOptionBit::None, &realInternalFormat, &realFormat, &realType); + return static_cast(width) * static_cast(height) * static_cast(depth) * + MG_Util::GetInternalBytesPerPixel(textureInternalFormat, + MG_Util::ConvertGLEnumToTexturePixelDataType(realType)); + } } // namespace const SharedPtr& GetTextureObjectByName(GLuint texture, const char* caller) { @@ -288,7 +329,84 @@ namespace MobileGL::MG_Impl::GLImpl { void TexSubImage3D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { - // TODO: implement + TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); + TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + + if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; + if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + if (!TextureImpl::ValidateTextureLevelNumber(level)) return; + if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadTarget, width, height)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, height, depth)) return; + if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadTarget, level)) return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto& textureObject = bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height, zoffset, + depth)) + return; + if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat, textureObject->GetFormat(), + texturePixelDataType)) + return; + + MOBILEGL_ASSERT(nullptr != static_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + + const void* originalPixels = pixels; + const auto& pixelUnpackBufferObject = + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); + if (pixelUnpackBufferObject) { + originalPixels = reinterpret_cast(pixelUnpackBufferObject->GetDataReadOnly()->data()) + + reinterpret_cast(pixels); + } + if (!originalPixels) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "No data supplied from pixels parameter and no PBO bound.")); + return; + } + + SizeT inputSize = 0; + void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( + originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureObject->GetFormat(), + textureInputFormat, texturePixelDataType, {width, height, depth}, false, inputSize); + if (!processedPixels || inputSize == 0) { + if (processedPixels) free(processedPixels); + return; + } + + const auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level); + const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureObject->GetFormat(), texturePixelDataType); + const SizeT srcRowSize = static_cast(width) * internalBpp; + const SizeT srcSliceSize = static_cast(height) * srcRowSize; + const SizeT destRowSize = static_cast(texelSize.x()) * internalBpp; + const SizeT destSliceSize = static_cast(texelSize.y()) * destRowSize; + + const auto* srcData = static_cast(processedPixels); + Uint8* destData = static_cast(textureMipmapObject->MapMipmapData(textureUploadTarget, level)); + if (destData) { + for (GLsizei z = 0; z < depth; ++z) { + for (GLsizei y = 0; y < height; ++y) { + const SizeT destRowOffset = + static_cast(zoffset + z) * destSliceSize + + static_cast(yoffset + y) * destRowSize + + static_cast(xoffset) * internalBpp; + const SizeT srcRowOffset = + static_cast(z) * srcSliceSize + static_cast(y) * srcRowSize; + Memcpy(destData + destRowOffset, srcData + srcRowOffset, srcRowSize); + } + } + } + + free(processedPixels); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, true); + MaybeAutoGenerateMipmap(target, textureObject, false, level); } void TexSubImage2D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, @@ -410,7 +528,66 @@ namespace MobileGL::MG_Impl::GLImpl { void TexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid* pixels) { - // TODO: implement + TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); + TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + + if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; + if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + if (!TextureImpl::ValidateTextureLevelNumber(level)) return; + if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadTarget, width, 1)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, 1, 1)) return; + if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadTarget, level)) return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto& textureObject = bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width)) return; + if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat, textureObject->GetFormat(), + texturePixelDataType)) + return; + + MOBILEGL_ASSERT(nullptr != static_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + + const void* originalPixels = pixels; + const auto& pixelUnpackBufferObject = + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); + if (pixelUnpackBufferObject) { + originalPixels = reinterpret_cast(pixelUnpackBufferObject->GetDataReadOnly()->data()) + + reinterpret_cast(pixels); + } + if (!originalPixels) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, + "No data supplied from pixels parameter and no PBO bound.")); + return; + } + + SizeT inputSize = 0; + void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( + originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureObject->GetFormat(), + textureInputFormat, texturePixelDataType, {width, 1, 1}, false, inputSize); + if (!processedPixels || inputSize == 0) { + if (processedPixels) free(processedPixels); + return; + } + + const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureObject->GetFormat(), texturePixelDataType); + const SizeT copySize = static_cast(width) * internalBpp; + Uint8* destData = static_cast(textureMipmapObject->MapMipmapData(textureUploadTarget, level)); + if (destData) { + Memcpy(destData + static_cast(xoffset) * internalBpp, processedPixels, copySize); + } + + free(processedPixels); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, true); + MaybeAutoGenerateMipmap(target, textureObject, false, level); } // TexParameteriv/TexParameterfv are introduced in OpenGL 4.0, so do not support them for now. @@ -522,25 +699,15 @@ namespace MobileGL::MG_Impl::GLImpl { break; } case GL_TEXTURE_SWIZZLE_RGBA: { - // ======================= Converting ================================ TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); - - // ======================= Processing ================================ auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget); if (!textureObject) return; - - Vec4 swizzleParams; - for (int i = 0; i < 4; i++) { - swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); - if (TextureSwizzleParam::Unknown == swizzleParams[i]) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeUnique("MG_Impl/GLImpl", __func__, "`params` is not valid.")); - return; - } + GLint signedParams[4] = {static_cast(params[0]), static_cast(params[1]), + static_cast(params[2]), static_cast(params[3])}; + if (!SetTextureSwizzleParamsFromInts(textureObject, signedParams, __func__)) { + return; } - textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -563,25 +730,13 @@ namespace MobileGL::MG_Impl::GLImpl { break; } case GL_TEXTURE_SWIZZLE_RGBA: { - // ======================= Converting ================================ TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); - - // ======================= Processing ================================ auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget); if (!textureObject) return; - - Vec4 swizzleParams; - for (int i = 0; i < 4; i++) { - swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); - if (TextureSwizzleParam::Unknown == swizzleParams[i]) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeUnique("MG_Impl/GLImpl", __func__, "`params` is not valid.")); - return; - } + if (!SetTextureSwizzleParamsFromInts(textureObject, params, __func__)) { + return; } - textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -601,25 +756,15 @@ namespace MobileGL::MG_Impl::GLImpl { break; } case GL_TEXTURE_SWIZZLE_RGBA: { - // ======================= Converting ================================ TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); - - // ======================= Processing ================================ auto& textureObject = GetTextureObjectByTarget(textureUploadTarget, textureTarget); if (!textureObject) return; - - Vec4 swizzleParams; - for (int i = 0; i < 4; i++) { - swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); - if (TextureSwizzleParam::Unknown == swizzleParams[i]) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeUnique("MG_Impl/GLImpl", __func__, "`params` is not valid.")); - return; - } + GLint signedParams[4] = {static_cast(params[0]), static_cast(params[1]), + static_cast(params[2]), static_cast(params[3])}; + if (!SetTextureSwizzleParamsFromInts(textureObject, signedParams, __func__)) { + return; } - textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -918,8 +1063,75 @@ namespace MobileGL::MG_Impl::GLImpl { void TexImage1D_State(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - // TODO: implement - THROW_UNIMPL_EXCEPTION; + TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); + TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); + + if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; + if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + if (!TextureImpl::ValidateTextureLevelNumber(level)) return; + if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadTarget, width, 1)) return; + if (!TextureImpl::ValidateTextureSizeRange(width, 1, 1)) return; + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (!TextureImpl::ValidateTextureBorderNumber(border)) return; + if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat, textureInternalFormat, + texturePixelDataType)) + return; + if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadTarget, level)) return; + + textureInternalFormat = + MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType); + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadTarget); + auto& textureObject = + isProxy ? TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadTarget) + : bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + + if (internalFormat == GL_ALPHA || format == GL_ALPHA) { + textureObject->SetSwizzleParamRGBA({TextureSwizzleParam::Zero, TextureSwizzleParam::Zero, + TextureSwizzleParam::Zero, TextureSwizzleParam::Red}); + } + + const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType); + const SizeT internalBytes = static_cast(width) * internalBpp; + textureObject->SetInternalFormat(textureInternalFormat); + + const void* originalPixels = pixels; + const auto& pixelUnpackBufferObject = + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); + if (pixelUnpackBufferObject) { + originalPixels = reinterpret_cast(pixelUnpackBufferObject->GetDataReadOnly()->data()) + + reinterpret_cast(pixels); + } + + MOBILEGL_ASSERT(nullptr != static_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + if (!isProxy) { + textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{width, 1, 1}, internalBytes}); + } + + if (!originalPixels) { + return; + } + + SizeT imageSize = 0; + void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack( + originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat, + textureInputFormat, texturePixelDataType, {width, 1, 1}, false, imageSize); + if (processedPixels && imageSize > 0) { + DataPtr texelInput{processedPixels, std::min(imageSize, internalBytes)}; + textureMipmapObject->UpdateMipmapSubData(textureUploadTarget, level, texelInput); + } + + free(processedPixels); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, true); + MaybeAutoGenerateMipmap(target, textureObject, isProxy, level); } void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) { @@ -1825,6 +2037,41 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width) { + auto textureObject = GetTextureObjectByName(texture, __func__); + if (!textureObject) return; + if (levels < 1) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "levels must be positive.")); + return; + } + if (!TextureImpl::ValidateTextureSizeRange(width, 1, 1)) return; + + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA, + TexturePixelDataType::UnsignedByte); + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (textureObject->GetStorageType() != TextureStorageType::Mipmap) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed.")); + return; + } + + const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject); + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + auto* textureMipmapObject = static_cast(textureObject.get()); + + textureObject->SetInternalFormat(textureInternalFormat); + for (GLsizei level = 0; level < levels; ++level) { + const GLsizei levelWidth = std::max(1, width >> level); + const SizeT byteSize = ComputeTextureStorageByteSize(textureInternalFormat, levelWidth, 1, 1); + textureMipmapObject->AllocateStorage(textureUploadTarget, level, {{levelWidth, 1, 1}, byteSize}); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false); + } + } + void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { auto textureObject = GetTextureObjectByName(texture, __func__); if (!textureObject) return; @@ -1870,6 +2117,60 @@ namespace MobileGL::MG_Impl::GLImpl { } } + void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth) { + auto textureObject = GetTextureObjectByName(texture, __func__); + if (!textureObject) return; + if (levels < 1) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "levels must be positive.")); + return; + } + if (!TextureImpl::ValidateTextureSizeRange(width, height, depth)) return; + + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA, + TexturePixelDataType::UnsignedByte); + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + if (textureObject->GetStorageType() != TextureStorageType::Mipmap) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", __func__, "Texture storage is not mipmap-backed.")); + return; + } + + const auto textureUploadTarget = GetPrimaryUploadTarget(textureObject); + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + auto* textureMipmapObject = static_cast(textureObject.get()); + + textureObject->SetInternalFormat(textureInternalFormat); + for (GLsizei level = 0; level < levels; ++level) { + const GLsizei levelWidth = std::max(1, width >> level); + const GLsizei levelHeight = std::max(1, height >> level); + const GLsizei levelDepth = std::max(1, depth >> level); + const SizeT byteSize = ComputeTextureStorageByteSize(textureInternalFormat, levelWidth, levelHeight, + levelDepth); + textureMipmapObject->AllocateStorage(textureUploadTarget, level, + {{levelWidth, levelHeight, levelDepth}, byteSize}); + textureMipmapObject->MarkStorageDirty(textureUploadTarget, level, false); + } + } + + void TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) { + const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + if (!TextureImpl::ValidateTextureTarget(textureTarget)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto& textureObject = bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + + TextureStorage1D(textureObject->GetExternalIndex(), levels, internalformat, width); + } + void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); @@ -1884,6 +2185,29 @@ namespace MobileGL::MG_Impl::GLImpl { TextureStorage2D(textureObject->GetExternalIndex(), levels, internalformat, width, height); } + void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth) { + const auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + const auto textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + if (!TextureImpl::ValidateTextureTarget(textureTarget)) return; + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return; + + auto& activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto& textureObject = bindingSlot.GetBoundObject(); + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + + TextureStorage3D(textureObject->GetExternalIndex(), levels, internalformat, width, height, depth); + } + + void TextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, + const void* pixels) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexSubImage1D_State(target, level, xoffset, width, format, type, pixels); + }); + } + void TextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) { auto textureObject = GetTextureObjectByName(texture, __func__); @@ -1960,6 +2284,14 @@ namespace MobileGL::MG_Impl::GLImpl { free(processedPixels); } + void TextureSubImage3D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); + }); + } + void TextureParameteri(GLuint texture, GLenum pname, GLint param) { auto textureObject = GetTextureObjectByName(texture, __func__); TextureParameterObject_State(textureObject, pname, param, __func__); @@ -1970,25 +2302,32 @@ namespace MobileGL::MG_Impl::GLImpl { TextureParameterObjectf_State(textureObject, pname, param, __func__); } + void TextureParameterfv(GLuint texture, GLenum pname, const GLfloat* params) { + if (!params) return; + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { TexParameterfv_State(target, pname, params); }); + } + void TextureParameteriv(GLuint texture, GLenum pname, const GLint* params) { if (!params) return; - if (pname == GL_TEXTURE_SWIZZLE_RGBA) { - auto textureObject = GetTextureObjectByName(texture, __func__); - if (!textureObject) return; - Vec4 swizzleParams; - for (int i = 0; i < 4; i++) { - swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); - if (TextureSwizzleParam::Unknown == swizzleParams[i]) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeUnique("MG_Impl/GLImpl", __func__, "`params` is not valid.")); - return; - } - } - textureObject->SetSwizzleParamRGBA(swizzleParams); - return; - } - TextureParameteri(texture, pname, *params); + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { TexParameteriv_State(target, pname, params); }); + } + + void TextureParameterIiv(GLuint texture, GLenum pname, const GLint* params) { + if (!params) return; + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexParameterIiv_State(target, pname, params); + }); + } + + void TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint* params) { + if (!params) return; + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + TexParameterIuiv_State(target, pname, params); + }); } void BindTextureUnit(GLuint unit, GLuint texture) { @@ -2070,37 +2409,36 @@ namespace MobileGL::MG_Impl::GLImpl { void GetTextureParameteriv(GLuint texture, GLenum pname, GLint* params) { auto textureObject = GetTextureObjectByName(texture, __func__); - GetTextureParameterObjectiv_State(textureObject, pname, params, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GetTexParameteriv_State(target, pname, params); }); + } + + void GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat* params) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GetTexParameterfv_State(target, pname, params); }); + } + + void GetTextureParameterIiv(GLuint texture, GLenum pname, GLint* params) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GetTexParameterIiv_State(target, pname, params); }); + } + + void GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint* params) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GetTexParameterIuiv_State(target, pname, params); }); } void GetTextureLevelParameteriv(GLuint texture, GLint level, GLenum pname, GLint* params) { auto textureObject = GetTextureObjectByName(texture, __func__); - if (!textureObject || !params) return; - if (!TextureImpl::ValidateTextureLevelNumber(level)) return; - if (textureObject->GetStorageType() != TextureStorageType::Mipmap) return; + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + GetTexLevelParameteriv_State(target, level, pname, params); + }); + } - auto textureUploadTarget = GetPrimaryUploadTarget(textureObject); - auto* textureMipmapObject = static_cast(textureObject.get()); - switch (pname) { - case GL_TEXTURE_WIDTH: - *params = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level).x(); - break; - case GL_TEXTURE_HEIGHT: - *params = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level).y(); - break; - case GL_TEXTURE_DEPTH: - *params = textureMipmapObject->GetMipmapTexelSize(textureUploadTarget, level).z(); - break; - case GL_TEXTURE_INTERNAL_FORMAT: - *params = (GLint)MG_Util::ConvertTextureInternalFormatToGLEnum(textureObject->GetFormat()); - break; - default: - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeUnique("MG_Impl/GLImpl", __func__, - "pname is not a valid texture level parameter.")); - return; - } + void GetTextureLevelParameterfv(GLuint texture, GLint level, GLenum pname, GLfloat* params) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { + GetTexLevelParameterfv_State(target, level, pname, params); + }); } void BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, @@ -2159,6 +2497,11 @@ namespace MobileGL::MG_Impl::GLImpl { GenerateMipmap_Backend(target); } + void GenerateTextureMipmap(GLuint texture) { + auto textureObject = GetTextureObjectByName(texture, __func__); + WithTemporarilyBoundNamedTexture(textureObject, [&](GLenum target) { GenerateMipmap_Backend(target); }); + } + void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) { if (!GetTexImage_State(target, level, format, type, pixels)) return; if (MG_Backend::gBackendFunctionsTable.GL.GetTexImage != nullptr) { @@ -2173,6 +2516,103 @@ namespace MobileGL::MG_Impl::GLImpl { __func__); } + void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) { + if (!params || bufSize <= 0) return; + + const TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + const Bool isRenderbufferTarget = target == GL_RENDERBUFFER; + if (!isRenderbufferTarget && !TextureImpl::ValidateTextureTarget(textureTarget)) return; + + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, TextureInputFormat::RGBA, + TexturePixelDataType::UnsignedByte); + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + + GLenum preferredInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(textureInternalFormat); + GLenum imageFormat = GL_RGBA; + GLenum imageType = GL_UNSIGNED_BYTE; + MG_Util::TextureFormatProcessor::NormalizePixelFormat(preferredInternalFormat, PixelFormatNormalizeOptionBit::None, + &preferredInternalFormat, &imageFormat, &imageType); + + auto writeValues = [&](std::initializer_list values) { + GLsizei index = 0; + for (GLint value : values) { + if (index >= bufSize) break; + params[index++] = value; + } + while (index < bufSize) { + params[index++] = 0; + } + }; + + const Bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(textureInternalFormat); + const Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(textureInternalFormat); + const Bool isIntegerFormat = imageFormat == GL_RED_INTEGER || imageFormat == GL_RG_INTEGER || + imageFormat == GL_RGB_INTEGER || imageFormat == GL_RGBA_INTEGER; + const Bool isLayeredTarget = target == GL_TEXTURE_3D || target == GL_TEXTURE_1D_ARRAY || + target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP || + target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + + GLint maxSamples = 1; + if (MG_Backend::pActiveBackendObject) { + const auto& dynamicParameters = MG_Backend::pActiveBackendObject->GetDynamicParameters(); + if (isDepthFormat || isStencilFormat) { + maxSamples = dynamicParameters.MaxDepthTextureSamples; + } else if (isIntegerFormat) { + maxSamples = dynamicParameters.MaxIntegerSamples; + } else { + maxSamples = dynamicParameters.MaxColorTextureSamples; + } + maxSamples = std::max(maxSamples, 1); + } + + switch (pname) { + case GL_INTERNALFORMAT_SUPPORTED: + writeValues({GL_TRUE}); + return; + case GL_INTERNALFORMAT_PREFERRED: + writeValues({static_cast(preferredInternalFormat)}); + return; + case GL_TEXTURE_IMAGE_FORMAT: + writeValues({static_cast(imageFormat)}); + return; + case GL_TEXTURE_IMAGE_TYPE: + writeValues({static_cast(imageType)}); + return; + case GL_COLOR_COMPONENTS: + writeValues({(!isDepthFormat && !isStencilFormat) ? GL_TRUE : GL_FALSE}); + return; + case GL_DEPTH_COMPONENTS: + writeValues({isDepthFormat ? GL_TRUE : GL_FALSE}); + return; + case GL_STENCIL_COMPONENTS: + writeValues({isStencilFormat ? GL_TRUE : GL_FALSE}); + return; + case GL_FRAMEBUFFER_RENDERABLE: + writeValues({GL_FULL_SUPPORT}); + return; + case GL_FRAMEBUFFER_RENDERABLE_LAYERED: + writeValues({isLayeredTarget ? GL_FULL_SUPPORT : GL_NONE}); + return; + case GL_NUM_SAMPLE_COUNTS: + writeValues({maxSamples > 1 ? 2 : 1}); + return; + case GL_SAMPLES: + if (maxSamples > 1) { + writeValues({maxSamples, 1}); + } else { + writeValues({1}); + } + return; + default: + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "pname is not supported by GetInternalformativ.")); + return; + } + } + 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) { TexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h index 1ea881e8..c5d214ea 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h @@ -16,19 +16,37 @@ namespace MobileGL::MG_Impl::GLImpl { void GenerateMipmap(GLenum target); void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); void CreateTextures(GLenum target, GLsizei n, GLuint* textures); + void TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); void TextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + void TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth); + void TextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, + const void* pixels); void TextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); + void TextureSubImage3D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); void TextureParameterf(GLuint texture, GLenum pname, GLfloat param); + void TextureParameterfv(GLuint texture, GLenum pname, const GLfloat* params); void TextureParameteri(GLuint texture, GLenum pname, GLint param); + void TextureParameterIiv(GLuint texture, GLenum pname, const GLint* params); + void TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint* params); void TextureParameteriv(GLuint texture, GLenum pname, const GLint* params); + void GenerateTextureMipmap(GLuint texture); void BindTextureUnit(GLuint unit, GLuint texture); void GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* pixels); void GetTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void* pixels); + void GetTextureParameterfv(GLuint texture, GLenum pname, GLfloat* params); + void GetTextureParameterIiv(GLuint texture, GLenum pname, GLint* params); + void GetTextureParameterIuiv(GLuint texture, GLenum pname, GLuint* params); void GetTextureParameteriv(GLuint texture, GLenum pname, GLint* params); + void GetTextureLevelParameterfv(GLuint texture, GLint level, GLenum pname, GLfloat* params); void GetTextureLevelParameteriv(GLuint texture, GLint level, GLenum pname, GLint* params); + void TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, + GLsizei depth); 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); void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, @@ -60,6 +78,7 @@ namespace MobileGL::MG_Impl::GLImpl { void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params); + void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); void GetCompressedTexImage(GLenum target, GLint level, void* img); void GenTextures(GLsizei n, GLuint* textures); void DeleteTextures(GLsizei n, const GLuint* textures); diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 8dd22cbf..a18c4441 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -125,6 +125,12 @@ namespace MobileGL::MG_State::GLState { Int GetActiveFragmentOutputCount() const { return m_program ? m_program->getNumPipeOutputs() : 0; } + const String& GetActiveFragmentOutputName(Uint index) const { + MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetActiveFragmentOutputName: program is null"); + MOBILEGL_ASSERT(index < static_cast(m_program->getNumPipeOutputs()), + "ProgramObject::GetActiveFragmentOutputName: index=%u out of range", index); + return m_program->getPipeOutput(static_cast(index)).name; + } Int GetFragmentOutputLocation(Uint index) const { MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputLocation: program is null"); MOBILEGL_ASSERT(index < static_cast(m_program->getNumPipeOutputs()), @@ -132,6 +138,12 @@ namespace MobileGL::MG_State::GLState { index); return static_cast(m_program->getPipeOutput(static_cast(index)).layoutLocation()); } + GLint GetActiveFragmentOutputArraySize(Uint index) const { + MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetActiveFragmentOutputArraySize: program is null"); + MOBILEGL_ASSERT(index < static_cast(m_program->getNumPipeOutputs()), + "ProgramObject::GetActiveFragmentOutputArraySize: index=%u out of range", index); + return m_program->getPipeOutput(static_cast(index)).size; + } GLenum GetFragmentOutputType(Uint index) const { MOBILEGL_ASSERT(m_program != nullptr, "ProgramObject::GetFragmentOutputType: program is null"); MOBILEGL_ASSERT(index < static_cast(m_program->getNumPipeOutputs()), diff --git a/MobileGL/MG_Test/Texture/TextureTest.cpp b/MobileGL/MG_Test/Texture/TextureTest.cpp index 68a41f07..dc51bfd7 100644 --- a/MobileGL/MG_Test/Texture/TextureTest.cpp +++ b/MobileGL/MG_Test/Texture/TextureTest.cpp @@ -232,6 +232,108 @@ TEST_F(TextureTest, TextureParameterfModifiesNamedObjectWithoutBinding) { EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); } +TEST_F(TextureTest, TextureStorage1DAndSubImageModifyNamedObjectOnly) { + GLuint namedTexture = 0; + GLuint boundTexture = 0; + MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_1D, 1, &namedTexture); + MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_1D, 1, &boundTexture); + MG_Impl::GLImpl::BindTextureUnit(0, boundTexture); + + const auto boundObjectBefore = + MG_State::pGLContext->GetTextureUnitObject(0).GetBindingSlot(TextureTarget::Texture1D).GetBoundObject(); + + MG_Impl::GLImpl::TextureStorage1D(namedTexture, 2, GL_RGBA8, 4); + const Uint8 pixels[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + }; + MG_Impl::GLImpl::TextureSubImage1D(namedTexture, 0, 0, 4, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + const auto textureObject = MG_State::pGLContext->GetTextureObject(namedTexture); + auto* mipmapObject = static_cast(textureObject.get()); + ASSERT_NE(mipmapObject, nullptr); + EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture1D, 0), IntVec3(4, 1, 1)); + EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture1D, 1), IntVec3(2, 1, 1)); + EXPECT_TRUE(mipmapObject->IsStorageDirty(TextureUploadTarget::Texture1D, 0)); + + const auto* stored = static_cast(mipmapObject->MapMipmapData(TextureUploadTarget::Texture1D, 0)); + ASSERT_NE(stored, nullptr); + EXPECT_EQ(std::memcmp(stored, pixels, sizeof(pixels)), 0); + + EXPECT_EQ(MG_State::pGLContext->GetTextureUnitObject(0).GetBindingSlot(TextureTarget::Texture1D).GetBoundObject(), + boundObjectBefore); + EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); +} + +TEST_F(TextureTest, TextureStorage3DAndSubImageModifyNamedObjectOnly) { + GLuint texture = 0; + MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_3D, 1, &texture); + MG_Impl::GLImpl::TextureStorage3D(texture, 2, GL_R8, 2, 2, 2); + + const Uint8 pixels[] = { + 1, 2, 3, 4, + 5, 6, 7, 8, + }; + MG_Impl::GLImpl::TextureSubImage3D(texture, 0, 0, 0, 0, 2, 2, 2, GL_RED, GL_UNSIGNED_BYTE, pixels); + + const auto textureObject = MG_State::pGLContext->GetTextureObject(texture); + auto* mipmapObject = static_cast(textureObject.get()); + ASSERT_NE(mipmapObject, nullptr); + EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 0), IntVec3(2, 2, 2)); + EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 1), IntVec3(1, 1, 1)); + EXPECT_TRUE(mipmapObject->IsStorageDirty(TextureUploadTarget::Texture3D, 0)); + + const auto* stored = static_cast(mipmapObject->MapMipmapData(TextureUploadTarget::Texture3D, 0)); + ASSERT_NE(stored, nullptr); + EXPECT_EQ(std::memcmp(stored, pixels, sizeof(pixels)), 0); + EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); +} + +TEST_F(TextureTest, NamedTextureVectorParametersAndGettersWorkWithoutBinding) { + GLuint texture = 0; + MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_2D, 1, &texture); + + const GLfloat borderColor[] = {0.25f, 0.5f, 0.75f, 1.0f}; + const GLint swizzle[] = {GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA}; + MG_Impl::GLImpl::TextureParameterfv(texture, GL_TEXTURE_BORDER_COLOR, borderColor); + MG_Impl::GLImpl::TextureParameterIiv(texture, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + + GLfloat reportedBorder[4] = {}; + GLint reportedSwizzle[4] = {}; + MG_Impl::GLImpl::GetTextureParameterfv(texture, GL_TEXTURE_BORDER_COLOR, reportedBorder); + MG_Impl::GLImpl::GetTextureParameterIiv(texture, GL_TEXTURE_SWIZZLE_RGBA, reportedSwizzle); + + EXPECT_FLOAT_EQ(reportedBorder[0], borderColor[0]); + EXPECT_FLOAT_EQ(reportedBorder[1], borderColor[1]); + EXPECT_FLOAT_EQ(reportedBorder[2], borderColor[2]); + EXPECT_FLOAT_EQ(reportedBorder[3], borderColor[3]); + EXPECT_EQ(reportedSwizzle[0], GL_BLUE); + EXPECT_EQ(reportedSwizzle[1], GL_GREEN); + EXPECT_EQ(reportedSwizzle[2], GL_RED); + EXPECT_EQ(reportedSwizzle[3], GL_ALPHA); + EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); +} + +TEST_F(TextureTest, GetInternalformativReportsBasicTextureMetadata) { + GLint params[4] = {}; + + MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_INTERNALFORMAT_SUPPORTED, 1, params); + EXPECT_EQ(params[0], GL_TRUE); + + MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, params); + EXPECT_EQ(params[0], GL_RGBA); + + MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, params); + EXPECT_EQ(params[0], GL_UNSIGNED_BYTE); + + MG_Impl::GLImpl::GetInternalformativ(GL_TEXTURE_3D, GL_DEPTH24_STENCIL8, GL_FRAMEBUFFER_RENDERABLE_LAYERED, 1, + params); + EXPECT_EQ(params[0], GL_FULL_SUPPORT); + EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR); +} + TEST_F(TextureTest, NormalizeDepth24Stencil8UsesPackedDepthStencilType) { GLenum internalFormat = 0; GLenum format = 0;