/* * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.prism.impl; import com.sun.prism.Image; import com.sun.prism.PixelFormat; import com.sun.prism.Texture; import java.nio.Buffer; public abstract class BaseTexture implements Texture { protected final T resource; private final PixelFormat format; private final int physicalWidth; private final int physicalHeight; private final int contentX; private final int contentY; protected int contentWidth; protected int contentHeight; //maximum possible user pixels of a texture (in case of POW2 texture allocation size) //currently only matters with RTT's private final int maxContentWidth; private final int maxContentHeight; // We do not provide a default wrapMode because it is so dependent on // how the texture will be used. private final WrapMode wrapMode; private final boolean useMipmap; private boolean linearFiltering = true; private int lastImageSerial; protected BaseTexture(BaseTexture sharedTex, WrapMode newMode, boolean useMipmap) { this.resource = sharedTex.resource; this.format = sharedTex.format; this.wrapMode = newMode; this.physicalWidth = sharedTex.physicalWidth; this.physicalHeight = sharedTex.physicalHeight; this.contentX = sharedTex.contentX; this.contentY = sharedTex.contentY; this.contentWidth = sharedTex.contentWidth; this.contentHeight = sharedTex.contentHeight; this.maxContentWidth = sharedTex.maxContentWidth; this.maxContentHeight = sharedTex.maxContentHeight; this.useMipmap = useMipmap; } protected BaseTexture(T resource, PixelFormat format, WrapMode wrapMode, int width, int height) { this(resource, format, wrapMode, width, height, 0, 0, width, height, false); } protected BaseTexture(T resource, PixelFormat format, WrapMode wrapMode, int physicalWidth, int physicalHeight, int contentX, int contentY, int contentWidth, int contentHeight, boolean useMipmap) { this.resource = resource; this.format = format; this.wrapMode = wrapMode; this.physicalWidth = physicalWidth; this.physicalHeight = physicalHeight; this.contentX = contentX; this.contentY = contentY; this.contentWidth = contentWidth; this.contentHeight = contentHeight; this.maxContentWidth = physicalWidth; this.maxContentHeight = physicalHeight; this.useMipmap = useMipmap; } protected BaseTexture(T resource, PixelFormat format, WrapMode wrapMode, int physicalWidth, int physicalHeight, int contentX, int contentY, int contentWidth, int contentHeight, int maxContentWidth, int maxContentHeight, boolean useMipmap) { this.resource = resource; this.format = format; this.wrapMode = wrapMode; this.physicalWidth = physicalWidth; this.physicalHeight = physicalHeight; this.contentX = contentX; this.contentY = contentY; this.contentWidth = contentWidth; this.contentHeight = contentHeight; this.maxContentWidth = maxContentWidth; this.maxContentHeight = maxContentHeight; this.useMipmap = useMipmap; } @Override public final PixelFormat getPixelFormat() { return format; } @Override public final int getPhysicalWidth() { return physicalWidth; } @Override public final int getPhysicalHeight() { return physicalHeight; } @Override public final int getContentX() { return contentX; } @Override public final int getContentY() { return contentY; } @Override public final int getContentWidth() { return contentWidth; } @Override public final int getContentHeight() { return contentHeight; } @Override public int getMaxContentWidth() { return maxContentWidth; } @Override public int getMaxContentHeight() { return maxContentHeight; } @Override public void setContentWidth(int contentW) { if (contentW > maxContentWidth) { throw new IllegalArgumentException("ContentWidth must be less than or " + "equal to maxContentWidth"); } contentWidth = contentW; } @Override public void setContentHeight(int contentH) { if (contentH > maxContentHeight) { throw new IllegalArgumentException("ContentWidth must be less than or " + "equal to maxContentHeight"); } contentHeight = contentH; } @Override public final WrapMode getWrapMode() { return wrapMode; } @Override public boolean getUseMipmap() { return useMipmap; } @Override public Texture getSharedTexture(WrapMode altMode) { assertLocked(); if (wrapMode == altMode) { lock(); return this; } switch (altMode) { case REPEAT: if (wrapMode != WrapMode.CLAMP_TO_EDGE) { return null; } break; case CLAMP_TO_EDGE: if (wrapMode != WrapMode.REPEAT) { return null; } break; default: return null; } Texture altTex = createSharedTexture(altMode); altTex.lock(); return altTex; } /** * Create a new version of this texture which shares the same * {@code ManagedResource} reference. * The lock counts for the shared resource reference are not * changed in the processing of this method. * * @param newMode the {@code WrapMode} to use for the new texture. * @return a new {@code Texture} object sharing the underlying resource. */ protected abstract Texture createSharedTexture(WrapMode newMode); @Override public final boolean getLinearFiltering() { return linearFiltering; } @Override public void setLinearFiltering(boolean linear) { this.linearFiltering = linear; } @Override public final int getLastImageSerial() { return lastImageSerial; } @Override public final void setLastImageSerial(int serial) { lastImageSerial = serial; } @Override public final void lock() { resource.lock(); } @Override public final boolean isLocked() { return resource.isLocked(); } @Override public final int getLockCount() { return resource.getLockCount(); } @Override public final void assertLocked() { resource.assertLocked(); } @Override public final void unlock() { resource.unlock(); } @Override public final void makePermanent() { resource.makePermanent(); } @Override public final void contentsUseful() { resource.contentsUseful(); } @Override public final void contentsNotUseful() { resource.contentsNotUseful(); } @Override public final boolean isSurfaceLost() { return !resource.isValid(); } @Override public final void dispose() { resource.dispose(); } @Override public void update(Image img) { update(img, 0, 0); } @Override public void update(Image img, int dstx, int dsty) { update(img, dstx, dsty, img.getWidth(), img.getHeight()); } @Override public void update(Image img, int dstx, int dsty, int w, int h) { update(img, dstx, dsty, w, h, false); } @Override public void update(Image img, int dstx, int dsty, int srcw, int srch, boolean skipFlush) { Buffer pbuffer = img.getPixelBuffer(); int pos = pbuffer.position(); update(pbuffer, img.getPixelFormat(), dstx, dsty, img.getMinX(), img.getMinY(), srcw, srch, img.getScanlineStride(), skipFlush); pbuffer.position(pos); } protected void checkUpdateParams(Buffer buf, PixelFormat fmt, int dstx, int dsty, int srcx, int srcy, int srcw, int srch, int srcscan) { if (format == PixelFormat.MULTI_YCbCr_420) { throw new IllegalArgumentException("MULTI_YCbCr_420 requires multitexturing"); } if (buf == null) { throw new IllegalArgumentException("Pixel buffer must be non-null"); } if (fmt != format) { throw new IllegalArgumentException( "Image format (" + fmt + ") " + "must match texture format (" + format + ")"); } if (dstx < 0 || dsty < 0) { throw new IllegalArgumentException( "dstx (" + dstx + ") and dsty (" + dsty + ") must be >= 0"); } if (srcx < 0 || srcy < 0) { throw new IllegalArgumentException( "srcx (" + srcx + ") and srcy (" + srcy + ") must be >= 0"); } if (srcw <= 0 || srch <= 0) { throw new IllegalArgumentException( "srcw (" + srcw + ") and srch (" + srch + ") must be > 0"); } int bytesPerPixel = fmt.getBytesPerPixelUnit(); if (srcscan % bytesPerPixel != 0) { throw new IllegalArgumentException( "srcscan (" + srcscan + ") " + "must be a multiple of the pixel stride (" + bytesPerPixel + ")"); } if (srcw > srcscan / bytesPerPixel) { throw new IllegalArgumentException( "srcw (" + srcw + ") " + "must be <= srcscan/bytesPerPixel (" + (srcscan/bytesPerPixel) + ")"); } if (dstx+srcw > contentWidth || dsty+srch > contentHeight) { throw new IllegalArgumentException( "Destination region " + "(x=" + dstx + ", y=" + dsty + ", w=" + srcw + ", h=" + srch + ") " + "must fit within texture content bounds " + "(contentWidth=" + contentWidth + ", contentHeight=" + contentHeight + ")"); } int bytesNeeded = (srcx * bytesPerPixel) + (srcy * srcscan) + ((srch-1) * srcscan) + (srcw * bytesPerPixel); int elemsNeeded = bytesNeeded / format.getDataType().getSizeInBytes(); if (elemsNeeded > buf.remaining()) { throw new IllegalArgumentException( "Upload requires " + elemsNeeded + " elements, but only " + buf.remaining() + " elements remain in the buffer"); } } @Override public String toString() { return super.toString() + " [format="+format+ " physicalWidth="+physicalWidth+ " physicalHeight="+physicalHeight+ " contentX="+contentX+ " contentY="+contentY+ " contentWidth="+contentWidth+ " contentHeight="+contentHeight+ " wrapMode="+wrapMode+ " linearFiltering="+linearFiltering+ "]"; } }