@@ -191,6 +191,78 @@ namespace dmRive
191191 return texture;
192192 }
193193
194+ static wgpu::TextureFormat GetASTCFormat (uint8_t blockW, uint8_t blockH)
195+ {
196+ // ASTC block sizes mapped to WebGPU sRGB formats (correct for color textures).
197+ // NOTE: Linear data (e.g. normal maps) would need Unorm variants instead,
198+ // but ASTC files don't contain color space info. For now we assume sRGB.
199+ if (blockW == 4 && blockH == 4 ) return wgpu::TextureFormat::ASTC4x4UnormSrgb;
200+ if (blockW == 5 && blockH == 4 ) return wgpu::TextureFormat::ASTC5x4UnormSrgb;
201+ if (blockW == 5 && blockH == 5 ) return wgpu::TextureFormat::ASTC5x5UnormSrgb;
202+ if (blockW == 6 && blockH == 5 ) return wgpu::TextureFormat::ASTC6x5UnormSrgb;
203+ if (blockW == 6 && blockH == 6 ) return wgpu::TextureFormat::ASTC6x6UnormSrgb;
204+ if (blockW == 8 && blockH == 5 ) return wgpu::TextureFormat::ASTC8x5UnormSrgb;
205+ if (blockW == 8 && blockH == 6 ) return wgpu::TextureFormat::ASTC8x6UnormSrgb;
206+ if (blockW == 8 && blockH == 8 ) return wgpu::TextureFormat::ASTC8x8UnormSrgb;
207+ if (blockW == 10 && blockH == 5 ) return wgpu::TextureFormat::ASTC10x5UnormSrgb;
208+ if (blockW == 10 && blockH == 6 ) return wgpu::TextureFormat::ASTC10x6UnormSrgb;
209+ if (blockW == 10 && blockH == 8 ) return wgpu::TextureFormat::ASTC10x8UnormSrgb;
210+ if (blockW == 10 && blockH == 10 ) return wgpu::TextureFormat::ASTC10x10UnormSrgb;
211+ if (blockW == 12 && blockH == 10 ) return wgpu::TextureFormat::ASTC12x10UnormSrgb;
212+ if (blockW == 12 && blockH == 12 ) return wgpu::TextureFormat::ASTC12x12UnormSrgb;
213+ return wgpu::TextureFormat::Undefined;
214+ }
215+
216+ rive::rcp<rive::gpu::Texture> MakeImageTextureASTC (uint32_t width,
217+ uint32_t height,
218+ uint8_t blockW,
219+ uint8_t blockH,
220+ const uint8_t astcData[],
221+ uint32_t astcDataSize) override
222+ {
223+ wgpu::TextureFormat format = GetASTCFormat (blockW, blockH);
224+ if (format == wgpu::TextureFormat::Undefined)
225+ {
226+ dmLogError (" Unsupported ASTC block size %dx%d" , blockW, blockH);
227+ return nullptr ;
228+ }
229+
230+ // All ASTC blocks are 16 bytes regardless of block dimensions
231+ uint32_t blocksX = (width + blockW - 1 ) / blockW;
232+ uint32_t blocksY = (height + blockH - 1 ) / blockH;
233+ uint32_t bytesPerRow = blocksX * 16 ;
234+ uint32_t expectedSize = blocksX * blocksY * 16 ;
235+
236+ if (astcDataSize < expectedSize)
237+ {
238+ dmLogError (" ASTC data size %u is less than expected %u for %ux%u texture with %dx%d blocks" ,
239+ astcDataSize, expectedSize, width, height, blockW, blockH);
240+ return nullptr ;
241+ }
242+
243+ wgpu::TextureDescriptor textureDesc = {
244+ .usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst,
245+ .dimension = wgpu::TextureDimension::e2D,
246+ .size = {width, height},
247+ .format = format,
248+ .mipLevelCount = 1 ,
249+ };
250+
251+ wgpu::Texture texture = m_Device.CreateTexture (&textureDesc);
252+
253+ wgpu::TexelCopyTextureInfo dest = {.texture = texture};
254+ wgpu::TexelCopyBufferLayout layout = {.bytesPerRow = bytesPerRow};
255+ wgpu::Extent3D extent = {width, height};
256+
257+ m_Queue.WriteTexture (&dest,
258+ astcData,
259+ astcDataSize,
260+ &layout,
261+ &extent);
262+
263+ return rive::make_rcp<rive::gpu::TextureWebGPUImpl>(width, height, std::move (texture));
264+ }
265+
194266 private:
195267 std::unique_ptr<rive::gpu::RenderContext> m_RenderContext;
196268 rive::rcp<rive::gpu::RenderTargetWebGPU> m_RenderTarget;
0 commit comments