mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
Merge branch 'worktree-agent-a1381c9e6b342e8d4' into dev
This commit is contained in:
@@ -1715,6 +1715,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
0, glFormat, glType, uploadData);
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
case TextureTarget::Texture2DArray:
|
||||
g_GLESFuncs.glTexImage3D(
|
||||
glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
|
||||
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.y()),
|
||||
@@ -1790,6 +1791,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static_cast<GLsizei>(baseSize.y()));
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
case TextureTarget::Texture2DArray:
|
||||
g_GLESFuncs.glTexStorage3D(target, static_cast<GLsizei>(mipmapCount), glInternalFormat,
|
||||
static_cast<GLsizei>(baseSize.x()),
|
||||
static_cast<GLsizei>(baseSize.y()),
|
||||
@@ -1835,6 +1837,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static_cast<GLsizei>(levelTexelSize.y()), glFormat, glType, uploadData);
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
case TextureTarget::Texture2DArray:
|
||||
g_GLESFuncs.glTexSubImage3D(
|
||||
glUploadTarget, static_cast<GLint>(level), 0, 0, 0,
|
||||
static_cast<GLsizei>(levelTexelSize.x()),
|
||||
@@ -1893,7 +1896,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType, uploadData);
|
||||
break;
|
||||
}
|
||||
case TextureTarget::Texture3D: {
|
||||
case TextureTarget::Texture3D:
|
||||
case TextureTarget::Texture2DArray: {
|
||||
g_GLESFuncs.glTexImage3D(
|
||||
glUploadTarget, static_cast<GLint>(level), (GLint)glInternalFormat,
|
||||
static_cast<GLsizei>(levelTexelSize.x()),
|
||||
@@ -1987,6 +1991,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
uploadData);
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
case TextureTarget::Texture2DArray:
|
||||
g_GLESFuncs.glTexSubImage3D(glUploadTarget, static_cast<GLint>(level), 0, 0, 0,
|
||||
static_cast<GLsizei>(texelSize.x()),
|
||||
static_cast<GLsizei>(texelSize.y()),
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
namespace TextureImpl {
|
||||
inline Bool IsSupportedTextureTarget(TextureTarget target) {
|
||||
if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
|
||||
target == TextureTarget::Texture1DArray || target == TextureTarget::Texture2DArray)
|
||||
target == TextureTarget::Texture1DArray)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -284,10 +284,16 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS));
|
||||
}
|
||||
|
||||
Uint ComputeFullMipmapLevelCount(const IntVec3& baseTexelSize) {
|
||||
// Array targets store their layer count in z; layers never participate in mip
|
||||
// reduction (GL 3.3 §3.8.14), only true 3D textures halve their depth per level.
|
||||
Bool DepthParticipatesInMipmapping(TextureTarget target) {
|
||||
return target == TextureTarget::Texture3D;
|
||||
}
|
||||
|
||||
Uint ComputeFullMipmapLevelCount(const IntVec3& baseTexelSize, Bool depthMips) {
|
||||
Int maxDimension = std::max<Int>(
|
||||
baseTexelSize.x(),
|
||||
std::max<Int>(baseTexelSize.y(), std::max<Int>(baseTexelSize.z(), 1)));
|
||||
std::max<Int>(baseTexelSize.y(), depthMips ? std::max<Int>(baseTexelSize.z(), 1) : 1));
|
||||
Uint mipLevelCount = 1;
|
||||
while (maxDimension > 1) {
|
||||
maxDimension = std::max<Int>(maxDimension / 2, 1);
|
||||
@@ -296,11 +302,12 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return mipLevelCount;
|
||||
}
|
||||
|
||||
IntVec3 ComputeMipmapTexelSize(const IntVec3& baseTexelSize, Uint relativeLevel) {
|
||||
IntVec3 ComputeMipmapTexelSize(const IntVec3& baseTexelSize, Uint relativeLevel, Bool depthMips) {
|
||||
return {
|
||||
std::max<Int>(baseTexelSize.x() >> static_cast<Int>(relativeLevel), 1),
|
||||
std::max<Int>(baseTexelSize.y() >> static_cast<Int>(relativeLevel), 1),
|
||||
std::max<Int>(baseTexelSize.z() >> static_cast<Int>(relativeLevel), 1),
|
||||
depthMips ? std::max<Int>(baseTexelSize.z() >> static_cast<Int>(relativeLevel), 1)
|
||||
: std::max<Int>(baseTexelSize.z(), 1),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -323,9 +330,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
const SizeT bytesPerTexel = baseByteSize / baseTexelCount;
|
||||
const Uint requiredLevelCount = ComputeFullMipmapLevelCount(baseTexelSize);
|
||||
const Bool depthMips = DepthParticipatesInMipmapping(texture.GetTarget());
|
||||
const Uint requiredLevelCount = ComputeFullMipmapLevelCount(baseTexelSize, depthMips);
|
||||
for (Uint level = 1; level < requiredLevelCount; ++level) {
|
||||
const IntVec3 levelTexelSize = ComputeMipmapTexelSize(baseTexelSize, level);
|
||||
const IntVec3 levelTexelSize = ComputeMipmapTexelSize(baseTexelSize, level, depthMips);
|
||||
const SizeT levelByteSize = bytesPerTexel * static_cast<SizeT>(levelTexelSize.x()) *
|
||||
static_cast<SizeT>(levelTexelSize.y()) *
|
||||
static_cast<SizeT>(levelTexelSize.z());
|
||||
@@ -2939,10 +2947,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||
|
||||
textureObject->SetInternalFormat(textureInternalFormat);
|
||||
// Array targets keep their layer count constant across levels; only true 3D
|
||||
// textures halve depth per level (GL 3.3 §3.9 glTexStorage3D).
|
||||
const Bool depthMips = DepthParticipatesInMipmapping(textureObject->GetTarget());
|
||||
for (GLsizei level = 0; level < levels; ++level) {
|
||||
const GLsizei levelWidth = std::max<GLsizei>(1, width >> level);
|
||||
const GLsizei levelHeight = std::max<GLsizei>(1, height >> level);
|
||||
const GLsizei levelDepth = std::max<GLsizei>(1, depth >> level);
|
||||
const GLsizei levelDepth = depthMips ? std::max<GLsizei>(1, depth >> level) : depth;
|
||||
const SizeT byteSize = ComputeTextureStorageByteSize(textureInternalFormat, levelWidth, levelHeight,
|
||||
levelDepth);
|
||||
textureMipmapObject->AllocateStorage(textureUploadTarget, level,
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
#include "Includes.h"
|
||||
#include "Init.h"
|
||||
#include <MG_Backend/BackendObjects.h>
|
||||
#include <MG_Backend/DirectGLES/Managers.h>
|
||||
#include <MG_Impl/GLImpl/Getter/GL_Getter.h>
|
||||
#include <MG_Impl/GLImpl/RenderState/GL_RenderState.h>
|
||||
#include <MG_Impl/GLImpl/Texture/GL_Texture.h>
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_State/GLState/TextureState/TextureObject.h>
|
||||
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
|
||||
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
|
||||
#include <MG_Util/Texture/TextureFormatProcessor.h>
|
||||
|
||||
@@ -935,6 +938,141 @@ TEST_F(TextureTest, BoundTexSubImage3DRejectsOutOfRangeLevel) {
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// The GL CTS KHR-GL33.pixelstoragemodes.teximage3d cases upload GL_TEXTURE_2D_ARRAY
|
||||
// textures through glTexImage3D with UNPACK_ROW_LENGTH / IMAGE_HEIGHT / SKIP_* set to
|
||||
// extract a sub-cuboid; this mirrors that shape (scaled down) on the 2D-array target.
|
||||
TEST_F(TextureTest, BoundTexImage3DOn2DArrayHonorsUnpackSubcuboidSelection) {
|
||||
GLuint texture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &texture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D_ARRAY, texture);
|
||||
|
||||
// Source cuboid: 3x3 RGBA texels per image, 3 images; skip 1 image, 1 row, 1 pixel;
|
||||
// upload the 2x2x2 sub-cuboid. Each source byte equals its own offset, so the stored
|
||||
// shadow bytes must equal the offsets of the selected texels.
|
||||
Uint8 pixels[3 * 3 * 3 * 4];
|
||||
for (SizeT i = 0; i < sizeof(pixels); ++i) {
|
||||
pixels[i] = static_cast<Uint8>(i);
|
||||
}
|
||||
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_ROW_LENGTH, 3);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 3);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_PIXELS, 1);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_ROWS, 1);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_IMAGES, 1);
|
||||
MG_Impl::GLImpl::TexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
MG_Impl::GLImpl::PixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
|
||||
|
||||
const auto textureObject = MG_State::pGLContext->GetTextureObject(texture);
|
||||
ASSERT_NE(textureObject, nullptr);
|
||||
EXPECT_EQ(textureObject->GetTarget(), TextureTarget::Texture2DArray);
|
||||
auto* mipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
|
||||
EXPECT_EQ(mipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DArray, 0), IntVec3(2, 2, 2));
|
||||
|
||||
const auto* stored =
|
||||
static_cast<const Uint8*>(mipmapObject->MapMipmapData(TextureUploadTarget::Texture2DArray, 0));
|
||||
ASSERT_NE(stored, nullptr);
|
||||
SizeT storedIndex = 0;
|
||||
for (SizeT image = 1; image <= 2; ++image) { // SKIP_IMAGES = 1
|
||||
for (SizeT row = 1; row <= 2; ++row) { // SKIP_ROWS = 1
|
||||
for (SizeT column = 1; column <= 2; ++column) { // SKIP_PIXELS = 1
|
||||
const SizeT srcOffset = image * 36 + row * 12 + column * 4;
|
||||
for (SizeT b = 0; b < 4; ++b, ++storedIndex) {
|
||||
EXPECT_EQ(stored[storedIndex], static_cast<Uint8>(srcOffset + b)) << "byte " << storedIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// The shadow mip for packed sized formats keeps the client's packed bytes, so the
|
||||
// canonical transfer triple must name the packed word type; the old default fallback
|
||||
// (GL_UNSIGNED_BYTE) made backends read 4 bytes per texel from a 2-byte-per-texel
|
||||
// shadow (KHR-GL33.pixelstoragemodes rgba4/rgb565 uploads), and GL_RGB10_A2UI got a
|
||||
// non-integer GL_RGB transfer format the driver rejects outright.
|
||||
TEST_F(TextureTest, NormalizePixelFormatKeepsPackedTransferTypesForPackedSizedFormats) {
|
||||
using MG_Util::TextureFormatProcessor::NormalizePixelFormat;
|
||||
struct {
|
||||
GLenum internalFormat;
|
||||
GLenum expectedFormat;
|
||||
GLenum expectedType;
|
||||
} cases[] = {
|
||||
{GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
|
||||
{GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
|
||||
{GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV},
|
||||
{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
|
||||
{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
|
||||
};
|
||||
for (const auto& c : cases) {
|
||||
GLenum outInternal = 0, outFormat = 0, outType = 0;
|
||||
NormalizePixelFormat(c.internalFormat, PixelFormatNormalizeOptionBit::None, &outInternal, &outFormat,
|
||||
&outType);
|
||||
EXPECT_EQ(outInternal, c.internalFormat) << "internalformat 0x" << std::hex << c.internalFormat;
|
||||
EXPECT_EQ(outFormat, c.expectedFormat) << "internalformat 0x" << std::hex << c.internalFormat;
|
||||
EXPECT_EQ(outType, c.expectedType) << "internalformat 0x" << std::hex << c.internalFormat;
|
||||
}
|
||||
}
|
||||
|
||||
// GL_RGB565 (ARB_ES2_compatibility / GL 4.1, used directly by the GL CTS) must round-trip
|
||||
// through the internal-format enums; it had no GLToMG mapping at all, so glTexImage* with
|
||||
// GL_RGB565 was rejected as an unknown internal format.
|
||||
TEST_F(TextureTest, Rgb565InternalFormatRoundTripsThroughEnumConverters) {
|
||||
EXPECT_EQ(MG_Util::ConvertGLEnumToTextureInternalFormat(GL_RGB565), TextureInternalFormat::RGB5);
|
||||
EXPECT_EQ(MG_Util::ConvertGLEnumToTextureInternalFormat(GL_RGB5), TextureInternalFormat::RGB5);
|
||||
// The ES-facing rendition of RGB5 is GL_RGB565 (desktop GL_RGB5 is not a legal sized
|
||||
// internalformat on OpenGL ES backends).
|
||||
EXPECT_EQ(MG_Util::ConvertTextureInternalFormatToGLEnum(TextureInternalFormat::RGB5),
|
||||
static_cast<GLenum>(GL_RGB565));
|
||||
}
|
||||
|
||||
// Regression guard: the DirectGLES backend must treat GL_TEXTURE_2D_ARRAY as a
|
||||
// syncable target — it used to be skipped entirely, so 2D-array textures were never
|
||||
// uploaded or bound (KHR-GL33.pixelstoragemodes.teximage3d.* failed wholesale).
|
||||
TEST_F(TextureTest, DirectGLESTreats2DArrayAsSupportedTextureTarget) {
|
||||
using MobileGL::MG_Backend::DirectGLES::TextureImpl::IsSupportedTextureTarget;
|
||||
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture2DArray));
|
||||
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture3D));
|
||||
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture2D));
|
||||
EXPECT_FALSE(IsSupportedTextureTarget(TextureTarget::Texture1D));
|
||||
EXPECT_FALSE(IsSupportedTextureTarget(TextureTarget::Texture1DArray));
|
||||
EXPECT_FALSE(IsSupportedTextureTarget(TextureTarget::TextureRectangle));
|
||||
}
|
||||
|
||||
// 2D-array textures keep their layer count constant across mip levels (GL 3.3 §3.9);
|
||||
// only true 3D textures halve depth per level.
|
||||
TEST_F(TextureTest, TexStorage3DOn2DArrayKeepsLayerCountAcrossLevels) {
|
||||
GLuint arrayTexture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &arrayTexture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D_ARRAY, arrayTexture);
|
||||
MG_Impl::GLImpl::TexStorage3D(GL_TEXTURE_2D_ARRAY, 3, GL_RGBA8, 8, 8, 4);
|
||||
|
||||
const auto arrayObject = MG_State::pGLContext->GetTextureObject(arrayTexture);
|
||||
ASSERT_NE(arrayObject, nullptr);
|
||||
auto* arrayMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(arrayObject.get());
|
||||
EXPECT_EQ(arrayMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DArray, 0), IntVec3(8, 8, 4));
|
||||
EXPECT_EQ(arrayMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DArray, 1), IntVec3(4, 4, 4));
|
||||
EXPECT_EQ(arrayMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2DArray, 2), IntVec3(2, 2, 4));
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// Control: a real 3D texture still halves its depth per level.
|
||||
GLuint volumeTexture = 0;
|
||||
MG_Impl::GLImpl::GenTextures(1, &volumeTexture);
|
||||
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_3D, volumeTexture);
|
||||
MG_Impl::GLImpl::TexStorage3D(GL_TEXTURE_3D, 3, GL_RGBA8, 8, 8, 4);
|
||||
|
||||
const auto volumeObject = MG_State::pGLContext->GetTextureObject(volumeTexture);
|
||||
ASSERT_NE(volumeObject, nullptr);
|
||||
auto* volumeMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(volumeObject.get());
|
||||
EXPECT_EQ(volumeMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 0), IntVec3(8, 8, 4));
|
||||
EXPECT_EQ(volumeMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 1), IntVec3(4, 4, 2));
|
||||
EXPECT_EQ(volumeMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture3D, 2), IntVec3(2, 2, 1));
|
||||
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);
|
||||
|
||||
@@ -131,6 +131,9 @@ namespace MobileGL {
|
||||
case GL_RGB4:
|
||||
return TextureInternalFormat::RGB4;
|
||||
case GL_RGB5:
|
||||
// GL_RGB565 (GL 4.1 / ARB_ES2_compatibility, used directly by the GL CTS) is the
|
||||
// ES-facing rendition of the legacy RGB5 resolution.
|
||||
case GL_RGB565:
|
||||
return TextureInternalFormat::RGB5;
|
||||
case GL_RGB8:
|
||||
return TextureInternalFormat::RGB8;
|
||||
|
||||
@@ -113,7 +113,10 @@ namespace MobileGL {
|
||||
case TextureInternalFormat::RGB4:
|
||||
return GL_RGB4;
|
||||
case TextureInternalFormat::RGB5:
|
||||
return GL_RGB5;
|
||||
// Emit the ES-compatible GL_RGB565 rendition: desktop GL_RGB5 is not a legal
|
||||
// sized internalformat on OpenGL ES backends, GL_RGB565 is (and GL 4.1+
|
||||
// accepts it too via ARB_ES2_compatibility).
|
||||
return GL_RGB565;
|
||||
case TextureInternalFormat::RGB8:
|
||||
return GL_RGB8;
|
||||
case TextureInternalFormat::RGB8Snorm:
|
||||
|
||||
@@ -282,12 +282,17 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
// Color sized other
|
||||
case GL_RGB9_E5:
|
||||
case GL_R11F_G11F_B10F:
|
||||
case GL_RGB565:
|
||||
*outFormat = GL_RGB;
|
||||
break;
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGB5_A1:
|
||||
case GL_RGBA4:
|
||||
*outFormat = GL_RGBA;
|
||||
break;
|
||||
case GL_RGB10_A2UI:
|
||||
*outFormat = GL_RGBA_INTEGER;
|
||||
break;
|
||||
|
||||
// Depth
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
@@ -459,11 +464,23 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
|
||||
*outType = GL_UNSIGNED_INT_10F_11F_11F_REV;
|
||||
break;
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGB10_A2UI:
|
||||
*outType = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
break;
|
||||
case GL_RGB5_A1:
|
||||
*outType = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
// The shadow mip keeps these formats' packed client bytes (legacy copy path),
|
||||
// so the canonical transfer type must stay the packed word — the previous
|
||||
// default (GL_UNSIGNED_BYTE) made the backend read 4 bytes per texel from a
|
||||
// 2-byte-per-texel shadow (KHR-GL33.pixelstoragemodes teximage rgba4/rgb565
|
||||
// sliced/garbled uploads).
|
||||
case GL_RGBA4:
|
||||
*outType = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case GL_RGB565:
|
||||
*outType = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
|
||||
// Depth
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
|
||||
Reference in New Issue
Block a user