transcodeCRNToDXT.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. * Cesium - https://github.com/CesiumGS/cesium
  3. *
  4. * Copyright 2011-2020 Cesium Contributors
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Columbus View (Pat. Pend.)
  19. *
  20. * Portions licensed separately.
  21. * See https://github.com/CesiumGS/cesium/blob/master/LICENSE.md for full licensing details.
  22. */
  23. define(['./when-8d13db60', './createTaskProcessorWorker', './RuntimeError-ba10bc3e', './WebGLConstants-4c11ee5f', './PixelFormat-e6d821ed'], function (when, createTaskProcessorWorker, RuntimeError, WebGLConstants, PixelFormat) { 'use strict';
  24. // Modified from texture-tester
  25. // See:
  26. // https://github.com/toji/texture-tester/blob/master/js/webgl-texture-util.js
  27. // http://toji.github.io/texture-tester/
  28. /**
  29. * @license
  30. *
  31. * Copyright (c) 2014, Brandon Jones. All rights reserved.
  32. *
  33. * Redistribution and use in source and binary forms, with or without modification,
  34. * are permitted provided that the following conditions are met:
  35. *
  36. * * Redistributions of source code must retain the above copyright notice, this
  37. * list of conditions and the following disclaimer.
  38. * * Redistributions in binary form must reproduce the above copyright notice,
  39. * this list of conditions and the following disclaimer in the documentation
  40. * and/or other materials provided with the distribution.
  41. *
  42. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  43. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  44. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  45. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  46. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  47. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  48. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  49. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  50. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  51. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  52. */
  53. // Taken from crnlib.h
  54. var CRN_FORMAT = {
  55. cCRNFmtInvalid: -1,
  56. cCRNFmtDXT1: 0,
  57. // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.
  58. cCRNFmtDXT3: 1,
  59. cCRNFmtDXT5: 2
  60. // Crunch supports more formats than this, but we can't use them here.
  61. };
  62. // Mapping of Crunch formats to DXT formats.
  63. var DXT_FORMAT_MAP = {};
  64. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT1] = PixelFormat.PixelFormat.RGB_DXT1;
  65. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT3] = PixelFormat.PixelFormat.RGBA_DXT3;
  66. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT5] = PixelFormat.PixelFormat.RGBA_DXT5;
  67. var dst;
  68. var dxtData;
  69. var cachedDstSize = 0;
  70. var crunch;
  71. // Copy an array of bytes into or out of the emscripten heap.
  72. function arrayBufferCopy(src, dst, dstByteOffset, numBytes) {
  73. var i;
  74. var dst32Offset = dstByteOffset / 4;
  75. var tail = (numBytes % 4);
  76. var src32 = new Uint32Array(src.buffer, 0, (numBytes - tail) / 4);
  77. var dst32 = new Uint32Array(dst.buffer);
  78. for (i = 0; i < src32.length; i++) {
  79. dst32[dst32Offset + i] = src32[i];
  80. }
  81. for (i = numBytes - tail; i < numBytes; i++) {
  82. dst[dstByteOffset + i] = src[i];
  83. }
  84. }
  85. /**
  86. * @private
  87. */
  88. function convertCRNToDXT(parameters, transferableObjects) {
  89. // Copy the contents of the arrayBuffer into emscriptens heap.
  90. var arrayBuffer = parameters.data;
  91. var srcSize = arrayBuffer.byteLength;
  92. var bytes = new Uint8Array(arrayBuffer);
  93. var src = crunch._malloc(srcSize);
  94. arrayBufferCopy(bytes, crunch.HEAPU8, src, srcSize);
  95. // Determine what type of compressed data the file contains.
  96. var crnFormat = crunch._crn_get_dxt_format(src, srcSize);
  97. var format = DXT_FORMAT_MAP[crnFormat];
  98. if (!when.defined(format)) {
  99. throw new RuntimeError.RuntimeError('Unsupported compressed format.');
  100. }
  101. // Gather basic metrics about the DXT data.
  102. var levels = crunch._crn_get_levels(src, srcSize);
  103. var width = crunch._crn_get_width(src, srcSize);
  104. var height = crunch._crn_get_height(src, srcSize);
  105. // Determine the size of the decoded DXT data.
  106. var dstSize = 0;
  107. var i;
  108. for (i = 0; i < levels; ++i) {
  109. dstSize += PixelFormat.PixelFormat.compressedTextureSizeInBytes(format, width >> i, height >> i);
  110. }
  111. // Allocate enough space on the emscripten heap to hold the decoded DXT data
  112. // or reuse the existing allocation if a previous call to this function has
  113. // already acquired a large enough buffer.
  114. if(cachedDstSize < dstSize) {
  115. if(when.defined(dst)) {
  116. crunch._free(dst);
  117. }
  118. dst = crunch._malloc(dstSize);
  119. dxtData = new Uint8Array(crunch.HEAPU8.buffer, dst, dstSize);
  120. cachedDstSize = dstSize;
  121. }
  122. // Decompress the DXT data from the Crunch file into the allocated space.
  123. crunch._crn_decompress(src, srcSize, dst, dstSize, 0, levels);
  124. // Release the crunch file data from the emscripten heap.
  125. crunch._free(src);
  126. var bOutMipMapData = when.defaultValue(parameters.bMipMap, false);
  127. if(bOutMipMapData){
  128. var dXTDataMipMap = dxtData.slice(0, dstSize);
  129. transferableObjects.push(dXTDataMipMap.buffer);
  130. return new PixelFormat.CompressedTextureBuffer(format, width, height, dXTDataMipMap);
  131. }
  132. else {
  133. // Mipmaps are unsupported, so copy the level 0 texture
  134. // When mipmaps are supported, a copy will still be necessary as dxtData is a view on the heap.
  135. var length = PixelFormat.PixelFormat.compressedTextureSizeInBytes(format, width, height);
  136. // Get a copy of the 0th mip level. dxtData will exceed length when there are more mip levels.
  137. // Equivalent to dxtData.slice(0, length), which is not supported in IE11
  138. var level0DXTDataView = dxtData.subarray(0, length);
  139. var level0DXTData = new Uint8Array(length);
  140. level0DXTData.set(level0DXTDataView, 0);
  141. transferableObjects.push(level0DXTData.buffer);
  142. return new PixelFormat.CompressedTextureBuffer(format, width, height, level0DXTData);
  143. }
  144. }
  145. function initWorker(crunchModule) {
  146. crunch = crunchModule;
  147. self.onmessage = createTaskProcessorWorker(convertCRNToDXT);
  148. self.postMessage(true);
  149. }
  150. function transcodeCRNToDXT(event) {
  151. var data = event.data;
  152. // Expect the first message to be to load a web assembly module
  153. var wasmConfig = data.webAssemblyConfig;
  154. if (when.defined(wasmConfig)) {
  155. // Require and compile WebAssembly module, or use fallback if not supported
  156. return require([wasmConfig.modulePath], function(crnModule) {
  157. if (when.defined(wasmConfig.wasmBinaryFile)) {
  158. if (!when.defined(crnModule)) {
  159. crnModule = self.Module;
  160. }
  161. initWorker(crnModule);
  162. } else {
  163. initWorker(crnModule);
  164. }
  165. });
  166. }
  167. }
  168. return transcodeCRNToDXT;
  169. });