Commits

ecsv committed 0ea303a

Allow to replace patented S3TC algorithm with compatible txc_dxtn

The S3TC is patented in some countries which makes it hard for distribution.
Mesa is using an external library which is using a compatible algorithm called
S2TC. But also S3TC implementations of this library are available.

Distributions can use this option to be on the safe side regarding the provided
functionality.

  • Participants
  • Parent commits 1538e5a

Comments (0)

Files changed (12)

projects/unix/Makefile

 CFLAGS += $(LIBPNG_CFLAGS)
 LDLIBS += $(LIBPNG_LDLIBS)
 
-
 # search for OpenGL libraries
 ifeq ($(OS), OSX)
   GL_LDLIBS = -framework OpenGL
 	$(SRCDIR)/GlideHQ/tc-1.1+/wrapper.c \
 	$(SRCDIR)/GlideHQ/tc-1.1+/texstore.c
 
-CPPFLAGS += -DTEXTURE_FILTER -DARGB -DYUV # -DDUMP_CACHE
+CPPFLAGS += -DTEXTURE_FILTER # -DDUMP_CACHE
 LDLIBS += -lboost_filesystem$(BOOST_SUFFIX) -lboost_system$(BOOST_SUFFIX)
+
+  ifeq ($(TXCDXTN), 1)
+    CPPFLAGS += -DTXCDXTN_EXTERNAL
+  else 
+    SOURCE += $(SRCDIR)/GlideHQ/tc-1.1+/dxtn.c
+  endif
 endif
 
 ifeq ($(OS),MINGW)
 	@echo "    PIC=(1|0)     == Force enable/disable of position independent code"
 	@echo "    POSTFIX=name  == String added to the name of the the build (default: '')"
 	@echo "    HIRES=(1|0)   == Enables/Disables support for hires textures and texture filters (default: 1)"
+	@echo "    TXCDXTN=(1|0) == Enable/Disable external txc_dxtn library (default: 0)"
 	@echo "  Install Options:"
 	@echo "    PREFIX=path   == install/uninstall prefix (default: /usr/local)"
 	@echo "    SHAREDIR=path == path to install shared data files (default: PREFIX/share/mupen64plus)"

src/Glide64/m64p.h

 #define CONFIG_API_VERSION          0x020000
 #define VIDEXT_API_VERSION          0x030000
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 void WriteLog(m64p_msg_level level, const char *msg, ...);
+#ifdef __cplusplus
+}
+#endif
 
 //The Glide API originally used an integer to pick an enumerated resolution.
 //To accomodate arbitrary resolutions, pack it into a 32-bit struct

src/Glide64/osal_dynamiclib.h

 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *   Mupen64plus-core - osal/dynamiclib.h                                  *
+ *   Mupen64plus-video-glide64mk2 - osal_dynamiclib.h                      *
  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *                                                                         *
 #if !defined(OSAL_DYNAMICLIB_H)
 #define OSAL_DYNAMICLIB_H
 
+#include "m64p_types.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include "m64p_types.h"
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath);
 
 void *     osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName);
 
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle);
+
 #ifdef __cplusplus
 }
 #endif

src/Glide64/osal_dynamiclib_unix.c

 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *   Mupen64plus-core - osal/dynamiclib_unix.c                             *
+ *   Mupen64plus-video-glide64mk2 - osal_dynamiclib_unix.c                 *
  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *                                                                         *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #include <stdlib.h>
+#include <string.h>
 #include <stdio.h>
 #include <dlfcn.h>
 
 #include "m64p_types.h"
+#include "m64p.h"
 #include "osal_dynamiclib.h"
 
+m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
+{
+    if (pLibHandle == NULL || pccLibraryPath == NULL)
+        return M64ERR_INPUT_ASSERT;
+
+    *pLibHandle = dlopen(pccLibraryPath, RTLD_NOW);
+
+    if (*pLibHandle == NULL)
+    {
+        /* only print an error message if there is a directory separator (/) in the pathname */
+        /* this prevents us from throwing an error for the use case where Mupen64Plus is not installed */
+        if (strchr(pccLibraryPath, '/') != NULL)
+            WriteLog(M64MSG_ERROR, "dlopen('%s') failed: %s", pccLibraryPath, dlerror());
+        return M64ERR_INPUT_NOT_FOUND;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
 void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
 {
     if (pccProcedureName == NULL)
     return dlsym(LibHandle, pccProcedureName);
 }
 
+m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle)
+{
+    int rval = dlclose(LibHandle);
 
+    if (rval != 0)
+    {
+        WriteLog(M64MSG_ERROR, "dlclose() failed: %s", dlerror());
+        return M64ERR_INTERNAL;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+

src/Glide64/osal_dynamiclib_win32.c

 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *   Mupen64plus-ui-console - osal_dynamiclib_win32.c                      *
+ *   Mupen64plus-video-glide64mk2 - osal_dynamiclib_win32.c                *
  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
  *   Copyright (C) 2009 Richard Goedeken                                   *
  *                                                                         *
 #include <stdio.h>
 
 #include "m64p_types.h"
+#include "m64p.h"
 #include "osal_dynamiclib.h"
 
 m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath)
         DWORD dwErr = GetLastError(); 
         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
-        fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg);
+        WriteLog(M64MSG_ERROR, "LoadLibrary('%s') error: %s", pccLibraryPath, pchErrMsg);
         LocalFree(pchErrMsg);
         return M64ERR_INPUT_NOT_FOUND;
     }
         DWORD dwErr = GetLastError(); 
         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL);
