mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
993 lines
43 KiB
C++
993 lines
43 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "WebGLFormats.h"
|
|
|
|
#include "gfxPrefs.h"
|
|
#include "GLDefs.h"
|
|
#include "mozilla/StaticMutex.h"
|
|
|
|
#ifdef FOO
|
|
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
namespace webgl {
|
|
|
|
template<typename K, typename V, typename K2, typename V2>
|
|
static inline void
|
|
AlwaysInsert(std::map<K,V>& dest, const K2& key, const V2& val)
|
|
{
|
|
auto res = dest.insert({ key, val });
|
|
bool didInsert = res.second;
|
|
MOZ_ALWAYS_TRUE(didInsert);
|
|
}
|
|
|
|
template<typename K, typename V, typename K2>
|
|
static inline V*
|
|
FindOrNull(const std::map<K,V*>& dest, const K2& key)
|
|
{
|
|
auto itr = dest.find(key);
|
|
if (itr == dest.end())
|
|
return nullptr;
|
|
|
|
return itr->second;
|
|
}
|
|
|
|
// Returns a pointer to the in-place value for `key`.
|
|
template<typename K, typename V, typename K2>
|
|
static inline V*
|
|
FindPtrOrNull(const std::map<K,V>& dest, const K2& key)
|
|
{
|
|
auto itr = dest.find(key);
|
|
if (itr == dest.end())
|
|
return nullptr;
|
|
|
|
return &(itr->second);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::map<EffectiveFormat, const CompressedFormatInfo> gCompressedFormatInfoMap;
|
|
std::map<EffectiveFormat, const FormatInfo> gFormatInfoMap;
|
|
|
|
static inline const CompressedFormatInfo*
|
|
GetCompressedFormatInfo(EffectiveFormat format)
|
|
{
|
|
MOZ_ASSERT(!gCompressedFormatInfoMap.empty());
|
|
return FindPtrOrNull(gCompressedFormatInfoMap, format);
|
|
}
|
|
|
|
static inline const FormatInfo*
|
|
GetFormatInfo_NoLock(EffectiveFormat format)
|
|
{
|
|
MOZ_ASSERT(!gFormatInfoMap.empty());
|
|
return FindPtrOrNull(gFormatInfoMap, format);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void
|
|
AddCompressedFormatInfo(EffectiveFormat format, uint16_t bitsPerBlock, uint8_t blockWidth,
|
|
uint8_t blockHeight, CompressionFamily family)
|
|
{
|
|
MOZ_ASSERT(bitsPerBlock % 8 == 0);
|
|
uint16_t bytesPerBlock = bitsPerBlock / 8; // The specs always state these in bits,
|
|
// but it's only ever useful to us as
|
|
// bytes.
|
|
MOZ_ASSERT(bytesPerBlock <= 255);
|
|
|
|
const CompressedFormatInfo info = { format, uint8_t(bytesPerBlock), blockWidth,
|
|
blockHeight, family };
|
|
AlwaysInsert(gCompressedFormatInfoMap, format, info);
|
|
}
|
|
|
|
static void
|
|
InitCompressedFormatInfo()
|
|
{
|
|
// GLES 3.0.4, p147, table 3.19
|
|
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_ETC2 , 64, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ETC2 , 64, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA8_ETC2_EAC , 128, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC , 128, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_R11_EAC , 64, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG11_EAC , 128, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_R11_EAC , 64, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RG11_EAC , 128, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , 64, 4, 4, CompressionFamily::ES3);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 64, 4, 4, CompressionFamily::ES3);
|
|
|
|
// AMD_compressed_ATC_texture
|
|
AddCompressedFormatInfo(EffectiveFormat::ATC_RGB_AMD , 64, 4, 4, CompressionFamily::ATC);
|
|
AddCompressedFormatInfo(EffectiveFormat::ATC_RGBA_EXPLICIT_ALPHA_AMD , 128, 4, 4, CompressionFamily::ATC);
|
|
AddCompressedFormatInfo(EffectiveFormat::ATC_RGBA_INTERPOLATED_ALPHA_AMD, 128, 4, 4, CompressionFamily::ATC);
|
|
|
|
// EXT_texture_compression_s3tc
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_S3TC_DXT1_EXT , 64, 4, 4, CompressionFamily::S3TC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT1_EXT, 64, 4, 4, CompressionFamily::S3TC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT3_EXT, 128, 4, 4, CompressionFamily::S3TC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT5_EXT, 128, 4, 4, CompressionFamily::S3TC);
|
|
|
|
// IMG_texture_compression_pvrtc
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_4BPPV1 , 256, 8, 8, CompressionFamily::PVRTC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_4BPPV1, 256, 8, 8, CompressionFamily::PVRTC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_2BPPV1 , 256, 16, 8, CompressionFamily::PVRTC);
|
|
AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_2BPPV1, 256, 16, 8, CompressionFamily::PVRTC);
|
|
|
|
// OES_compressed_ETC1_RGB8_texture
|
|
AddCompressedFormatInfo(EffectiveFormat::ETC1_RGB8_OES, 64, 4, 4, CompressionFamily::ETC1);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void
|
|
AddFormatInfo(EffectiveFormat format, const char* name, GLenum sizedFormat,
|
|
uint8_t bytesPerPixel, UnsizedFormat unsizedFormat, bool isSRGB,
|
|
ComponentType componentType)
|
|
{
|
|
bool isColorFormat = false;
|
|
bool hasAlpha = false;
|
|
bool hasDepth = false;
|
|
bool hasStencil = false;
|
|
|
|
switch (unsizedFormat) {
|
|
case UnsizedFormat::L:
|
|
case UnsizedFormat::R:
|
|
case UnsizedFormat::RG:
|
|
case UnsizedFormat::RGB:
|
|
isColorFormat = true;
|
|
break;
|
|
|
|
case UnsizedFormat::A: // Alpha is a 'color format' since it's 'color-attachable'.
|
|
case UnsizedFormat::LA:
|
|
case UnsizedFormat::RGBA:
|
|
isColorFormat = true;
|
|
hasAlpha = true;
|
|
break;
|
|
|
|
case UnsizedFormat::D:
|
|
hasDepth = true;
|
|
break;
|
|
|
|
case UnsizedFormat::S:
|
|
hasStencil = true;
|
|
break;
|
|
|
|
case UnsizedFormat::DS:
|
|
hasDepth = true;
|
|
hasStencil = true;
|
|
break;
|
|
|
|
default:
|
|
MOZ_CRASH("Missing UnsizedFormat case.");
|
|
}
|
|
|
|
const CompressedFormatInfo* compressedFormatInfo = GetCompressedFormatInfo(format);
|
|
MOZ_ASSERT(!bytesPerPixel == bool(compressedFormatInfo));
|
|
|
|
const FormatInfo info = { format, name, sizedFormat, unsizedFormat, componentType,
|
|
bytesPerPixel, isColorFormat, isSRGB, hasAlpha, hasDepth,
|
|
hasStencil, compressedFormatInfo };
|
|
AlwaysInsert(gFormatInfoMap, format, info);
|
|
}
|
|
|
|
static void
|
|
InitFormatInfo()
|
|
{
|
|
#define FOO(x) EffectiveFormat::x, #x, LOCAL_GL_ ## x
|
|
|
|
// GLES 3.0.4, p130-132, table 3.13
|
|
AddFormatInfo(FOO(R8 ), 1, UnsizedFormat::R , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(R8_SNORM ), 1, UnsizedFormat::R , false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(RG8 ), 2, UnsizedFormat::RG , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RG8_SNORM ), 2, UnsizedFormat::RG , false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(RGB8 ), 3, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGB8_SNORM ), 3, UnsizedFormat::RGB , false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(RGB565 ), 2, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGBA4 ), 2, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGB5_A1 ), 2, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGBA8 ), 4, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGBA8_SNORM ), 4, UnsizedFormat::RGBA, false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(RGB10_A2 ), 4, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(RGB10_A2UI ), 4, UnsizedFormat::RGBA, false, ComponentType::UInt );
|
|
|
|
AddFormatInfo(FOO(SRGB8 ), 3, UnsizedFormat::RGB , true , ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(SRGB8_ALPHA8 ), 4, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
|
|
|
|
AddFormatInfo(FOO(R16F ), 2, UnsizedFormat::R , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RG16F ), 4, UnsizedFormat::RG , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RGB16F ), 6, UnsizedFormat::RGB , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RGBA16F ), 8, UnsizedFormat::RGBA, false, ComponentType::Float );
|
|
AddFormatInfo(FOO(R32F ), 4, UnsizedFormat::R , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RG32F ), 8, UnsizedFormat::RG , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RGB32F ), 12, UnsizedFormat::RGB , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RGBA32F ), 16, UnsizedFormat::RGBA, false, ComponentType::Float );
|
|
|
|
AddFormatInfo(FOO(R11F_G11F_B10F), 4, UnsizedFormat::RGB , false, ComponentType::Float );
|
|
AddFormatInfo(FOO(RGB9_E5 ), 4, UnsizedFormat::RGB , false, ComponentType::Float );
|
|
|
|
AddFormatInfo(FOO(R8I ), 1, UnsizedFormat::R , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(R8UI ), 1, UnsizedFormat::R , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(R16I ), 2, UnsizedFormat::R , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(R16UI ), 2, UnsizedFormat::R , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(R32I ), 4, UnsizedFormat::R , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(R32UI ), 4, UnsizedFormat::R , false, ComponentType::UInt );
|
|
|
|
AddFormatInfo(FOO(RG8I ), 2, UnsizedFormat::RG , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RG8UI ), 2, UnsizedFormat::RG , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RG16I ), 4, UnsizedFormat::RG , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RG16UI ), 4, UnsizedFormat::RG , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RG32I ), 8, UnsizedFormat::RG , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RG32UI ), 8, UnsizedFormat::RG , false, ComponentType::UInt );
|
|
|
|
AddFormatInfo(FOO(RGB8I ), 3, UnsizedFormat::RGB , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGB8UI ), 3, UnsizedFormat::RGB , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RGB16I ), 6, UnsizedFormat::RGB , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGB16UI ), 6, UnsizedFormat::RGB , false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RGB32I ), 12, UnsizedFormat::RGB , false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGB32UI ), 12, UnsizedFormat::RGB , false, ComponentType::UInt );
|
|
|
|
AddFormatInfo(FOO(RGBA8I ), 4, UnsizedFormat::RGBA, false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGBA8UI ), 4, UnsizedFormat::RGBA, false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RGBA16I ), 8, UnsizedFormat::RGBA, false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGBA16UI ), 8, UnsizedFormat::RGBA, false, ComponentType::UInt );
|
|
AddFormatInfo(FOO(RGBA32I ), 16, UnsizedFormat::RGBA, false, ComponentType::Int );
|
|
AddFormatInfo(FOO(RGBA32UI ), 16, UnsizedFormat::RGBA, false, ComponentType::UInt );
|
|
|
|
// GLES 3.0.4, p133, table 3.14
|
|
AddFormatInfo(FOO(DEPTH_COMPONENT16 ), 2, UnsizedFormat::D , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(DEPTH_COMPONENT24 ), 3, UnsizedFormat::D , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(DEPTH_COMPONENT32F), 4, UnsizedFormat::D , false, ComponentType::Float);
|
|
AddFormatInfo(FOO(DEPTH24_STENCIL8 ), 4, UnsizedFormat::DS, false, ComponentType::Special);
|
|
AddFormatInfo(FOO(DEPTH32F_STENCIL8 ), 5, UnsizedFormat::DS, false, ComponentType::Special);
|
|
|
|
// GLES 3.0.4, p205-206, "Required Renderbuffer Formats"
|
|
AddFormatInfo(FOO(STENCIL_INDEX8), 1, UnsizedFormat::S, false, ComponentType::UInt);
|
|
|
|
// GLES 3.0.4, p147, table 3.19
|
|
// GLES 3.0.4 p286+ $C.1 "ETC Compressed Texture Image Formats"
|
|
AddFormatInfo(FOO(COMPRESSED_RGB8_ETC2 ), 0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_SRGB8_ETC2 ), 0, UnsizedFormat::RGB , true , ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA8_ETC2_EAC ), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC ), 0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_R11_EAC ), 0, UnsizedFormat::R , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RG11_EAC ), 0, UnsizedFormat::RG , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_SIGNED_R11_EAC ), 0, UnsizedFormat::R , false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(COMPRESSED_SIGNED_RG11_EAC ), 0, UnsizedFormat::RG , false, ComponentType::NormInt );
|
|
AddFormatInfo(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), 0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
|
|
|
|
// AMD_compressed_ATC_texture
|
|
AddFormatInfo(FOO(ATC_RGB_AMD ), 0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(ATC_RGBA_EXPLICIT_ALPHA_AMD ), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(ATC_RGBA_INTERPOLATED_ALPHA_AMD), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
|
|
// EXT_texture_compression_s3tc
|
|
AddFormatInfo(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT ), 0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
|
|
// IMG_texture_compression_pvrtc
|
|
AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_4BPPV1 ), 0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_2BPPV1 ), 0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1), 0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
|
|
|
|
// OES_compressed_ETC1_RGB8_texture
|
|
AddFormatInfo(FOO(ETC1_RGB8_OES), 0, UnsizedFormat::RGB, false, ComponentType::NormUInt);
|
|
|
|
#undef FOO
|
|
|
|
// 'Virtual' effective formats have no sizedFormat.
|
|
#define FOO(x) EffectiveFormat::x, #x, 0
|
|
|
|
// GLES 3.0.4, p128, table 3.12.
|
|
AddFormatInfo(FOO(Luminance8Alpha8), 2, UnsizedFormat::LA, false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(Luminance8 ), 1, UnsizedFormat::L , false, ComponentType::NormUInt);
|
|
AddFormatInfo(FOO(Alpha8 ), 1, UnsizedFormat::A , false, ComponentType::NormUInt);
|
|
|
|
// OES_texture_float
|
|
AddFormatInfo(FOO(Luminance32FAlpha32F), 8, UnsizedFormat::LA, false, ComponentType::Float);
|
|
AddFormatInfo(FOO(Luminance32F ), 4, UnsizedFormat::L , false, ComponentType::Float);
|
|
AddFormatInfo(FOO(Alpha32F ), 4, UnsizedFormat::A , false, ComponentType::Float);
|
|
|
|
// OES_texture_half_float
|
|
AddFormatInfo(FOO(Luminance16FAlpha16F), 4, UnsizedFormat::LA, false, ComponentType::Float);
|
|
AddFormatInfo(FOO(Luminance16F ), 2, UnsizedFormat::L , false, ComponentType::Float);
|
|
AddFormatInfo(FOO(Alpha16F ), 2, UnsizedFormat::A , false, ComponentType::Float);
|
|
|
|
#undef FOO
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool gAreFormatTablesInitialized = false;
|
|
|
|
static void
|
|
EnsureInitFormatTables(const StaticMutexAutoLock&) // Prove that you locked it!
|
|
{
|
|
if (MOZ_LIKELY(gAreFormatTablesInitialized))
|
|
return;
|
|
|
|
gAreFormatTablesInitialized = true;
|
|
|
|
InitCompressedFormatInfo();
|
|
InitFormatInfo();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// Public funcs
|
|
|
|
StaticMutex gFormatMapMutex;
|
|
|
|
const FormatInfo*
|
|
GetFormat(EffectiveFormat format)
|
|
{
|
|
StaticMutexAutoLock lock(gFormatMapMutex);
|
|
EnsureInitFormatTables(lock);
|
|
|
|
return GetFormatInfo_NoLock(format);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
uint8_t
|
|
BytesPerPixel(const PackingInfo& packing)
|
|
{
|
|
uint8_t bytesPerChannel;
|
|
switch (packing.type) {
|
|
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
|
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
|
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
|
return 2;
|
|
|
|
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
|
|
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
|
|
case LOCAL_GL_UNSIGNED_INT_24_8:
|
|
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
|
|
return 4;
|
|
|
|
case LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
|
|
return 8;
|
|
|
|
// Alright, that's all the fixed-size unpackTypes.
|
|
|
|
case LOCAL_GL_BYTE:
|
|
case LOCAL_GL_UNSIGNED_BYTE:
|
|
bytesPerChannel = 1;
|
|
break;
|
|
|
|
case LOCAL_GL_SHORT:
|
|
case LOCAL_GL_UNSIGNED_SHORT:
|
|
case LOCAL_GL_HALF_FLOAT:
|
|
case LOCAL_GL_HALF_FLOAT_OES:
|
|
bytesPerChannel = 2;
|
|
break;
|
|
|
|
case LOCAL_GL_INT:
|
|
case LOCAL_GL_UNSIGNED_INT:
|
|
case LOCAL_GL_FLOAT:
|
|
bytesPerChannel = 4;
|
|
break;
|
|
|
|
default:
|
|
MOZ_CRASH("invalid PackingInfo");
|
|
}
|
|
|
|
uint8_t channels;
|
|
switch (packing.format) {
|
|
case LOCAL_GL_RG:
|
|
case LOCAL_GL_RG_INTEGER:
|
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
|
channels = 2;
|
|
break;
|
|
|
|
case LOCAL_GL_RGB:
|
|
case LOCAL_GL_RGB_INTEGER:
|
|
channels = 3;
|
|
break;
|
|
|
|
case LOCAL_GL_RGBA:
|
|
case LOCAL_GL_RGBA_INTEGER:
|
|
channels = 4;
|
|
break;
|
|
|
|
default:
|
|
channels = 1;
|
|
break;
|
|
}
|
|
|
|
return bytesPerChannel * channels;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// FormatUsageAuthority
|
|
|
|
bool
|
|
FormatUsageInfo::IsUnpackValid(const PackingInfo& key,
|
|
const DriverUnpackInfo** const out_value) const
|
|
{
|
|
auto itr = validUnpacks.find(key);
|
|
if (itr == validUnpacks.end())
|
|
return false;
|
|
|
|
*out_value = &(itr->second);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
FormatUsageInfo::ResolveMaxSamples(gl::GLContext* gl)
|
|
{
|
|
MOZ_ASSERT(!this->maxSamplesKnown);
|
|
MOZ_ASSERT(this->maxSamples == 0);
|
|
MOZ_ASSERT(gl->IsCurrent());
|
|
|
|
this->maxSamplesKnown = true;
|
|
|
|
const GLenum internalFormat = this->format->sizedFormat;
|
|
if (!internalFormat)
|
|
return;
|
|
|
|
if (!gl->IsSupported(gl::GLFeature::internalformat_query))
|
|
return; // Leave it at 0.
|
|
|
|
GLint maxSamplesGL = 0;
|
|
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalFormat, LOCAL_GL_SAMPLES, 1,
|
|
&maxSamplesGL);
|
|
|
|
this->maxSamples = maxSamplesGL;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
static void
|
|
AddSimpleUnsized(FormatUsageAuthority* fua, GLenum unpackFormat, GLenum unpackType,
|
|
EffectiveFormat effFormat)
|
|
{
|
|
auto usage = fua->EditUsage(effFormat);
|
|
usage->isFilterable = true;
|
|
|
|
const PackingInfo pi = {unpackFormat, unpackType};
|
|
const DriverUnpackInfo dui = {unpackFormat, unpackFormat, unpackType};
|
|
fua->AddTexUnpack(usage, pi, dui);
|
|
|
|
fua->AllowUnsizedTexFormat(pi, usage);
|
|
};
|
|
|
|
|
|
/*static*/ const GLint FormatUsageInfo::kLuminanceSwizzleRGBA[4] = { LOCAL_GL_RED,
|
|
LOCAL_GL_RED,
|
|
LOCAL_GL_RED,
|
|
LOCAL_GL_ONE };
|
|
/*static*/ const GLint FormatUsageInfo::kAlphaSwizzleRGBA[4] = { LOCAL_GL_ZERO,
|
|
LOCAL_GL_ZERO,
|
|
LOCAL_GL_ZERO,
|
|
LOCAL_GL_RED };
|
|
/*static*/ const GLint FormatUsageInfo::kLumAlphaSwizzleRGBA[4] = { LOCAL_GL_RED,
|
|
LOCAL_GL_RED,
|
|
LOCAL_GL_RED,
|
|
LOCAL_GL_GREEN };
|
|
|
|
static bool
|
|
AddLegacyFormats_LA8(FormatUsageAuthority* fua, gl::GLContext* gl)
|
|
{
|
|
if (gl->IsCoreProfile()) {
|
|
if (!gl->IsSupported(gl::GLFeature::texture_swizzle))
|
|
return false;
|
|
|
|
PackingInfo pi;
|
|
DriverUnpackInfo dui;
|
|
|
|
const auto fnAdd = [fua, &pi, &dui](EffectiveFormat effFormat,
|
|
const GLint* swizzle)
|
|
{
|
|
auto usage = fua->EditUsage(effFormat);
|
|
usage->isFilterable = true;
|
|
usage->textureSwizzleRGBA = swizzle;
|
|
|
|
fua->AddTexUnpack(usage, pi, dui);
|
|
|
|
fua->AllowUnsizedTexFormat(pi, usage);
|
|
};
|
|
|
|
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE};
|
|
dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
|
|
fnAdd(EffectiveFormat::Luminance8, FormatUsageInfo::kLuminanceSwizzleRGBA);
|
|
|
|
pi = {LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
|
|
dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
|
|
fnAdd(EffectiveFormat::Alpha8, FormatUsageInfo::kAlphaSwizzleRGBA);
|
|
|
|
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
|
|
dui = {LOCAL_GL_RG8, LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE};
|
|
fnAdd(EffectiveFormat::Luminance8Alpha8, FormatUsageInfo::kLumAlphaSwizzleRGBA);
|
|
} else {
|
|
AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8 );
|
|
AddSimpleUnsized(fua, LOCAL_GL_ALPHA , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Alpha8 );
|
|
AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8Alpha8);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
AddUnsizedFormats(FormatUsageAuthority* fua, gl::GLContext* gl)
|
|
{
|
|
// GLES 2.0.25, p63, Table 3.4
|
|
AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE , EffectiveFormat::RGBA8 );
|
|
AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4, EffectiveFormat::RGBA4 );
|
|
AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1, EffectiveFormat::RGB5_A1);
|
|
AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_BYTE , EffectiveFormat::RGB8 );
|
|
AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_SHORT_5_6_5 , EffectiveFormat::RGB565 );
|
|
|
|
// L, A, LA
|
|
return AddLegacyFormats_LA8(fua, gl);
|
|
}
|
|
|
|
UniquePtr<FormatUsageAuthority>
|
|
FormatUsageAuthority::CreateForWebGL1(gl::GLContext* gl)
|
|
{
|
|
UniquePtr<FormatUsageAuthority> ret(new FormatUsageAuthority);
|
|
const auto ptr = ret.get();
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Usages
|
|
|
|
const auto fnSet = [ptr](EffectiveFormat effFormat, bool isRenderable,
|
|
bool isFilterable)
|
|
{
|
|
MOZ_ASSERT(!ptr->GetUsage(effFormat));
|
|
|
|
auto usage = ptr->EditUsage(effFormat);
|
|
usage->isRenderable = isRenderable;
|
|
usage->isFilterable = isFilterable;
|
|
};
|
|
|
|
// GLES 2.0.25, p117, Table 4.5
|
|
// RGBA8 is made renderable in WebGL 1.0, "Framebuffer Object Attachments"
|
|
// render filter
|
|
// able able
|
|
fnSet(EffectiveFormat::RGBA8 , true, true);
|
|
fnSet(EffectiveFormat::RGBA4 , true, true);
|
|
fnSet(EffectiveFormat::RGB5_A1, true, true);
|
|
fnSet(EffectiveFormat::RGB565 , true, true);
|
|
|
|
// RGB8 is not guaranteed to be renderable, but we should allow it for web-compat.
|
|
// Min-capability mode should mark this as non-renderable.
|
|
fnSet(EffectiveFormat::RGB8, true, true);
|
|
|
|
fnSet(EffectiveFormat::Luminance8Alpha8, false, true);
|
|
fnSet(EffectiveFormat::Luminance8 , false, true);
|
|
fnSet(EffectiveFormat::Alpha8 , false, true);
|
|
|
|
fnSet(EffectiveFormat::DEPTH_COMPONENT16, true, false);
|
|
fnSet(EffectiveFormat::STENCIL_INDEX8 , true, false);
|
|
|
|
// Added in WebGL 1.0 spec:
|
|
fnSet(EffectiveFormat::DEPTH24_STENCIL8, true, false);
|
|
|
|
////////////////////////////////////
|
|
// RB formats
|
|
|
|
#define FOO(x) ptr->AllowRBFormat(LOCAL_GL_ ## x, ptr->GetUsage(EffectiveFormat::x))
|
|
|
|
FOO(RGBA4 );
|
|
FOO(RGB5_A1 );
|
|
FOO(RGB565 );
|
|
FOO(DEPTH_COMPONENT16);
|
|
FOO(STENCIL_INDEX8 );
|
|
//FOO(DEPTH24_STENCIL8 ); // WebGL 1 uses DEPTH_STENCIL instead of DEPTH24_STENCIL8.
|
|
|
|
#undef FOO
|
|
|
|
ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
|
|
ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
if (!AddUnsizedFormats(ptr, gl))
|
|
return nullptr;
|
|
|
|
return Move(ret);
|
|
}
|
|
|
|
UniquePtr<FormatUsageAuthority>
|
|
FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
|
|
{
|
|
UniquePtr<FormatUsageAuthority> ret(new FormatUsageAuthority);
|
|
const auto ptr = ret.get();
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// GLES 3.0.4 p111-113
|
|
|
|
const auto fnAddSizedUnpack = [ptr](EffectiveFormat effFormat, GLenum internalFormat,
|
|
GLenum unpackFormat, GLenum unpackType)
|
|
{
|
|
auto usage = ptr->EditUsage(effFormat);
|
|
|
|
const PackingInfo pi = {unpackFormat, unpackType};
|
|
const DriverUnpackInfo dui = {internalFormat, unpackFormat, unpackType};
|
|
ptr->AddTexUnpack(usage, pi, dui);
|
|
};
|
|
|
|
#define FOO(x) EffectiveFormat::x, LOCAL_GL_ ## x
|
|
|
|
// RGBA
|
|
fnAddSizedUnpack(FOO(RGBA8 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGBA4 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 );
|
|
fnAddSizedUnpack(FOO(RGBA4 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 );
|
|
fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
fnAddSizedUnpack(FOO(SRGB8_ALPHA8), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGBA8_SNORM ), LOCAL_GL_RGBA, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB10_A2 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
fnAddSizedUnpack(FOO(RGBA16F ), LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGBA16F ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGBA32F ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT );
|
|
|
|
// RGBA_INTEGER
|
|
fnAddSizedUnpack(FOO(RGBA8UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGBA8I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(RGBA16UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_SHORT );
|
|
fnAddSizedUnpack(FOO(RGBA16I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_SHORT );
|
|
fnAddSizedUnpack(FOO(RGBA32UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(RGBA32I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_INT );
|
|
fnAddSizedUnpack(FOO(RGB10_A2UI), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
|
|
// RGB
|
|
fnAddSizedUnpack(FOO(RGB8 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(SRGB8 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB565 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_SHORT_5_6_5 );
|
|
fnAddSizedUnpack(FOO(RGB565 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB8_SNORM ), LOCAL_GL_RGB, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV);
|
|
fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGB16F ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGB16F ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV );
|
|
fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(RGB32F ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
|
|
|
|
// RGB_INTEGER
|
|
fnAddSizedUnpack(FOO(RGB8UI ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB8I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(RGB16UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
|
|
fnAddSizedUnpack(FOO(RGB16I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_SHORT );
|
|
fnAddSizedUnpack(FOO(RGB32UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(RGB32I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_INT );
|
|
|
|
// RG
|
|
fnAddSizedUnpack(FOO(RG8 ), LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE);
|
|
fnAddSizedUnpack(FOO(RG8_SNORM), LOCAL_GL_RG, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(RG16F ), LOCAL_GL_RG, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(RG16F ), LOCAL_GL_RG, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(RG32F ), LOCAL_GL_RG, LOCAL_GL_FLOAT );
|
|
|
|
// RG_INTEGER
|
|
fnAddSizedUnpack(FOO(RG8UI ), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(RG8I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(RG16UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
|
|
fnAddSizedUnpack(FOO(RG16I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_SHORT );
|
|
fnAddSizedUnpack(FOO(RG32UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(RG32I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_INT );
|
|
|
|
// RED
|
|
fnAddSizedUnpack(FOO(R8 ), LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE);
|
|
fnAddSizedUnpack(FOO(R8_SNORM), LOCAL_GL_RED, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(R16F ), LOCAL_GL_RED, LOCAL_GL_HALF_FLOAT );
|
|
fnAddSizedUnpack(FOO(R16F ), LOCAL_GL_RED, LOCAL_GL_FLOAT );
|
|
fnAddSizedUnpack(FOO(R32F ), LOCAL_GL_RED, LOCAL_GL_FLOAT );
|
|
|
|
// RED_INTEGER
|
|
fnAddSizedUnpack(FOO(R8UI ), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
|
|
fnAddSizedUnpack(FOO(R8I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_BYTE );
|
|
fnAddSizedUnpack(FOO(R16UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
|
|
fnAddSizedUnpack(FOO(R16I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_SHORT );
|
|
fnAddSizedUnpack(FOO(R32UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(R32I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_INT );
|
|
|
|
// DEPTH_COMPONENT
|
|
fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_SHORT);
|
|
fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(DEPTH_COMPONENT24 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT );
|
|
fnAddSizedUnpack(FOO(DEPTH_COMPONENT32F), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_FLOAT );
|
|
|
|
// DEPTH_STENCIL
|
|
fnAddSizedUnpack(FOO(DEPTH24_STENCIL8 ), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_UNSIGNED_INT_24_8 );
|
|
fnAddSizedUnpack(FOO(DEPTH32F_STENCIL8), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
|
|
|
#undef FOO
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For renderable, see GLES 3.0.4, p212 "Framebuffer Completeness"
|
|
// For filterable, see GLES 3.0.4, p161 "...a texture is complete unless..."
|
|
|
|
const auto fnAllowES3TexFormat = [ptr](GLenum sizedFormat, EffectiveFormat effFormat,
|
|
bool isRenderable, bool isFilterable)
|
|
{
|
|
auto usage = ptr->EditUsage(effFormat);
|
|
usage->isRenderable = isRenderable;
|
|
usage->isFilterable = isFilterable;
|
|
|
|
ptr->AllowSizedTexFormat(sizedFormat, usage);
|
|
|
|
if (isRenderable) {
|
|
ptr->AllowRBFormat(sizedFormat, usage);
|
|
}
|
|
};
|
|
|
|
#define FOO(x) LOCAL_GL_ ## x, EffectiveFormat::x
|
|
|
|
// GLES 3.0.4, p128-129 "Required Texture Formats"
|
|
// GLES 3.0.4, p130-132, table 3.13
|
|
// render filter
|
|
// able able
|
|
fnAllowES3TexFormat(FOO(R8 ), true , true );
|
|
fnAllowES3TexFormat(FOO(R8_SNORM ), false, true );
|
|
fnAllowES3TexFormat(FOO(RG8 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RG8_SNORM ), false, true );
|
|
fnAllowES3TexFormat(FOO(RGB8 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGB8_SNORM ), false, true );
|
|
fnAllowES3TexFormat(FOO(RGB565 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGBA4 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGB5_A1 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGBA8 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGBA8_SNORM), false, true );
|
|
fnAllowES3TexFormat(FOO(RGB10_A2 ), true , true );
|
|
fnAllowES3TexFormat(FOO(RGB10_A2UI ), true , false);
|
|
|
|
fnAllowES3TexFormat(FOO(SRGB8 ), false, true);
|
|
fnAllowES3TexFormat(FOO(SRGB8_ALPHA8), true , true);
|
|
|
|
fnAllowES3TexFormat(FOO(R16F ), false, true);
|
|
fnAllowES3TexFormat(FOO(RG16F ), false, true);
|
|
fnAllowES3TexFormat(FOO(RGB16F ), false, true);
|
|
fnAllowES3TexFormat(FOO(RGBA16F), false, true);
|
|
|
|
fnAllowES3TexFormat(FOO(R32F ), false, false);
|
|
fnAllowES3TexFormat(FOO(RG32F ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB32F ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGBA32F), false, false);
|
|
|
|
fnAllowES3TexFormat(FOO(R11F_G11F_B10F), false, true);
|
|
fnAllowES3TexFormat(FOO(RGB9_E5 ), false, true);
|
|
|
|
fnAllowES3TexFormat(FOO(R8I ), true, false);
|
|
fnAllowES3TexFormat(FOO(R8UI ), true, false);
|
|
fnAllowES3TexFormat(FOO(R16I ), true, false);
|
|
fnAllowES3TexFormat(FOO(R16UI), true, false);
|
|
fnAllowES3TexFormat(FOO(R32I ), true, false);
|
|
fnAllowES3TexFormat(FOO(R32UI), true, false);
|
|
|
|
fnAllowES3TexFormat(FOO(RG8I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RG8UI ), true, false);
|
|
fnAllowES3TexFormat(FOO(RG16I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RG16UI), true, false);
|
|
fnAllowES3TexFormat(FOO(RG32I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RG32UI), true, false);
|
|
|
|
fnAllowES3TexFormat(FOO(RGB8I ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB8UI ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB16I ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB16UI), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB32I ), false, false);
|
|
fnAllowES3TexFormat(FOO(RGB32UI), false, false);
|
|
|
|
fnAllowES3TexFormat(FOO(RGBA8I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RGBA8UI ), true, false);
|
|
fnAllowES3TexFormat(FOO(RGBA16I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RGBA16UI), true, false);
|
|
fnAllowES3TexFormat(FOO(RGBA32I ), true, false);
|
|
fnAllowES3TexFormat(FOO(RGBA32UI), true, false);
|
|
|
|
// GLES 3.0.4, p133, table 3.14
|
|
fnAllowES3TexFormat(FOO(DEPTH_COMPONENT16 ), true, false);
|
|
fnAllowES3TexFormat(FOO(DEPTH_COMPONENT24 ), true, false);
|
|
fnAllowES3TexFormat(FOO(DEPTH_COMPONENT32F), true, false);
|
|
fnAllowES3TexFormat(FOO(DEPTH24_STENCIL8 ), true, false);
|
|
fnAllowES3TexFormat(FOO(DEPTH32F_STENCIL8 ), true, false);
|
|
|
|
// GLES 3.0.4, p147, table 3.19
|
|
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
|
|
#if ALLOW_ES3_FORMATS
|
|
// Note that all compressed texture formats are filterable:
|
|
// GLES 3.0.4 p161:
|
|
// "[A] texture is complete unless any of the following conditions hold true:
|
|
// [...]
|
|
// * The effective internal format specified for the texture arrays is a sized
|
|
// internal color format that is not texture-filterable (see table 3.13) and [the
|
|
// mag filter requires filtering]."
|
|
// Compressed formats are not sized internal color formats, and indeed they are not
|
|
// listed in table 3.13.
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_ETC2 ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_ETC2 ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_RGBA8_ETC2_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_R11_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_RG11_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_R11_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_SIGNED_RG11_EAC ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), false, true);
|
|
fnAllowES3TexFormat(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), false, true);
|
|
#endif
|
|
#undef FOO
|
|
|
|
// GLES 3.0.4, p206, "Required Renderbuffer Formats":
|
|
// "Implementations are also required to support STENCIL_INDEX8. Requesting this
|
|
// internal format for a renderbuffer will allocate at least 8 stencil bit planes."
|
|
|
|
auto usage = ptr->EditUsage(EffectiveFormat::STENCIL_INDEX8);
|
|
usage->isRenderable = true;
|
|
ptr->AllowRBFormat(LOCAL_GL_STENCIL_INDEX8, usage);
|
|
|
|
////////////////
|
|
// Legacy formats
|
|
|
|
if (!AddUnsizedFormats(ptr, gl))
|
|
return nullptr;
|
|
|
|
ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
|
|
ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
|
|
|
|
if (gfxPrefs::WebGL2CompatMode()) {
|
|
AddSimpleUnsized(ptr, LOCAL_GL_RGBA, LOCAL_GL_FLOAT, EffectiveFormat::RGBA32F);
|
|
AddSimpleUnsized(ptr, LOCAL_GL_RGB , LOCAL_GL_FLOAT, EffectiveFormat::RGB32F );
|
|
|
|
AddSimpleUnsized(ptr, LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES, EffectiveFormat::RGBA16F);
|
|
AddSimpleUnsized(ptr, LOCAL_GL_RGB , LOCAL_GL_HALF_FLOAT_OES, EffectiveFormat::RGB16F );
|
|
}
|
|
|
|
return Move(ret);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
FormatUsageAuthority::AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi,
|
|
const DriverUnpackInfo& dui)
|
|
{
|
|
// Don't AlwaysInsert here, since we'll see duplicates from sized and unsized formats.
|
|
auto res = usage->validUnpacks.insert({ pi, dui });
|
|
auto itr = res.first;
|
|
|
|
if (!usage->idealUnpack) {
|
|
// First one!
|
|
usage->idealUnpack = &(itr->second);
|
|
}
|
|
|
|
mValidTexUnpackFormats.insert(pi.format);
|
|
mValidTexUnpackTypes.insert(pi.type);
|
|
}
|
|
|
|
static bool
|
|
Contains(const std::set<GLenum>& set, GLenum key)
|
|
{
|
|
return set.find(key) != set.end();
|
|
}
|
|
|
|
bool
|
|
FormatUsageAuthority::IsInternalFormatEnumValid(GLenum internalFormat) const
|
|
{
|
|
return Contains(mValidTexInternalFormats, internalFormat);
|
|
}
|
|
|
|
bool
|
|
FormatUsageAuthority::AreUnpackEnumsValid(GLenum unpackFormat, GLenum unpackType) const
|
|
{
|
|
return (Contains(mValidTexUnpackFormats, unpackFormat) &&
|
|
Contains(mValidTexUnpackTypes, unpackType));
|
|
}
|
|
|
|
////////////////////
|
|
|
|
void
|
|
FormatUsageAuthority::AllowRBFormat(GLenum sizedFormat, const FormatUsageInfo* usage)
|
|
{
|
|
MOZ_ASSERT(!usage->format->compression);
|
|
MOZ_ASSERT(usage->format->sizedFormat);
|
|
MOZ_ASSERT(usage->isRenderable);
|
|
|
|
AlwaysInsert(mRBFormatMap, sizedFormat, usage);
|
|
}
|
|
|
|
void
|
|
FormatUsageAuthority::AllowSizedTexFormat(GLenum sizedFormat,
|
|
const FormatUsageInfo* usage)
|
|
{
|
|
if (usage->format->compression) {
|
|
MOZ_ASSERT(usage->isFilterable, "Compressed formats should be filterable.");
|
|
} else {
|
|
MOZ_ASSERT(usage->validUnpacks.size() && usage->idealUnpack,
|
|
"AddTexUnpack() first.");
|
|
}
|
|
|
|
AlwaysInsert(mSizedTexFormatMap, sizedFormat, usage);
|
|
|
|
mValidTexInternalFormats.insert(sizedFormat);
|
|
}
|
|
|
|
void
|
|
FormatUsageAuthority::AllowUnsizedTexFormat(const PackingInfo& pi,
|
|
const FormatUsageInfo* usage)
|
|
{
|
|
MOZ_ASSERT(!usage->format->compression);
|
|
MOZ_ASSERT(usage->validUnpacks.size() && usage->idealUnpack, "AddTexUnpack() first.");
|
|
|
|
AlwaysInsert(mUnsizedTexFormatMap, pi, usage);
|
|
|
|
mValidTexInternalFormats.insert(pi.format);
|
|
mValidTexUnpackFormats.insert(pi.format);
|
|
mValidTexUnpackTypes.insert(pi.type);
|
|
}
|
|
|
|
const FormatUsageInfo*
|
|
FormatUsageAuthority::GetRBUsage(GLenum sizedFormat) const
|
|
{
|
|
return FindOrNull(mRBFormatMap, sizedFormat);
|
|
}
|
|
|
|
const FormatUsageInfo*
|
|
FormatUsageAuthority::GetSizedTexUsage(GLenum sizedFormat) const
|
|
{
|
|
return FindOrNull(mSizedTexFormatMap, sizedFormat);
|
|
}
|
|
|
|
const FormatUsageInfo*
|
|
FormatUsageAuthority::GetUnsizedTexUsage(const PackingInfo& pi) const
|
|
{
|
|
return FindOrNull(mUnsizedTexFormatMap, pi);
|
|
}
|
|
|
|
FormatUsageInfo*
|
|
FormatUsageAuthority::EditUsage(EffectiveFormat format)
|
|
{
|
|
auto itr = mUsageMap.find(format);
|
|
|
|
if (itr == mUsageMap.end()) {
|
|
const FormatInfo* formatInfo = GetFormat(format);
|
|
MOZ_RELEASE_ASSERT(formatInfo);
|
|
|
|
FormatUsageInfo usage(formatInfo);
|
|
|
|
auto res = mUsageMap.insert({ format, usage });
|
|
DebugOnly<bool> didInsert = res.second;
|
|
MOZ_ASSERT(didInsert);
|
|
|
|
itr = res.first;
|
|
}
|
|
|
|
return &(itr->second);
|
|
}
|
|
|
|
const FormatUsageInfo*
|
|
FormatUsageAuthority::GetUsage(EffectiveFormat format) const
|
|
{
|
|
auto itr = mUsageMap.find(format);
|
|
if (itr == mUsageMap.end())
|
|
return nullptr;
|
|
|
|
return &(itr->second);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
} // namespace webgl
|
|
} // namespace mozilla
|