summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHailin Zhang <hailinzhang@google.com>2022-01-10 22:44:23 -0800
committerHailin Zhang <hailinzhang@google.com>2022-01-12 19:46:00 -0800
commit811540f9c3085346a43663b8d003a232ff6cc4dc (patch)
treeb2c58b3a30c48b4ddb7f0f548cde6e541baef797
parent2089f050df7b8400b0fdde43f8e420e4ff410c47 (diff)
downloadvulkan-cereal-811540f9c3085346a43663b8d003a232ff6cc4dc.tar.gz
add rgtc externsion support
Bug: b/213168245 Change-Id: Ib05f46888221ea76ab3707baae762d6f124efedb
-rw-r--r--host-common/FeatureControlDefHost.h1
-rw-r--r--stream-servers/GfxStreamBackend.cpp1
-rw-r--r--stream-servers/RenderControl.cpp6
-rw-r--r--stream-servers/glestranslator/GLES_V2/GLESv2Validate.cpp4
-rw-r--r--stream-servers/glestranslator/GLcommon/Android.bp1
-rw-r--r--stream-servers/glestranslator/GLcommon/CMakeLists.txt1
-rw-r--r--stream-servers/glestranslator/GLcommon/GLEScontext.cpp6
-rw-r--r--stream-servers/glestranslator/GLcommon/TextureUtils.cpp116
-rw-r--r--stream-servers/glestranslator/GLcommon/rgtc.cpp149
-rw-r--r--stream-servers/glestranslator/include/GLcommon/GLEScontext.h1
-rw-r--r--stream-servers/glestranslator/include/GLcommon/TextureUtils.h26
-rw-r--r--stream-servers/glestranslator/include/GLcommon/rgtc.h42
12 files changed, 350 insertions, 4 deletions
diff --git a/host-common/FeatureControlDefHost.h b/host-common/FeatureControlDefHost.h
index 8b437887..72d3c9f5 100644
--- a/host-common/FeatureControlDefHost.h
+++ b/host-common/FeatureControlDefHost.h
@@ -71,5 +71,6 @@ FEATURE_CONTROL_ITEM(BptcTextureSupport)
FEATURE_CONTROL_ITEM(GuestUsesAngle)
FEATURE_CONTROL_ITEM(VirtioVsockPipe)
FEATURE_CONTROL_ITEM(S3tcTextureSupport)
+FEATURE_CONTROL_ITEM(RgtcTextureSupport)
FEATURE_CONTROL_ITEM(VulkanNativeSwapchain)
FEATURE_CONTROL_ITEM(VirtioGpuFenceContexts)
diff --git a/stream-servers/GfxStreamBackend.cpp b/stream-servers/GfxStreamBackend.cpp
index dd6fc61f..4c69ee2c 100644
--- a/stream-servers/GfxStreamBackend.cpp
+++ b/stream-servers/GfxStreamBackend.cpp
@@ -407,6 +407,7 @@ extern "C" VG_EXPORT void gfxstream_backend_init(
kFeature_BptcTextureSupport, bptcTextureSupport);
feature_set_enabled_override(
kFeature_S3tcTextureSupport, s3tcTextureSupport);
+ feature_set_enabled_override(kFeature_RgtcTextureSupport, true);
feature_set_enabled_override(
kFeature_GLDirectMem, false);
feature_set_enabled_override(
diff --git a/stream-servers/RenderControl.cpp b/stream-servers/RenderControl.cpp
index db6507b4..09dbf9c1 100644
--- a/stream-servers/RenderControl.cpp
+++ b/stream-servers/RenderControl.cpp
@@ -659,7 +659,11 @@ static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
if (feature_is_enabled(kFeature_S3tcTextureSupport)) {
glStr += "GL_EXT_texture_compression_s3tc ";
- }
+ }
+
+ if (feature_is_enabled(kFeature_RgtcTextureSupport)) {
+ glStr += "GL_EXT_texture_compression_rgtc ";
+ }
// Host side tracing support.
glStr += kHostSideTracing;
diff --git a/stream-servers/glestranslator/GLES_V2/GLESv2Validate.cpp b/stream-servers/glestranslator/GLES_V2/GLESv2Validate.cpp
index 1db5a503..c661bed6 100644
--- a/stream-servers/glestranslator/GLES_V2/GLESv2Validate.cpp
+++ b/stream-servers/glestranslator/GLES_V2/GLESv2Validate.cpp
@@ -759,6 +759,10 @@ bool GLESv2Validate::isCompressedFormat(GLenum format) {
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
return true;
}
return false;
diff --git a/stream-servers/glestranslator/GLcommon/Android.bp b/stream-servers/glestranslator/GLcommon/Android.bp
index c44b1473..91be25d5 100644
--- a/stream-servers/glestranslator/GLcommon/Android.bp
+++ b/stream-servers/glestranslator/GLcommon/Android.bp
@@ -25,6 +25,7 @@ cc_library_static {
],
srcs: [
"etc.cpp",
+ "rgtc.cpp",
"FramebufferData.cpp",
"GLBackgroundLoader.cpp",
"GLDispatch.cpp",
diff --git a/stream-servers/glestranslator/GLcommon/CMakeLists.txt b/stream-servers/glestranslator/GLcommon/CMakeLists.txt
index 671f9b4d..176f990d 100644
--- a/stream-servers/glestranslator/GLcommon/CMakeLists.txt
+++ b/stream-servers/glestranslator/GLcommon/CMakeLists.txt
@@ -1,6 +1,7 @@
add_library(
GLcommon
etc.cpp
+ rgtc.cpp
FramebufferData.cpp
GLBackgroundLoader.cpp
GLDispatch.cpp
diff --git a/stream-servers/glestranslator/GLcommon/GLEScontext.cpp b/stream-servers/glestranslator/GLcommon/GLEScontext.cpp
index 5462d814..f8131dc4 100644
--- a/stream-servers/glestranslator/GLcommon/GLEScontext.cpp
+++ b/stream-servers/glestranslator/GLcommon/GLEScontext.cpp
@@ -1880,6 +1880,12 @@ void GLEScontext::initCapsLocked(const GLubyte * extensionString)
s_glSupport.hasS3tcSupport = true;
}
}
+
+ if (feature_is_enabled(kFeature_RgtcTextureSupport)) {
+ if (strstr(cstring, "GL_EXT_texture_compression_rgtc") != NULL) {
+ s_glSupport.hasRgtcSupport = true;
+ }
+ }
}
void GLEScontext::buildStrings(bool isGles1, const char* baseVendor,
diff --git a/stream-servers/glestranslator/GLcommon/TextureUtils.cpp b/stream-servers/glestranslator/GLcommon/TextureUtils.cpp
index d716437a..2daf1dd1 100644
--- a/stream-servers/glestranslator/GLcommon/TextureUtils.cpp
+++ b/stream-servers/glestranslator/GLcommon/TextureUtils.cpp
@@ -343,7 +343,14 @@ GLenum decompressedInternalFormat(GLEScontext* ctx, GLenum compressedFormat) {
case GL_PALETTE8_RGBA4_OES:
case GL_PALETTE8_RGB5_A1_OES:
return glrgba;
-
+ case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
+ return GL_R8;
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
+ return GL_R8_SNORM;
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
+ return GL_RG8;
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
+ return GL_RG8_SNORM;
default:
return compressedFormat;
}
@@ -400,7 +407,7 @@ void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
&unpackBuffer);
needUnpackBuffer = unpackBuffer;
}
-
+ TextureUnpackReset unpack(ctx);
if (isEtcFormat(internalformat)) {
GLint format = GL_RGB;
GLint type = GL_UNSIGNED_BYTE;
@@ -514,7 +521,8 @@ void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
width, height, ctx->getMaxTexSize() + 2),
GL_INVALID_VALUE);
SET_ERROR_IF(!data,GL_INVALID_OPERATION);
-
+ //the decoder fully packed the pixels.
+ ctx->dispatcher().glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
int nMipmaps = -level + 1;
GLsizei tmpWidth = width;
GLsizei tmpHeight = height;
@@ -532,6 +540,61 @@ void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
tmpHeight /= 2;
delete [] uncompressed;
}
+ } else if (isRgtcFormat(internalformat)) {
+ GLint format, type;
+ GLint convertedInternalFormat = decompressedInternalFormat(ctx, internalformat);
+ RGTCImageFormat rgtcFormat;
+ switch (internalformat) {
+ case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
+ format = GL_RED;
+ type = GL_UNSIGNED_BYTE;
+ rgtcFormat = BC4_UNORM;
+ break;
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
+ format = GL_RED;
+ type = GL_BYTE;
+ rgtcFormat = BC4_SNORM;
+ break;
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
+ format = GL_RG;
+ type = GL_UNSIGNED_BYTE;
+ rgtcFormat = BC5_UNORM;
+ break;
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
+ format = GL_RG;
+ type = GL_BYTE;
+ rgtcFormat = BC5_SNORM;
+ break;
+ }
+ size_t pixelSize = rgtc_get_decoded_pixel_size(rgtcFormat);
+ GLsizei compressedSize = rgtc_get_encoded_image_size(rgtcFormat, width, height);
+ SET_ERROR_IF((compressedSize != imageSize), GL_INVALID_VALUE);
+ std::unique_ptr<ScopedFetchUnpackData> unpackData;
+ bool emulateCompressedData = false;
+ if (needUnpackBuffer) {
+ unpackData.reset(
+ new ScopedFetchUnpackData(ctx, reinterpret_cast<GLintptr>(data), compressedSize));
+ data = unpackData->data();
+ SET_ERROR_IF(!data, GL_INVALID_OPERATION);
+ } else {
+ if (!data) {
+ emulateCompressedData = true;
+ data = new char[compressedSize];
+ }
+ }
+ const int32_t align = ctx->getUnpackAlignment() - 1;
+ const int32_t bpr = ((width * pixelSize) + align) & ~align;
+ const size_t size = bpr * height;
+ std::unique_ptr<uint8_t[]> pOut(new uint8_t[size]);
+
+ int res =
+ rgtc_decode_image((const uint8_t*)data, rgtcFormat, pOut.get(), width, height, bpr);
+ SET_ERROR_IF(res != 0, GL_INVALID_VALUE);
+ glTexImage2DPtr(target, level, convertedInternalFormat, width, height, border, format, type,
+ pOut.get());
+ if (emulateCompressedData) {
+ delete[](char*) data;
+ }
} else {
SET_ERROR_IF(1, GL_INVALID_ENUM);
}
@@ -791,6 +854,19 @@ void forEachS3tcFormat(std::function<void(GLint format)> f) {
f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
}
+bool isRgtcFormat(GLenum format) {
+ switch (format) {
+ case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
bool isEtc2OrAstcFormat(GLenum format) {
switch (format) {
case GL_COMPRESSED_RGB8_ETC2:
@@ -819,6 +895,8 @@ bool shouldPassthroughCompressedFormat(GLEScontext* ctx, GLenum internalformat)
return ctx->getCaps()->hasBptcSupport;
} else if (isS3tcFormat(internalformat)) {
return ctx->getCaps()->hasS3tcSupport;
+ } else if (isRgtcFormat(internalformat)) {
+ return ctx->getCaps()->hasRgtcSupport;
}
return false;
}
@@ -1154,3 +1232,35 @@ GLenum getTypeFromInternalFormat(GLint internalFormat) {
return GL_UNSIGNED_BYTE;
}
}
+
+
+GLint TextureUnpackReset::unpackCheckAndUpdate(GLenum name, GLint newValue) {
+ GLint curValue;
+ glesContext->dispatcher().glGetIntegerv(name, &curValue);
+ if (curValue != newValue) {
+ glesContext->dispatcher().glPixelStorei(name, newValue);
+ }
+ return curValue;
+}
+
+TextureUnpackReset::TextureUnpackReset(GLEScontext* ctx) : glesContext(ctx) {
+ if (glesContext->getMajorVersion() >= 3) {
+ unpackRowLength = unpackCheckAndUpdate(GL_UNPACK_ROW_LENGTH, kUnpackRowLength);
+ unpackImageHeight = unpackCheckAndUpdate(GL_UNPACK_IMAGE_HEIGHT, kUnpackImageHeight);
+ unpackSkipRows = unpackCheckAndUpdate(GL_UNPACK_SKIP_ROWS, kUnpackSkipRows);
+ unpackSkipPixels = unpackCheckAndUpdate(GL_UNPACK_SKIP_PIXELS, kUnpackSkipPixels);
+ unpackSkipImages = unpackCheckAndUpdate(GL_UNPACK_SKIP_IMAGES, kUnpackSkipImages);
+ unpackAlignment = unpackCheckAndUpdate(GL_UNPACK_ALIGNMENT, kUnpackAlignment);
+ }
+}
+TextureUnpackReset::~TextureUnpackReset() {
+ if (glesContext->getMajorVersion() >= 3) {
+ unpackCheckAndUpdate(GL_UNPACK_ROW_LENGTH, unpackRowLength);
+ unpackCheckAndUpdate(GL_UNPACK_IMAGE_HEIGHT, unpackImageHeight);
+ unpackCheckAndUpdate(GL_UNPACK_SKIP_ROWS, unpackSkipRows);
+ unpackCheckAndUpdate(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
+ unpackCheckAndUpdate(GL_UNPACK_SKIP_IMAGES, unpackSkipImages);
+ unpackCheckAndUpdate(GL_UNPACK_ALIGNMENT, unpackAlignment);
+ }
+}
+
diff --git a/stream-servers/glestranslator/GLcommon/rgtc.cpp b/stream-servers/glestranslator/GLcommon/rgtc.cpp
new file mode 100644
index 00000000..7cebe32d
--- /dev/null
+++ b/stream-servers/glestranslator/GLcommon/rgtc.cpp
@@ -0,0 +1,149 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "GLcommon/rgtc.h"
+#include <cstring>
+#include <assert.h>
+#include <type_traits>
+
+// From https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_compression_rgtc.txt
+// according to the spec
+// RGTC1_RED = BC4_UNORM,
+// RGTC1_SIGNED_RED = BC4_SNORM,
+// RGTC2_RG = BC5_UNORM,
+// RGTC2_SIGNED_RG = BC5_SNORM.
+// the full codec spec can be found here
+// https://docs.microsoft.com/en-gb/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc5
+
+static constexpr int kBlockSize = 4;
+
+inline size_t rgtc_get_block_size(RGTCImageFormat format) {
+ switch (format) {
+ case BC4_UNORM:
+ case BC4_SNORM:
+ return 8;
+ case BC5_UNORM:
+ case BC5_SNORM:
+ return 16;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+size_t rgtc_get_decoded_pixel_size(RGTCImageFormat format) {
+ switch (format) {
+ case BC4_UNORM:
+ case BC4_SNORM:
+ return 1;
+ case BC5_UNORM:
+ case BC5_SNORM:
+ return 2;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+template <typename genType>
+struct get_expand_type {};
+
+template <>
+struct get_expand_type<int8_t> {
+ typedef int32_t type;
+};
+
+template <>
+struct get_expand_type<uint8_t> {
+ typedef uint32_t type;
+};
+
+template <class T>
+void rgtc_decode_subblock(const uint32_t* data, T* out, int step, T d0, T d1 ) {
+ T r0 = static_cast<T>(data[0] & 0xff);
+ T r1 = static_cast<T>((data[0] >> 8) & 0xff);
+ uint64_t color_indexs = ((uint64_t)data[1] << 32 | data[0]) >> 16;
+ T colors[8] = {r0, r1,};
+ typename get_expand_type<T>::type c0 = r0;
+ typename get_expand_type<T>::type c1 = r1;
+ if (c0 > c1) {
+ // 6 interpolated color values
+ for (int i = 2; i < 8; i++) {
+ colors[i] = static_cast<T>((c0 * (8 - i) + c1 * (i - 1)) / 7.0f + 0.5f);
+ }
+ } else {
+ // 4 interpolated color values
+ for (int i = 2; i < 6; i++) {
+ colors[i] = static_cast<T>((c0 * (6 - i) + c1 * (i - 1)) / 5.0f + 0.5f);
+ }
+ colors[6] = d0;
+ colors[7] = d1;
+ }
+ uint64_t index = color_indexs;
+ for (int i = 0 ; i < 16 ; i ++) {
+ *out = colors[index & 0x7];
+ out += step;
+ index >>= 3;
+ }
+}
+
+int rgtc_decode_image(const uint8_t* in, RGTCImageFormat format, uint8_t* out, uint32_t width,
+ uint32_t height, uint32_t stride) {
+ size_t data_block_size = rgtc_get_block_size(format);
+ size_t texel_size = rgtc_get_decoded_pixel_size(format);
+ const uint8_t* data_in = in;
+ // BC5 2 bytes per pixel
+ uint8_t pixels[kBlockSize * kBlockSize * 2];
+ for (uint32_t y = 0; y < height; y += kBlockSize) {
+ uint32_t yEnd = height - y;
+ if (yEnd > kBlockSize) {
+ yEnd = kBlockSize;
+ }
+ for (uint32_t x = 0; x < width; x += kBlockSize) {
+ uint32_t xEnd = width - x;
+ if (xEnd > kBlockSize) {
+ xEnd = kBlockSize;
+ }
+ switch (format) {
+ case BC4_UNORM:
+ rgtc_decode_subblock<uint8_t>((const uint32_t*)data_in, pixels, 1, 0, 1);
+ break;
+ case BC4_SNORM:
+ rgtc_decode_subblock<int8_t>((const uint32_t*)data_in, (int8_t*)pixels, 1, -1, 1);
+ break;
+ case BC5_UNORM:
+ rgtc_decode_subblock<uint8_t>((const uint32_t*)data_in, pixels, 2, 0, 1);
+ rgtc_decode_subblock<uint8_t>((const uint32_t*)data_in + 2, pixels + 1, 2, 0, 1);
+ break;
+ case BC5_SNORM:
+ rgtc_decode_subblock<int8_t>((const uint32_t*)data_in, (int8_t*)pixels, 2, -1, 1);
+ rgtc_decode_subblock<int8_t>((const uint32_t*)data_in + 2, (int8_t*)(pixels + 1),
+ 2, -1, 1);
+ break;
+ }
+ for (uint32_t cy = 0; cy < yEnd; cy ++) {
+ uint8_t* data_out = out + (y + cy) * stride + x * texel_size;
+ std::memcpy(data_out, pixels + kBlockSize * texel_size * cy, texel_size * xEnd);
+ }
+ data_in += data_block_size;
+ }
+ }
+ return 0;
+}
+
+size_t rgtc_get_encoded_image_size(RGTCImageFormat format, uint32_t width, uint32_t height) {
+ uint32_t w = (width + kBlockSize - 1) / kBlockSize;
+ uint32_t h = (height + kBlockSize - 1) / kBlockSize;
+ return w * h * rgtc_get_block_size(format);
+} \ No newline at end of file
diff --git a/stream-servers/glestranslator/include/GLcommon/GLEScontext.h b/stream-servers/glestranslator/include/GLcommon/GLEScontext.h
index e5809e5e..4ebf1871 100644
--- a/stream-servers/glestranslator/include/GLcommon/GLEScontext.h
+++ b/stream-servers/glestranslator/include/GLcommon/GLEScontext.h
@@ -111,6 +111,7 @@ struct GLSupport {
bool hasAstcSupport = false;
bool hasBptcSupport = false;
bool hasS3tcSupport = false;
+ bool hasRgtcSupport = false;
};
struct ArrayData {
diff --git a/stream-servers/glestranslator/include/GLcommon/TextureUtils.h b/stream-servers/glestranslator/include/GLcommon/TextureUtils.h
index 77e60ae0..21cb70f1 100644
--- a/stream-servers/glestranslator/include/GLcommon/TextureUtils.h
+++ b/stream-servers/glestranslator/include/GLcommon/TextureUtils.h
@@ -19,6 +19,7 @@
#include "GLEScontext.h"
#include "PaletteTexture.h"
#include "etc.h"
+#include "rgtc.h"
#include <functional>
#include <GLES/gl.h>
@@ -37,6 +38,7 @@ bool isEtc2Format(GLenum internalformat);
bool isBptcFormat(GLenum internalformat);
bool isS3tcFormat(GLenum internalformat);
bool isPaletteFormat(GLenum internalformat);
+bool isRgtcFormat(GLenum internalformat);
int getCompressedFormats(int majorVersion, int* formats);
void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
GLenum internalformat, GLsizei width,
@@ -102,4 +104,28 @@ uint32_t texImageSize(GLenum internalformat,
GLenum getFormatFromInternalFormat(GLint internalFormat);
GLenum getTypeFromInternalFormat(GLint internalFormat);
+class TextureUnpackReset {
+ public:
+ // Initial value for unpack
+ static constexpr GLint kUnpackRowLength = 0;
+ static constexpr GLint kUnpackImageHeight = 0;
+ static constexpr GLint kUnpackSkipRows = 0;
+ static constexpr GLint kUnpackSkipPixels = 0;
+ static constexpr GLint kUnpackSkipImages = 0;
+ static constexpr GLint kUnpackAlignment = 4;
+
+ TextureUnpackReset(GLEScontext* ctx);
+ ~TextureUnpackReset();
+
+ GLint unpackRowLength;
+ GLint unpackImageHeight;
+ GLint unpackSkipRows;
+ GLint unpackSkipPixels;
+ GLint unpackSkipImages;
+ GLint unpackAlignment;
+ GLEScontext* glesContext = nullptr;
+ private:
+ GLint unpackCheckAndUpdate(GLenum name, GLint newValue);
+};
+
#endif
diff --git a/stream-servers/glestranslator/include/GLcommon/rgtc.h b/stream-servers/glestranslator/include/GLcommon/rgtc.h
new file mode 100644
index 00000000..0de5c60d
--- /dev/null
+++ b/stream-servers/glestranslator/include/GLcommon/rgtc.h
@@ -0,0 +1,42 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include <cstddef>
+
+enum RGTCImageFormat { BC4_UNORM, BC4_SNORM, BC5_UNORM, BC5_SNORM };
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Decode an entire image.
+// pIn - pointer to encoded data.
+// pOut - pointer to the image data. Will be written such that
+// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
+// large enough to store entire image.
+// (pixelSize=3 for rgb images, pixelSize=4 for images with alpha channel)
+// returns non-zero if there is an error.
+int rgtc_decode_image(const uint8_t* pIn, RGTCImageFormat format, uint8_t* pOut, uint32_t width,
+ uint32_t height, uint32_t stride);
+
+size_t rgtc_get_encoded_image_size(RGTCImageFormat format, uint32_t width, uint32_t height);
+
+size_t rgtc_get_decoded_pixel_size(RGTCImageFormat format);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file