On Thu, 3 Apr 2025 06:09:03 GMT, Sergey Bylokhov <s...@openjdk.org> wrote:
>>> > is it possible for pixelStride to be smaller than maxBandOff? >>> >>> Surprisingly, yes! Band offsets are arbitrary, even for >>> `PixelInterleavedSampleModel`, the only restriction is that `maxBandOff - >>> minBandOff <= pixelStride` >> >> But isn't it essentially the same thing? It just shifts the "pixelStride" >> window in one direction or another. >> >>> Both could be correct and there doesn't seem to be any other info, which >>> could allow us to determine this unambiguously. This "real starting pixel >>> offset" is implicitly assumed, when working with [known types in native >>> code](https://github.com/openjdk/jdk/blob/209e72d311234c8279289172dab2cbb255e4fed9/src/java.desktop/share/classes/sun/awt/image/BufImgSurfaceData.java#L319), >>> but is explicitly stored nowhere. >> >> It depends on where and when the ColorModel/SampleModel/Raster were created. >> If the raster was created by our code and we can determine the starting >> offsets, and if we can confirm that the gaps are safe to read, then we could >> set some flags. These flags could be recognized by the pipelines to enable >> fast-path optimizations. >> >> Just one example: >> >> private static BufferedImage makeCustom3BYTE_BGR() { >> ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); >> int[] nBits = {8, 8, 8}; >> int[] bOffs = {2, 1, 0}; >> ColorModel colorModel = new ComponentColorModel(cs, nBits, false, >> false, >> Transparency.OPAQUE, >> >> DataBuffer.TYPE_BYTE); >> >> PixelInterleavedSampleModel sm = >> new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, >> 2, 1, 400, 4000, bOffs); >> WritableRaster raster = Raster.createWritableRaster(sm, null); >> >> System.out.println("raster.getDataBuffer().getSize() = " + >> raster.getDataBuffer().getSize()); >> return new BufferedImage(colorModel, raster, true, null); >> } >> >> BufferedImage bi = new BufferedImage(3000, 3000, TYPE_INT_ARGB); >> BufferedImage src = makeCustom3BYTE_BGR(); >> Graphics2D g2d = bi.createGraphics(); >> g2d.setTransform(new AffineTransform()); >> g2d.drawImage(src, 0, 0, null); >> g2d.dispose(); >> >> >> The size of the image is "403", meaning it does not include the gap after >> the last pixel data. >> >> Now, if we attempt to blit this into various pipelines, we may encounter >> different slow/fast pat... > > Probably, the changes similar to https://github.com/openjdk/jdk/pull/24378 > will help in some cases. However, for the generic case with random rasters, > it will be necessary to determine whether the gaps at the end of the image > are actually stored in the raster or not. > as of now, we simply don't have generic native loops that support pixel gaps That was kinda what I was actually implementing in Vulkan when I faced this issue. I just accepted any pixel-interleaved surface with 4-byte stride and assumed that I can blit it directly. Just because the stride is 4 bytes, I know I can copy the whole scanline in one go into a matching Vulkan format, like B8G8R8A8_UNORM, and I can handle any component order (including missing alpha channel) with simple swizzling. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24111#discussion_r2026301933