UnZipData.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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', './pako_inflate-8ea163f9', './PixelFormat-e6d821ed'], function (when, createTaskProcessorWorker, RuntimeError, WebGLConstants, pako_inflate, PixelFormat) { 'use strict';
  24. var CRN_FORMAT = {
  25. cCRNFmtInvalid: -1,
  26. cCRNFmtDXT1: 0,
  27. // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.
  28. cCRNFmtDXT3: 1,
  29. cCRNFmtDXT5: 2
  30. // Crunch supports more formats than this, but we can't use them here.
  31. };
  32. // Mapping of Crunch formats to DXT formats.
  33. var DXT_FORMAT_MAP = {};
  34. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT1] = PixelFormat.PixelFormat.RGB_DXT1;
  35. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT3] = PixelFormat.PixelFormat.RGBA_DXT3;
  36. DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT5] = PixelFormat.PixelFormat.RGBA_DXT5;
  37. var dst;
  38. var dxtData;
  39. var cachedDstSize = 0;
  40. var crunch;
  41. // Copy an array of bytes into or out of the emscripten heap.
  42. function arrayBufferCopy(src, dst, dstByteOffset, numBytes) {
  43. var i;
  44. var dst32Offset = dstByteOffset / 4;
  45. var tail = (numBytes % 4);
  46. var src32 = new Uint32Array(src.buffer, 0, (numBytes - tail) / 4);
  47. var dst32 = new Uint32Array(dst.buffer);
  48. for (i = 0; i < src32.length; i++) {
  49. dst32[dst32Offset + i] = src32[i];
  50. }
  51. for (i = numBytes - tail; i < numBytes; i++) {
  52. dst[dstByteOffset + i] = src[i];
  53. }
  54. }
  55. /**
  56. * @private
  57. */
  58. function convertCRNToDXT(parameters) {
  59. // Copy the contents of the arrayBuffer into emscriptens heap.
  60. var arrayBuffer = parameters.data;
  61. var srcSize = arrayBuffer.byteLength;
  62. var bytes = new Uint8Array(arrayBuffer, parameters.offset);
  63. var src = crunch._malloc(srcSize);
  64. arrayBufferCopy(bytes, crunch.HEAPU8, src, srcSize);
  65. // Determine what type of compressed data the file contains.
  66. var crnFormat = crunch._crn_get_dxt_format(src, srcSize);
  67. var format = DXT_FORMAT_MAP[crnFormat];
  68. if (!when.defined(format)) {
  69. throw new RuntimeError.RuntimeError('Unsupported compressed format.');
  70. }
  71. // Gather basic metrics about the DXT data.
  72. var levels = crunch._crn_get_levels(src, srcSize);
  73. var width = crunch._crn_get_width(src, srcSize);
  74. var height = crunch._crn_get_height(src, srcSize);
  75. // Determine the size of the decoded DXT data.
  76. var dstSize = 0;
  77. var i;
  78. for (i = 0; i < levels; ++i) {
  79. dstSize += PixelFormat.PixelFormat.compressedTextureSizeInBytes(format, width >> i, height >> i);
  80. }
  81. // Allocate enough space on the emscripten heap to hold the decoded DXT data
  82. // or reuse the existing allocation if a previous call to this function has
  83. // already acquired a large enough buffer.
  84. if(cachedDstSize < dstSize) {
  85. if(when.defined(dst)) {
  86. crunch._free(dst);
  87. }
  88. dst = crunch._malloc(dstSize);
  89. dxtData = new Uint8Array(crunch.HEAPU8.buffer, dst, dstSize);
  90. cachedDstSize = dstSize;
  91. }
  92. // Decompress the DXT data from the Crunch file into the allocated space.
  93. crunch._crn_decompress(src, srcSize, dst, dstSize, 0, levels);
  94. // Release the crunch file data from the emscripten heap.
  95. crunch._free(src);
  96. var bOutMipMapData = when.defaultValue(parameters.bMipMap, false);
  97. if(bOutMipMapData){
  98. var dXTDataMipMap = dxtData.slice(0, dstSize);
  99. return new PixelFormat.CompressedTextureBuffer(format, width, height, dXTDataMipMap);
  100. }
  101. else {
  102. // Mipmaps are unsupported, so copy the level 0 texture
  103. // When mipmaps are supported, a copy will still be necessary as dxtData is a view on the heap.
  104. var length = PixelFormat.PixelFormat.compressedTextureSizeInBytes(format, width, height);
  105. // Get a copy of the 0th mip level. dxtData will exceed length when there are more mip levels.
  106. // Equivalent to dxtData.slice(0, length), which is not supported in IE11
  107. var level0DXTDataView = dxtData.subarray(0, length);
  108. var level0DXTData = new Uint8Array(length);
  109. level0DXTData.set(level0DXTDataView, 0);
  110. return new PixelFormat.CompressedTextureBuffer(format, width, height, level0DXTData);
  111. }
  112. }
  113. function unzipToCrn(arrayBuffer){
  114. var view = new DataView(arrayBuffer);
  115. var offset = 0;
  116. var compressType = view.getUint32(offset, true);
  117. offset += Uint32Array.BYTES_PER_ELEMENT;
  118. var width = view.getUint32(offset, true);
  119. offset += Uint32Array.BYTES_PER_ELEMENT;
  120. var height = view.getUint32(offset, true);
  121. offset += Uint32Array.BYTES_PER_ELEMENT;
  122. var format = view.getUint32(offset, true);
  123. offset += Uint32Array.BYTES_PER_ELEMENT;
  124. var size = view.getUint32(offset, true);
  125. offset += Uint32Array.BYTES_PER_ELEMENT;
  126. var data = arrayBuffer.slice(offset, offset + size);
  127. var dxtBuffer = convertCRNToDXT({
  128. data : data
  129. }).bufferView;
  130. var unzipBuffer = new ArrayBuffer(offset + dxtBuffer.byteLength);
  131. var bufferView = new Uint8Array(unzipBuffer);
  132. var uint32BufferView = new Uint32Array(unzipBuffer);
  133. offset = 0;
  134. uint32BufferView[0] = compressType;
  135. offset += Uint32Array.BYTES_PER_ELEMENT;
  136. uint32BufferView[1] = width;
  137. offset += Uint32Array.BYTES_PER_ELEMENT;
  138. uint32BufferView[2] = height;
  139. offset += Uint32Array.BYTES_PER_ELEMENT;
  140. uint32BufferView[3] = format;
  141. offset += Uint32Array.BYTES_PER_ELEMENT;
  142. uint32BufferView[4] = dxtBuffer.byteLength;
  143. offset += Uint32Array.BYTES_PER_ELEMENT;
  144. bufferView.set(dxtBuffer, offset);
  145. return unzipBuffer;
  146. }
  147. function unzip(parameters, transferableObjects) {
  148. var buffers = parameters.data;
  149. var unzipBuffers = [];
  150. for(var i = 0;i < buffers.length;i++){
  151. var bufferObj = buffers[i];
  152. var unzipBuffer;
  153. try{
  154. var dataZip = new Uint8Array(bufferObj.zipBuffer);
  155. unzipBuffer = pako_inflate.pako.inflate(dataZip).buffer;
  156. if(parameters.isCRN){
  157. unzipBuffer = unzipToCrn(unzipBuffer);
  158. }
  159. transferableObjects.push(unzipBuffer);
  160. unzipBuffers.push({
  161. unzipBuffer : unzipBuffer,
  162. name : bufferObj.name
  163. });
  164. }
  165. catch (e){
  166. if(bufferObj.unzipLength === bufferObj.zippedLength){
  167. unzipBuffer = bufferObj.zipBuffer.buffer;
  168. if(parameters.isCRN){
  169. unzipBuffer = unzipToCrn(unzipBuffer);
  170. }
  171. transferableObjects.push(unzipBuffer);
  172. unzipBuffers.push({
  173. unzipBuffer : unzipBuffer,
  174. name : bufferObj.name
  175. });
  176. }
  177. continue ;
  178. }
  179. }
  180. return {
  181. data : unzipBuffers
  182. };
  183. }
  184. function initWorker() {
  185. self.onmessage = createTaskProcessorWorker(unzip);
  186. self.postMessage(true);
  187. }
  188. function UnZipData(event) {
  189. var data = event.data;
  190. var wasmConfig = data.webAssemblyConfig;
  191. if (when.defined(wasmConfig)) {
  192. return require([wasmConfig.modulePath], function (crnModule) {
  193. if (when.defined(wasmConfig.wasmBinaryFile)) {
  194. if (!when.defined(crnModule)) {
  195. crnModule = self.Module;
  196. }
  197. crunch = crnModule;
  198. initWorker();
  199. } else {
  200. crunch = crnModule;
  201. initWorker();
  202. }
  203. });
  204. }
  205. }
  206. return UnZipData;
  207. });