mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
1382 lines
71 KiB
C++
1382 lines
71 KiB
C++
// MobileGL - MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp
|
|
// Copyright (c) 2025 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v2.1:
|
|
// http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
|
|
// SPDX-License-Identifier: LGPL-2.1-only
|
|
// End of Source File Header
|
|
|
|
#include "GL_Texture.h"
|
|
#include "GL/gl.h"
|
|
#include "Config.h"
|
|
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
|
|
#include <MG_Backend/DirectGLES/DirectGLES.h>
|
|
#endif
|
|
#include "MG_Util/Types.h"
|
|
#include "Validators.h"
|
|
#include "ProxyTexture.h"
|
|
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
|
|
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
|
|
|
|
#include <MG_State/GLState/Core.h>
|
|
#include <MG_Util/Metrics/TextureMetrics.h>
|
|
#include <MG_State/GLState/ErrorState/Error.h>
|
|
#include <MG_Util/Texture/PixelStoreProcessor.h>
|
|
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
|
|
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
|
|
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
|
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
|
|
|
namespace MobileGL {
|
|
namespace MG_Impl::GLImpl {
|
|
SharedPtr<MG_State::GLState::ITextureObject> GetTextureObjectByTarget(TextureUploadTarget textureUploadingTarget, TextureTarget textureTarget) {
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
|
|
textureObject =
|
|
TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
if (!TextureImpl::ValidateTextureObject(textureObject))
|
|
return nullptr;
|
|
|
|
return textureObject;
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
void TexSubImage2D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
|
GLsizei height, GLenum format, GLenum type, const void* pixels) {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = 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(format);
|
|
MGLOG_D("TexSubImage2D_State: (%d, %d), format = %s, pixels = %p", width, height,
|
|
MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(),
|
|
pixels);
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
|
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
|
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
|
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
|
if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return;
|
|
if (!TextureImpl::ValidateTextureSizeRange(width, height)) return;
|
|
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
|
|
|
// TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the
|
|
// GL_PIXEL_UNPACK_BUFFER target and the buffer object's data store is currently mapped.
|
|
// GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the
|
|
// GL_PIXEL_UNPACK_BUFFER target and the data would be unpacked from the buffer object such that the
|
|
// memory reads required would exceed the data store size. GL_INVALID_OPERATION is generated if a
|
|
// non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER target and data is not evenly
|
|
// divisible into the number of bytes needed to store in memory a datum indicated by type.
|
|
|
|
// ======================= Processing ================================
|
|
auto activeUnit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
auto textureObject = bindingSlot.GetBoundObject();
|
|
TextureInternalFormat textureInternalFormat = textureObject->GetFormat();
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return;
|
|
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat,
|
|
textureInternalFormat,
|
|
texturePixelDataType))
|
|
return;
|
|
|
|
// ======================= Processing ================================
|
|
// Texture object here should always be an object with mipmap
|
|
// Assert this for extra safety.
|
|
// This should automatically compiled out in release,
|
|
// so that we don't take the perf hit of dyn-cast.
|
|
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
|
"Texture object here should always be an object with mipmap");
|
|
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
|
|
|
|
SizeT inputSize = 0;
|
|
|
|
const void* originalPixels = pixels;
|
|
|
|
// PBO
|
|
const auto& pixelUnpackBufferObject =
|
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
|
if (pixelUnpackBufferObject) {
|
|
MGLOG_D("TexSubImage2D_State: Using Pixel Unpack Buffer Object ID: %u",
|
|
pixelUnpackBufferObject->GetExternalIndex());
|
|
originalPixels = reinterpret_cast<const char*>(pixelUnpackBufferObject->GetDataReadOnly()->data()) +
|
|
reinterpret_cast<SizeT>(pixels);
|
|
}
|
|
|
|
if (!originalPixels) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidOperation,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No data supplied from pixels parameter and no PBO bound."));
|
|
return;
|
|
}
|
|
|
|
void* processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
|
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true), textureInternalFormat, textureInputFormat, texturePixelDataType, {width, height, 1},
|
|
false /*TODO*/, inputSize);
|
|
|
|
if (!processedPixels || inputSize == 0) {
|
|
MGLOG_E("TexSubImage2D_State: Failed to process pixel data for TexSubImage2D, width: %d, height: %d",
|
|
width, height);
|
|
if (processedPixels) free(processedPixels);
|
|
return;
|
|
}
|
|
|
|
const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
|
|
|
const SizeT srcRowSize = width * internalBpp;
|
|
const SizeT destRowSize = texelSize.x() * internalBpp;
|
|
|
|
if (xoffset + width > static_cast<GLsizei>(texelSize.x()) ||
|
|
yoffset + height > static_cast<GLsizei>(texelSize.y())) {
|
|
MGLOG_E("TexSubImage2D_State: Specified region exceeds texture dimensions, xoffset: %d, yoffset: %d, "
|
|
"width: %d, height: %d, mipmap size: (%d, %d)",
|
|
xoffset, yoffset, width, height, texelSize.x(), texelSize.y());
|
|
free(processedPixels);
|
|
return;
|
|
}
|
|
|
|
const auto* srcData = static_cast<const Uint8*>(processedPixels);
|
|
Uint8* destData = (Uint8*)textureMipmapObject->MapMipmapData(textureUploadingTarget, level);
|
|
// No allocation should be done here
|
|
// if (data.empty()) {
|
|
// SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel;
|
|
// data.resize(totalSize);
|
|
// }
|
|
|
|
for (GLsizei y = 0; y < height; y++) {
|
|
const SizeT destRowOffset = (yoffset + y) * destRowSize + xoffset * internalBpp;
|
|
const SizeT srcRowOffset = y * srcRowSize;
|
|
Memcpy(destData + destRowOffset, srcData + srcRowOffset, srcRowSize);
|
|
}
|
|
|
|
free(processedPixels);
|
|
|
|
textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true);
|
|
// mipmap.dirty = true;
|
|
// mipmap.hasData = true;
|
|
}
|
|
|
|
void TexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
|
|
const GLvoid* pixels) {
|
|
// TODO: implement
|
|
}
|
|
|
|
// TexParameteriv/TexParameterfv are introduced in OpenGL 4.0, so do not support them for now.
|
|
void TexParameterf_State(GLenum target, GLenum pname, GLfloat param) {
|
|
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_MAG_FILTER:
|
|
textureObject->GetSamplerObject()->SetMagFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(param));
|
|
break;
|
|
case GL_TEXTURE_MIN_FILTER:
|
|
textureObject->GetSamplerObject()->SetMinFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(param));
|
|
textureObject->GetSamplerObject()->SetMipmapMode(MG_Util::ConvertGLEnumToSamplerMipmapMode(param));
|
|
break;
|
|
case GL_TEXTURE_MIN_LOD: {
|
|
Float maxLod = textureObject->GetSamplerObject()->GetMaxLod();
|
|
textureObject->GetSamplerObject()->SetLodRange(param, maxLod);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_MAX_LOD: {
|
|
Float minLod = textureObject->GetSamplerObject()->GetMinLod();
|
|
textureObject->GetSamplerObject()->SetLodRange(minLod, param);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_BASE_LEVEL:
|
|
textureObject->SetBaseLevel(param);
|
|
break;
|
|
case GL_TEXTURE_MAX_LEVEL:
|
|
textureObject->SetMaxLevel(param);
|
|
break;
|
|
case GL_TEXTURE_SWIZZLE_R:
|
|
case GL_TEXTURE_SWIZZLE_G:
|
|
case GL_TEXTURE_SWIZZLE_B:
|
|
case GL_TEXTURE_SWIZZLE_A: {
|
|
auto swizzleParam = MG_Util::ConvertGLEnumPnameToTextureSwizzleParam(pname);
|
|
auto swizzleValue = MG_Util::ConvertGLEnumToTextureSwizzleParam(param);
|
|
textureObject->SetSwizzleParam(swizzleParam, swizzleValue);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_WRAP_S:
|
|
textureObject->GetSamplerObject()->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_WRAP_T:
|
|
textureObject->GetSamplerObject()->SetWrapT(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_WRAP_R:
|
|
textureObject->GetSamplerObject()->SetWrapR(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_COMPARE_MODE:
|
|
textureObject->GetSamplerObject()->SetCompareMode(MG_Util::ConvertGLEnumToSamplerCompareMode(param));
|
|
break;
|
|
case GL_TEXTURE_COMPARE_FUNC:
|
|
textureObject->GetSamplerObject()->SetSamplerCompareFunc(
|
|
MG_Util::ConvertGLEnumToSamplerCompareFunc(param));
|
|
break;
|
|
case GL_TEXTURE_LOD_BIAS:
|
|
textureObject->GetSamplerObject()->SetLodBias(param);
|
|
break;
|
|
case GL_TEXTURE_SWIZZLE_RGBA:
|
|
// Not supported in this function
|
|
case GL_TEXTURE_BORDER_COLOR:
|
|
// Not supported in this function
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
std::format("pname {} is not a valid texture parameter.", MG_Util::ConvertGLEnumToString(pname))));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void TexParameteri_State(GLenum target, GLenum pname, GLint param) {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_MAG_FILTER:
|
|
textureObject->GetSamplerObject()->SetMagFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(param));
|
|
break;
|
|
case GL_TEXTURE_MIN_FILTER:
|
|
textureObject->GetSamplerObject()->SetMinFilter(MG_Util::ConvertGLEnumToSamplerFilterMode(param));
|
|
textureObject->GetSamplerObject()->SetMipmapMode(MG_Util::ConvertGLEnumToSamplerMipmapMode(param));
|
|
break;
|
|
case GL_TEXTURE_MIN_LOD: {
|
|
Float maxLod = textureObject->GetSamplerObject()->GetMaxLod();
|
|
textureObject->GetSamplerObject()->SetLodRange(param, maxLod);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_MAX_LOD: {
|
|
Float minLod = textureObject->GetSamplerObject()->GetMinLod();
|
|
textureObject->GetSamplerObject()->SetLodRange(minLod, param);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_BASE_LEVEL:
|
|
textureObject->SetBaseLevel(param);
|
|
break;
|
|
case GL_TEXTURE_MAX_LEVEL:
|
|
textureObject->SetMaxLevel(param);
|
|
break;
|
|
case GL_TEXTURE_SWIZZLE_R:
|
|
case GL_TEXTURE_SWIZZLE_G:
|
|
case GL_TEXTURE_SWIZZLE_B:
|
|
case GL_TEXTURE_SWIZZLE_A: {
|
|
auto swizzleParam = MG_Util::ConvertGLEnumPnameToTextureSwizzleParam(pname);
|
|
auto swizzleValue = MG_Util::ConvertGLEnumToTextureSwizzleParam(param);
|
|
textureObject->SetSwizzleParam(swizzleParam, swizzleValue);
|
|
break;
|
|
}
|
|
case GL_TEXTURE_WRAP_S:
|
|
textureObject->GetSamplerObject()->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_WRAP_T:
|
|
textureObject->GetSamplerObject()->SetWrapT(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_WRAP_R:
|
|
textureObject->GetSamplerObject()->SetWrapR(MG_Util::ConvertGLEnumToSamplerWrapMode(param));
|
|
break;
|
|
case GL_TEXTURE_COMPARE_MODE:
|
|
textureObject->GetSamplerObject()->SetCompareMode(MG_Util::ConvertGLEnumToSamplerCompareMode(param));
|
|
break;
|
|
case GL_TEXTURE_COMPARE_FUNC:
|
|
textureObject->GetSamplerObject()->SetSamplerCompareFunc(
|
|
MG_Util::ConvertGLEnumToSamplerCompareFunc(param));
|
|
break;
|
|
case GL_TEXTURE_LOD_BIAS:
|
|
textureObject->GetSamplerObject()->SetLodBias((GLfloat)param);
|
|
break;
|
|
case GL_TEXTURE_SWIZZLE_RGBA:
|
|
// Not supported in this function
|
|
case GL_TEXTURE_BORDER_COLOR:
|
|
// Not supported in this function
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
std::format("pname {} is not a valid texture parameter.", MG_Util::ConvertGLEnumToString(pname))));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Quick and dirty TexParameter*v implementation to make NeoForge happy.
|
|
// TODO: implement the missing part
|
|
void TexParameterfv_State(GLenum target, GLenum pname, const GLfloat * params) {
|
|
switch (pname) {
|
|
case GL_TEXTURE_BORDER_COLOR: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
THROW_UNIMPL_EXCEPTION;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_SWIZZLE_RGBA: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
Vec4<TextureSwizzleParam> swizzleParams;
|
|
for (int i = 0; i < 4; i++) {
|
|
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
|
|
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"`params` is not valid."));
|
|
return;
|
|
}
|
|
}
|
|
textureObject->SetSwizzleParamRGBA(swizzleParams);
|
|
break;
|
|
}
|
|
default:
|
|
TexParameterf_State(target, pname, *params);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TexParameteriv_State(GLenum target, GLenum pname, const GLint * params) {
|
|
switch (pname) {
|
|
case GL_TEXTURE_BORDER_COLOR: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
THROW_UNIMPL_EXCEPTION;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_SWIZZLE_RGBA: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
Vec4<TextureSwizzleParam> swizzleParams;
|
|
for (int i = 0; i < 4; i++) {
|
|
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
|
|
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"`params` is not valid."));
|
|
return;
|
|
}
|
|
}
|
|
textureObject->SetSwizzleParamRGBA(swizzleParams);
|
|
break;
|
|
}
|
|
default:
|
|
TexParameteri_State(target, pname, *params);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TexParameterIiv_State(GLenum target, GLenum pname, const GLint * params) {
|
|
switch (pname) {
|
|
case GL_TEXTURE_BORDER_COLOR: {
|
|
THROW_UNIMPL_EXCEPTION;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_SWIZZLE_RGBA: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
Vec4<TextureSwizzleParam> swizzleParams;
|
|
for (int i = 0; i < 4; i++) {
|
|
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
|
|
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"`params` is not valid."));
|
|
return;
|
|
}
|
|
}
|
|
textureObject->SetSwizzleParamRGBA(swizzleParams);
|
|
break;
|
|
}
|
|
default:
|
|
TexParameteri_State(target, pname, *params);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint * params) {
|
|
switch (pname) {
|
|
case GL_TEXTURE_BORDER_COLOR: {
|
|
THROW_UNIMPL_EXCEPTION;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_SWIZZLE_RGBA: {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject =
|
|
GetTextureObjectByTarget(textureUploadingTarget, textureTarget);
|
|
if (!textureObject)
|
|
return;
|
|
|
|
Vec4<TextureSwizzleParam> swizzleParams;
|
|
for (int i = 0; i < 4; i++) {
|
|
swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast<GLint>(params[i]));
|
|
if (TextureSwizzleParam::Unknown == swizzleParams[i]) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"`params` is not valid."));
|
|
return;
|
|
}
|
|
}
|
|
textureObject->SetSwizzleParamRGBA(swizzleParams);
|
|
break;
|
|
}
|
|
default:
|
|
TexParameteri_State(target, pname, static_cast<GLint>(*params));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TexImage3DMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
|
|
GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void TexImage2DMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
|
|
GLsizei height, GLboolean fixedsamplelocations) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void TexImage3D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
|
|
GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void TexImage2D_State(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
|
|
GLint border, GLenum format, GLenum type, const void* pixels) {
|
|
MGLOG_D(
|
|
"TexImage2D_State called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, "
|
|
"border: %d, format: %s, type: %s (%u), pixels: %p",
|
|
MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target))
|
|
.c_str(),
|
|
level,
|
|
MG_Util::ConvertTextureInternalFormatToString(
|
|
MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat))
|
|
.c_str(),
|
|
width, height, border,
|
|
MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(),
|
|
MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type))
|
|
.c_str(),type,
|
|
pixels);
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = 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);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return;
|
|
if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return;
|
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
|
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
|
if (!TextureImpl::ValidateTextureSizeWithTextureUploadTarget(textureUploadingTarget, width, height)) return;
|
|
if (!TextureImpl::ValidateTextureSizeRange(width, height)) return;
|
|
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
|
if (!TextureImpl::ValidateTextureBorderNumber(border)) return;
|
|
if (!TextureImpl::ValidateTextureInternalFormatCompatibleWithInput(textureInputFormat,
|
|
textureInternalFormat,
|
|
texturePixelDataType))
|
|
return;
|
|
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
|
|
|
// TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the
|
|
// GL_PIXEL_UNPACK_BUFFER target and the buffer object's data store is currently mapped.
|
|
// GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
|
|
// target and the data would be unpacked from the buffer object such that the memory reads required would
|
|
// exceed the data store size.
|
|
// GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
|
|
// target and data is not evenly divisible into the number of bytes needed to store in memory a datum
|
|
// indicated by type.
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget);
|
|
if (isProxy) {
|
|
textureObject =
|
|
TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
|
|
// ======================= Processing ================================
|
|
|
|
SizeT imageSize = 0;
|
|
const SizeT inputBpp = MG_Util::GetInputBytesPerPixel(textureInputFormat, texturePixelDataType);
|
|
const SizeT internalBpp = MG_Util::GetInternalBytesPerPixel(textureInternalFormat, texturePixelDataType);
|
|
const SizeT internalBytes = width * height * internalBpp;
|
|
|
|
textureObject->SetInternalFormat(textureInternalFormat);
|
|
|
|
// if isProxy, no more pixel transfer needed below
|
|
if (isProxy) return;
|
|
|
|
const void* originalPixels = pixels;
|
|
|
|
// PBO
|
|
const auto& pixelUnpackBufferObject =
|
|
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
|
|
if (pixelUnpackBufferObject) {
|
|
MGLOG_D("TexImage2D_State: Using Pixel Unpack Buffer Object ID: %u",
|
|
pixelUnpackBufferObject->GetExternalIndex());
|
|
originalPixels = reinterpret_cast<const char*>(pixelUnpackBufferObject->GetDataReadOnly()->data()) +
|
|
reinterpret_cast<SizeT>(pixels);
|
|
}
|
|
|
|
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
|
|
"Texture object here should always be an object with mipmap");
|
|
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
|
|
|
|
// Allocate in TextureObject
|
|
textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, internalBytes});
|
|
|
|
if (!originalPixels) {
|
|
MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer");
|
|
return;
|
|
}
|
|
|
|
void* processedPixels = nullptr;
|
|
processedPixels = MG_Util::PixelStoreProcessor::ProcessTexturePixelsDataUnpack(
|
|
originalPixels, MG_State::pGLContext->GetPixelStoreParameters(true),
|
|
textureInternalFormat, textureInputFormat, texturePixelDataType,
|
|
{width, height, 1},
|
|
false, imageSize);
|
|
|
|
if (processedPixels && imageSize > 0) {
|
|
if (imageSize != internalBytes) {
|
|
MGLOG_W("TexImage2D_State: Processed pixel data size (%zu) does not match expected size (%zu). "
|
|
"This may indicate an alignment or processing issue.",
|
|
imageSize, internalBytes);
|
|
}
|
|
|
|
const SizeT copySize = std::min(imageSize, internalBytes);
|
|
DataPtr texelInput{processedPixels, copySize};
|
|
textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput);
|
|
}
|
|
|
|
free(processedPixels);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) {
|
|
// ======================= Converting ================================
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
|
|
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
|
|
// TODO: make sure `internalformat` is in one of supported format for TexBuffer
|
|
auto bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
|
|
if (!bufferObject) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidOperation,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"`buffer` is not zero and is not the name of an existing buffer object."));
|
|
return;
|
|
}
|
|
|
|
// ======================= Processing ================================
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
auto textureObject = bindingSlot.GetBoundObject();
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
if (textureObject->GetStorageType() != TextureStorageType::Buffer) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
|
"The effective target of `texture` is not `GL_TEXTURE_BUFFER`."));
|
|
return;
|
|
}
|
|
|
|
// ======================= Processing ================================
|
|
// Now we can rest assured, and down-cast texture object to texture buffer
|
|
auto* texBufferObject = static_cast<MG_State::GLState::TextureObjectBuffer*>(textureObject.get());
|
|
auto& bufferSlot = texBufferObject->GetBufferBindingSlot();
|
|
bufferSlot.Bind(bufferObject);
|
|
|
|
texBufferObject->SetInternalFormat(textureInternalFormat);
|
|
}
|
|
|
|
GLboolean IsTexture_State(GLuint texture) {
|
|
// ======================= Processing ================================
|
|
if (!TextureImpl::ValidateTextureName(texture, true)) return GL_FALSE;
|
|
return MG_State::pGLContext->ValidateTextureObject(texture) ? GL_TRUE : GL_FALSE;
|
|
}
|
|
|
|
void GetTexParameterIuiv_State(GLenum target, GLenum pname, GLuint* params) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void GetTexParameterIiv_State(GLenum target, GLenum pname, GLint* params) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void GetTexParameteriv_State(GLenum target, GLenum pname, GLint* params) {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
|
|
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_MAG_FILTER:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerFilterModeToGLEnum(
|
|
textureObject->GetSamplerObject()->GetMagFilter(), SamplerMipmapMode::None);
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MIN_FILTER:
|
|
if (params) {
|
|
*params =
|
|
MG_Util::ConvertSamplerFilterModeToGLEnum(textureObject->GetSamplerObject()->GetMinFilter(),
|
|
textureObject->GetSamplerObject()->GetMipmapMode());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MIN_LOD:
|
|
if (params) {
|
|
*params = static_cast<GLint>(textureObject->GetSamplerObject()->GetMinLod());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MAX_LOD:
|
|
if (params) {
|
|
*params = static_cast<GLint>(textureObject->GetSamplerObject()->GetMaxLod());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_BASE_LEVEL:
|
|
case GL_TEXTURE_MAX_LEVEL:
|
|
case GL_TEXTURE_BORDER_COLOR:
|
|
break; // TODO
|
|
case GL_TEXTURE_WRAP_S:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_WRAP_T:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapT());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_WRAP_R:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapR());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_COMPARE_MODE:
|
|
if (params) {
|
|
*params =
|
|
MG_Util::ConvertSamplerCompareModeToGLEnum(textureObject->GetSamplerObject()->GetCompareMode());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_COMPARE_FUNC:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerCompareFuncToGLEnum(
|
|
textureObject->GetSamplerObject()->GetSamplerCompareFunc());
|
|
}
|
|
break;
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexParameteriv_State",
|
|
"pname is not a valid texture parameter."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void GetTexParameterfv_State(GLenum target, GLenum pname, GLfloat* params) {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
|
|
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_MAG_FILTER:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerFilterModeToGLEnum(
|
|
textureObject->GetSamplerObject()->GetMagFilter(), SamplerMipmapMode::None);
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MIN_FILTER:
|
|
if (params) {
|
|
*params =
|
|
MG_Util::ConvertSamplerFilterModeToGLEnum(textureObject->GetSamplerObject()->GetMinFilter(),
|
|
textureObject->GetSamplerObject()->GetMipmapMode());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MIN_LOD:
|
|
if (params) {
|
|
*params = static_cast<GLfloat>(textureObject->GetSamplerObject()->GetMinLod());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_MAX_LOD:
|
|
if (params) {
|
|
*params = static_cast<GLfloat>(textureObject->GetSamplerObject()->GetMaxLod());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_BASE_LEVEL:
|
|
case GL_TEXTURE_MAX_LEVEL:
|
|
case GL_TEXTURE_SWIZZLE_R:
|
|
case GL_TEXTURE_SWIZZLE_G:
|
|
case GL_TEXTURE_SWIZZLE_B:
|
|
case GL_TEXTURE_SWIZZLE_A:
|
|
case GL_TEXTURE_SWIZZLE_RGBA:
|
|
case GL_TEXTURE_BORDER_COLOR:
|
|
break; // TODO
|
|
case GL_TEXTURE_WRAP_S:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapS());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_WRAP_T:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapT());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_WRAP_R:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerWrapModeToGLEnum(textureObject->GetSamplerObject()->GetWrapR());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_COMPARE_MODE:
|
|
if (params) {
|
|
*params =
|
|
MG_Util::ConvertSamplerCompareModeToGLEnum(textureObject->GetSamplerObject()->GetCompareMode());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_COMPARE_FUNC:
|
|
if (params) {
|
|
*params = MG_Util::ConvertSamplerCompareFuncToGLEnum(
|
|
textureObject->GetSamplerObject()->GetSamplerCompareFunc());
|
|
}
|
|
break;
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexParameterfv_State",
|
|
"pname is not a valid texture parameter."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void GetTexLevelParameteriv_State(GLenum target, GLint level, GLenum pname, GLint* params) {
|
|
MGLOG_D("GetTexLevelParameteriv_State called");
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
|
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
|
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
|
|
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
|
|
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_WIDTH:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
}
|
|
break;
|
|
case GL_TEXTURE_HEIGHT:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
}
|
|
break;
|
|
case GL_TEXTURE_DEPTH:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
}
|
|
break;
|
|
case GL_TEXTURE_INTERNAL_FORMAT:
|
|
if (params) {
|
|
*params = MG_Util::ConvertTextureInternalFormatToGLEnum(textureObject->GetFormat());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_RED_TYPE:
|
|
case GL_TEXTURE_GREEN_TYPE:
|
|
case GL_TEXTURE_BLUE_TYPE:
|
|
case GL_TEXTURE_ALPHA_TYPE:
|
|
case GL_TEXTURE_DEPTH_TYPE:
|
|
case GL_TEXTURE_RED_SIZE:
|
|
case GL_TEXTURE_GREEN_SIZE:
|
|
case GL_TEXTURE_BLUE_SIZE:
|
|
case GL_TEXTURE_ALPHA_SIZE:
|
|
case GL_TEXTURE_DEPTH_SIZE:
|
|
case GL_TEXTURE_COMPRESSED:
|
|
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
|
|
break; // TODO
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexLevelParameteriv_State",
|
|
"pname is not a valid texture level parameter."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void GetTexLevelParameterfv_State(GLenum target, GLint level, GLenum pname, GLfloat* params) {
|
|
// ======================= Converting ================================
|
|
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
|
|
if (!TextureImpl::ValidateTextureLevelNumber(level)) return;
|
|
if (!TextureImpl::ValidateTextureLevelWithUploadTarget(textureUploadingTarget, level)) return;
|
|
|
|
// ======================= Processing ================================
|
|
SharedPtr<MG_State::GLState::ITextureObject> textureObject = nullptr;
|
|
if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) {
|
|
textureObject = TextureImpl::pProxyTextureManager->GetProxyTextureObject(textureUploadingTarget);
|
|
} else {
|
|
auto activeUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
|
|
textureObject = bindingSlot.GetBoundObject();
|
|
}
|
|
|
|
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
|
|
|
|
switch (pname) {
|
|
case GL_TEXTURE_WIDTH:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
}
|
|
break;
|
|
case GL_TEXTURE_HEIGHT:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
}
|
|
break;
|
|
case GL_TEXTURE_DEPTH:
|
|
if (params) {
|
|
switch (textureObject->GetStorageType()) {
|
|
case TextureStorageType::Mipmap: {
|
|
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
|
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
|
|
break;
|
|
}
|
|
default:
|
|
THROW_UNIMPL_EXCEPTION;
|
|
} }
|
|
break;
|
|
case GL_TEXTURE_INTERNAL_FORMAT:
|
|
if (params) {
|
|
*params = MG_Util::ConvertTextureInternalFormatToGLEnum(textureObject->GetFormat());
|
|
}
|
|
break;
|
|
case GL_TEXTURE_RED_TYPE:
|
|
case GL_TEXTURE_GREEN_TYPE:
|
|
case GL_TEXTURE_BLUE_TYPE:
|
|
case GL_TEXTURE_ALPHA_TYPE:
|
|
case GL_TEXTURE_DEPTH_TYPE:
|
|
case GL_TEXTURE_RED_SIZE:
|
|
case GL_TEXTURE_GREEN_SIZE:
|
|
case GL_TEXTURE_BLUE_SIZE:
|
|
case GL_TEXTURE_ALPHA_SIZE:
|
|
case GL_TEXTURE_DEPTH_SIZE:
|
|
case GL_TEXTURE_COMPRESSED:
|
|
case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
|
|
break; // TODO
|
|
default:
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GetTexLevelParameterfv_State",
|
|
"pname is not a valid texture level parameter."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void GetTexImage_State(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void GetCompressedTexImage_State(GLenum target, GLint level, void* img) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void GenTextures_State(GLsizei n, GLuint* textures) {
|
|
// ===================== Error Checking ==============================
|
|
if (n < 0) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidValue,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "GenTextures_State", "n must be non-negative"));
|
|
return;
|
|
}
|
|
|
|
// ======================= Processing ================================
|
|
auto textureNames = MG_State::pGLContext->GenTextureNames(n);
|
|
Copy(textureNames.data(), textures, textureNames.size());
|
|
}
|
|
|
|
void DeleteTextures_State(GLsizei n, const GLuint* textures) {
|
|
// ===================== Error Checking ==============================
|
|
if (n < 0) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidValue,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteTextures_State", "n must be non-negative."));
|
|
return;
|
|
}
|
|
|
|
if (!textures) {
|
|
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
|
|
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", "DeleteTextures_State",
|
|
"Texture names array cannot be null."));
|
|
return;
|
|
}
|
|
|
|
// ======================= Processing ================================
|
|
for (SizeT i = 0; i < static_cast<SizeT>(n); ++i) {
|
|
Uint textureName = textures[i];
|
|
if (textureName == 0) continue;
|
|
if (!TextureImpl::ValidateTextureName(textureName, true)) continue;
|
|
MG_State::pGLContext->MarkTextureObjectForDeletion(textureName);
|
|
}
|
|
}
|
|
|
|
void CopyTexSubImage3D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x,
|
|
GLint y, GLsizei width, GLsizei height) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void CopyTexSubImage2D_Backend(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
|
|
GLsizei width, GLsizei height) {
|
|
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
|
|
MG_Backend::DirectGLES::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
|
#endif
|
|
}
|
|
|
|
void CopyTexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
|
|
// TODO: implement
|
|
}
|
|
|
|
void CopyTexImage2D_Backend(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
|
GLsizei height, GLint border) {
|
|
#if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES
|
|
MG_Backend::DirectGLES::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
|
|
#endif
|
|
}
|
|
|
|
void CopyTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
|
GLint border) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexSubImage3D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
|
GLsizei width, GLsizei height, GLsizei depth, GLenum format,
|
|
GLsizei imageSize, const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexSubImage2D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
|
GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexSubImage1D_State(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
|
|
GLsizei imageSize, const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexImage3D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width,
|
|
GLsizei height, GLsizei depth, GLint border, GLsizei imageSize,
|
|
const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width,
|
|
GLsizei height, GLint border, GLsizei imageSize, const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void CompressedTexImage1D_State(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
|
|
GLsizei imageSize, const void* data) {
|
|
// TODO: implement
|
|
THROW_UNIMPL_EXCEPTION;
|
|
}
|
|
|
|
void BindTexture_State(GLenum target, GLuint texture) {
|
|
MGLOG_D("BindTexture_State called with target: 0x%X, texture: %u", target, texture);
|
|
// ======================= Converting ================================
|
|
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureName(texture, true)) return;
|
|
if (!TextureImpl::ValidateTextureTarget(textureTarget)) return;
|
|
|
|
// ======================= Processing ================================
|
|
auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
|
|
|
|
// ===================== Error Checking ==============================
|
|
if (!TextureImpl::ValidateTextureTargetUniformity(textureObject, textureTarget)) return;
|
|
|
|
// ======================= Processing ================================
|
|
if (!textureObject) {
|
|
textureObject = MG_State::pGLContext->CreateTextureObject(texture, textureTarget);
|
|
}
|
|
|
|
auto& currentUnit =
|
|
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
|
auto& bindingSlot = currentUnit.GetBindingSlot(textureTarget);
|
|
bindingSlot.Bind(textureObject);
|
|
}
|
|
|
|
void ActiveTexture_State(GLenum texture) {
|
|
// ===================== Error Checking ==============================
|
|
if (texture < GL_TEXTURE0 || texture > GL_TEXTURE31) {
|
|
MG_State::pGLContext->RecordError(
|
|
ErrorCode::InvalidEnum,
|
|
MakeShared<GenericErrorInfo>(
|
|
"MG_Impl/GLImpl", "ActiveTexture_State",
|
|
std::format("Texture must be one of GL_TEXTUREi, where i is in the range 0 to 31, but got "
|
|
"invalid enum: 0x{:X}, which may stand for unit {}.",
|
|
texture, texture - GL_TEXTURE0)));
|
|
return;
|
|
}
|
|
|
|
// ======================= Processing ================================
|
|
MG_State::pGLContext->SetActiveTextureUnit(texture - GL_TEXTURE0);
|
|
}
|
|
|
|
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
|
|
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);
|
|
}
|
|
|
|
void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
|
|
GLenum format, GLenum type, const void* pixels) {
|
|
TexSubImage2D_State(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
|
}
|
|
|
|
void TexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
|
|
const GLvoid* pixels) {
|
|
TexSubImage1D_State(target, level, xoffset, width, format, type, pixels);
|
|
}
|
|
|
|
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
|
TexParameterf_State(target, pname, param);
|
|
}
|
|
|
|
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
|
TexParameteri_State(target, pname, param);
|
|
}
|
|
|
|
void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params) {
|
|
TexParameterfv_State(target, pname, params);
|
|
}
|
|
|
|
void TexParameteriv(GLenum target, GLenum pname, const GLint * params) {
|
|
TexParameteriv_State(target, pname, params);
|
|
}
|
|
|
|
void TexParameterIiv(GLenum target, GLenum pname, const GLint * params) {
|
|
TexParameterIiv_State(target, pname, params);
|
|
}
|
|
|
|
void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params) {
|
|
TexParameterIuiv_State(target, pname, params);
|
|
}
|
|
|
|
void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height,
|
|
GLsizei depth, GLboolean fixedsamplelocations) {
|
|
TexImage3DMultisample_State(target, samples, internalformat, width, height, depth, fixedsamplelocations);
|
|
}
|
|
|
|
void TexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height,
|
|
GLboolean fixedsamplelocations) {
|
|
TexImage2DMultisample_State(target, samples, internalformat, width, height, fixedsamplelocations);
|
|
}
|
|
|
|
void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth,
|
|
GLint border, GLenum format, GLenum type, const void* pixels) {
|
|
TexImage3D_State(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
|
}
|
|
|
|
void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border,
|
|
GLenum format, GLenum type, const void* pixels) {
|
|
TexImage2D_State(target, level, internalformat, width, height, border, format, type, pixels);
|
|
}
|
|
|
|
void TexImage1D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format,
|
|
GLenum type, const GLvoid* pixels) {
|
|
TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels);
|
|
}
|
|
|
|
void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer) {
|
|
TexBuffer_State(target, internalformat, buffer);
|
|
}
|
|
|
|
GLboolean IsTexture(GLuint texture) {
|
|
return IsTexture_State(texture);
|
|
}
|
|
|
|
void GetTexParameterIuiv(GLenum target, GLenum pname, GLuint* params) {
|
|
GetTexParameterIuiv_State(target, pname, params);
|
|
}
|
|
|
|
void GetTexParameterIiv(GLenum target, GLenum pname, GLint* params) {
|
|
GetTexParameterIiv_State(target, pname, params);
|
|
}
|
|
|
|
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
|
|
GetTexParameteriv_State(target, pname, params);
|
|
}
|
|
|
|
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
|
|
GetTexParameterfv_State(target, pname, params);
|
|
}
|
|
|
|
void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) {
|
|
GetTexLevelParameteriv_State(target, level, pname, params);
|
|
}
|
|
|
|
void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params) {
|
|
GetTexLevelParameterfv_State(target, level, pname, params);
|
|
}
|
|
|
|
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
|
GetTexImage_State(target, level, format, type, pixels);
|
|
}
|
|
|
|
void GetCompressedTexImage(GLenum target, GLint level, void* img) {
|
|
GetCompressedTexImage_State(target, level, img);
|
|
}
|
|
|
|
void GenTextures(GLsizei n, GLuint* textures) {
|
|
GenTextures_State(n, textures);
|
|
}
|
|
|
|
void DeleteTextures(GLsizei n, const GLuint* textures) {
|
|
DeleteTextures_State(n, textures);
|
|
}
|
|
|
|
void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x,
|
|
GLint y, GLsizei width, GLsizei height) {
|
|
CopyTexSubImage3D_State(target, level, xoffset, yoffset, zoffset, x, y, width, height);
|
|
}
|
|
|
|
void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
|
|
GLsizei width, GLsizei height) {
|
|
CopyTexSubImage2D_Backend(target, level, xoffset, yoffset, x, y, width, height);
|
|
}
|
|
|
|
void CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
|
|
CopyTexSubImage1D_State(target, level, xoffset, x, y, width);
|
|
}
|
|
|
|
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
|
GLsizei height, GLint border) {
|
|
CopyTexImage2D_Backend(target, level, internalformat, x, y, width, height, border);
|
|
}
|
|
|
|
void CopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,
|
|
GLint border) {
|
|
CopyTexImage1D_State(target, level, internalformat, x, y, width, border);
|
|
}
|
|
|
|
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
|
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize,
|
|
const void* data) {
|
|
CompressedTexSubImage3D_State(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
|
|
imageSize, data);
|
|
}
|
|
|
|
void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
|
|
GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
|
|
CompressedTexSubImage2D_State(target, level, xoffset, yoffset, width, height, format, imageSize, data);
|
|
}
|
|
|
|
void CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
|
|
GLsizei imageSize, const void* data) {
|
|
CompressedTexSubImage1D_State(target, level, xoffset, width, format, imageSize, data);
|
|
}
|
|
|
|
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
|
GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
|
|
CompressedTexImage3D_State(target, level, internalformat, width, height, depth, border, imageSize, data);
|
|
}
|
|
|
|
void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
|
|
GLint border, GLsizei imageSize, const void* data) {
|
|
CompressedTexImage2D_State(target, level, internalformat, width, height, border, imageSize, data);
|
|
}
|
|
|
|
void CompressedTexImage1D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
|
|
GLsizei imageSize, const void* data) {
|
|
CompressedTexImage1D_State(target, level, internalformat, width, border, imageSize, data);
|
|
}
|
|
|
|
void BindTexture(GLenum target, GLuint texture) {
|
|
BindTexture_State(target, texture);
|
|
}
|
|
|
|
void ActiveTexture(GLenum texture) {
|
|
ActiveTexture_State(texture);
|
|
}
|
|
|
|
} // namespace MG_Impl::GLImpl
|
|
} // namespace MobileGL
|