--- old/modules/graphics/src/main/java/com/sun/javafx/sg/prism/RegionImageCache.java 2014-10-21 14:36:04.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/sg/prism/RegionImageCache.java 2014-10-21 14:36:04.000000000 -0700 @@ -58,7 +58,16 @@ RegionImageCache(final ResourceFactory factory) { imageMap = new HashMap<>(); - backingStore = factory.createRTTexture(WIDTH + WIDTH, HEIGHT, WrapMode.CLAMP_TO_ZERO); + WrapMode mode; + int pad; + if (factory.isWrapModeSupported(WrapMode.CLAMP_TO_ZERO)) { + mode = WrapMode.CLAMP_TO_ZERO; + pad = 0; + } else { + mode = WrapMode.CLAMP_NOT_NEEDED; + pad = 1; + } + backingStore = factory.createRTTexture(WIDTH + WIDTH, HEIGHT, mode); backingStore.contentsUseful(); backingStore.makePermanent(); factory.setRegionTexture(backingStore); @@ -66,8 +75,11 @@ // horizontal regions and the other vertical regions. Otherwise, mixing // horizontal and vertical regions on the same area, would result in // a lot of waste texture space. - hPacker = new RectanglePacker(backingStore, 0, 0, WIDTH, HEIGHT, false); - vPacker = new RectanglePacker(backingStore, WIDTH, 0, WIDTH, HEIGHT, true); + // Note that requests are already padded on the right and bottom edges + // (and that includes the gap between the caches) so we only have to + // pad top and left edges if CLAMP_TO_ZERO needs to be simulated. + hPacker = new RectanglePacker(backingStore, pad, pad, WIDTH-pad, HEIGHT-pad, false); + vPacker = new RectanglePacker(backingStore, WIDTH, pad, WIDTH, HEIGHT-pad, true); } /** --- old/modules/graphics/src/main/java/com/sun/prism/ResourceFactory.java 2014-10-21 14:36:05.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/ResourceFactory.java 2014-10-21 14:36:05.000000000 -0700 @@ -25,6 +25,7 @@ package com.sun.prism; +import com.sun.prism.Texture.WrapMode; import com.sun.prism.impl.TextureResourcePool; import com.sun.prism.impl.VertexBuffer; import com.sun.prism.shape.ShapeRep; @@ -204,6 +205,15 @@ public boolean isFormatSupported(PixelFormat format); /** + * Returns true iff the indicated {@link WrapMode wrap mode} is directly + * supported (i.e. not simulated) by the underlying pipeline and platform. + * + * @param mode the desired {@code WrapMode} + * @return true iff the wrap mode is supported and not simulated + */ + public boolean isWrapModeSupported(WrapMode mode); + + /** * Returns the maximum supported texture dimension for this device. * For example, if this method returns 2048, it means that textures * larger than 2048x2048 cannot be created. --- old/modules/graphics/src/main/java/com/sun/prism/impl/BaseResourceFactory.java 2014-10-21 14:36:06.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/impl/BaseResourceFactory.java 2014-10-21 14:36:06.000000000 -0700 @@ -284,4 +284,35 @@ return superShaderAllowed; } + protected boolean canClampToZero() { + return true; + } + + protected boolean canClampToEdge() { + return true; + } + + protected boolean canRepeat() { + return true; + } + + @Override + public boolean isWrapModeSupported(WrapMode mode) { + switch (mode) { + case CLAMP_NOT_NEEDED: + return true; + case CLAMP_TO_EDGE: + return canClampToEdge(); + case REPEAT: + return canRepeat(); + case CLAMP_TO_ZERO: + return canClampToZero(); + case CLAMP_TO_EDGE_SIMULATED: + case CLAMP_TO_ZERO_SIMULATED: + case REPEAT_SIMULATED: + throw new InternalError("Cannot test support for simulated wrap modes"); + default: + throw new InternalError("Unrecognized wrap mode: "+mode); + } + } } --- old/modules/graphics/src/main/java/com/sun/prism/es2/ES2ResourceFactory.java 2014-10-21 14:36:07.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/es2/ES2ResourceFactory.java 2014-10-21 14:36:07.000000000 -0700 @@ -101,6 +101,23 @@ return tex instanceof ES2Texture; } + @Override + protected boolean canClampToZero() { + return context.getGLContext().canClampToZero(); + } + + @Override + protected boolean canRepeat() { + // Actually, this depends on the size. It works for pow2 textures... + return context.getGLContext().canCreateNonPowTwoTextures(); + } + + @Override + protected boolean canClampToEdge() { + // Actually, this depends on the size. It works for pow2 textures... + return context.getGLContext().canCreateNonPowTwoTextures(); + } + public Texture createTexture(PixelFormat formatHint, Usage usageHint, WrapMode wrapMode, --- old/modules/graphics/src/main/java/com/sun/prism/sw/SWResourceFactory.java 2014-10-21 14:36:08.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/sw/SWResourceFactory.java 2014-10-21 14:36:08.000000000 -0700 @@ -153,6 +153,11 @@ } } + @Override + protected boolean canClampToZero() { + return false; + } + @Override public Texture createTexture(MediaFrame vdb) { return new SWArgbPreTexture(this, WrapMode.CLAMP_TO_EDGE, vdb.getWidth(), vdb.getHeight()); } --- old/modules/graphics/src/main/java/com/sun/prism/j2d/J2DResourceFactory.java 2014-10-21 14:36:09.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/j2d/J2DResourceFactory.java 2014-10-21 14:36:09.000000000 -0700 @@ -145,7 +145,12 @@ public boolean isCompatibleTexture(Texture tex) { return tex instanceof J2DTexture; } - + + @Override + protected boolean canClampToZero() { + return false; + } + public int getMaximumTextureSize() { return Integer.MAX_VALUE; } --- old/modules/graphics/src/test/java/com/sun/javafx/sg/prism/TestGraphics.java 2014-10-21 14:36:10.000000000 -0700 +++ new/modules/graphics/src/test/java/com/sun/javafx/sg/prism/TestGraphics.java 2014-10-21 14:36:10.000000000 -0700 @@ -186,6 +186,7 @@ @Override public Texture createTexture(PixelFormat formatHint, Texture.Usage usageHint, Texture.WrapMode wrapMode, int w, int h, boolean useMipmap) { return null; } @Override public Texture createTexture(MediaFrame frame) { return null; } @Override public boolean isCompatibleTexture(Texture tex) { return true; } + @Override public boolean isWrapModeSupported(Texture.WrapMode mode) { return true; } @Override public Texture getCachedTexture(Image image, WrapMode wrapMode) { return null; } @Override public Texture getCachedTexture(Image image, WrapMode wrapMode, boolean useMipmap) { return null; } @Override public boolean isFormatSupported(PixelFormat format) { return false; }