@carbonenginejs/runtime 0.1.0-alpha.4 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global/blue/BlueClasses.js +200 -0
- package/dist/global/blue/BlueClasses.js.map +1 -0
- package/dist/global/blue/IBlueClasses.js +79 -0
- package/dist/global/blue/IBlueClasses.js.map +1 -0
- package/dist/global/blue/IBlueDynamicResourceConstructor.js +16 -0
- package/dist/global/blue/IBlueDynamicResourceConstructor.js.map +1 -1
- package/dist/global/blue/blue.js +8 -2
- package/dist/global/blue/blue.js.map +1 -1
- package/dist/global/blue/index.js +2 -0
- package/dist/global/blue/index.js.map +1 -1
- package/dist/global/consts/index.js +0 -1
- package/dist/global/consts/index.js.map +1 -1
- package/dist/global/consts/renderContext/formats.js +26 -25
- package/dist/global/consts/renderContext/formats.js.map +1 -1
- package/dist/{trinityal/Tr2BitmapDimensions.js → global/imageio/BitmapDimensions.js} +19 -15
- package/dist/global/imageio/BitmapDimensions.js.map +1 -0
- package/dist/global/imageio/Cutout.js +28 -0
- package/dist/global/imageio/Cutout.js.map +1 -0
- package/dist/global/imageio/HostBitmap.js +1106 -0
- package/dist/global/imageio/HostBitmap.js.map +1 -0
- package/dist/global/imageio/ImageIOResult.js +99 -0
- package/dist/global/imageio/ImageIOResult.js.map +1 -0
- package/dist/global/imageio/ImageUtility.js +205 -0
- package/dist/global/imageio/ImageUtility.js.map +1 -0
- package/dist/global/imageio/LoadParameters.js +86 -0
- package/dist/global/imageio/LoadParameters.js.map +1 -0
- package/dist/global/imageio/Metadata.js +22 -0
- package/dist/global/imageio/Metadata.js.map +1 -0
- package/dist/global/imageio/index.js +8 -0
- package/dist/global/{consts/webgpu → imageio}/index.js.map +1 -1
- package/dist/global/index.js +2 -1
- package/dist/global/index.js.map +1 -1
- package/dist/global/math/color.js +1 -1
- package/dist/global/math/color.js.map +1 -1
- package/dist/global/schema/CjsSchema.js +8 -0
- package/dist/global/schema/CjsSchema.js.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/resource/CjsResMan.js +47 -7
- package/dist/resource/CjsResMan.js.map +1 -1
- package/dist/resource/Tr2LightProfileRes.js +37 -0
- package/dist/resource/Tr2LightProfileRes.js.map +1 -1
- package/dist/resource/format/CjsByteWriter.js +46 -46
- package/dist/resource/format/CjsByteWriter.js.map +1 -1
- package/dist/resource/format/CjsFormat.js +7 -8
- package/dist/resource/format/CjsFormat.js.map +1 -1
- package/dist/resource/format/CjsFormatStore.js +8 -8
- package/dist/resource/format/CjsFormatStore.js.map +1 -1
- package/dist/resource/format/CjsGeometryFormat.js +114 -0
- package/dist/resource/format/CjsGeometryFormat.js.map +1 -0
- package/dist/resource/format/CjsImageFormat.js +282 -0
- package/dist/resource/format/CjsImageFormat.js.map +1 -0
- package/dist/resource/format/CjsResourceProbe.js +12 -48
- package/dist/resource/format/CjsResourceProbe.js.map +1 -1
- package/dist/resource/format/CjsStringTable.js +37 -37
- package/dist/resource/format/CjsStringTable.js.map +1 -1
- package/dist/resource/format/carbonEffect/CjsCarbonEffectReader.js +10 -10
- package/dist/resource/format/carbonEffect/CjsCarbonEffectReader.js.map +1 -1
- package/dist/resource/format/carbonEffect/CjsCarbonEffectWriter.js +37 -37
- package/dist/resource/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -1
- package/dist/resource/format/carbonEffect/carbonEffectBackendBlock.js +35 -7
- package/dist/resource/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -1
- package/dist/resource/format/index.js +3 -1
- package/dist/resource/format/index.js.map +1 -1
- package/dist/resource/formats/black/CjsBlackFormat.js +130 -137
- package/dist/resource/formats/black/CjsBlackFormat.js.map +1 -1
- package/dist/resource/formats/bnk/CjsBnkFormat.js +12 -19
- package/dist/resource/formats/bnk/CjsBnkFormat.js.map +1 -1
- package/dist/resource/formats/bnk/core/helpers.js +1 -3
- package/dist/resource/formats/bnk/core/helpers.js.map +1 -1
- package/dist/resource/formats/cmf/CjsCmfFormat.js +19 -82
- package/dist/resource/formats/cmf/CjsCmfFormat.js.map +1 -1
- package/dist/resource/formats/cmf/core/constants.js +1 -2
- package/dist/resource/formats/cmf/core/constants.js.map +1 -1
- package/dist/resource/formats/{stl/core/targets.js → cmf/core/flatShared.js} +9 -8
- package/dist/resource/formats/cmf/core/flatShared.js.map +1 -0
- package/dist/resource/formats/cmf/core/helpers.js +13 -13
- package/dist/resource/formats/cmf/core/helpers.js.map +1 -1
- package/dist/resource/formats/cmf/core/writer.js +24 -24
- package/dist/resource/formats/cmf/core/writer.js.map +1 -1
- package/dist/resource/formats/dds/CjsDdsFormat.js +134 -17
- package/dist/resource/formats/dds/CjsDdsFormat.js.map +1 -1
- package/dist/resource/formats/dds/core/helpers.js +125 -40
- package/dist/resource/formats/dds/core/helpers.js.map +1 -1
- package/dist/resource/formats/dxbc/CjsDxbcFormat.js +14 -16
- package/dist/resource/formats/dxbc/CjsDxbcFormat.js.map +1 -1
- package/dist/resource/formats/dxbc/core/{container.js → DxbcContainer.js} +2 -2
- package/dist/resource/formats/dxbc/core/DxbcContainer.js.map +1 -0
- package/dist/resource/formats/dxbc/core/{errors.js → DxbcReadError.js} +1 -1
- package/dist/resource/formats/dxbc/core/DxbcReadError.js.map +1 -0
- package/dist/resource/formats/dxbc/core/DxbcReader.js +1 -1
- package/dist/resource/formats/dxbc/core/DxbcReader.js.map +1 -1
- package/dist/resource/formats/dxbc/core/{program.js → DxbcShaderProgram.js} +2 -2
- package/dist/resource/formats/dxbc/core/DxbcShaderProgram.js.map +1 -0
- package/dist/resource/formats/dxbc/core/{signature.js → DxbcSignatureChunk.js} +2 -2
- package/dist/resource/formats/dxbc/core/DxbcSignatureChunk.js.map +1 -0
- package/dist/resource/formats/dxbc/core/decoder.js +2 -2
- package/dist/resource/formats/dxbc/core/decoder.js.map +1 -1
- package/dist/resource/formats/dxbc/core/helpers.js +3 -3
- package/dist/resource/formats/dxbc/core/helpers.js.map +1 -1
- package/dist/resource/formats/fbx/CjsFbxFormat.js +18 -20
- package/dist/resource/formats/fbx/CjsFbxFormat.js.map +1 -1
- package/dist/resource/formats/flac/CjsFlacFormat.js +7 -13
- package/dist/resource/formats/flac/CjsFlacFormat.js.map +1 -1
- package/dist/resource/formats/fsd/32/CjsFsd32Format.js +29 -29
- package/dist/resource/formats/fsd/32/CjsFsd32Format.js.map +1 -1
- package/dist/resource/formats/fsd/64/CjsFsd64Format.js +3 -3
- package/dist/resource/formats/fsd/64/CjsFsd64Format.js.map +1 -1
- package/dist/resource/formats/fsd/64/core/CjsFsd64Binary.js +23 -23
- package/dist/resource/formats/fsd/64/core/CjsFsd64Binary.js.map +1 -1
- package/dist/resource/formats/fsd/64/core/CjsFsd64Reader.js +8 -8
- package/dist/resource/formats/fsd/64/core/CjsFsd64Reader.js.map +1 -1
- package/dist/resource/formats/fsd/CjsFsdFormat.js +23 -23
- package/dist/resource/formats/fsd/CjsFsdFormat.js.map +1 -1
- package/dist/resource/formats/gif/CjsGifFormat.js +24 -15
- package/dist/resource/formats/gif/CjsGifFormat.js.map +1 -1
- package/dist/resource/formats/gltf/CjsGltfFormat.js +33 -98
- package/dist/resource/formats/gltf/CjsGltfFormat.js.map +1 -1
- package/dist/resource/formats/gltf/core/helpers.js +3 -12
- package/dist/resource/formats/gltf/core/helpers.js.map +1 -1
- package/dist/resource/formats/gr2/CjsGr2Format.js +27 -91
- package/dist/resource/formats/gr2/CjsGr2Format.js.map +1 -1
- package/dist/resource/formats/hlsl/CjsHlslFormat.js +22 -25
- package/dist/resource/formats/hlsl/CjsHlslFormat.js.map +1 -1
- package/dist/resource/formats/hlsl/core/carbonDescriptionToRuntime.js +1 -1
- package/dist/resource/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -1
- package/dist/resource/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js +3 -3
- package/dist/resource/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js.map +1 -1
- package/dist/resource/formats/ies/CjsIESFormat.js +29 -29
- package/dist/resource/formats/ies/CjsIESFormat.js.map +1 -1
- package/dist/resource/formats/jpeg/CjsJpegFormat.js +24 -15
- package/dist/resource/formats/jpeg/CjsJpegFormat.js.map +1 -1
- package/dist/resource/formats/jpeg/core/helpers.js +3 -5
- package/dist/resource/formats/jpeg/core/helpers.js.map +1 -1
- package/dist/resource/formats/jpeg/core/jpeg.js +58 -58
- package/dist/resource/formats/jpeg/core/jpeg.js.map +1 -1
- package/dist/resource/formats/jsonl/CjsJsonlFormat.js +3 -3
- package/dist/resource/formats/jsonl/CjsJsonlFormat.js.map +1 -1
- package/dist/resource/formats/mp3/CjsMp3Format.js +7 -14
- package/dist/resource/formats/mp3/CjsMp3Format.js.map +1 -1
- package/dist/resource/formats/mp3/core/helpers.js +3 -5
- package/dist/resource/formats/mp3/core/helpers.js.map +1 -1
- package/dist/resource/formats/mp4/CjsMp4Format.js +7 -13
- package/dist/resource/formats/mp4/CjsMp4Format.js.map +1 -1
- package/dist/resource/formats/mp4/core/helpers.js +3 -5
- package/dist/resource/formats/mp4/core/helpers.js.map +1 -1
- package/dist/resource/formats/obj/CjsObjFormat.js +92 -157
- package/dist/resource/formats/obj/CjsObjFormat.js.map +1 -1
- package/dist/resource/formats/obj/core/helpers.js +5 -113
- package/dist/resource/formats/obj/core/helpers.js.map +1 -1
- package/dist/resource/formats/ogg/CjsOggFormat.js +7 -14
- package/dist/resource/formats/ogg/CjsOggFormat.js.map +1 -1
- package/dist/resource/formats/pickle/CjsPickleFormat.js +7 -12
- package/dist/resource/formats/pickle/CjsPickleFormat.js.map +1 -1
- package/dist/resource/formats/pickle/core/CjsPickleProtocol0Reader.js +7 -7
- package/dist/resource/formats/pickle/core/CjsPickleProtocol0Reader.js.map +1 -1
- package/dist/resource/formats/pickle/core/CjsPickleProtocol4Reader.js +7 -7
- package/dist/resource/formats/pickle/core/CjsPickleProtocol4Reader.js.map +1 -1
- package/dist/resource/formats/png/CjsPngFormat.js +40 -15
- package/dist/resource/formats/png/CjsPngFormat.js.map +1 -1
- package/dist/resource/formats/png/core/helpers.js +4 -6
- package/dist/resource/formats/png/core/helpers.js.map +1 -1
- package/dist/resource/formats/red/CjsRedFormat.js +22 -28
- package/dist/resource/formats/red/CjsRedFormat.js.map +1 -1
- package/dist/resource/formats/schemabound/CjsSchemaBoundFormat.js +3 -7
- package/dist/resource/formats/schemabound/CjsSchemaBoundFormat.js.map +1 -1
- package/dist/resource/formats/schemabound/core/schemaBoundValues.js +5 -0
- package/dist/resource/formats/schemabound/core/schemaBoundValues.js.map +1 -1
- package/dist/resource/formats/sqlite/CjsSqliteFormat.js +4 -9
- package/dist/resource/formats/sqlite/CjsSqliteFormat.js.map +1 -1
- package/dist/resource/formats/static/CjsStaticFormat.js +4 -4
- package/dist/resource/formats/static/CjsStaticFormat.js.map +1 -1
- package/dist/resource/formats/stl/CjsStlFormat.js +39 -104
- package/dist/resource/formats/stl/CjsStlFormat.js.map +1 -1
- package/dist/resource/formats/stl/core/helpers.js +5 -19
- package/dist/resource/formats/stl/core/helpers.js.map +1 -1
- package/dist/resource/formats/tga/CjsTgaFormat.js +26 -15
- package/dist/resource/formats/tga/CjsTgaFormat.js.map +1 -1
- package/dist/resource/formats/tga/core/helpers.js +3 -5
- package/dist/resource/formats/tga/core/helpers.js.map +1 -1
- package/dist/resource/formats/vta/CjsVtaFormat.js +8 -15
- package/dist/resource/formats/vta/CjsVtaFormat.js.map +1 -1
- package/dist/resource/formats/wav/CjsWavFormat.js +7 -14
- package/dist/resource/formats/wav/CjsWavFormat.js.map +1 -1
- package/dist/resource/formats/wav/core/helpers.js +3 -5
- package/dist/resource/formats/wav/core/helpers.js.map +1 -1
- package/dist/resource/formats/webgl/CjsWebglFormat.js +103 -105
- package/dist/resource/formats/webgl/CjsWebglFormat.js.map +1 -1
- package/dist/resource/formats/webgl/core/{errors.js → WebglReadError.js} +1 -1
- package/dist/resource/formats/webgl/core/WebglReadError.js.map +1 -0
- package/dist/resource/formats/webgl/core/effectPackage.js +1 -1
- package/dist/resource/formats/webgl/core/effectPackage.js.map +1 -1
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslEmitter.js +3 -3
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -1
- package/dist/resource/formats/webgl/core/glsl/{DxbcGlslHelpers.js → DxbcGlslHelperRegistry.js} +2 -2
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslHelperRegistry.js.map +1 -0
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js +1 -1
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js.map +1 -1
- package/dist/resource/formats/webgl/core/glslBackendBlock.js +1 -1
- package/dist/resource/formats/webgl/core/glslBackendBlock.js.map +1 -1
- package/dist/resource/formats/webgl/core/helpers.js.map +1 -1
- package/dist/resource/formats/webgpu/CjsWebgpuFormat.js +28 -29
- package/dist/resource/formats/webgpu/CjsWebgpuFormat.js.map +1 -1
- package/dist/resource/formats/webgpu/core/{errors.js → WebgpuReadError.js} +1 -1
- package/dist/resource/formats/webgpu/core/WebgpuReadError.js.map +1 -0
- package/dist/resource/formats/webgpu/core/carbonWebgpu/validateContainer.js +1 -1
- package/dist/resource/formats/webgpu/core/carbonWebgpu/validateContainer.js.map +1 -1
- package/dist/resource/formats/webgpu/core/helpers.js +1 -1
- package/dist/resource/formats/webgpu/core/helpers.js.map +1 -1
- package/dist/resource/formats/webgpu/core/ir/lowerDxbcToIr.js +1 -1
- package/dist/resource/formats/webgpu/core/ir/lowerDxbcToIr.js.map +1 -1
- package/dist/resource/formats/webgpu/core/wgsl/buildWgslSet.js +18 -6
- package/dist/resource/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -1
- package/dist/resource/formats/webgpu/core/wgsl/lowerBindingLayout.js +39 -13
- package/dist/resource/formats/webgpu/core/wgsl/lowerBindingLayout.js.map +1 -1
- package/dist/resource/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js +16 -14
- package/dist/resource/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js.map +1 -1
- package/dist/resource/formats/webm/CjsWebmFormat.js +8 -13
- package/dist/resource/formats/webm/CjsWebmFormat.js.map +1 -1
- package/dist/resource/formats/webm/core/helpers.js +3 -5
- package/dist/resource/formats/webm/core/helpers.js.map +1 -1
- package/dist/resource/formats/webp/CjsWebpFormat.js +8 -12
- package/dist/resource/formats/webp/CjsWebpFormat.js.map +1 -1
- package/dist/resource/formats/wem/CjsWemFormat.js +9 -17
- package/dist/resource/formats/wem/CjsWemFormat.js.map +1 -1
- package/dist/resource/formats/wem/core/bitStream.js +35 -35
- package/dist/resource/formats/wem/core/bitStream.js.map +1 -1
- package/dist/resource/formats/wem/core/helpers.js +1 -3
- package/dist/resource/formats/wem/core/helpers.js.map +1 -1
- package/dist/resource/formats/yaml/CjsYamlFormat.js +28 -37
- package/dist/resource/formats/yaml/CjsYamlFormat.js.map +1 -1
- package/dist/resource/imageio/ImageIO.js +142 -0
- package/dist/resource/imageio/ImageIO.js.map +1 -0
- package/dist/resource/imageio/index.js +17 -0
- package/dist/resource/imageio/index.js.map +1 -0
- package/dist/resource/index.js +7 -0
- package/dist/resource/index.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +24 -2
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +76 -5
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/texture/CjsTextureArrayConstructor.js +97 -0
- package/dist/resource/texture/CjsTextureArrayConstructor.js.map +1 -0
- package/dist/resource/texture/CjsTexturePackConstructor.js +160 -0
- package/dist/resource/texture/CjsTexturePackConstructor.js.map +1 -0
- package/dist/resource/texture/CjsTexturePipelineStepArray.js +72 -0
- package/dist/resource/texture/CjsTexturePipelineStepArray.js.map +1 -0
- package/dist/resource/texture/CjsTexturePipelineStepConvert.js +73 -0
- package/dist/resource/texture/CjsTexturePipelineStepConvert.js.map +1 -0
- package/dist/resource/texture/CjsTexturePipelineStepPack.js +71 -0
- package/dist/resource/texture/CjsTexturePipelineStepPack.js.map +1 -0
- package/dist/resource/texture/CjsTexturePipelineStepResize.js +123 -0
- package/dist/resource/texture/CjsTexturePipelineStepResize.js.map +1 -0
- package/dist/resource/texture/SolidColorTextureConstructor.js +11 -1
- package/dist/resource/texture/SolidColorTextureConstructor.js.map +1 -1
- package/dist/resource/texture/Tr2ImageRes.js +100 -68
- package/dist/resource/texture/Tr2ImageRes.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipeline.js +45 -25
- package/dist/resource/texture/Tr2TexturePipeline.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipelineStepCompress.js +34 -1
- package/dist/resource/texture/Tr2TexturePipelineStepCompress.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipelineStepGenerateMips.js +30 -3
- package/dist/resource/texture/Tr2TexturePipelineStepGenerateMips.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipelineStepLimitSize.js +81 -1
- package/dist/resource/texture/Tr2TexturePipelineStepLimitSize.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipelineStepLoad.js +36 -1
- package/dist/resource/texture/Tr2TexturePipelineStepLoad.js.map +1 -1
- package/dist/resource/texture/Tr2TexturePipelineStepPack.js +146 -24
- package/dist/resource/texture/Tr2TexturePipelineStepPack.js.map +1 -1
- package/dist/resource/texture/TriTextureRes.js +151 -29
- package/dist/resource/texture/TriTextureRes.js.map +1 -1
- package/dist/resource/texture/index.js +7 -0
- package/dist/resource/texture/index.js.map +1 -1
- package/dist/resource/texture/registerTextureResources.js +83 -0
- package/dist/resource/texture/registerTextureResources.js.map +1 -0
- package/dist/resource/texture/solidColorTexture.js +10 -19
- package/dist/resource/texture/solidColorTexture.js.map +1 -1
- package/dist/sof/EveSOF.js +39 -7
- package/dist/sof/EveSOF.js.map +1 -1
- package/dist/trinity/core/Tr2GpuResourcePool/Tr2GpuResourcePool.js +2 -2
- package/dist/trinity/core/Tr2GpuResourcePool/Tr2GpuResourcePool.js.map +1 -1
- package/dist/trinity/core/Tr2ImageIOHelpers.js +80 -17
- package/dist/trinity/core/Tr2ImageIOHelpers.js.map +1 -1
- package/dist/trinity/core/Tr2RenderUtils.js +1 -1
- package/dist/trinity/core/Tr2TextureArray/Tr2TextureArray.js +49 -62
- package/dist/trinity/core/Tr2TextureArray/Tr2TextureArray.js.map +1 -1
- package/dist/trinity/core/Tr2TextureReference.js +114 -0
- package/dist/trinity/core/Tr2TextureReference.js.map +1 -0
- package/dist/trinity/core/device/Tr2DepthStencil.js +2 -2
- package/dist/trinity/core/device/Tr2DepthStencil.js.map +1 -1
- package/dist/trinity/core/device/Tr2RingBuffer/Tr2RingBuffer.js +1 -1
- package/dist/trinity/core/index.js +1 -0
- package/dist/trinity/core/index.js.map +1 -1
- package/dist/trinity/core/lighting/Tr2LightManager.js +5 -4
- package/dist/trinity/core/lighting/Tr2LightManager.js.map +1 -1
- package/dist/trinity/core/procedural/GradientTextureConstructor.js +5 -4
- package/dist/trinity/core/procedural/GradientTextureConstructor.js.map +1 -1
- package/dist/trinity/core/procedural/gradientTexture.js +10 -13
- package/dist/trinity/core/procedural/gradientTexture.js.map +1 -1
- package/dist/trinity/core/volumetrics/Tr2VolumetricsRenderer.js +1 -1
- package/dist/trinity/core/volumetrics/Tr2VolumetricsRenderer.js.map +1 -1
- package/dist/trinity/eve/EveImpactOverlay.js +102 -50
- package/dist/trinity/eve/EveImpactOverlay.js.map +1 -1
- package/dist/trinity/eve/EveModularObjectModifier.js +9 -18
- package/dist/trinity/eve/EveModularObjectModifier.js.map +1 -1
- package/dist/trinity/eve/attachment/turrets/EveTurretSet.js +175 -157
- package/dist/trinity/eve/attachment/turrets/EveTurretSet.js.map +1 -1
- package/dist/trinity/eve/attachment/turrets/EveTurretTarget.js +100 -83
- package/dist/trinity/eve/attachment/turrets/EveTurretTarget.js.map +1 -1
- package/dist/trinity/eve/child/EveChildInstancedMeshes/EveChildInstancedMesh.js +26 -20
- package/dist/trinity/eve/child/EveChildInstancedMeshes/EveChildInstancedMesh.js.map +1 -1
- package/dist/trinity/eve/child/EveChildInstancedMeshes/EveChildInstancedMeshes.js +368 -179
- package/dist/trinity/eve/child/EveChildInstancedMeshes/EveChildInstancedMeshes.js.map +1 -1
- package/dist/trinity/eve/child/EveChildMesh.js +242 -234
- package/dist/trinity/eve/child/EveChildMesh.js.map +1 -1
- package/dist/trinity/eve/child/EveChildTurret.js +57 -16
- package/dist/trinity/eve/child/EveChildTurret.js.map +1 -1
- package/dist/trinity/eve/child/EveSpaceObjectChild.js +28 -1
- package/dist/trinity/eve/child/EveSpaceObjectChild.js.map +1 -1
- package/dist/trinity/eve/index.js +2 -2
- package/dist/trinity/eve/overlays/EveDamageOverlay.js +5 -1
- package/dist/trinity/eve/overlays/EveDamageOverlay.js.map +1 -1
- package/dist/trinity/eve/scene/EveSpaceScene.js +234 -233
- package/dist/trinity/eve/scene/EveSpaceScene.js.map +1 -1
- package/dist/trinity/eve/scene/EveSpaceSceneRenderDriver.js +2 -0
- package/dist/trinity/eve/scene/EveSpaceSceneRenderDriver.js.map +1 -1
- package/dist/trinity/eve/spaceObject/EveSpaceObject2.js +492 -437
- package/dist/trinity/eve/spaceObject/EveSpaceObject2.js.map +1 -1
- package/dist/trinity/generated/index.js +0 -1
- package/dist/trinity/generated/index.js.map +1 -1
- package/dist/trinity/generated/trinityCore/index.js +0 -1
- package/dist/trinity/generated/trinityCore/index.js.map +1 -1
- package/dist/trinity/index.js +3 -3
- package/dist/trinity/particle/emitter/Tr2GpuSharedEmitter.js +10 -1
- package/dist/trinity/particle/emitter/Tr2GpuSharedEmitter.js.map +1 -1
- package/dist/trinity/shader/Tr2DataTextureManager.js +152 -66
- package/dist/trinity/shader/Tr2DataTextureManager.js.map +1 -1
- package/dist/trinity/shader/Tr2Material.js +1 -1
- package/dist/trinityal/Tr2HalHelperStructures/Tr2TextureSubresource.js +5 -5
- package/dist/trinityal/Tr2HalHelperStructures/Tr2TextureSubresource.js.map +1 -1
- package/dist/trinityal/index.js +1 -1
- package/dist/trinityal/stub/Tr2RenderContextALStub/Tr2RenderContextALStub.js +2 -2
- package/dist/trinityal/stub/Tr2RenderContextALStub/Tr2RenderContextALStub.js.map +1 -1
- package/dist/trinityal/stub/Tr2SwapChainALStub.js +45 -45
- package/dist/trinityal/stub/Tr2SwapChainALStub.js.map +1 -1
- package/dist/trinityal/stub/Tr2TextureALStub.js +170 -170
- package/dist/trinityal/stub/Tr2TextureALStub.js.map +1 -1
- package/dist/trinityal/webgpu/CjsWebgpuDevice.js +234 -164
- package/dist/trinityal/webgpu/CjsWebgpuDevice.js.map +1 -1
- package/dist/trinityal/webgpu/CjsWebgpuRenderContextAL.js +7 -0
- package/dist/trinityal/webgpu/CjsWebgpuRenderContextAL.js.map +1 -1
- package/dist/trinityal/webgpu/CjsWebgpuTextureAL.js +78 -14
- package/dist/trinityal/webgpu/CjsWebgpuTextureAL.js.map +1 -1
- package/dist/trinityal/webgpu/core/CjsWebgpuUtils.js +94 -0
- package/dist/trinityal/webgpu/core/CjsWebgpuUtils.js.map +1 -0
- package/dist/trinityal/webgpu/internal.js +1 -0
- package/dist/trinityal/webgpu/internal.js.map +1 -1
- package/docs/global/reference/classes/README.md +90 -0
- package/docs/resource/concepts/format-capabilities.md +3 -3
- package/docs/resource/formats/README.md +1 -1
- package/docs/resource/reference/classes/core.md +31 -1
- package/docs/resource/reference/classes/formats.md +7 -7
- package/docs/resource/reference/classes/resources.md +76 -16
- package/docs/trinity/reference/classes/generated.md +0 -10
- package/docs/trinity/reference/classes/trinity-core.md +1692 -1682
- package/docs/trinityal/reference/classes/README.md +0 -10
- package/docs/trinityal/webgpu/reference/classes/README.md +276 -266
- package/package.json +4 -3
- package/dist/global/consts/webgpu/index.js +0 -2
- package/dist/global/consts/webgpu/textureFormats.js +0 -180
- package/dist/global/consts/webgpu/textureFormats.js.map +0 -1
- package/dist/resource/formats/dxbc/core/container.js.map +0 -1
- package/dist/resource/formats/dxbc/core/errors.js.map +0 -1
- package/dist/resource/formats/dxbc/core/program.js.map +0 -1
- package/dist/resource/formats/dxbc/core/signature.js.map +0 -1
- package/dist/resource/formats/stl/core/targets.js.map +0 -1
- package/dist/resource/formats/webgl/core/errors.js.map +0 -1
- package/dist/resource/formats/webgl/core/glsl/DxbcGlslHelpers.js.map +0 -1
- package/dist/resource/formats/webgpu/core/errors.js.map +0 -1
- package/dist/resource/texture/texturePipelineBehavior.js +0 -332
- package/dist/resource/texture/texturePipelineBehavior.js.map +0 -1
- package/dist/trinity/generated/trinityCore/Tr2TextureReference.js +0 -40
- package/dist/trinity/generated/trinityCore/Tr2TextureReference.js.map +0 -1
- package/dist/trinityal/Tr2BitmapDimensions.js.map +0 -1
|
@@ -0,0 +1,1106 @@
|
|
|
1
|
+
import { CjsSchema } from '#schema';
|
|
2
|
+
import { PixelFormat, IsCompressedFormat, TextureType, GetBytesPerPixel, GetBlockByteSize } from '../consts/renderContext/formats.js';
|
|
3
|
+
import '../consts/renderContext/pipeline.js';
|
|
4
|
+
import { BitmapDimensions } from './BitmapDimensions.js';
|
|
5
|
+
import { ImageUtility } from './ImageUtility.js';
|
|
6
|
+
|
|
7
|
+
// Source: imageio/include/HostBitmap.h
|
|
8
|
+
// Source: imageio/HostBitmap.cpp
|
|
9
|
+
//
|
|
10
|
+
// Carbon's CPU-side image: a `BitmapDimensions` plus the bytes it describes.
|
|
11
|
+
// It is what image data travels in between a reader and a texture - the image
|
|
12
|
+
// handlers fill one, the texture pipeline steps pass it along, and the upload
|
|
13
|
+
// reads its mips out of it.
|
|
14
|
+
//
|
|
15
|
+
// LAYOUT (HostBitmap.cpp:11-40, 437-470). Array-element-major: each array
|
|
16
|
+
// element (each cube face) holds its whole mip chain, level 0 first, and
|
|
17
|
+
// element k starts at `k * size / arraySize`. There is no padding; the pitch of
|
|
18
|
+
// an uncompressed level is width * bytes-per-pixel. A compressed level rounds
|
|
19
|
+
// each dimension up to a whole 4x4 block, never below one block.
|
|
20
|
+
//
|
|
21
|
+
// JAVASCRIPT DIFFERENCES, each marked `adapted:` at its site:
|
|
22
|
+
// - `m_data` is a Uint8Array, and a raw pointer becomes a view into it
|
|
23
|
+
// (`subarray`) that runs to the end of the buffer, as the pointer does.
|
|
24
|
+
// - Out-parameters (`GetAverageColor`, `GetPixel`) return an object, or null
|
|
25
|
+
// where Carbon returns false.
|
|
26
|
+
// - Carbon's move constructor and move assignment become `Swap`.
|
|
27
|
+
// - No logging facility is ported; each CCP_LOG call is kept as a comment
|
|
28
|
+
// with its message, and the failure is reported by the return value alone.
|
|
29
|
+
//
|
|
30
|
+
// CARBON'S DEFECTS ARE FIXED, NOT REPRODUCED (operator, 2026-09-22: fix the
|
|
31
|
+
// image-io defects in our library and report them upstream). Each fix is marked
|
|
32
|
+
// `diverged:` with its issue number in /docs/research/carbon-imageio-issue.md. Behaviour
|
|
33
|
+
// that is Carbon's design rather than a defect is kept and marked `quirk:`.
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Bytes needed for a description's whole mip chain times its array size
|
|
37
|
+
* (the anonymous-namespace `GetDataSize`, HostBitmap.cpp:11-40).
|
|
38
|
+
*
|
|
39
|
+
* @param {BitmapDimensions} dim Description.
|
|
40
|
+
* @returns {number} Byte size.
|
|
41
|
+
*/
|
|
42
|
+
function GetDataSize(dim) {
|
|
43
|
+
let mipCount = dim.GetTrueMipCount();
|
|
44
|
+
let width = dim.GetWidth();
|
|
45
|
+
let height = dim.GetHeight();
|
|
46
|
+
let depth = dim.GetType() === TextureType.TEX_TYPE_3D ? dim.GetDepth() : 1;
|
|
47
|
+
let size = 0;
|
|
48
|
+
if (IsCompressedFormat(dim.GetFormat())) {
|
|
49
|
+
const blockBytes = GetBlockByteSize(dim.GetFormat());
|
|
50
|
+
while (mipCount-- > 0) {
|
|
51
|
+
size += Math.floor(Math.max(width + 3 & -4, 4) * Math.max(height + 3 & -4, 4) * depth * blockBytes / 16);
|
|
52
|
+
width = Math.max(Math.floor(width / 2), 1);
|
|
53
|
+
height = Math.max(Math.floor(height / 2), 1);
|
|
54
|
+
depth = Math.max(Math.floor(depth / 2), 1);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
const bpp = GetBytesPerPixel(dim.GetFormat());
|
|
58
|
+
while (mipCount-- > 0) {
|
|
59
|
+
size += width * height * depth * bpp;
|
|
60
|
+
width = Math.max(Math.floor(width / 2), 1);
|
|
61
|
+
height = Math.max(Math.floor(height / 2), 1);
|
|
62
|
+
depth = Math.max(Math.floor(depth / 2), 1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return size * dim.GetArraySize();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** The 8-bit-per-channel formats Downsample2x2 and GenerateMipMaps accept (HostBitmap.cpp:653-676, 1044-1072). */
|
|
69
|
+
const EIGHT_BIT_FORMATS = new Set([PixelFormat.PIXEL_FORMAT_R8G8B8A8_TYPELESS, PixelFormat.PIXEL_FORMAT_R8G8B8A8_UNORM, PixelFormat.PIXEL_FORMAT_R8G8B8A8_UNORM_SRGB, PixelFormat.PIXEL_FORMAT_R8G8B8A8_UINT, PixelFormat.PIXEL_FORMAT_R8G8B8A8_SNORM, PixelFormat.PIXEL_FORMAT_R8G8B8A8_SINT, PixelFormat.PIXEL_FORMAT_R8G8_TYPELESS, PixelFormat.PIXEL_FORMAT_R8G8_UNORM, PixelFormat.PIXEL_FORMAT_R8G8_UINT, PixelFormat.PIXEL_FORMAT_R8G8_SNORM, PixelFormat.PIXEL_FORMAT_R8G8_SINT, PixelFormat.PIXEL_FORMAT_R8_TYPELESS, PixelFormat.PIXEL_FORMAT_R8_UNORM, PixelFormat.PIXEL_FORMAT_R8_UINT, PixelFormat.PIXEL_FORMAT_R8_SNORM, PixelFormat.PIXEL_FORMAT_R8_SINT, PixelFormat.PIXEL_FORMAT_A8_UNORM, PixelFormat.PIXEL_FORMAT_B8G8R8A8_UNORM, PixelFormat.PIXEL_FORMAT_B8G8R8X8_UNORM, PixelFormat.PIXEL_FORMAT_B8G8R8A8_TYPELESS, PixelFormat.PIXEL_FORMAT_B8G8R8A8_UNORM_SRGB, PixelFormat.PIXEL_FORMAT_B8G8R8X8_TYPELESS, PixelFormat.PIXEL_FORMAT_B8G8R8X8_UNORM_SRGB]);
|
|
70
|
+
const EMPTY = new Uint8Array(0);
|
|
71
|
+
|
|
72
|
+
/** `ImageIO::HostBitmap` - a texture description and its CPU bytes. */
|
|
73
|
+
class HostBitmap extends BitmapDimensions {
|
|
74
|
+
/** m_name - never set by Carbon; only swapped by the moves. */
|
|
75
|
+
_name = "";
|
|
76
|
+
|
|
77
|
+
/** m_data - the bytes; empty means invalid. */
|
|
78
|
+
_data = EMPTY;
|
|
79
|
+
|
|
80
|
+
/** HostBitmap() (HostBitmap.cpp:47-49): an empty, invalid bitmap. */
|
|
81
|
+
constructor() {
|
|
82
|
+
super();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Resize `_data`, keeping the prefix, as `CcpMallocBuffer::resize` does.
|
|
87
|
+
*
|
|
88
|
+
* @param {number} size New byte size.
|
|
89
|
+
*/
|
|
90
|
+
_Resize(size) {
|
|
91
|
+
if (size === this._data.length) return;
|
|
92
|
+
const next = new Uint8Array(size);
|
|
93
|
+
next.set(size < this._data.length ? this._data.subarray(0, size) : this._data);
|
|
94
|
+
this._data = next;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Exchange everything with another bitmap.
|
|
99
|
+
*
|
|
100
|
+
* adapted: Carbon's move assignment (HostBitmap.cpp:63-69) swaps the
|
|
101
|
+
* dimensions, name and data; `std::swap(HostBitmap, HostBitmap)` does the
|
|
102
|
+
* same through it (Tr2TexturePipelineStepLimitSize). JavaScript has no moves,
|
|
103
|
+
* so the swap is named.
|
|
104
|
+
*
|
|
105
|
+
* @param {HostBitmap} other The bitmap to exchange with.
|
|
106
|
+
* @returns {HostBitmap} This bitmap.
|
|
107
|
+
*/
|
|
108
|
+
Swap(other) {
|
|
109
|
+
for (const key of ["_width", "_height", "_depth", "_mipCount", "_arraySize", "_type", "_format", "_name", "_data"]) {
|
|
110
|
+
const value = this[key];
|
|
111
|
+
this[key] = other[key];
|
|
112
|
+
other[key] = value;
|
|
113
|
+
}
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A 2D bitmap with one array element (HostBitmap.cpp:71-110).
|
|
119
|
+
*
|
|
120
|
+
* @param {number} width Width of mip 0.
|
|
121
|
+
* @param {number} height Height of mip 0.
|
|
122
|
+
* @param {number} mipCount Mip count; 0 means the full chain.
|
|
123
|
+
* @param {number} format A `PixelFormat` value.
|
|
124
|
+
* @returns {boolean} Whether it was created.
|
|
125
|
+
*/
|
|
126
|
+
Create(width, height, mipCount, format) {
|
|
127
|
+
this.Destroy();
|
|
128
|
+
if (!width || !height || format >= PixelFormat.PIXEL_FORMAT_SENTINEL) {
|
|
129
|
+
// Carbon: CCP_LOGWARN("HostBitmap::Create invalid parameters: %d x %d, %d mips, format %d")
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (IsCompressedFormat(format) && (width % 4 !== 0 || height % 4 !== 0)) {
|
|
133
|
+
// Carbon: CCP_LOGWARN("HostBitmap::Create invalid compressed size: %d x %d")
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
this._width = width;
|
|
137
|
+
this._height = height;
|
|
138
|
+
this._depth = 1;
|
|
139
|
+
this._format = format;
|
|
140
|
+
this._mipCount = mipCount;
|
|
141
|
+
this._arraySize = 1;
|
|
142
|
+
this._type = TextureType.TEX_TYPE_2D;
|
|
143
|
+
this._data = new Uint8Array(GetDataSize(this));
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* A 2D array bitmap (HostBitmap.cpp:112-151).
|
|
149
|
+
*
|
|
150
|
+
* @param {number} width Width of mip 0.
|
|
151
|
+
* @param {number} height Height of mip 0.
|
|
152
|
+
* @param {number} mipCount Mip count; 0 means the full chain.
|
|
153
|
+
* @param {number} arraySize Array elements.
|
|
154
|
+
* @param {number} format A `PixelFormat` value.
|
|
155
|
+
* @returns {boolean} Whether it was created.
|
|
156
|
+
*/
|
|
157
|
+
Create2DArray(width, height, mipCount, arraySize, format) {
|
|
158
|
+
this.Destroy();
|
|
159
|
+
if (!width || !height || !arraySize || format >= PixelFormat.PIXEL_FORMAT_SENTINEL) {
|
|
160
|
+
// Carbon: CCP_LOGWARN("HostBitmap::Create2DArray invalid parameters: %d x %d, %d mips, %d array elements, format %d")
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
if (IsCompressedFormat(format) && (width % 4 !== 0 || height % 4 !== 0)) {
|
|
164
|
+
// Carbon: CCP_LOGWARN("HostBitmap::Create invalid compressed size: %d x %d")
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
this._width = width;
|
|
168
|
+
this._height = height;
|
|
169
|
+
this._depth = 1;
|
|
170
|
+
this._format = format;
|
|
171
|
+
this._mipCount = mipCount;
|
|
172
|
+
this._arraySize = arraySize;
|
|
173
|
+
this._type = TextureType.TEX_TYPE_2D;
|
|
174
|
+
this._data = new Uint8Array(GetDataSize(this));
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* A cube bitmap: six square faces (HostBitmap.cpp:153-182).
|
|
180
|
+
*
|
|
181
|
+
* (Carbon does not check its allocation here, issue 15; a JavaScript
|
|
182
|
+
* allocation throws instead of returning null.)
|
|
183
|
+
*
|
|
184
|
+
* @param {number} width Face width and height.
|
|
185
|
+
* @param {number} mipCount Mip count; 0 means the full chain.
|
|
186
|
+
* @param {number} format A `PixelFormat` value.
|
|
187
|
+
* @returns {boolean} Whether it was created.
|
|
188
|
+
*/
|
|
189
|
+
CreateCube(width, mipCount, format) {
|
|
190
|
+
this.Destroy();
|
|
191
|
+
if (!width || format >= PixelFormat.PIXEL_FORMAT_SENTINEL) return false;
|
|
192
|
+
if (IsCompressedFormat(format) && width % 4 !== 0) return false;
|
|
193
|
+
this._width = width;
|
|
194
|
+
this._height = width;
|
|
195
|
+
this._depth = 1;
|
|
196
|
+
this._format = format;
|
|
197
|
+
this._mipCount = mipCount;
|
|
198
|
+
this._type = TextureType.TEX_TYPE_CUBE;
|
|
199
|
+
this._arraySize = 6;
|
|
200
|
+
this._data = new Uint8Array(GetDataSize(this));
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A volume bitmap (HostBitmap.cpp:184-213).
|
|
206
|
+
*
|
|
207
|
+
* diverged: height and depth are validated; Carbon checks width only (issue 15).
|
|
208
|
+
*
|
|
209
|
+
* @param {number} width Width of mip 0.
|
|
210
|
+
* @param {number} height Height of mip 0.
|
|
211
|
+
* @param {number} depth Depth of mip 0.
|
|
212
|
+
* @param {number} mipCount Mip count; 0 means the full chain.
|
|
213
|
+
* @param {number} format A `PixelFormat` value.
|
|
214
|
+
* @returns {boolean} Whether it was created.
|
|
215
|
+
*/
|
|
216
|
+
CreateVolume(width, height, depth, mipCount, format) {
|
|
217
|
+
this.Destroy();
|
|
218
|
+
if (!width || !height || !depth || format >= PixelFormat.PIXEL_FORMAT_SENTINEL) return false;
|
|
219
|
+
if (IsCompressedFormat(format) && (width % 4 !== 0 || height % 4 !== 0)) return false;
|
|
220
|
+
this._width = width;
|
|
221
|
+
this._height = height;
|
|
222
|
+
this._depth = depth;
|
|
223
|
+
this._format = format;
|
|
224
|
+
this._mipCount = mipCount;
|
|
225
|
+
this._type = TextureType.TEX_TYPE_3D;
|
|
226
|
+
this._arraySize = 1;
|
|
227
|
+
this._data = new Uint8Array(GetDataSize(this));
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Take a description and allocate its bytes (HostBitmap.cpp:215-228).
|
|
233
|
+
*
|
|
234
|
+
* quirk: unlike the Create family it does not call Destroy() first, and it
|
|
235
|
+
* does not check that a compressed size is a multiple of 4 (217).
|
|
236
|
+
*
|
|
237
|
+
* @param {BitmapDimensions} dimensions Description to copy.
|
|
238
|
+
* @returns {boolean} Whether it was created.
|
|
239
|
+
*/
|
|
240
|
+
CreateFromBitmapDimensions(dimensions) {
|
|
241
|
+
if (dimensions.GetWidth() === 0 || dimensions.GetFormat() === PixelFormat.PIXEL_FORMAT_UNKNOWN) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
this._width = dimensions.GetWidth();
|
|
245
|
+
this._height = dimensions.GetHeight();
|
|
246
|
+
this._depth = dimensions.GetDepth();
|
|
247
|
+
this._mipCount = dimensions.GetMipCount();
|
|
248
|
+
this._arraySize = dimensions.GetArraySize();
|
|
249
|
+
this._type = dimensions.GetType();
|
|
250
|
+
this._format = dimensions.GetFormat();
|
|
251
|
+
this._Resize(GetDataSize(this));
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Whether the bitmap holds data (HostBitmap.cpp:230-233).
|
|
257
|
+
*
|
|
258
|
+
* @returns {boolean} Whether it is valid.
|
|
259
|
+
*/
|
|
260
|
+
IsValid() {
|
|
261
|
+
return this._data.length !== 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Clear the data and invalidate the description (HostBitmap.cpp:235-240).
|
|
266
|
+
* Only the type and format are reset; the sizes are kept, as in Carbon.
|
|
267
|
+
*
|
|
268
|
+
* @returns {void}
|
|
269
|
+
*/
|
|
270
|
+
Destroy() {
|
|
271
|
+
super.Destroy();
|
|
272
|
+
this._data = EMPTY;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Relabel the format without touching the bytes (HostBitmap.cpp:242-255).
|
|
277
|
+
*
|
|
278
|
+
* @param {number} format A `PixelFormat` value of the same byte size.
|
|
279
|
+
* @returns {boolean} Whether the label changed.
|
|
280
|
+
*/
|
|
281
|
+
ChangeFormat(format) {
|
|
282
|
+
if (!this.IsValid()) return false;
|
|
283
|
+
if (IsCompressedFormat(format) || IsCompressedFormat(this._format) || GetBytesPerPixel(format) !== GetBytesPerPixel(this._format)) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
this._format = format;
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Convert the bytes to another format, for the few transitions Carbon
|
|
292
|
+
* supports (HostBitmap.cpp:270-403): BGRA <-> BGRX, BGRA/BGRX -> R8,
|
|
293
|
+
* RGBA8 <-> BGRA/BGRX, R8 -> BGRA/BGRX and R8G8 -> BGRA. Every mip and array
|
|
294
|
+
* element is converted.
|
|
295
|
+
*
|
|
296
|
+
* Compressed formats are refused here, as in Carbon. The browser conversions
|
|
297
|
+
* that decode and encode block formats are layered on top in resource/imageio.
|
|
298
|
+
*
|
|
299
|
+
* @param {number} format A `PixelFormat` value.
|
|
300
|
+
* @returns {boolean} Whether the conversion was done.
|
|
301
|
+
*/
|
|
302
|
+
ConvertFormat(format) {
|
|
303
|
+
if (!this.IsValid()) return false;
|
|
304
|
+
if (format === this._format) return true;
|
|
305
|
+
const F = PixelFormat;
|
|
306
|
+
const current = this._format;
|
|
307
|
+
const isBgra = current === F.PIXEL_FORMAT_B8G8R8A8_UNORM;
|
|
308
|
+
const isBgrx = current === F.PIXEL_FORMAT_B8G8R8X8_UNORM;
|
|
309
|
+
if (format === F.PIXEL_FORMAT_B8G8R8X8_UNORM && isBgra) {
|
|
310
|
+
this._format = format;
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
if (format === F.PIXEL_FORMAT_B8G8R8A8_UNORM && isBgrx) {
|
|
314
|
+
const data = this._data;
|
|
315
|
+
for (let i = 0; i !== data.length; i += 4) {
|
|
316
|
+
data[i + 3] = 0xff;
|
|
317
|
+
}
|
|
318
|
+
this._format = F.PIXEL_FORMAT_B8G8R8A8_UNORM;
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
if (format === F.PIXEL_FORMAT_R8_UNORM && (isBgra || isBgrx)) {
|
|
322
|
+
// diverged: keeps byte 2, red; Carbon keeps byte 0, which is blue in
|
|
323
|
+
// B8G8R8 memory order (HostBitmap.cpp:321-325, issue 6).
|
|
324
|
+
const pixelCount = Math.floor(this._data.length / GetBytesPerPixel(current));
|
|
325
|
+
const src = this._data;
|
|
326
|
+
const dst = new Uint8Array(pixelCount);
|
|
327
|
+
for (let i = 0; i < pixelCount; ++i) {
|
|
328
|
+
dst[i] = src[i * 4 + 2];
|
|
329
|
+
}
|
|
330
|
+
this._data = dst;
|
|
331
|
+
this._format = format;
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
if (format === F.PIXEL_FORMAT_R8G8B8A8_UNORM && (isBgra || isBgrx) || current === F.PIXEL_FORMAT_R8G8B8A8_UNORM && (format === F.PIXEL_FORMAT_B8G8R8A8_UNORM || format === F.PIXEL_FORMAT_B8G8R8X8_UNORM)) {
|
|
335
|
+
// diverged: a BGRX source gets an opaque alpha; Carbon swaps bytes 0 and
|
|
336
|
+
// 2 only and keeps the undefined X byte as alpha (HostBitmap.cpp:332-349,
|
|
337
|
+
// issue 7).
|
|
338
|
+
const data = this._data;
|
|
339
|
+
const bpp = GetBytesPerPixel(current);
|
|
340
|
+
for (let i = 0; i < data.length - 2; i += bpp) {
|
|
341
|
+
const tmp = data[i];
|
|
342
|
+
data[i] = data[i + 2];
|
|
343
|
+
data[i + 2] = tmp;
|
|
344
|
+
if (isBgrx) data[i + 3] = 0xff;
|
|
345
|
+
}
|
|
346
|
+
this._format = format;
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
if (format === F.PIXEL_FORMAT_B8G8R8A8_UNORM && (current === F.PIXEL_FORMAT_R8_UNORM || current === F.PIXEL_FORMAT_R8G8_UNORM) || format === F.PIXEL_FORMAT_B8G8R8X8_UNORM && current === F.PIXEL_FORMAT_R8_UNORM) {
|
|
350
|
+
const pixelCount = Math.floor(this._data.length / GetBytesPerPixel(current));
|
|
351
|
+
const src = this._data;
|
|
352
|
+
const dst = new Uint8Array(pixelCount * 4);
|
|
353
|
+
let s = 0;
|
|
354
|
+
let d = 0;
|
|
355
|
+
if (current === F.PIXEL_FORMAT_R8_UNORM) {
|
|
356
|
+
for (let i = 0; i < pixelCount; ++i) {
|
|
357
|
+
dst[d++] = src[s];
|
|
358
|
+
dst[d++] = src[s];
|
|
359
|
+
dst[d++] = src[s];
|
|
360
|
+
++s;
|
|
361
|
+
dst[d++] = 0xff;
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
for (let i = 0; i < pixelCount; ++i) {
|
|
365
|
+
dst[d++] = src[s];
|
|
366
|
+
dst[d++] = src[s];
|
|
367
|
+
dst[d++] = src[s];
|
|
368
|
+
++s;
|
|
369
|
+
dst[d++] = src[s++];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
this._data = dst;
|
|
373
|
+
this._format = format;
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Whether another description can take this bitmap's data (HostBitmap.cpp:405-435).
|
|
381
|
+
*
|
|
382
|
+
* adapted: Carbon returns bool and writes `alphaConvert` through a
|
|
383
|
+
* reference; JavaScript returns both. Protected in Carbon and unused in
|
|
384
|
+
* imageio.
|
|
385
|
+
*
|
|
386
|
+
* @param {BitmapDimensions} bd Description to compare with.
|
|
387
|
+
* @param {boolean} checkDimensions Whether width and height must match.
|
|
388
|
+
* @param {string} _log Log prefix (no logging is ported).
|
|
389
|
+
* @returns {{match: boolean, alphaConvert: boolean}} The answer.
|
|
390
|
+
*/
|
|
391
|
+
_CheckForMatch(bd, checkDimensions, _log) {
|
|
392
|
+
if (!this.IsValid()) {
|
|
393
|
+
// Carbon: CCP_LOGWARN("%s: invalid source or destination")
|
|
394
|
+
return {
|
|
395
|
+
match: false,
|
|
396
|
+
alphaConvert: false
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
if (checkDimensions && (bd.GetWidth() !== this._width || bd.GetHeight() !== this._height)) {
|
|
400
|
+
// Carbon: CCP_LOGWARN("%s: incompatible size")
|
|
401
|
+
return {
|
|
402
|
+
match: false,
|
|
403
|
+
alphaConvert: false
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Carbon: CCP_LOGWARN("%s: miplevels mismatch, data may be truncated")
|
|
408
|
+
// when the true mip counts differ - a warning only, not a failure.
|
|
409
|
+
|
|
410
|
+
const formatMatch = bd.GetFormat() === this._format;
|
|
411
|
+
const alphaConvert = bd.GetFormat() === PixelFormat.PIXEL_FORMAT_B8G8R8X8_UNORM && this._format === PixelFormat.PIXEL_FORMAT_B8G8R8A8_UNORM;
|
|
412
|
+
if (!formatMatch && !alphaConvert) {
|
|
413
|
+
// Carbon: CCP_LOGWARN("%s: incompatible size/pixelformat")
|
|
414
|
+
return {
|
|
415
|
+
match: false,
|
|
416
|
+
alphaConvert
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
match: true,
|
|
421
|
+
alphaConvert
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* The bytes of one mip of one array element (HostBitmap.cpp:437-470).
|
|
427
|
+
*
|
|
428
|
+
* adapted: returns a view from that mip to the end of the buffer, as the
|
|
429
|
+
* pointer Carbon returns does, or null.
|
|
430
|
+
*
|
|
431
|
+
* quirk: a compressed offset adds `GetMipHeight(i) / 4` block rows per level
|
|
432
|
+
* (448-453), and assumes every array element is `size / arraySize` bytes
|
|
433
|
+
* (Carbon's own comment: "is it safe to assume this?").
|
|
434
|
+
*
|
|
435
|
+
* @param {number} level Mip level.
|
|
436
|
+
* @param {number} [arrayIndex=0] Array element.
|
|
437
|
+
* @returns {Uint8Array|null} View of the mip's bytes onward.
|
|
438
|
+
*/
|
|
439
|
+
GetMipRawData(level, arrayIndex = 0) {
|
|
440
|
+
if (!this.IsValid() || level >= this.GetTrueMipCount()) return null;
|
|
441
|
+
if (arrayIndex >= this.GetArraySize()) return null;
|
|
442
|
+
let offset = 0;
|
|
443
|
+
if (IsCompressedFormat(this._format)) {
|
|
444
|
+
for (let i = 0; i !== level; ++i) {
|
|
445
|
+
offset += Math.floor(this.GetMipHeight(i) / 4) * this.GetMipPitch(i) * Math.max(this._depth >>> i, 1);
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
for (let i = 0; i !== level; ++i) {
|
|
449
|
+
offset += this.GetMipHeight(i) * this.GetMipPitch(i) * Math.max(this._depth >>> i, 1);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (arrayIndex > 0) {
|
|
453
|
+
offset += Math.floor(this._data.length / this.GetArraySize()) * arrayIndex;
|
|
454
|
+
}
|
|
455
|
+
return this._data.subarray(offset);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* The pitch of mip 0 in bytes (HostBitmap.cpp:477-489); for a compressed
|
|
460
|
+
* format, the bytes in one row of blocks.
|
|
461
|
+
*
|
|
462
|
+
* @returns {number} Pitch.
|
|
463
|
+
*/
|
|
464
|
+
GetPitch() {
|
|
465
|
+
if (!this.IsValid()) return 0;
|
|
466
|
+
if (this.IsCompressed()) {
|
|
467
|
+
return Math.floor(this._width * GetBlockByteSize(this._format) / 4);
|
|
468
|
+
}
|
|
469
|
+
return this._width * GetBytesPerPixel(this._format);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* The bytes, or a view from one pixel of mip 0 onward
|
|
474
|
+
* (HostBitmap.cpp:491-522).
|
|
475
|
+
*
|
|
476
|
+
* adapted: Carbon's two overloads - `GetRawData()` and `GetRawData(x, y)` -
|
|
477
|
+
* are one method told apart by argument count.
|
|
478
|
+
*
|
|
479
|
+
* quirk: for a compressed format `y` indexes block rows while `x` advances a
|
|
480
|
+
* quarter block per pixel (517-519); ported as written.
|
|
481
|
+
*
|
|
482
|
+
* @param {number} [x] Column.
|
|
483
|
+
* @param {number} [y] Row.
|
|
484
|
+
* @returns {Uint8Array|null} The bytes, a view into them, or null.
|
|
485
|
+
*/
|
|
486
|
+
GetRawData(x, y) {
|
|
487
|
+
if (!this.IsValid()) return null;
|
|
488
|
+
if (x === undefined) return this._data;
|
|
489
|
+
if (this.IsCompressed()) {
|
|
490
|
+
return this._data.subarray(y * this.GetPitch() + Math.floor(x * GetBlockByteSize(this._format) / 4));
|
|
491
|
+
}
|
|
492
|
+
return this._data.subarray(y * this.GetPitch() + x * GetBytesPerPixel(this._format));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* The byte size of the data (HostBitmap.cpp:524-527).
|
|
497
|
+
*
|
|
498
|
+
* @returns {number} Byte size.
|
|
499
|
+
*/
|
|
500
|
+
GetRawDataSize() {
|
|
501
|
+
return this._data.length;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* The byte size of one array element (HostBitmap.cpp:529-532).
|
|
506
|
+
*
|
|
507
|
+
* @returns {number} Byte size.
|
|
508
|
+
*/
|
|
509
|
+
GetArrayElementSize() {
|
|
510
|
+
return Math.floor(this._data.length / this._arraySize);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Copy the inner rectangle's edge pixels outward into a margin, for a
|
|
515
|
+
* clamping effect (HostBitmap.cpp:539-595). The corners are not written.
|
|
516
|
+
*
|
|
517
|
+
* @param {number} margin Margin width in pixels.
|
|
518
|
+
* @returns {boolean} Whether the margin was filled.
|
|
519
|
+
*/
|
|
520
|
+
PopulateMargin(margin) {
|
|
521
|
+
if (!this.IsValid() || this.IsCompressed() || this._mipCount !== 1 || 2 * margin >= this.GetWidth() || 2 * margin >= this.GetHeight() || this.GetType() !== TextureType.TEX_TYPE_2D || this._arraySize > 1) {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
const data = this._data;
|
|
525
|
+
const bpp = GetBytesPerPixel(this.GetFormat());
|
|
526
|
+
const pitch = this.GetPitch();
|
|
527
|
+
const at = (x, y) => y * pitch + x * bpp;
|
|
528
|
+
const width = this.GetWidth() - 2 * margin;
|
|
529
|
+
const height = this.GetHeight() - 2 * margin;
|
|
530
|
+
let src = at(margin, margin);
|
|
531
|
+
for (let i = 0; i !== margin; ++i) {
|
|
532
|
+
data.copyWithin(at(margin, i), src, src + bpp * width);
|
|
533
|
+
}
|
|
534
|
+
src = at(margin, height + margin - 1);
|
|
535
|
+
for (let i = 0; i !== margin; ++i) {
|
|
536
|
+
data.copyWithin(at(margin, height + margin + i), src, src + bpp * width);
|
|
537
|
+
}
|
|
538
|
+
for (let y = 0; y !== height; ++y) {
|
|
539
|
+
src = at(margin, y + margin);
|
|
540
|
+
let dst = at(0, y + margin);
|
|
541
|
+
for (let i = 0; i !== margin; ++i) {
|
|
542
|
+
for (let j = 0; j !== bpp; ++j) {
|
|
543
|
+
data[dst + i * bpp + j] = data[src + j];
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
src += (width - 1) * bpp;
|
|
547
|
+
dst += width * bpp + bpp * margin;
|
|
548
|
+
for (let i = 0; i !== margin; ++i) {
|
|
549
|
+
for (let j = 0; j !== bpp; ++j) {
|
|
550
|
+
data[dst + i * bpp + j] = data[src + j];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Copy one byte channel from another bitmap of the same shape
|
|
559
|
+
* (HostBitmap.cpp:597-643). Channels are byte indices, so for BGRA formats
|
|
560
|
+
* they are in memory order: 0 is blue.
|
|
561
|
+
*
|
|
562
|
+
* @param {HostBitmap} source Source bitmap.
|
|
563
|
+
* @param {number} srcChannel Source byte index within a pixel.
|
|
564
|
+
* @param {number} dstChannel Destination byte index within a pixel.
|
|
565
|
+
* @returns {boolean} Whether the channel was copied.
|
|
566
|
+
*/
|
|
567
|
+
CopyChannel(source, srcChannel, dstChannel) {
|
|
568
|
+
if (!this.IsValid() || this.IsCompressed() || !source.IsValid() || source.IsCompressed()) {
|
|
569
|
+
// Carbon: CCP_LOGWARN("HostBitmap.CopyChannel: Need a valid uncompressed bitmap")
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
if (this._type !== source._type || this._arraySize !== source._arraySize || this._mipCount !== source._mipCount || this._width !== source._width || this._height !== source._height) {
|
|
573
|
+
// Carbon: CCP_LOGWARN("HostBitmap.CopyChannel: Bitmaps need same type and dimensions")
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
const dstBPP = GetBytesPerPixel(this.GetFormat());
|
|
577
|
+
const srcBPP = GetBytesPerPixel(source.GetFormat());
|
|
578
|
+
|
|
579
|
+
// Carbon: CCP_LOGWARN("HostBitmap.CopyChannel: Destination channel out of range")
|
|
580
|
+
if (dstChannel >= dstBPP) return false;
|
|
581
|
+
|
|
582
|
+
// Carbon: CCP_LOGWARN("HostBitmap.CopyChannel: Source channel out of range")
|
|
583
|
+
if (srcChannel >= srcBPP) return false;
|
|
584
|
+
if (source === this && srcChannel === dstChannel) return true;
|
|
585
|
+
const src = source._data;
|
|
586
|
+
const dst = this._data;
|
|
587
|
+
for (let srcPos = srcChannel, dstPos = dstChannel; dstPos < dst.length && srcPos < src.length; srcPos += srcBPP, dstPos += dstBPP) {
|
|
588
|
+
dst[dstPos] = src[srcPos];
|
|
589
|
+
}
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Halve the bitmap in place with a 2x2 box filter (HostBitmap.cpp:645-743).
|
|
595
|
+
* New level k is the box-filtered old level k; the smallest old level is
|
|
596
|
+
* dropped when there was more than one.
|
|
597
|
+
*
|
|
598
|
+
* quirk: SNORM and SINT bytes are averaged as unsigned (716-719).
|
|
599
|
+
*
|
|
600
|
+
* @returns {boolean} Whether it was downsampled.
|
|
601
|
+
*/
|
|
602
|
+
Downsample2x2() {
|
|
603
|
+
if (!this.IsValid() || this._width & 1 || this._height & 1 || this._type !== TextureType.TEX_TYPE_2D && this._type !== TextureType.TEX_TYPE_CUBE) {
|
|
604
|
+
// Carbon: CCP_LOGWARN("Downsample2x2 only works with valid, even sized bitmaps")
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
if (!EIGHT_BIT_FORMATS.has(this.GetFormat())) {
|
|
608
|
+
// Carbon: CCP_LOGWARN("Downsample2x2 does not support this pixel format")
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// diverged: counts from the true mip count; Carbon's `m_mipCount - 1`
|
|
613
|
+
// wraps for a full-chain bitmap (mip count 0, HostBitmap.cpp:689, issue 12).
|
|
614
|
+
const mipCountBefore = this.GetTrueMipCount();
|
|
615
|
+
const data = this._data;
|
|
616
|
+
const bpp = GetBytesPerPixel(this._format);
|
|
617
|
+
const newMipCount = Math.max(mipCountBefore - 1, 1);
|
|
618
|
+
let src = 0;
|
|
619
|
+
let dst = 0;
|
|
620
|
+
for (let l = 0; l < this._arraySize; l++) {
|
|
621
|
+
let curWidth = this._width;
|
|
622
|
+
let curHeight = this._height;
|
|
623
|
+
for (let k = 0; k < newMipCount; k++, curWidth = Math.floor(curWidth / 2), curHeight = Math.floor(curHeight / 2)) {
|
|
624
|
+
for (let j = 0; j !== Math.floor(curHeight / 2); ++j) {
|
|
625
|
+
for (let i = 0; i !== Math.floor(curWidth / 2); ++i) {
|
|
626
|
+
for (let byte = 0; byte < bpp; ++byte, ++src, ++dst) {
|
|
627
|
+
const sum = data[src] + data[src + bpp] + data[src + curWidth * bpp] + data[src + curWidth * bpp + bpp];
|
|
628
|
+
data[dst] = Math.floor(sum / 4);
|
|
629
|
+
}
|
|
630
|
+
src += bpp;
|
|
631
|
+
}
|
|
632
|
+
src += curWidth * bpp;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Skip lowest mip level, but only if we had any mips to begin with.
|
|
637
|
+
if (mipCountBefore !== 1) {
|
|
638
|
+
src += curHeight * curWidth * bpp;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
this._mipCount = newMipCount;
|
|
642
|
+
this._width = Math.floor(this._width / 2);
|
|
643
|
+
this._height = Math.floor(this._height / 2);
|
|
644
|
+
let mipCount = newMipCount;
|
|
645
|
+
let width = this._width;
|
|
646
|
+
let height = this._height;
|
|
647
|
+
let size = 0;
|
|
648
|
+
while (mipCount-- > 0) {
|
|
649
|
+
size += width * height * bpp;
|
|
650
|
+
width = Math.max(Math.floor(width / 2), 1);
|
|
651
|
+
height = Math.max(Math.floor(height / 2), 1);
|
|
652
|
+
}
|
|
653
|
+
this._Resize(size * this._arraySize);
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Crop a single-mip 2D bitmap in place (HostBitmap.cpp:745-781); `right` and
|
|
659
|
+
* `bottom` are exclusive.
|
|
660
|
+
*
|
|
661
|
+
* diverged: an empty rectangle returns false and leaves the bitmap intact;
|
|
662
|
+
* Carbon Destroy()s it and returns true (758-762, issue 14).
|
|
663
|
+
*
|
|
664
|
+
* @param {number} left Left column.
|
|
665
|
+
* @param {number} top Top row.
|
|
666
|
+
* @param {number} right Right column, exclusive.
|
|
667
|
+
* @param {number} bottom Bottom row, exclusive.
|
|
668
|
+
* @returns {boolean} Whether it was cropped.
|
|
669
|
+
*/
|
|
670
|
+
Crop(left, top, right, bottom) {
|
|
671
|
+
if (!this.IsValid() || this._mipCount !== 1 || this._type !== TextureType.TEX_TYPE_2D || this._arraySize > 1 || IsCompressedFormat(this._format)) {
|
|
672
|
+
// Carbon: CCP_LOGWARN("Crop only works with valid, single miplevel 2D bitmaps in uncompressed format")
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
left = Math.min(left, this._width);
|
|
676
|
+
right = Math.min(right, this._width);
|
|
677
|
+
top = Math.min(top, this._height);
|
|
678
|
+
bottom = Math.min(bottom, this._height);
|
|
679
|
+
if (left >= right || top >= bottom) return false;
|
|
680
|
+
const data = this._data;
|
|
681
|
+
const bpp = GetBytesPerPixel(this._format);
|
|
682
|
+
const srcStride = this._width * bpp;
|
|
683
|
+
const dstStride = (right - left) * bpp;
|
|
684
|
+
let src = left * bpp + srcStride * top;
|
|
685
|
+
let dst = 0;
|
|
686
|
+
for (let j = top; j !== bottom; ++j) {
|
|
687
|
+
data.copyWithin(dst, src, src + dstStride);
|
|
688
|
+
dst += dstStride;
|
|
689
|
+
src += srcStride;
|
|
690
|
+
}
|
|
691
|
+
this._width = right - left;
|
|
692
|
+
this._height = bottom - top;
|
|
693
|
+
this._Resize(this._width * this._height * bpp);
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Rotate one face clockwise by a multiple of 90 degrees (HostBitmap.cpp:787-868).
|
|
699
|
+
*
|
|
700
|
+
* diverged: requires exactly one mip level; Carbon's `GetMipCount() > 1`
|
|
701
|
+
* lets a full-chain bitmap (mip count 0) through (795, issue 17).
|
|
702
|
+
*
|
|
703
|
+
* @param {number} face Array element.
|
|
704
|
+
* @param {number} times Quarter turns.
|
|
705
|
+
* @returns {boolean} Whether it was rotated.
|
|
706
|
+
*/
|
|
707
|
+
RotateFaceClockwise(face, times) {
|
|
708
|
+
if (!this.IsValid()) return false;
|
|
709
|
+
if (this.GetType() !== TextureType.TEX_TYPE_2D && this.GetType() !== TextureType.TEX_TYPE_CUBE || this.GetTrueMipCount() !== 1) {
|
|
710
|
+
// Carbon: CCP_LOGERR("HostBitmap.RotateFaceClockwise requires 2D/CUBE bitmap with a single mip level")
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Carbon: CCP_LOGERR("HostBitmap.RotateFaceClockwise: index out of range")
|
|
715
|
+
if (face >= this.GetArraySize()) return false;
|
|
716
|
+
|
|
717
|
+
// Carbon: CCP_LOGERR("HostBitmap.RotateFaceClockwise: width must be equal to height")
|
|
718
|
+
if (this.GetWidth() !== this.GetHeight()) return false;
|
|
719
|
+
|
|
720
|
+
// Carbon: CCP_LOGERR("HostBitmap.RotateFaceClockwise: don't support compressed images")
|
|
721
|
+
if (IsCompressedFormat(this.GetFormat())) return false;
|
|
722
|
+
times = times % 4;
|
|
723
|
+
if (!times) return true;
|
|
724
|
+
const size = this.GetWidth();
|
|
725
|
+
const pitch = this.GetPitch();
|
|
726
|
+
const bpp = GetBytesPerPixel(this._format);
|
|
727
|
+
const srcRaw = this._data;
|
|
728
|
+
const dstRaw = srcRaw.slice();
|
|
729
|
+
const offset = pitch * size * face;
|
|
730
|
+
for (let oldX = 0; oldX < size; oldX++) {
|
|
731
|
+
for (let oldY = 0; oldY < size; oldY++) {
|
|
732
|
+
let newX = oldX;
|
|
733
|
+
let newY = oldY;
|
|
734
|
+
for (let i = 0; i < times; i++) {
|
|
735
|
+
const y = newX;
|
|
736
|
+
newX = size - 1 - newY;
|
|
737
|
+
newY = y;
|
|
738
|
+
}
|
|
739
|
+
const src = offset + (oldX + oldY * size) * bpp;
|
|
740
|
+
const dst = offset + (newX + newY * size) * bpp;
|
|
741
|
+
for (let k = 0; k < bpp; ++k) {
|
|
742
|
+
dstRaw[dst + k] = srcRaw[src + k];
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
this._data = dstRaw;
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Convert a 3:4 cross map into a cube (HostBitmap.cpp:874-953). Faces are
|
|
752
|
+
* +X (2,1), -X (0,1), +Y (1,0), -Y (1,2), +Z (1,1), -Z (1,3) in face-size
|
|
753
|
+
* cells, and -Z is turned 180 degrees.
|
|
754
|
+
*
|
|
755
|
+
* @returns {boolean} Whether it was converted.
|
|
756
|
+
*/
|
|
757
|
+
ConvertCrossmapToCubemap() {
|
|
758
|
+
if (!this.IsValid()) return false;
|
|
759
|
+
|
|
760
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertCrossmapToCubemap requires a 2D bitmap")
|
|
761
|
+
if (this.GetType() !== TextureType.TEX_TYPE_2D || this._arraySize > 1) return false;
|
|
762
|
+
|
|
763
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertCrossmapToCubemap: Bitmap has mips. Use DropMipMaps() first.")
|
|
764
|
+
if (this.GetMipCount() !== 1) return false;
|
|
765
|
+
|
|
766
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertCrossmapToCubemap: source image does not represent a 3:4 crossmap!")
|
|
767
|
+
if (this.GetWidth() % 3 !== 0 || this.GetHeight() % 4 !== 0 || this.GetWidth() / 3 !== this.GetHeight() / 4) return false;
|
|
768
|
+
|
|
769
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertCrossmapToCubemap: don't support compressed images")
|
|
770
|
+
if (IsCompressedFormat(this.GetFormat())) return false;
|
|
771
|
+
const cubeSize = this.GetWidth() / 3;
|
|
772
|
+
const srcPitch = this.GetPitch();
|
|
773
|
+
const dstPitch = cubeSize * GetBytesPerPixel(this._format);
|
|
774
|
+
const third = Math.floor(srcPitch / 3);
|
|
775
|
+
const faceOffsets = [srcPitch * cubeSize + third * 2, srcPitch * cubeSize, third, srcPitch * cubeSize * 2 + third, srcPitch * cubeSize + third, srcPitch * cubeSize * 3 + third];
|
|
776
|
+
const srcRaw = this._data;
|
|
777
|
+
const dstRaw = new Uint8Array(dstPitch * cubeSize * 6);
|
|
778
|
+
for (let face = 0; face < 6; face++) {
|
|
779
|
+
const srcOffset = faceOffsets[face];
|
|
780
|
+
const dstOffset = face * cubeSize * dstPitch;
|
|
781
|
+
for (let line = 0; line < cubeSize; ++line) {
|
|
782
|
+
const from = srcOffset + line * srcPitch;
|
|
783
|
+
dstRaw.set(srcRaw.subarray(from, from + dstPitch), dstOffset + line * dstPitch);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
this._data = dstRaw;
|
|
787
|
+
this._type = TextureType.TEX_TYPE_CUBE;
|
|
788
|
+
this._width = this._height = cubeSize;
|
|
789
|
+
this._arraySize = 6;
|
|
790
|
+
this.RotateFaceClockwise(5, 2);
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Convert a horizontal strip of square slices into a cubic volume
|
|
796
|
+
* (HostBitmap.cpp:960-1023). The strip is read bottom-aligned.
|
|
797
|
+
*
|
|
798
|
+
* diverged: a block-compressed bitmap is refused; Carbon's row pitch
|
|
799
|
+
* `GetPitch() / GetWidth() * cubeSize` (991) and its per-line copy are wrong
|
|
800
|
+
* for block rows, so it produced a corrupt volume (issue 16).
|
|
801
|
+
*
|
|
802
|
+
* @returns {boolean} Whether it was converted.
|
|
803
|
+
*/
|
|
804
|
+
ConvertToVolume() {
|
|
805
|
+
if (!this.IsValid()) return false;
|
|
806
|
+
|
|
807
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertToVolume requires 2D bitmap")
|
|
808
|
+
if (this.GetType() !== TextureType.TEX_TYPE_2D || this._arraySize > 1) return false;
|
|
809
|
+
let cubeSize = this.GetHeight();
|
|
810
|
+
|
|
811
|
+
// Carbon: CCP_LOGERR("HostBitmap.ConvertToVolume: source image does not represent a cubic volume texture!")
|
|
812
|
+
if (cubeSize * cubeSize < this.GetWidth()) return false;
|
|
813
|
+
if (IsCompressedFormat(this.GetFormat())) return false;
|
|
814
|
+
cubeSize = Math.floor(Math.sqrt(Math.fround(this.GetWidth())));
|
|
815
|
+
const pitch = this.GetPitch();
|
|
816
|
+
const rowPitch = Math.floor(pitch / this.GetWidth()) * cubeSize;
|
|
817
|
+
const slicePitch = rowPitch * cubeSize;
|
|
818
|
+
const volumeSize = slicePitch * cubeSize;
|
|
819
|
+
const srcRaw = this._data;
|
|
820
|
+
const dstRaw = new Uint8Array(volumeSize);
|
|
821
|
+
const sourceOffset = (this.GetHeight() - cubeSize) * pitch;
|
|
822
|
+
for (let slice = 0; slice < cubeSize; ++slice) {
|
|
823
|
+
const srcSlice = sourceOffset + Math.floor(slice * pitch / cubeSize);
|
|
824
|
+
const dstSlice = slice * slicePitch;
|
|
825
|
+
for (let line = 0; line < cubeSize; ++line) {
|
|
826
|
+
const from = line * pitch + srcSlice;
|
|
827
|
+
dstRaw.set(srcRaw.subarray(from, from + rowPitch), line * rowPitch + dstSlice);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
this._data = dstRaw;
|
|
831
|
+
this._type = TextureType.TEX_TYPE_3D;
|
|
832
|
+
this._mipCount = 1;
|
|
833
|
+
this._width = this._height = this._depth = cubeSize;
|
|
834
|
+
return true;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Generate the mip chain from mip 0 with a 2x2 box filter
|
|
839
|
+
* (HostBitmap.cpp:1036-1130). Only 2D and cube bitmaps with one level, in
|
|
840
|
+
* an 8-bit-per-channel format.
|
|
841
|
+
*
|
|
842
|
+
* diverged: checks validity, and leaves the mip count untouched when it
|
|
843
|
+
* refuses; Carbon has no validity check and leaves it at 0 (1036-1080, issue 13).
|
|
844
|
+
*
|
|
845
|
+
* @param {number} [levels=0] Total levels to keep; 0 means the full chain.
|
|
846
|
+
* @returns {boolean} Whether the mips were generated.
|
|
847
|
+
*/
|
|
848
|
+
GenerateMipMaps(levels = 0) {
|
|
849
|
+
if (!this.IsValid() || this._type !== TextureType.TEX_TYPE_2D && this._type !== TextureType.TEX_TYPE_CUBE || this._mipCount > 1) {
|
|
850
|
+
return false;
|
|
851
|
+
}
|
|
852
|
+
const format = this.GetFormat();
|
|
853
|
+
if (!EIGHT_BIT_FORMATS.has(format)) return false;
|
|
854
|
+
const previousMipCount = this._mipCount;
|
|
855
|
+
this._mipCount = 0;
|
|
856
|
+
let mipCount = this.GetTrueMipCount();
|
|
857
|
+
if (levels) {
|
|
858
|
+
if (levels > mipCount) {
|
|
859
|
+
this._mipCount = previousMipCount;
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
mipCount = levels;
|
|
863
|
+
} else {
|
|
864
|
+
levels = mipCount;
|
|
865
|
+
}
|
|
866
|
+
const bpp = GetBytesPerPixel(format);
|
|
867
|
+
let width = this._width;
|
|
868
|
+
let height = this._height;
|
|
869
|
+
let size = 0;
|
|
870
|
+
while (mipCount-- > 0) {
|
|
871
|
+
size += width * height * bpp;
|
|
872
|
+
width = Math.max(Math.floor(width / 2), 1);
|
|
873
|
+
height = Math.max(Math.floor(height / 2), 1);
|
|
874
|
+
}
|
|
875
|
+
const originalSize = this._data.length;
|
|
876
|
+
this._Resize(size * this.GetArraySize());
|
|
877
|
+
for (let j = this.GetArraySize() - 1; j >= 0; --j) {
|
|
878
|
+
width = this._width;
|
|
879
|
+
height = this._height;
|
|
880
|
+
const topSize = width * height * bpp;
|
|
881
|
+
const to = Math.floor(this._data.length / this.GetArraySize()) * j;
|
|
882
|
+
const from = Math.floor(originalSize / this.GetArraySize()) * j;
|
|
883
|
+
this._data.copyWithin(to, from, from + topSize);
|
|
884
|
+
for (let i = 0; i + 1 < levels; ++i) {
|
|
885
|
+
this._GenerateMipLevel(this.GetMipRawData(i, j), width, height, this.GetMipRawData(i + 1, j));
|
|
886
|
+
width = Math.max(Math.floor(width / 2), 1);
|
|
887
|
+
height = Math.max(Math.floor(height / 2), 1);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
this._mipCount = levels;
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* One mip from the one above it: a 2x2 box per byte, `(a+b+c+d) >> 2`, with
|
|
896
|
+
* no sRGB handling (HostBitmap.cpp:1132-1167). A 1-wide or 1-tall source
|
|
897
|
+
* duplicates, neighbours clamp to the right column and bottom row, and an odd
|
|
898
|
+
* trailing column or row is dropped. Private in Carbon.
|
|
899
|
+
*
|
|
900
|
+
* @param {Uint8Array} source The source mip.
|
|
901
|
+
* @param {number} width Source width.
|
|
902
|
+
* @param {number} height Source height.
|
|
903
|
+
* @param {Uint8Array} destination The destination mip.
|
|
904
|
+
* @returns {boolean} Always true.
|
|
905
|
+
*/
|
|
906
|
+
_GenerateMipLevel(source, width, height, destination) {
|
|
907
|
+
const bpp = GetBytesPerPixel(this._format);
|
|
908
|
+
const dstWidth = Math.max(Math.floor(width / 2), 1);
|
|
909
|
+
const dstHeight = Math.max(Math.floor(height / 2), 1);
|
|
910
|
+
const srcStride = width * bpp;
|
|
911
|
+
const vertStep = height > 1 ? srcStride : 0;
|
|
912
|
+
const horizStep = width > 1 ? bpp : 0;
|
|
913
|
+
const bottom = (height - 1) * srcStride;
|
|
914
|
+
let src00 = 0;
|
|
915
|
+
let src01 = vertStep;
|
|
916
|
+
let dst = 0;
|
|
917
|
+
for (let i = 0; i < dstHeight; ++i) {
|
|
918
|
+
const right0 = src00 + (width - 1) * bpp;
|
|
919
|
+
const right1 = src01 + (width - 1) * bpp;
|
|
920
|
+
for (let j = 0; j < dstWidth; ++j) {
|
|
921
|
+
let src10 = Math.min(src00 + horizStep, right0);
|
|
922
|
+
let src11 = Math.min(src01 + horizStep, right1);
|
|
923
|
+
for (let k = 0; k < bpp; ++k) {
|
|
924
|
+
destination[dst++] = source[src00++] + source[src01++] + source[src10++] + source[src11++] >>> 2;
|
|
925
|
+
}
|
|
926
|
+
src00 += horizStep;
|
|
927
|
+
src01 += horizStep;
|
|
928
|
+
}
|
|
929
|
+
src00 = Math.min(right0 + bpp + vertStep, bottom);
|
|
930
|
+
src01 = Math.min(right1 + bpp + vertStep, bottom);
|
|
931
|
+
}
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Keep mip 0 of every array element and drop the rest (HostBitmap.cpp:1176-1198).
|
|
937
|
+
*
|
|
938
|
+
* @returns {boolean} False only for an invalid bitmap.
|
|
939
|
+
*/
|
|
940
|
+
DropMipMaps() {
|
|
941
|
+
if (!this.IsValid()) {
|
|
942
|
+
// Carbon: CCP_LOGERR("HostBitmap.DropMipMaps: bitmap is not valid")
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
if (this._mipCount === 1) return true;
|
|
946
|
+
const size = this._data.length - this.GetMipRawData(1, 0).length;
|
|
947
|
+
for (let i = 1; i < this._arraySize; i++) {
|
|
948
|
+
const from = this._data.length - this.GetMipRawData(0, i).length;
|
|
949
|
+
this._data.copyWithin(size * i, from, from + size);
|
|
950
|
+
}
|
|
951
|
+
this._Resize(size * this.GetArraySize());
|
|
952
|
+
this._mipCount = 1;
|
|
953
|
+
return true;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* The average colour of a single 2D image, sampled on a grid over its
|
|
958
|
+
* smallest mip (HostBitmap.cpp:1200-1301). BGRX, BGRA, BC1 and BC3 only.
|
|
959
|
+
*
|
|
960
|
+
* adapted: returns `{r, g, b, a}` in 0..1, or null where Carbon returns
|
|
961
|
+
* false and writes nothing.
|
|
962
|
+
*
|
|
963
|
+
* quirk: it samples the SMALLEST mip level, a cheap average by design.
|
|
964
|
+
*
|
|
965
|
+
* diverged: the level is `GetTrueMipCount() - 1` and the average divides by
|
|
966
|
+
* the samples actually taken; Carbon's `GetMipCount() - 1` wraps for a
|
|
967
|
+
* full-chain bitmap so it always fails, and it divides by the whole grid even
|
|
968
|
+
* when samples were skipped (1217, 1292, issue 9).
|
|
969
|
+
*
|
|
970
|
+
* @returns {{r: number, g: number, b: number, a: number}|null} The colour.
|
|
971
|
+
*/
|
|
972
|
+
GetAverageColor() {
|
|
973
|
+
if (!this.IsValid()) {
|
|
974
|
+
// Carbon: CCP_LOGERR("GetAverageColor: bitmap %s is not valid") - its %s has no argument (1203, issue 9).
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
977
|
+
if (this.GetType() !== TextureType.TEX_TYPE_2D || this.GetArraySize() >= 2) return null;
|
|
978
|
+
const F = PixelFormat;
|
|
979
|
+
const format = this.GetFormat();
|
|
980
|
+
if (format !== F.PIXEL_FORMAT_B8G8R8X8_UNORM && format !== F.PIXEL_FORMAT_B8G8R8A8_UNORM && format !== F.PIXEL_FORMAT_BC1_UNORM && format !== F.PIXEL_FORMAT_BC3_UNORM) {
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
const mipLevel = this.GetTrueMipCount() - 1;
|
|
984
|
+
const width = this.GetMipWidth(mipLevel);
|
|
985
|
+
const height = this.GetMipHeight(mipLevel);
|
|
986
|
+
if (width === 0 || height === 0) return null;
|
|
987
|
+
const pitch = this.GetMipPitch(mipLevel);
|
|
988
|
+
const data = this.GetMipRawData(mipLevel);
|
|
989
|
+
const yStep = Math.min(height, Math.max(1, Math.floor(Math.sqrt(Math.fround(height)))));
|
|
990
|
+
const xStep = Math.min(width, Math.max(1, Math.floor(Math.sqrt(Math.fround(width)))));
|
|
991
|
+
const xSampleCount = Math.floor(Math.fround(width / xStep) + 0.5);
|
|
992
|
+
const ySampleCount = Math.floor(Math.fround(height / yStep) + 0.5);
|
|
993
|
+
let xOffset = Math.floor(width % xStep / 2);
|
|
994
|
+
let yOffset = Math.floor(height % yStep / 2);
|
|
995
|
+
if (xOffset === 0) xOffset = Math.floor(xStep / 2);
|
|
996
|
+
if (yOffset === 0) yOffset = Math.floor(yStep / 2);
|
|
997
|
+
let getPixel;
|
|
998
|
+
switch (format) {
|
|
999
|
+
case F.PIXEL_FORMAT_B8G8R8A8_UNORM:
|
|
1000
|
+
getPixel = (x, y) => ImageUtility.getPixelColor_BGRA(x, y, pitch, data);
|
|
1001
|
+
break;
|
|
1002
|
+
case F.PIXEL_FORMAT_B8G8R8X8_UNORM:
|
|
1003
|
+
getPixel = (x, y) => ImageUtility.getPixelColor_BGRX(x, y, pitch, data);
|
|
1004
|
+
break;
|
|
1005
|
+
case F.PIXEL_FORMAT_BC1_UNORM:
|
|
1006
|
+
getPixel = (x, y) => ImageUtility.getPixelColor_BC1(x, y, width, pitch, data);
|
|
1007
|
+
break;
|
|
1008
|
+
default:
|
|
1009
|
+
getPixel = (x, y) => ImageUtility.getPixelColor_BC3(x, y, width, pitch, data);
|
|
1010
|
+
break;
|
|
1011
|
+
}
|
|
1012
|
+
let rChannel = 0,
|
|
1013
|
+
gChannel = 0,
|
|
1014
|
+
bChannel = 0,
|
|
1015
|
+
aChannel = 0,
|
|
1016
|
+
samples = 0;
|
|
1017
|
+
for (let x = 0; x < xSampleCount; ++x) {
|
|
1018
|
+
for (let y = 0; y < ySampleCount; ++y) {
|
|
1019
|
+
if (x * xStep + xOffset >= width) continue;
|
|
1020
|
+
if (y * yStep + yOffset >= height) continue;
|
|
1021
|
+
const pixelValue = getPixel(x * xStep + xOffset, y * yStep + yOffset);
|
|
1022
|
+
samples++;
|
|
1023
|
+
rChannel += pixelValue >>> 16 & 0xff;
|
|
1024
|
+
gChannel += pixelValue >>> 8 & 0xff;
|
|
1025
|
+
bChannel += pixelValue & 0xff;
|
|
1026
|
+
aChannel += pixelValue >>> 24 & 0xff;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (samples === 0) return null;
|
|
1030
|
+
const multiplier = Math.fround(Math.fround(1 / samples) / 255);
|
|
1031
|
+
return {
|
|
1032
|
+
r: Math.fround(rChannel * multiplier),
|
|
1033
|
+
g: Math.fround(gChannel * multiplier),
|
|
1034
|
+
b: Math.fround(bChannel * multiplier),
|
|
1035
|
+
a: Math.fround(aChannel * multiplier)
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* One pixel of mip 0 of a 2D image, as 0..1 floats (HostBitmap.cpp:1303-1357).
|
|
1041
|
+
* BGRX, BGRA, BC1 and BC3 only.
|
|
1042
|
+
*
|
|
1043
|
+
* adapted: returns `{r, g, b, a}`, or null where Carbon returns false.
|
|
1044
|
+
*
|
|
1045
|
+
* diverged: the bounds test is `>=`, and R8 is accepted; Carbon tests
|
|
1046
|
+
* `x > width || y > height` (1324), reading one past the row, and its R8 case
|
|
1047
|
+
* (1332) is unreachable behind the format guard (issue 8).
|
|
1048
|
+
*
|
|
1049
|
+
* @param {number} x Column.
|
|
1050
|
+
* @param {number} y Row.
|
|
1051
|
+
* @returns {{r: number, g: number, b: number, a: number}|null} The colour.
|
|
1052
|
+
*/
|
|
1053
|
+
GetPixel(x, y) {
|
|
1054
|
+
if (!this.IsValid()) {
|
|
1055
|
+
// Carbon: CCP_LOGERR("GetPixel: bitmap is not valid")
|
|
1056
|
+
return null;
|
|
1057
|
+
}
|
|
1058
|
+
if (this.GetType() !== TextureType.TEX_TYPE_2D) return null;
|
|
1059
|
+
const F = PixelFormat;
|
|
1060
|
+
const format = this.GetFormat();
|
|
1061
|
+
if (format !== F.PIXEL_FORMAT_B8G8R8X8_UNORM && format !== F.PIXEL_FORMAT_B8G8R8A8_UNORM && format !== F.PIXEL_FORMAT_BC1_UNORM && format !== F.PIXEL_FORMAT_BC3_UNORM && format !== F.PIXEL_FORMAT_R8_UNORM) {
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
const width = this.GetWidth();
|
|
1065
|
+
const height = this.GetHeight();
|
|
1066
|
+
if (x >= width || y >= height) {
|
|
1067
|
+
// Carbon: CCP_LOGERR("GetPixel: pixel index out of range. Requested pixel (%d, %d), dimensions (%d, %d)")
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
const pitch = this.GetPitch();
|
|
1071
|
+
const data = this._data;
|
|
1072
|
+
let pixelValue = 0;
|
|
1073
|
+
switch (format) {
|
|
1074
|
+
case F.PIXEL_FORMAT_R8_UNORM:
|
|
1075
|
+
pixelValue = ImageUtility.getPixelColor_R(x, y, pitch, data);
|
|
1076
|
+
break;
|
|
1077
|
+
case F.PIXEL_FORMAT_B8G8R8A8_UNORM:
|
|
1078
|
+
pixelValue = ImageUtility.getPixelColor_BGRA(x, y, pitch, data);
|
|
1079
|
+
break;
|
|
1080
|
+
case F.PIXEL_FORMAT_B8G8R8X8_UNORM:
|
|
1081
|
+
pixelValue = ImageUtility.getPixelColor_BGRX(x, y, pitch, data);
|
|
1082
|
+
break;
|
|
1083
|
+
case F.PIXEL_FORMAT_BC1_UNORM:
|
|
1084
|
+
pixelValue = ImageUtility.getPixelColor_BC1(x, y, width, pitch, data);
|
|
1085
|
+
break;
|
|
1086
|
+
case F.PIXEL_FORMAT_BC3_UNORM:
|
|
1087
|
+
pixelValue = ImageUtility.getPixelColor_BC3(x, y, width, pitch, data);
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
return {
|
|
1091
|
+
r: Math.fround((pixelValue >>> 16 & 0xff) / 255),
|
|
1092
|
+
g: Math.fround((pixelValue >>> 8 & 0xff) / 255),
|
|
1093
|
+
b: Math.fround((pixelValue & 0xff) / 255),
|
|
1094
|
+
a: Math.fround((pixelValue >>> 24 & 0xff) / 255)
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// A call, not a decorator: see BitmapDimensions.js.
|
|
1100
|
+
CjsSchema.define(HostBitmap, {
|
|
1101
|
+
className: "HostBitmap",
|
|
1102
|
+
carbon: "HostBitmap"
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
export { HostBitmap };
|
|
1106
|
+
//# sourceMappingURL=HostBitmap.js.map
|