-        fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg);
+        WriteLog(M64MSG_ERROR, "FreeLibrary() error: %s", pchErrMsg);
         LocalFree(pchErrMsg);
         return M64ERR_INTERNAL;
     }

src/GlideHQ/TxQuantize.cpp

 
   /* get dxtn extensions */
   _tx_compress_fxt1 = TxLoadLib::getInstance()->getfxtCompressTexFuncExt();
-  _tx_compress_dxtn = TxLoadLib::getInstance()->getdxtCompressTexFuncExt();
+  _tx_compress_dxtn_rgba = TxLoadLib::getInstance()->getdxtCompressTexFuncExt();
 }
 
 
 
   boolean bRet = 0;
 
-  if (_tx_compress_dxtn &&
+  if (_tx_compress_dxtn_rgba &&
       srcwidth >= 4 && srcheight >= 4) {
     /* compress to dxtn
      * width and height must be larger than 4
         unsigned int srcStride = (srcwidth * blkheight) << 2;
         unsigned int destStride = dstRowStride * blkrow;
         for (i = 0; i < numcore - 1; i++) {
-          thrd[i] = new std::thread(std::bind(_tx_compress_dxtn,
+          thrd[i] = new std::thread(std::bind(_tx_compress_dxtn_rgba,
                                               4,
                                               srcwidth,
                                               blkheight,
           src  += srcStride;
           dest += destStride;
         }
-        thrd[i] = new std::thread(std::bind(_tx_compress_dxtn,
+        thrd[i] = new std::thread(std::bind(_tx_compress_dxtn_rgba,
                                             4,
                                             srcwidth,
                                             srcheight - blkheight * i,
           delete thrd[i];
         }
       } else {
-        (*_tx_compress_dxtn)(4,             /* comps: ARGB8888=4, RGB888=3 */
+        (*_tx_compress_dxtn_rgba)(4,             /* comps: ARGB8888=4, RGB888=3 */
                              srcwidth,      /* width */
                              srcheight,     /* height */
                              src,           /* source */
                                              * others = 16 bytes per 4x4 texel */
       }
 #else
-      (*_tx_compress_dxtn)(4,             /* comps: ARGB8888=4, RGB888=3 */
+      (*_tx_compress_dxtn_rgba)(4,             /* comps: ARGB8888=4, RGB888=3 */
                            srcwidth,      /* width */
                            srcheight,     /* height */
                            src,           /* source */

src/GlideHQ/TxQuantize.h

   int _numcore;
 
   fxtCompressTexFuncExt _tx_compress_fxt1;
-  dxtCompressTexFuncExt _tx_compress_dxtn;
+  dxtCompressTexFuncExt _tx_compress_dxtn_rgba;
 
   /* fast optimized... well, sort of. */
   void ARGB1555_ARGB8888(uint32* src, uint32* dst, int width, int height);

src/GlideHQ/TxUtil.cpp

     _dxtnlib = LoadLibrary("dxtn");
 
   if (_dxtnlib) {
-    if (!_tx_compress_dxtn)
-      _tx_compress_dxtn = (dxtCompressTexFuncExt)DLSYM(_dxtnlib, "tx_compress_dxtn");
+    if (!_tx_compress_dxtn_rgba)
+      _tx_compress_dxtn_rgba = (dxtCompressTexFuncExt)DLSYM(_dxtnlib, "tx_compress_dxtn_rgba");
 
     if (!_tx_compress_fxt1)
       _tx_compress_fxt1 = (fxtCompressTexFuncExt)DLSYM(_dxtnlib, "fxt1_encode");
   }
 #else
-  _tx_compress_dxtn = tx_compress_dxtn;
+  _tx_compress_dxtn_rgba = tx_compress_dxtn_rgba;
   _tx_compress_fxt1 = fxt1_encode;
 
 #endif
 dxtCompressTexFuncExt
 TxLoadLib::getdxtCompressTexFuncExt()
 {
-  return _tx_compress_dxtn;
+  return _tx_compress_dxtn_rgba;
 }
 
 

src/GlideHQ/TxUtil.h

 #ifdef __cplusplus
 extern "C"{
 #endif
-void tx_compress_dxtn(int srccomps, int width, int height,
+void tx_compress_dxtn_rgba(int srccomps, int width, int height,
                       const void *source, int destformat, void *dest,
                       int destRowStride);
 
   HMODULE _dxtnlib;
 #endif
   fxtCompressTexFuncExt _tx_compress_fxt1;
-  dxtCompressTexFuncExt _tx_compress_dxtn;
+  dxtCompressTexFuncExt _tx_compress_dxtn_rgba;
   TxLoadLib();
 public:
   static TxLoadLib* getInstance() {

src/GlideHQ/tc-1.1+/texstore.c

 #include "types.h"
 #include "internal.h"
 
-
 void
 _mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
 			  unsigned int outWidth, unsigned int outHeight,

src/GlideHQ/tc-1.1+/wrapper.c

 
 
 #include <assert.h>
+#include <stdlib.h>
 
 #include "types.h"
 #include "internal.h"
+#include "../../Glide64/m64p.h"
+
+typedef void (*dxtCompressTexFuncExt)(int srccomps, int width,
+                                      int height, const byte *srcPixData,
+                                      int destformat, byte *dest,
+                                      int dstRowStride);
+static dxtCompressTexFuncExt _tx_compress_dxtn = NULL;
+
+#ifdef TXCDXTN_EXTERNAL
+
+#include "../../Glide64/osal_dynamiclib.h"
+
+#if defined(_WIN32) || defined(WIN32)
+#define DXTN_LIBNAME "dxtn.dll"
+#elif defined(__DJGPP__)
+#define DXTN_LIBNAME "dxtn.dxe"
+#else
+#define DXTN_LIBNAME "libtxc_dxtn.so"
+#endif
+
+static m64p_dynlib_handle dxtn_lib_handle;
+
+static void tx_compress_dxtn_init()
+{
+    m64p_error rval;
+
+    rval = osal_dynlib_open(&dxtn_lib_handle, DXTN_LIBNAME);
+    if (rval != M64ERR_SUCCESS) {
+        WriteLog(M64MSG_WARNING, "Failed to open %s", DXTN_LIBNAME);
+        return;
+    }
+
+    _tx_compress_dxtn = osal_dynlib_getproc(dxtn_lib_handle, "tx_compress_dxtn");
+    if (!_tx_compress_dxtn) {
+        WriteLog(M64MSG_WARNING, "Shared library '%s' invalid; no PluginGetVersion() function found.", DXTN_LIBNAME, "tx_compress_dxtn");
+	osal_dynlib_close(dxtn_lib_handle);
+        return;
+    }
+}
+
+#else
+
 #include "dxtn.h"
 
-
 #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
 
-
 TAPI void TAPIENTRY
 fetch_2d_texel_rgb_dxt1 (int texImage_RowStride,
 			 const byte *texImage_Data,
 }
 
 
-TAPI void TAPIENTRY
+static
 tx_compress_dxtn (int srccomps, int width, int height,
 		  const byte *source, int destformat, byte *dest,
 		  int destRowStride)
 	    assert(0);
     }
 }
+
+static void tx_compress_dxtn_init()
+{
+	_tx_compress_dxtn = tx_compress_dxtn;
+}
+
+#endif
+
+
+TAPI void TAPIENTRY
+tx_compress_dxtn_rgba(int srccomps, int width, int height,
+                      const byte *source, int destformat, byte *dest,
+                      int destRowStride)
+{
+    int srcRowStride = width * srccomps;
+    void *newSource = NULL;
+
+    tx_compress_dxtn_init();
+    if (!_tx_compress_dxtn) {
+        WriteLog(M64MSG_ERROR, "Failed to initialize S3TC compressor");
+        return;
+    }
+
+    assert(srccomps == 3 || srccomps == 4);
+
+    if (srccomps == 3)
+        newSource = reorder_source_3_alloc(source, width, height, srcRowStride);
+    if (srccomps == 4)
+        newSource = reorder_source_4_alloc(source, width, height, srcRowStride);
+
+    _tx_compress_dxtn(srccomps, width, height, newSource, destformat, dest,
+                      destRowStride);
+
+    free(newSource);
+}

src/Glitch64/main.h

 #include <m64p_types.h>
 
 #define LOG(...) WriteLog(M64MSG_VERBOSE, __VA_ARGS__)
+#ifdef __cplusplus
+extern "C" {
+#endif
 void WriteLog(m64p_msg_level level, const char *msg, ...);
+#ifdef __cplusplus
+}
+#endif
 
 
 #ifndef _WIN32