• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / luma.gl / 23357510199

20 Mar 2026 06:40PM UTC coverage: 58.158% (+5.9%) from 52.213%
23357510199

push

github

web-flow
chore: Run tests on src instead of dist (#2555)

3021 of 6029 branches covered (50.11%)

Branch coverage included in aggregate %.

7102 of 11377 relevant lines covered (62.42%)

243.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.43
/modules/engine/src/compute/texture-transform.ts
1
// luma.gl
2
// SPDX-License-Identifier: MIT
3
// Copyright (c) vis.gl contributors
4

5
import {Buffer, Device, Framebuffer, RenderPassProps, Sampler, Texture} from '@luma.gl/core';
6
import {getPassthroughFS} from '@luma.gl/shadertools';
7
import {Model, ModelProps} from '../model/model';
8
import {uid} from '../utils/uid';
9

10
/**
11
 * Properties for creating a {@link TextureTransform}
12
 */
13
export type TextureTransformProps = Omit<ModelProps, 'fs'> & {
14
  fs?: ModelProps['fs']; // override as optional
15
  /** @deprecated TODO(donmccurdy): Needed? */
16
  inject?: Record<string, string>;
17
  /** @deprecated TODO(donmccurdy): Needed? */
18
  framebuffer?: Framebuffer;
19
  /** @deprecated TODO(donmccurdy): Model already handles this? */
20
  sourceBuffers?: Record<string, Buffer>;
21
  /** @deprecated TODO(donmccurdy): Model already handles this? */
22
  sourceTextures?: Record<string, Texture>;
23
  targetTexture: Texture;
24
  targetTextureChannels: 1 | 2 | 3 | 4;
25
  targetTextureVarying: string;
26
};
27

28
type TextureBinding = {
29
  sourceBuffers: Record<string, Buffer>;
30
  sourceTextures: Record<string, Texture>;
31
  targetTexture: Texture;
32
  framebuffer?: Framebuffer;
33
};
34

35
const FS_OUTPUT_VARIABLE = 'transform_output';
58✔
36

37
/**
38
 * Creates a pipeline for texture→texture transforms.
39
 * @deprecated
40
 */
41
export class TextureTransform {
42
  readonly device: Device;
43
  readonly model: Model;
44
  readonly sampler: Sampler;
45

46
  currentIndex = 0;
3✔
47
  samplerTextureMap: Record<string, any> | null = null;
3✔
48
  bindings: TextureBinding[] = []; // each element is an object : {sourceTextures, targetTexture, framebuffer}
3✔
49
  resources: Record<string, any> = {}; // resources to be deleted
3✔
50

51
  constructor(device: Device, props: TextureTransformProps) {
52
    this.device = device;
3✔
53

54
    // For precise picking of element IDs.
55
    this.sampler = device.createSampler({
3✔
56
      addressModeU: 'clamp-to-edge',
57
      addressModeV: 'clamp-to-edge',
58
      minFilter: 'nearest',
59
      magFilter: 'nearest',
60
      mipmapFilter: 'nearest'
61
    });
62

63
    this.model = new Model(this.device, {
3✔
64
      id: props.id || uid('texture-transform-model'),
6✔
65
      fs:
66
        props.fs ||
5✔
67
        getPassthroughFS({
68
          input: props.targetTextureVarying,
69
          inputChannels: props.targetTextureChannels,
70
          output: FS_OUTPUT_VARIABLE
71
        }),
72
      vertexCount: props.vertexCount, // TODO(donmccurdy): Naming?
73
      ...props
74
    });
75

76
    this._initialize(props);
3✔
77
    Object.seal(this);
3✔
78
  }
79

80
  // Delete owned resources.
81
  destroy(): void {
82
    this.model.destroy();
2✔
83
    for (const binding of this.bindings) {
2✔
84
      binding.framebuffer?.destroy();
2✔
85
    }
86
  }
87

88
  /** @deprecated Use {@link destroy}. */
89
  delete(): void {
90
    this.destroy();
×
91
  }
92

93
  run(options?: RenderPassProps): void {
94
    const {framebuffer} = this.bindings[this.currentIndex];
3✔
95
    const renderPass = this.device.beginRenderPass({framebuffer, ...options});
3✔
96
    this.model.draw(renderPass);
3✔
97
    renderPass.end();
3✔
98
    this.device.submit();
3✔
99
  }
100

101
  getTargetTexture(): Texture {
102
    const {targetTexture} = this.bindings[this.currentIndex];
1✔
103
    return targetTexture;
1✔
104
  }
105

106
  getFramebuffer(): Framebuffer | undefined {
107
    const currentResources = this.bindings[this.currentIndex];
×
108
    return currentResources.framebuffer;
×
109
  }
110

111
  // Private
112

113
  _initialize(props: TextureTransformProps): void {
114
    this._updateBindings(props);
3✔
115
  }
116

117
  _updateBindings(props: TextureTransformProps) {
118
    this.bindings[this.currentIndex] = this._updateBinding(this.bindings[this.currentIndex], props);
3✔
119
  }
120

121
  _updateBinding(
122
    binding: TextureBinding,
123
    {sourceBuffers, sourceTextures, targetTexture}: TextureTransformProps
124
  ): TextureBinding {
125
    if (!binding) {
3!
126
      binding = {
3✔
127
        sourceBuffers: {},
128
        sourceTextures: {},
129
        // @ts-expect-error
130
        targetTexture: null
131
      };
132
    }
133
    Object.assign(binding.sourceTextures, sourceTextures);
3✔
134
    Object.assign(binding.sourceBuffers, sourceBuffers);
3✔
135
    if (targetTexture) {
3!
136
      binding.targetTexture = targetTexture;
3✔
137
      const {width, height} = targetTexture;
3✔
138
      // TODO(donmccurdy): When is this called, and is this expected?
139
      if (binding.framebuffer) {
3!
140
        binding.framebuffer.destroy();
×
141
      }
142
      binding.framebuffer = this.device.createFramebuffer({
3✔
143
        id: 'transform-framebuffer',
144
        width,
145
        height,
146
        colorAttachments: [targetTexture]
147
      });
148
      binding.framebuffer.resize({width, height});
3✔
149
    }
150
    return binding;
3✔
151
  }
152

153
  // set texture filtering parameters on source textures.
154
  _setSourceTextureParameters(): void {
155
    const index = this.currentIndex;
×
156
    const {sourceTextures} = this.bindings[index];
×
157
    for (const name in sourceTextures) {
×
158
      sourceTextures[name].sampler = this.sampler;
×
159
    }
160
  }
161
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc