0
0
mirror of https://github.com/termux/termux-packages.git synced 2025-05-10 06:55:47 +00:00
Files
termux-packages/packages/virglrenderer-android/0008-Impl-DXTn-S3TC-texture-decompression-in-virglrenderer.patch.beforehostbuild

727 lines
26 KiB
Diff
Raw Permalink Blame History

Based on https://github.com/alexvorxx/VirGL-Overlay-Rebuild/commit/e365e02209f5337eae21a53f3c463f5a3c122aa6
and https://github.com/alexvorxx/VirGL-Overlay-Rebuild/commit/d3052d9ee353d43867fa2fcf15ef072fcdaae2c4
---
src/gl4es-decompress.c | 477 +++++++++++++++++++++++++++++++++++++++++
src/gl4es-decompress.h | 29 +++
src/meson.build | 1 +
src/vrend_formats.c | 4 +-
src/vrend_renderer.c | 106 ++++++++-
5 files changed, 612 insertions(+), 5 deletions(-)
create mode 100644 src/gl4es-decompress.c
create mode 100644 src/gl4es-decompress.h
diff --git a/src/gl4es-decompress.c b/src/gl4es-decompress.c
new file mode 100644
index 00000000..6ceb43a4
--- /dev/null
+++ b/src/gl4es-decompress.c
@@ -0,0 +1,477 @@
+// Origin: https://github.com/alexvorxx/VirGL-Overlay-Rebuild/commit/d3052d9ee353d43867fa2fcf15ef072fcdaae2c4
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <epoxy/gl.h>
+
+#include "gl4es-decompress.h"
+
+/*
+DXT1/DXT3/DXT5 texture decompression
+The original code is from Benjamin Dobell, see below for details. Compared to
+the original this one adds DXT3 decompression, is valid C89, and is x64
+compatible as it uses fixed size integers everywhere. It also uses a different
+PackRGBA order.
+---
+Copyright (c) 2012, Matth<74>us G. "Anteru" Chajdas (http://anteru.net)
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+---
+Copyright (C) 2009 Benjamin Dobell, Glass Echidna
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+---
+*/
+static uint32_t PackRGBA (uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+ return r | (g << 8) | (b << 16) | (a << 24);
+}
+
+static void DecompressBlockDXT1Internal (const uint8_t* block,
+ uint32_t* output,
+ uint32_t outputStride,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ const uint8_t* alphaValues)
+{
+ uint32_t temp, code;
+
+ uint16_t color0, color1;
+ uint8_t r0, g0, b0, r1, g1, b1;
+
+ int i, j;
+
+ color0 = *(const uint16_t*)(block);
+ color1 = *(const uint16_t*)(block + 2);
+
+ temp = (color0 >> 11) * 255 + 16;
+ r0 = (uint8_t)((temp/32 + temp)/32);
+ temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+ g0 = (uint8_t)((temp/64 + temp)/64);
+ temp = (color0 & 0x001F) * 255 + 16;
+ b0 = (uint8_t)((temp/32 + temp)/32);
+
+ temp = (color1 >> 11) * 255 + 16;
+ r1 = (uint8_t)((temp/32 + temp)/32);
+ temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+ g1 = (uint8_t)((temp/64 + temp)/64);
+ temp = (color1 & 0x001F) * 255 + 16;
+ b1 = (uint8_t)((temp/32 + temp)/32);
+
+ code = *(const uint32_t*)(block + 4);
+
+ if (color0 > color1) {
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < 4; ++i) {
+ uint32_t finalColor, positionCode;
+ uint8_t alpha;
+
+ alpha = alphaValues [j*4+i];
+
+ finalColor = 0;
+ positionCode = (code >> 2*(4*j+i)) & 0x03;
+
+ switch (positionCode) {
+ case 0:
+ finalColor = PackRGBA(r0, g0, b0, alpha);
+ break;
+ case 1:
+ finalColor = PackRGBA(r1, g1, b1, alpha);
+ break;
+ case 2:
+ finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, alpha);
+ break;
+ case 3:
+ finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, alpha);
+ break;
+ }
+ if(transparent0 && (finalColor==0xff000000)) {
+ alpha=0;
+ finalColor = 0;
+ }
+ if(!alpha)
+ *simpleAlpha = 1;
+ else if(alpha<0xff)
+ *complexAlpha = 1;
+ output [j*outputStride + i] = finalColor;
+ }
+ }
+ } else {
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < 4; ++i) {
+ uint32_t finalColor, positionCode;
+ uint8_t alpha;
+
+ alpha = alphaValues [j*4+i];
+
+ finalColor = 0;
+ positionCode = (code >> 2*(4*j+i)) & 0x03;
+
+ switch (positionCode) {
+ case 0:
+ finalColor = PackRGBA(r0, g0, b0, alpha);
+ break;
+ case 1:
+ finalColor = PackRGBA(r1, g1, b1, alpha);
+ break;
+ case 2:
+ finalColor = PackRGBA((r0+r1)/2, (g0+g1)/2, (b0+b1)/2, alpha);
+ break;
+ case 3:
+ finalColor = PackRGBA(0, 0, 0, alpha);
+ break;
+ }
+
+ if(transparent0 && (finalColor==0xff000000)) {
+ alpha = 0;
+ finalColor = 0;
+ }
+ if(!alpha)
+ *simpleAlpha = 1;
+ else if(alpha<0xff)
+ *complexAlpha = 1;
+
+ output [j*outputStride + i] = finalColor;
+ }
+ }
+ }
+}
+
+/*
+void DecompressBlockDXT1(): Decompresses one block of a DXT1 texture and stores the resulting pixels at the appropriate offset in 'image'.
+uint32_t x: x-coordinate of the first pixel in the block.
+uint32_t y: y-coordinate of the first pixel in the block.
+uint32_t width: width of the texture being decompressed.
+const uint8_t *blockStorage: pointer to the block to decompress.
+uint32_t *image: pointer to image where the decompressed pixel data should be stored.
+*/
+void DecompressBlockDXT1(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image)
+{
+ static const uint8_t const_alpha [] = {
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255,
+ 255, 255, 255, 255
+ };
+
+ DecompressBlockDXT1Internal (blockStorage,
+ image + x + (y * width), width, transparent0, simpleAlpha, complexAlpha, const_alpha);
+}
+
+/*
+void DecompressBlockDXT5(): Decompresses one block of a DXT5 texture and stores the resulting pixels at the appropriate offset in 'image'.
+uint32_t x: x-coordinate of the first pixel in the block.
+uint32_t y: y-coordinate of the first pixel in the block.
+uint32_t width: width of the texture being decompressed.
+const uint8_t *blockStorage: pointer to the block to decompress.
+uint32_t *image: pointer to image where the decompressed pixel data should be stored.
+*/
+void DecompressBlockDXT5(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image)
+{
+ uint8_t alpha0, alpha1;
+ const uint8_t* bits;
+ uint32_t alphaCode1;
+ uint16_t alphaCode2;
+
+ uint16_t color0, color1;
+ uint8_t r0, g0, b0, r1, g1, b1;
+
+ int i, j;
+
+ uint32_t temp, code;
+
+ alpha0 = *(blockStorage);
+ alpha1 = *(blockStorage + 1);
+
+ bits = blockStorage + 2;
+ alphaCode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24);
+ alphaCode2 = bits[0] | (bits[1] << 8);
+
+ color0 = *(const uint16_t*)(blockStorage + 8);
+ color1 = *(const uint16_t*)(blockStorage + 10);
+
+ temp = (color0 >> 11) * 255 + 16;
+ r0 = (uint8_t)((temp/32 + temp)/32);
+ temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
+ g0 = (uint8_t)((temp/64 + temp)/64);
+ temp = (color0 & 0x001F) * 255 + 16;
+ b0 = (uint8_t)((temp/32 + temp)/32);
+
+ temp = (color1 >> 11) * 255 + 16;
+ r1 = (uint8_t)((temp/32 + temp)/32);
+ temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
+ g1 = (uint8_t)((temp/64 + temp)/64);
+ temp = (color1 & 0x001F) * 255 + 16;
+ b1 = (uint8_t)((temp/32 + temp)/32);
+
+ code = *(const uint32_t*)(blockStorage + 12);
+
+ for (j = 0; j < 4; j++) {
+ for (i = 0; i < 4; i++) {
+ uint8_t finalAlpha;
+ int alphaCode, alphaCodeIndex;
+ uint8_t colorCode;
+ uint32_t finalColor;
+
+ alphaCodeIndex = 3*(4*j+i);
+ if (alphaCodeIndex <= 12) {
+ alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
+ } else if (alphaCodeIndex == 15) {
+ alphaCode = (alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06);
+ } else /* alphaCodeIndex >= 18 && alphaCodeIndex <= 45 */ {
+ alphaCode = (alphaCode1 >> (alphaCodeIndex - 16)) & 0x07;
+ }
+
+ if (alphaCode == 0) {
+ finalAlpha = alpha0;
+ } else if (alphaCode == 1) {
+ finalAlpha = alpha1;
+ } else {
+ if (alpha0 > alpha1) {
+ finalAlpha = (uint8_t)(((8-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/7);
+ } else {
+ if (alphaCode == 6) {
+ finalAlpha = 0;
+ } else if (alphaCode == 7) {
+ finalAlpha = 255;
+ } else {
+ finalAlpha = (uint8_t)(((6-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/5);
+ }
+ }
+ }
+
+ colorCode = (code >> 2*(4*j+i)) & 0x03;
+ finalColor = 0;
+
+ switch (colorCode) {
+ case 0:
+ finalColor = PackRGBA(r0, g0, b0, finalAlpha);
+ break;
+ case 1:
+ finalColor = PackRGBA(r1, g1, b1, finalAlpha);
+ break;
+ case 2:
+ finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, finalAlpha);
+ break;
+ case 3:
+ finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, finalAlpha);
+ break;
+ }
+
+ if(finalAlpha==0) *simpleAlpha = 1;
+ else if(finalAlpha<0xff) *complexAlpha = 1;
+
+ image [i + x + (width* (y+j))] = finalColor;
+ }
+ }
+}
+
+/*
+void DecompressBlockDXT3(): Decompresses one block of a DXT3 texture and stores the resulting pixels at the appropriate offset in 'image'.
+uint32_t x: x-coordinate of the first pixel in the block.
+uint32_t y: y-coordinate of the first pixel in the block.
+uint32_t height: height of the texture being decompressed.
+const uint8_t *blockStorage: pointer to the block to decompress.
+uint32_t *image: pointer to image where the decompressed pixel data should be stored.
+*/
+void DecompressBlockDXT3(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image)
+{
+ int i;
+
+ uint8_t alphaValues [16] = { 0 };
+
+ for (i = 0; i < 4; ++i) {
+ const uint16_t* alphaData = (const uint16_t*) (blockStorage);
+
+ alphaValues [i*4 + 0] = (((*alphaData) >> 0) & 0xF ) * 17;
+ alphaValues [i*4 + 1] = (((*alphaData) >> 4) & 0xF ) * 17;
+ alphaValues [i*4 + 2] = (((*alphaData) >> 8) & 0xF ) * 17;
+ alphaValues [i*4 + 3] = (((*alphaData) >> 12) & 0xF) * 17;
+
+ blockStorage += 2;
+ }
+
+ DecompressBlockDXT1Internal (blockStorage,
+ image + x + (y * width), width, transparent0, simpleAlpha, complexAlpha, alphaValues);
+}
+
+static int inline nlevel(int size, int level) {
+ if(size) {
+ size>>=level;
+ if(!size) size=1;
+ }
+ return size;
+}
+
+// return the max level for that WxH size
+static int inline maxlevel(int w, int h) {
+ int mlevel = 0;
+ while(w!=1 || h!=1) {
+ w>>=1; h>>=1;
+ if(!w) w=1;
+ if(!h) h=1;
+ ++mlevel;
+ }
+ return mlevel;
+}
+
+static GLboolean isDXTc(GLenum format) {
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return 1;
+ }
+ return 0;
+}
+
+GLboolean isDXTcSRGB(GLenum format) {
+ switch (format) {
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return 1;
+ }
+ return 0;
+}
+
+GLboolean isDXTcAlpha(GLenum format) {
+ switch (format) {
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return 1;
+ }
+ return 0;
+}
+
+static GLboolean isNotCompressed(GLenum format) {
+ switch(format) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_RGBA8:
+ case GL_RGB8:
+ case GL_RGB5:
+ case GL_RGB565:
+ return true;
+ }
+ return false;
+}
+
+static GLenum compressedMinMipmap(GLenum param)
+{
+ switch(param) {
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ return GL_NEAREST;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return GL_LINEAR;
+ default:
+ return param;
+ }
+}
+
+GLvoid *uncompressDXTc(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize,
+ int transparent0, int* simpleAlpha, int* complexAlpha, const GLvoid *data)
+{
+ // uncompress a DXTc image
+ // get pixel size of uncompressed image => fixed RGBA
+ int pixelsize = 4;
+
+/* if (format==COMPRESSED_RGB_S3TC_DXT1_EXT)
+ pixelsize = 3;*/
+ // check with the size of the input data stream if the stream is in fact uncompressed
+ if (imageSize == width*height*pixelsize || data==NULL) {
+ // uncompressed stream
+ return (GLvoid*)data;
+ }
+ // alloc memory
+ GLvoid *pixels = malloc(((width+3)&~3)*((height+3)&~3)*pixelsize);
+ // uncompress loop
+ int blocksize;
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ blocksize = 8;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_RGBA_DXT5_S3TC:
+ blocksize = 16;
+ break;
+ }
+ uintptr_t src = (uintptr_t) data;
+ for (int y=0; y<height; y+=4) {
+ for (int x=0; x<width; x+=4) {
+ switch(format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ DecompressBlockDXT1(x, y, width, (uint8_t*)src, transparent0, simpleAlpha, complexAlpha, pixels);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ DecompressBlockDXT3(x, y, width, (uint8_t*)src, transparent0, simpleAlpha, complexAlpha, pixels);
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_RGBA_DXT5_S3TC:
+ DecompressBlockDXT5(x, y, width, (uint8_t*)src, transparent0, simpleAlpha, complexAlpha, pixels);
+ break;
+ }
+ src+=blocksize;
+ }
+ }
+ return pixels;
+}
diff --git a/src/gl4es-decompress.h b/src/gl4es-decompress.h
new file mode 100644
index 00000000..742500da
--- /dev/null
+++ b/src/gl4es-decompress.h
@@ -0,0 +1,29 @@
+#ifndef _GL4ES_DECOMPRESS_H_
+#define _GL4ES_DECOMPRESS_H_
+
+#include <stdint.h>
+#include <epoxy/gl.h>
+
+void DecompressBlockDXT1(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image);
+
+void DecompressBlockDXT3(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image);
+
+void DecompressBlockDXT5(uint32_t x, uint32_t y, uint32_t width,
+ const uint8_t* blockStorage,
+ int transparent0, int* simpleAlpha, int *complexAlpha,
+ uint32_t* image);
+
+GLboolean isDXTcSRGB(GLenum format);
+
+GLboolean isDXTcAlpha(GLenum format);
+
+GLvoid *uncompressDXTc(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize,
+ int transparent0, int* simpleAlpha, int* complexAlpha, const GLvoid *data);
+
+#endif // _GL4ES_DECOMPRESS_H_
diff --git a/src/meson.build b/src/meson.build
index e9c97f72..34b2983f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -55,6 +55,7 @@ vrend_sources = [
'vrend_tweaks.h',
'vrend_winsys.c',
'vrend_winsys.h',
+ 'gl4es-decompress.c',
]
virglrenderer_sources = [
diff --git a/src/vrend_formats.c b/src/vrend_formats.c
index fde607c2..0fa94960 100644
--- a/src/vrend_formats.c
+++ b/src/vrend_formats.c
@@ -534,6 +534,8 @@ static void vrend_add_compressed_formats(struct vrend_format_table *table, int n
#define add_formats(x) vrend_add_formats((x), ARRAY_SIZE((x)))
#define add_compressed_formats(x) vrend_add_compressed_formats((x), ARRAY_SIZE((x)))
+extern int dxtn_decompress;
+
void vrend_build_format_list_common(void)
{
add_formats(base_rgba_formats);
@@ -564,7 +566,7 @@ void vrend_build_format_list_common(void)
/* compressed */
if (epoxy_has_gl_extension("GL_S3_s3tc") ||
epoxy_has_gl_extension("GL_EXT_texture_compression_s3tc") ||
- epoxy_has_gl_extension("GL_ANGLE_texture_compression_dxt")) {
+ epoxy_has_gl_extension("GL_ANGLE_texture_compression_dxt") || dxtn_decompress) {
add_compressed_formats(dxtn_formats);
add_compressed_formats(dxtn_srgb_formats);
}
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 6608bb6d..dba5f65a 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -68,6 +68,17 @@
#include <vrend_video.h>
#endif
+#include "gl4es-decompress.h"
+const int dxtn_decompress = 1;
+static void CheckGlError( const char* pFunctionName )
+{
+ GLint error = glGetError();
+ if( error != GL_NO_ERROR )
+ {
+ printf("%s returned glError 0x%x\n", pFunctionName, error);
+ }
+}
+
/*
* VIRGL_RENDERER_CAPSET_VIRGL has version 0 and 1, but they are both
* virgl_caps_v1 and are exactly the same.
@@ -8465,6 +8479,9 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
{
void *data;
+ GLvoid *decompressed_data;
+ short decompress_success = 0;
+
if ((is_only_bit(res->storage_bits, VREND_STORAGE_GUEST_MEMORY) ||
has_bit(res->storage_bits, VREND_STORAGE_HOST_SYSTEM_MEMORY)) && res->iov) {
return vrend_copy_iovec(iov, num_iovs, info->offset,
@@ -8653,10 +8670,65 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
else
vrend_scale_depth(data, send_size, depth_scale);
}
+ if (compressed && dxtn_decompress) {
+ // from gl4es code
+ int simpleAlpha = 0;
+ int complexAlpha = 0;
+ int transparent0 = (glformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+ glformat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) ? 1 : 0;
+
+ if(isDXTcAlpha(glformat))
+ simpleAlpha = complexAlpha = 1;
+
+ if (data) {
+ if ((info->box->width & 3) || (info->box->height & 3)) {
+ GLvoid *tmp;
+ GLsizei nw = info->box->width;
+ GLsizei nh = info->box->height;
+ int y_tmp;
+ if (nw < 4) nw = 4;
+ if (nh < 4) nh = 4;
+ tmp = uncompressDXTc(nw, nh, glformat, comp_size, transparent0,
+ &simpleAlpha, &complexAlpha, data);
+ decompressed_data = malloc(4 * info->box->width * info->box->height);
+
+ for (y_tmp = 0; y_tmp < info->box->height; y_tmp ++)
+ memcpy(decompressed_data + y_tmp * info->box->width * 4, tmp + y_tmp * nw * 4,
+ info->box->width * 4);
+ free(tmp);
+ } else {
+ decompressed_data = uncompressDXTc(info->box->width, info->box->height, glformat,
+ comp_size, transparent0, &simpleAlpha, &complexAlpha, data);
+ }
+ }
+
+ if((gltype != GL_UNSIGNED_BYTE) && isDXTcSRGB(glformat)) {
+
+ if(simpleAlpha && !complexAlpha) {
+ glformat = GL_RGBA;
+ gltype = GL_UNSIGNED_SHORT_5_5_5_1;
+ } else if(complexAlpha || simpleAlpha) {
+ glformat = GL_RGBA;
+ gltype = GL_UNSIGNED_SHORT_4_4_4_4;
+ } else {
+ glformat = GL_RGB;
+ gltype = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ } else {
+ glformat = GL_RGBA;
+ }
+ decompress_success = 1;
+ }
if (res->target == GL_TEXTURE_CUBE_MAP) {
GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info->box->z;
if (compressed) {
- glCompressedTexSubImage2D(ctarget, info->level, x, y,
+ if (dxtn_decompress) {
+ glTexImage2D(ctarget, info->level, glformat, info->box->width,
+ info->box->height, 0, glformat, gltype, decompressed_data);
+ CheckGlError("glTexImage2D");
+ }
+ else
+ glCompressedTexSubImage2D(ctarget, info->level, x, y,
info->box->width, info->box->height,
glformat, comp_size, data);
} else {
@@ -8665,7 +8737,14 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
}
} else if (res->target == GL_TEXTURE_3D || res->target == GL_TEXTURE_2D_ARRAY || res->target == GL_TEXTURE_CUBE_MAP_ARRAY) {
if (compressed) {
- glCompressedTexSubImage3D(res->target, info->level, x, y, info->box->z,
+ if (dxtn_decompress) {
+ glTexImage3D(res->target, info->level, glformat,
+ info->box->width, info->box->height, info->box->depth,
+ 0, glformat, gltype, decompressed_data);
+ CheckGlError("glTexImage3D");
+ }
+ else
+ glCompressedTexSubImage3D(res->target, info->level, x, y, info->box->z,
info->box->width, info->box->height, info->box->depth,
glformat, comp_size, data);
} else {
@@ -8674,7 +8753,12 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
glformat, gltype, data);
}
} else if (res->target == GL_TEXTURE_1D) {
- if (vrend_state.use_gles) {
+ if (compressed && dxtn_decompress) {
+ glTexImage1D(res->target, info->level, glformat, info->box->width,
+ 0, glformat, gltype, decompressed_data);
+ CheckGlError("glTexImage1D");
+ }
+ else if (vrend_state.use_gles) {
/* Covers both compressed and none compressed. */
report_gles_missing_func(ctx, "gl[Compressed]TexSubImage1D");
} else if (compressed) {
@@ -8687,7 +8771,18 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
}
} else {
if (compressed) {
- glCompressedTexSubImage2D(res->target, info->level, x, res->target == GL_TEXTURE_1D_ARRAY ? info->box->z : y,
+ if (dxtn_decompress) {
+ glTexImage2D(res->target, info->level, glformat, info->box->width,
+ info->box->height, 0, glformat, gltype, NULL);
+ CheckGlError("glTexImage2D");
+ glTexSubImage2D(res->target, info->level, x, res->target == GL_TEXTURE_1D_ARRAY ? info->box->z : y,
+ info->box->width,
+ res->target == GL_TEXTURE_1D_ARRAY ? info->box->depth : info->box->height,
+ glformat, gltype, decompressed_data);
+ CheckGlError("glTexSubImage2D");
+ }
+ else
+ glCompressedTexSubImage2D(res->target, info->level, x, res->target == GL_TEXTURE_1D_ARRAY ? info->box->z : y,
info->box->width, info->box->height,
glformat, comp_size, data);
} else {
@@ -8710,6 +8805,9 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx,
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ if (decompress_success)
+ free(decompressed_data);
+
if (need_temp)
free(data);
}
--
2.34.1