Merge "Issue #2333 Merging gl refactor from GOES-R work. Preparing GL for data units in image." into development

Former-commit-id: 41462b804bf079368bead7c1271b1abdb7d4bf63
This commit is contained in:
Nate Jensen 2013-10-21 14:44:17 -05:00 committed by Gerrit Code Review
commit 50bf735240
30 changed files with 1335 additions and 636 deletions

View file

@ -27,12 +27,16 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.geometry.Envelope2D;
import org.opengis.coverage.grid.GridEnvelope;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.geospatial.ISpatialObject;
@ -55,6 +59,7 @@ import com.raytheon.uf.viz.core.map.IMapMeshExtension;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
import com.vividsolutions.jts.geom.Coordinate;
/**
* {@link TileSetRenderable} for 2D {@link PluginDataObject}s. Groups adjacent
@ -68,7 +73,9 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 19, 2013 2122 mschenke Initial creation.
* Jun 19, 2013 2122 mschenke Initial creation.
* Oct 16, 2013 2333 mschenke Added method for auto-unit conversion
* interrogating
*
* </pre>
*
@ -199,7 +206,7 @@ public class RecordTileSetRenderable extends TileSetRenderable {
BufferSlicer.slice(data.getBuffer(),
tileRect, bigTileRect), new int[] {
tileRect.width, tileRect.height },
data.getDataType());
data.getDataType(), data.getDataUnit());
callbacks.get(i).setRetrievedData(subData);
try {
@ -353,6 +360,69 @@ public class RecordTileSetRenderable extends TileSetRenderable {
tile.getRectangle()).getColorMapData();
}
@Override
public double interrogate(Coordinate coordinate) throws VizException {
ColorMapParameters parameters = colormapping.getColorMapParameters();
return interrogate(coordinate, parameters.getNoDataValue());
}
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate in units of desiredUnit
*
* @param coordinate
* in lat/lon space
* @param desiredUnit
* unit to convert data value to if not nanValue
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, Unit<?> desiredUnit)
throws VizException {
ColorMapParameters parameters = colormapping.getColorMapParameters();
return interrogate(coordinate, parameters.getNoDataValue(), desiredUnit);
}
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate in units of desiredUnit
*
* @param coordinate
* in lat/lon space
* @param nanValue
* if interrogated value is equal to nanValue, {@link Double#NaN}
* will be returned
* @param desiredUnit
* unit to convert data value to if not nanValue
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, double nanValue,
Unit<?> desiredUnit) throws VizException {
double dataValue = super.interrogate(coordinate, nanValue);
if (Double.isNaN(dataValue) == false) {
ColorMapParameters params = colormapping.getColorMapParameters();
Unit<?> dataUnit = params.getDataUnit();
if (dataUnit != null && desiredUnit != null
&& dataUnit != desiredUnit) {
if (dataUnit.isCompatible(desiredUnit)) {
dataValue = dataUnit.getConverterTo(desiredUnit).convert(
dataValue);
} else {
throw new IllegalArgumentException(
"Unable to interrogate tile set. "
+ String.format(
"Desired unit (%s) is not compatible with data unit (%s).",
UnitFormat.getUCUMInstance()
.format(desiredUnit),
UnitFormat.getUCUMInstance()
.format(dataUnit)));
}
}
}
return dataValue;
}
/**
* @param target
*/

View file

@ -62,11 +62,12 @@ import com.vividsolutions.jts.geom.Coordinate;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 8, 2012 mschenke Initial creation
* May 28, 2013 2037 njensen Made imageMap concurrent to fix leak
* Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made
* canceling jobs safer
*
* Aug 8, 2012 mschenke Initial creation
* May 28, 2013 2037 njensen Made imageMap concurrent to fix leak
* Jun 20, 2013 2122 mschenke Fixed null pointer in interrogate and made
* canceling jobs safer
* Oct 16, 2013 2333 mschenke Added auto NaN checking for interrogation
*
* </pre>
*
* @author mschenke
@ -474,6 +475,24 @@ public class TileSetRenderable implements IRenderable {
* @throws VizException
*/
public double interrogate(Coordinate coordinate) throws VizException {
return interrogate(coordinate, Double.NaN);
}
/**
* Returns the raw image value from tile image that contains the lat/lon
* coordinate. Any values matching nanValue will return {@link Double#NaN}
*
* @param coordinate
* in lat/lon space
* @param nanValue
* if interrogated value is equal to nanValue, {@link Double#NaN}
* will be returned
* @return
* @throws VizException
*/
public double interrogate(Coordinate coordinate, double nanValue)
throws VizException {
double dataValue = Double.NaN;
try {
double[] local = new double[2];
llToLocalProj
@ -490,15 +509,20 @@ public class TileSetRenderable implements IRenderable {
if (di != null) {
IImage image = di.getImage();
if (image instanceof IColormappedImage) {
return ((IColormappedImage) image).getValue(
IColormappedImage cmapImage = (IColormappedImage) image;
dataValue = cmapImage.getValue(
(int) grid[0] % tileSize, (int) grid[1]
% tileSize);
if (dataValue == nanValue) {
dataValue = Double.NaN;
}
}
}
}
} catch (TransformException e) {
throw new VizException("Error interrogating ", e);
}
return Double.NaN;
return dataValue;
}
}

View file

@ -117,7 +117,7 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
GLOffscreenRenderingExtension extension = target
.getExtension(GLOffscreenRenderingExtension.class);
try {
extension.renderOffscreen(trueColorImage,
extension.beginOffscreenRendering(trueColorImage,
trueColorImage.getImageExtent());
boolean allPainted = true;
for (Channel channel : Channel.values()) {
@ -145,7 +145,8 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
}
}
} catch (VizException e) {
extension.renderOnscreen();
// Exception: end rendering now instead of postImageRender
extension.endOffscreenRendering();
throw e;
}
renderingChannel = null;
@ -180,7 +181,7 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
AbstractGLImage image, Object data) throws VizException {
if (image instanceof GLTrueColorImage) {
target.getExtension(GLOffscreenRenderingExtension.class)
.renderOnscreen();
.endOffscreenRendering();
target.drawRasters(paintProps, new DrawableImage(
((GLTrueColorImage) image).getWrappedImage(),
(PixelCoverage) data));

View file

@ -32,7 +32,8 @@ import javax.media.opengl.GL;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 21, 2011 mschenke Initial creation
* Nov 21, 2011 mschenke Initial creation
* Oct 16, 2013 2333 mschenke Removed Buffer from GLColorMapData
*
* </pre>
*
@ -83,6 +84,16 @@ public abstract class AbstractGLColorMapDataFormat {
*/
public abstract double getDataFormatMax();
/**
* Returns true if the data format is a signed data format (values in format
* can be less than 0), false otherwise
*
* @return true if signed format
*/
public boolean isSignedFormat() {
return getDataFormatMin() < 0;
}
/**
* Create a buffer object for specified data for copying data from out of GL
*
@ -93,8 +104,7 @@ public abstract class AbstractGLColorMapDataFormat {
/**
* Specifies if the data format type's values are scaled when copied to GL
* and referenced in shader. True means the values will by default be scaled
* to -1 to 1, false indicates shader will receive values as is
* and referenced in shader.
*
* @return
*/
@ -108,9 +118,11 @@ public abstract class AbstractGLColorMapDataFormat {
* @param x
* @param y
* @param data
* @param dataBuffer
* @return
*/
public abstract Number getValue(int x, int y, GLColorMapData data);
public abstract Number getValue(int x, int y, GLColorMapData data,
Buffer dataBuffer);
/**
* Get the number of bytes each pixel takes up

View file

@ -0,0 +1,102 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.gl.dataformat;
import java.nio.Buffer;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.colormap.image.ColorMapData;
/**
* GLColorMapData backed by a java Buffer
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 16, 2013 2333 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class GLBufferColorMapData extends GLColorMapData {
private Buffer data;
private int textureType;
private Unit<?> dataUnit;
public GLBufferColorMapData(ColorMapData cmData,
AbstractGLColorMapDataFormat dataFormat) {
super(dataFormat, cmData.getDataType(), cmData.getDimensions());
this.textureType = dataFormat.getTextureType();
this.data = dataFormat.formatForGL(cmData.getBuffer(), this);
this.dataUnit = cmData.getDataUnit();
}
public Buffer getData() {
return data;
}
public void setData(Buffer data) {
this.data = data;
}
public Buffer getCopybackBuffer() {
return dataFormat.getCopybackBuffer(this);
}
public int getCopyBackTextureType() {
return dataFormat.getCopyBackTextureType();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.dataformat.GLColorMapData#getTextureType()
*/
@Override
public int getTextureType() {
return textureType;
}
public void setTextureType(int textureType) {
this.textureType = textureType;
}
public Number getValue(int x, int y) {
return dataFormat.getValue(x, y, this, data);
}
/**
* @return
*/
public Unit<?> getDataUnit() {
return dataUnit;
}
}

View file

@ -110,8 +110,7 @@ public class GLByteDataFormat extends AbstractGLColorMapDataFormat {
* (int, int, java.nio.Buffer)
*/
@Override
public Short getValue(int x, int y, GLColorMapData data) {
Buffer dataBuffer = data.getData();
public Short getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (data.getTextureType() != GL.GL_UNSIGNED_BYTE) {
throw new IllegalArgumentException(
"Cannot process texture of type " + data.getTextureType());

View file

@ -19,10 +19,7 @@
**/
package com.raytheon.viz.core.gl.dataformat;
import java.nio.Buffer;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
/**
*
@ -34,7 +31,8 @@ import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 10, 2011 bsteffen Initial creation
* Aug 10, 2011 bsteffen Initial creation
* Oct 16, 2013 2333 mschenke Removed Buffer from this object
*
* </pre>
*
@ -43,31 +41,17 @@ import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
*/
public class GLColorMapData {
private final AbstractGLColorMapDataFormat dataFormat;
protected final AbstractGLColorMapDataFormat dataFormat;
private Buffer data;
private final int[] dimensions;
private int[] dimensions;
private final ColorMapData.ColorMapDataType dataType;
private ColorMapData.ColorMapDataType dataType;
private int textureType;
public GLColorMapData(ColorMapData cmData,
AbstractGLColorMapDataFormat dataFormat) {
public GLColorMapData(AbstractGLColorMapDataFormat dataFormat,
ColorMapData.ColorMapDataType dataType, int[] dimensions) {
this.dataFormat = dataFormat;
this.dimensions = cmData.getDimensions();
this.dataType = cmData.getDataType();
this.textureType = dataFormat.getTextureType();
this.data = dataFormat.formatForGL(cmData.getBuffer(), this);
}
public Buffer getData() {
return data;
}
public void setData(Buffer data) {
this.data = data;
this.dataType = dataType;
this.dimensions = dimensions;
}
public int getTextureFormat() {
@ -79,21 +63,13 @@ public class GLColorMapData {
}
public int getTextureType() {
return textureType;
}
public void setTextureType(int textureType) {
this.textureType = textureType;
return dataFormat.getTextureType();
}
public ColorMapData.ColorMapDataType getDataType() {
return dataType;
}
public int getCopyBackTextureType() {
return dataFormat.getCopyBackTextureType();
}
public double getDataFormatMin() {
return dataFormat.getDataFormatMin();
}
@ -106,12 +82,8 @@ public class GLColorMapData {
return dataFormat.isScaled();
}
public Buffer getCopybackBuffer() {
return dataFormat.getCopybackBuffer(this);
}
public Number getValue(int x, int y) {
return dataFormat.getValue(x, y, this);
public boolean isDataFormatSigned() {
return dataFormat.isSignedFormat();
}
public int getDimensionSize(int index) {

View file

@ -107,18 +107,18 @@ public class GLFloatDataFormat extends AbstractGLColorMapDataFormat {
* (int, int, com.raytheon.viz.core.gl.dataprep.GLColorMapData)
*/
@Override
public Float getValue(int x, int y, GLColorMapData data) {
public Float getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (data.getTextureType() != GL.GL_FLOAT) {
throw new IllegalArgumentException(
"Cannot process texture of type " + data.getTextureType());
} else if (!(data.getData() instanceof FloatBuffer)) {
} else if (!(dataBuffer instanceof FloatBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a FloatBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = data.getDimensionSize(0);
int index = y * width + x;
FloatBuffer buffer = (FloatBuffer) data.getData();
FloatBuffer buffer = (FloatBuffer) dataBuffer;
return buffer.get(index);
}

View file

@ -121,18 +121,18 @@ public class GLHalfFloatDataFormat extends AbstractGLColorMapDataFormat {
* (int, int, com.raytheon.viz.core.gl.dataprep.GLColorMapData)
*/
@Override
public Float getValue(int x, int y, GLColorMapData data) {
public Float getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (data.getTextureType() != GL.GL_HALF_FLOAT_ARB) {
throw new IllegalArgumentException(
"Cannot process texture of type " + data.getTextureType());
} else if (!(data.getData() instanceof ShortBuffer)) {
} else if (!(dataBuffer instanceof ShortBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a ShortBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = getAlignedWidth(data.getDimensionSize(0));
int index = y * width + x;
ShortBuffer buffer = (ShortBuffer) data.getData();
ShortBuffer buffer = (ShortBuffer) dataBuffer;
return convertFromFloat16(buffer.get(index));
}

View file

@ -100,15 +100,15 @@ public class GLIntDataFormat extends AbstractGLColorMapDataFormat {
* (int, int, com.raytheon.viz.core.gl.dataprep.GLColorMapData)
*/
@Override
public Integer getValue(int x, int y, GLColorMapData data) {
if (!(data.getData() instanceof IntBuffer)) {
public Integer getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (!(dataBuffer instanceof IntBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a IntBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = data.getDimensionSize(0);
int index = y * width + x;
IntBuffer buffer = (IntBuffer) data.getData();
IntBuffer buffer = (IntBuffer) dataBuffer;
int value = buffer.get(index);
switch (data.getTextureType()) {
case GL.GL_INT:

View file

@ -105,15 +105,15 @@ public class GLShortDataFormat extends AbstractGLColorMapDataFormat {
* (int, int, com.raytheon.viz.core.gl.dataprep.GLColorMapData)
*/
@Override
public Number getValue(int x, int y, GLColorMapData data) {
if (!(data.getData() instanceof ShortBuffer)) {
public Number getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (!(dataBuffer instanceof ShortBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a ShortBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = getAlignedWidth(data.getDimensionSize(0));
int index = y * width + x;
ShortBuffer buffer = (ShortBuffer) data.getData();
ShortBuffer buffer = (ShortBuffer) dataBuffer;
short value = buffer.get(index);
switch (data.getTextureType()) {
case GL.GL_SHORT:

View file

@ -19,6 +19,7 @@
**/
package com.raytheon.viz.core.gl.dataformat;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.media.opengl.GL;
@ -49,15 +50,15 @@ public class GLSignedByteDataFormat extends GLByteDataFormat {
* int, com.raytheon.viz.core.gl.dataprep.GLColorMapData)
*/
@Override
public Short getValue(int x, int y, GLColorMapData data) {
if (!(data.getData() instanceof ByteBuffer)) {
public Short getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (!(dataBuffer instanceof ByteBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a ByteBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = getAlignedWidth(data.getDimensionSize(0));
int index = y * width + x;
ByteBuffer buffer = (ByteBuffer) data.getData();
ByteBuffer buffer = (ByteBuffer) dataBuffer;
byte value = buffer.get(index);
switch (data.getTextureType()) {
case GL.GL_BYTE:

View file

@ -19,6 +19,7 @@
**/
package com.raytheon.viz.core.gl.dataformat;
import java.nio.Buffer;
import java.nio.ShortBuffer;
import javax.media.opengl.GL;
@ -82,15 +83,15 @@ public class GLUnsignedShortDataFormat extends GLShortDataFormat {
* int, com.raytheon.viz.core.gl.dataformat.GLColorMapData)
*/
@Override
public Number getValue(int x, int y, GLColorMapData data) {
if (!(data.getData() instanceof ShortBuffer)) {
public Number getValue(int x, int y, GLColorMapData data, Buffer dataBuffer) {
if (!(dataBuffer instanceof ShortBuffer)) {
throw new IllegalArgumentException(
"Expecting data to contain a ShortBuffer but instead it is a "
+ data.getData().getClass().getSimpleName());
+ dataBuffer.getClass().getSimpleName());
}
int width = getAlignedWidth(data.getDimensionSize(0));
int index = y * width + x;
ShortBuffer buffer = (ShortBuffer) data.getData();
ShortBuffer buffer = (ShortBuffer) dataBuffer;
return (buffer.get(index) & 0xFFFF);
}

View file

@ -53,7 +53,7 @@ public interface IGLColorMapDataFormatProvider {
public AbstractGLColorMapDataFormat getGLColorMapDataFormat(
ColorMapData colorMapData) {
return GLColorMapDataFormatFactory
.getGLColorMapDataFormat(colorMapData);
.getGLColorMapDataFormat(colorMapData.getDataType());
}
};

View file

@ -22,18 +22,14 @@ package com.raytheon.viz.core.gl.ext;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Stack;
import javax.media.opengl.GL;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IView;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
import com.raytheon.uf.viz.core.drawables.IImage;
import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension;
@ -42,11 +38,13 @@ import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.core.gl.IGLTarget;
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
import com.raytheon.viz.core.gl.dataformat.GLByteDataFormat;
import com.raytheon.viz.core.gl.dataformat.GLColorMapData;
import com.raytheon.viz.core.gl.dataformat.GLColorMapDataFormatFactory;
import com.raytheon.viz.core.gl.dataformat.IGLColorMapDataFormatProvider;
import com.raytheon.viz.core.gl.ext.imaging.GLColormappedImageExtension;
import com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension;
import com.raytheon.viz.core.gl.images.AbstractGLImage;
import com.raytheon.viz.core.gl.images.GLColormappedImage;
import com.raytheon.viz.core.gl.images.GLImage;
import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
import com.raytheon.viz.core.gl.internal.GLView2D;
/**
@ -97,17 +95,29 @@ public class GLOffscreenRenderingExtension extends GraphicsExtension<IGLTarget>
private ViewInfo currentInfo = null;
public void renderOffscreen(IImage offscreenImage) throws VizException {
renderOffscreen(offscreenImage, target.getView().getExtent());
/**
* Begins offscreen rendering to the glImage. All rendering after this call
* will occur on the image until {@link #endOffscreenRendering()} is called.
* Render area will be set to the current view's extent
*
* @param glImage
* @throws VizException
*/
public void beginOffscreenRendering(AbstractGLImage glImage)
throws VizException {
beginOffscreenRendering(glImage, target.getView().getExtent());
}
public void renderOffscreen(IImage offscreenImage, IExtent offscreenExtent)
throws VizException {
if (!(offscreenImage instanceof AbstractGLImage)) {
throw new VizException(
"Can only use GLImages as offscreen frameBuffer on GLTarget");
}
AbstractGLImage glImage = (AbstractGLImage) offscreenImage;
/**
* Begins offscreen rendering to the glImage. All rendering after this call
* will occur on the image until {@link #endOffscreenRendering()} is called.
* Render area will be set to the offscreenExtent provided
*
* @param glImage
* @throws VizException
*/
public void beginOffscreenRendering(AbstractGLImage glImage,
IExtent offscreenExtent) throws VizException {
if (glImage.getStatus() == IImage.Status.UNLOADED
|| glImage.getStatus() == IImage.Status.LOADING) {
glImage.setStatus(IImage.Status.LOADING);
@ -129,8 +139,16 @@ public class GLOffscreenRenderingExtension extends GraphicsExtension<IGLTarget>
setCurrentView(new ViewInfo(view, glImage));
}
public void renderOnscreen() throws VizException {
if (viewStack.size() > 0) {
/**
* Ends offscreen rendering. Should only be called if a call to
* {@link #beginOffscreenRendering(AbstractGLImage)} or
* {@link #beginOffscreenRendering(AbstractGLImage, IExtent)} was
* successfully called first first
*
* @throws VizException
*/
public void endOffscreenRendering() throws VizException {
if (viewStack.isEmpty() == false) {
setCurrentView(viewStack.pop());
}
}
@ -167,60 +185,84 @@ public class GLOffscreenRenderingExtension extends GraphicsExtension<IGLTarget>
return Compatibilty.TARGET_COMPATIBLE;
}
public IImage constructOffscreenImage(final int[] dimensions)
/**
* Creates an RGB based image for use in offscreen rendering
*
* @param dimensions
* @return
* @throws VizException
*/
public AbstractGLImage constructOffscreenImage(final int[] dimensions)
throws VizException {
return target.initializeRaster(new IRenderedImageCallback() {
return new GLImage(new IRenderedImageCallback() {
@Override
public RenderedImage getImage() throws VizException {
return new BufferedImage(dimensions[0], dimensions[1],
BufferedImage.TYPE_INT_RGB);
}
});
}, GLDefaultImagingExtension.class);
}
public GLColormappedImage constructOffscreenImage(
/**
* Creates a colormapped offscreen image with the specified dataType and
* dimensions
*
* @param dataType
* @param dimensions
* @return
* @throws VizException
*/
public GLOffscreenColormappedImage constructOffscreenImage(
ColorMapDataType dataType, int[] dimensions) throws VizException {
return constructOffscreenImage(dataType, dimensions, null);
}
public GLColormappedImage constructOffscreenImage(
/**
* Creates a colormapped offscreen image with the specified dataType and
* dimensions and default colormap parameters
*
* @param dataType
* @param dimensions
* @param parameters
* @return
* @throws VizException
*/
public GLOffscreenColormappedImage constructOffscreenImage(
final ColorMapDataType dataType, final int[] dimensions,
ColorMapParameters parameters) throws VizException {
GLColormappedImageExtension cmapExt = target
.getExtension(GLColormappedImageExtension.class);
if (!supportsLuminance) {
return cmapExt.initializeRaster(new NoLuminanceDataCallback(
dimensions, dataType), parameters);
} else {
GLColormappedImage image = cmapExt.initializeRaster(
new IColorMapDataRetrievalCallback() {
AbstractGLColorMapDataFormat format = null;
@Override
public ColorMapData getColorMapData()
throws VizException {
return new ColorMapData(dataType, dimensions);
}
}, parameters);
if (!checkedLuminance) {
checkedLuminance = true;
try {
renderOffscreen(image);
} catch (VizException e) {
// Log this so it is easy to see in the console logs.
new VizException(
"Graphics card does not support luminance textures.",
e).printStackTrace(System.out);
// assume we don't support luminance
supportsLuminance = false;
// Reconstruct image
image = constructOffscreenImage(dataType, dimensions,
parameters);
} finally {
renderOnscreen();
}
}
return image;
if (supportsLuminance) {
format = GLColorMapDataFormatFactory
.getGLColorMapDataFormat(dataType);
} else {
format = new NoLuminanceDataFormat(dataType);
}
GLOffscreenColormappedImage image = new GLOffscreenColormappedImage(
new GLColorMapData(format, dataType, dimensions), parameters,
GLColormappedImageExtension.class);
if (!checkedLuminance) {
checkedLuminance = true;
try {
beginOffscreenRendering(image);
} catch (VizException e) {
// Log this so it is easy to see in the console logs.
new VizException(
"Graphics card does not support luminance textures.", e)
.printStackTrace(System.out);
// assume we don't support luminance
supportsLuminance = false;
// Reconstruct image
image = constructOffscreenImage(dataType, dimensions,
parameters);
} finally {
endOffscreenRendering();
}
}
return image;
}
private static final class NoLuminanceDataFormat extends GLByteDataFormat {
@ -228,10 +270,11 @@ public class GLOffscreenRenderingExtension extends GraphicsExtension<IGLTarget>
// Used to get the original min/max which makes signed bytes work and
// theoretically will give better looking results for other integer data
// types.
private final ColorMapDataType originalType;
private final AbstractGLColorMapDataFormat originalFormat;
private NoLuminanceDataFormat(ColorMapDataType originalType) {
this.originalType = originalType;
this.originalFormat = GLColorMapDataFormatFactory
.getGLColorMapDataFormat(originalType);
}
@Override
@ -251,46 +294,14 @@ public class GLOffscreenRenderingExtension extends GraphicsExtension<IGLTarget>
@Override
public double getDataFormatMin() {
return getOriginalGLColorMapDataFormat().getDataFormatMin();
return originalFormat.getDataFormatMin();
}
@Override
public double getDataFormatMax() {
return getOriginalGLColorMapDataFormat().getDataFormatMax();
return originalFormat.getDataFormatMax();
}
private AbstractGLColorMapDataFormat getOriginalGLColorMapDataFormat() {
return GLColorMapDataFormatFactory
.getGLColorMapDataFormat(originalType);
}
}
private static final class NoLuminanceDataCallback implements
IColorMapDataRetrievalCallback, IGLColorMapDataFormatProvider {
private int[] dimensions;
private final ColorMapDataType originalType;
private NoLuminanceDataCallback(int[] dimensions,
ColorMapDataType type) {
this.dimensions = dimensions;
this.originalType = type;
}
@Override
public AbstractGLColorMapDataFormat getGLColorMapDataFormat(
ColorMapData colorMapData) {
return new NoLuminanceDataFormat(originalType);
}
@Override
public ColorMapData getColorMapData() throws VizException {
Buffer buffer = ByteBuffer.allocate(dimensions[0] * dimensions[1]
* 3);
return new ColorMapData(buffer, dimensions, originalType);
}
}
}

View file

@ -34,6 +34,7 @@ import com.raytheon.uf.viz.core.drawables.ext.colormap.IColormappedImageExtensio
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
import com.raytheon.viz.core.gl.images.AbstractGLImage;
import com.raytheon.viz.core.gl.images.GLColormappedImage;
import com.raytheon.viz.core.gl.objects.GLTextureObject;
@ -48,10 +49,11 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 18, 2011 mschenke Initial creation
* Nov 18, 2011 mschenke Initial creation
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
* parameters, disable colormap interpolation
* by default.
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled
*
* </pre>
*
@ -94,10 +96,10 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
public Object preImageRender(PaintProperties paintProps,
AbstractGLImage image, PixelCoverage coverage) throws VizException {
GLColormappedImageExtensionData data = null;
if (image instanceof GLColormappedImage) {
if (image instanceof AbstractGLColormappedImage) {
data = new GLColormappedImageExtensionData();
GL gl = target.getGl();
GLColormappedImage glImage = (GLColormappedImage) image;
AbstractGLColormappedImage glImage = (AbstractGLColormappedImage) image;
// First see if the colormap has been loaded
ColorMapParameters usedColorMapParameters = ((IColormappedImage) glImage)
.getColorMapParameters();
@ -199,31 +201,30 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
public void loadShaderData(GLShaderProgram program, IImage iimage,
PaintProperties paintProps) throws VizException {
// Get image as AbstractGLImage
GLColormappedImage image = null;
if (iimage instanceof GLColormappedImage == false) {
AbstractGLColormappedImage image = null;
if (iimage instanceof AbstractGLColormappedImage == false) {
throw new VizException(
"Cannot apply glsl colormap raster shader to non gl colormap image");
}
image = (GLColormappedImage) iimage;
image = (AbstractGLColormappedImage) iimage;
GLColormappedImage colormappedImg = (GLColormappedImage) image;
ColorMapParameters colorMapParameters = colormappedImg
.getColorMapParameters();
ColorMapParameters colorMapParameters = image.getColorMapParameters();
program.setUniform("colorMapSz", colorMapParameters.getColorMap()
.getSize());
int textureType = image.getTextureType();
boolean isFloat = textureType == GL.GL_FLOAT
|| textureType == GL.GL_HALF_FLOAT_ARB;
boolean isScaled = image.isImageFormatScaled();
double dataMin = colorMapParameters.getDataMin();
double dataMax = colorMapParameters.getDataMax();
if (isFloat == false) {
if (isScaled) {
// get format from image and get data min/max from it
dataMin = image.getDataMin();
dataMax = image.getDataMax();
}
program.setUniform("isFloat", isFloat);
double cmapMin = colorMapParameters.getColorMapMin();
double cmapMax = colorMapParameters.getColorMapMax();
program.setUniform("isFloat", !isScaled);
program.setUniform("logarithmic",
colorMapParameters.isLogarithmic() ? 1 : 0);
program.setUniform("logFactor", colorMapParameters.getLogFactor());
@ -233,8 +234,8 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
program.setUniform("naturalMin", dataMin);
program.setUniform("naturalMax", dataMax);
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
program.setUniform("cmapMin", cmapMin);
program.setUniform("cmapMax", cmapMax);
program.setUniform("alphaMask", 2);
program.setUniform("colorMap", 1);

View file

@ -0,0 +1,280 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.gl.images;
import javax.media.opengl.GL;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
import com.raytheon.uf.viz.core.exception.VizException;
import com.sun.opengl.util.texture.TextureCoords;
/**
* Base implementation of a gl colormapped image.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 16, 2013 2333 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public abstract class AbstractGLColormappedImage extends AbstractGLImage
implements IColormappedImage {
protected ColorMapParameters colorMapParameters;
protected GLCMTextureData data;
public AbstractGLColormappedImage(GLCMTextureData data,
ColorMapParameters params,
Class<? extends IImagingExtension> extensionClass) {
super(extensionClass);
this.data = data;
this.colorMapParameters = params;
if (data.isLoaded()) {
setStatus(Status.LOADED);
} else if (data.isStaged()) {
setStatus(Status.STAGED);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#stageTexture()
*/
@Override
public boolean stageTexture() throws VizException {
if (data == null) {
throw new VizException(
"Cannot stage texture, image has been disposed");
}
return data.stageTexture();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.internal.GLImage#loadTexture(javax.media.opengl
* .GLContext)
*/
@Override
public void loadTexture(GL gl) throws VizException {
if (data.loadTexture(gl)) {
// Add to texture cache
setStatus(Status.LOADED);
} else {
setStatus(Status.FAILED);
}
}
/**
* Return the texture's data type
*
* Example: GL.GL_FLOAT
*
* @return the data type of the texture
*
*/
public int getTextureType() {
return data.getTextureType();
}
public ColorMapDataType getColorMapDataType() {
return data.getColorMapDataType();
}
/**
* Return the texture's format
*
* Example: GL.GL_LUMINANCE
*
* @return the texture format
*/
public int getTextureFormat() {
return data.getTextureFormat();
}
/**
* Return the texture's internal format
*
* This is the format of the texture after driver manipulation
*
* Example: GL.GL_LUMINANCE8
*
* @return the texture internal format
*/
public int getTextureInternalFormat() {
return data.getTextureInternalFormat();
}
/**
* @return the textureid
*/
public int getTextureid() {
return data.getTexId();
}
/**
* the absolute minimum value of a pixel in this image. {@link Double#NaN}
* if no absolute minimum exists
*
* @return
*/
public double getDataMin() {
return data.getDataMin();
}
/**
* the absolute maximum value of a pixel in this image. {@link Double#NaN}
* if no absolute maximum exists
*
* @return
*/
public double getDataMax() {
return data.getDataMax();
}
/**
* Returns true if the image values will be scaled when loaded into GL
*
* @return
*/
public boolean isImageFormatScaled() {
return data.isDataFormatScaled();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.drawables.IColormappedImage#getColorMapParameters()
*/
@Override
public ColorMapParameters getColorMapParameters() {
return this.colorMapParameters;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.drawables.IColormappedImage#setColorMapParameters
* (com.raytheon.viz.core.drawables.ColorMapParameters)
*/
@Override
public void setColorMapParameters(ColorMapParameters params) {
this.colorMapParameters = params;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.internal.images.GLImage#getTextureStorageType()
*/
@Override
public int getTextureStorageType() {
return data.getTextureStorageType();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.internal.images.GLImage#getHeight()
*/
@Override
public int getHeight() {
return data.getDimensionSize(1);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.internal.images.GLImage#getWidth()
*/
@Override
public int getWidth() {
return data.getDimensionSize(0);
}
@Override
public void dispose() {
super.dispose();
if (data != null) {
data.dispose();
data = null;
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getStatus()
*/
@Override
public Status getStatus() {
Status status = super.getStatus();
if (data == null) {
if (status != Status.UNLOADED) {
setStatus(Status.UNLOADED);
}
} else if (data.isLoaded()) {
if (status != Status.LOADED) {
setStatus(Status.LOADED);
}
} else if (data.isStaged()) {
if (status != Status.STAGED) {
setStatus(Status.STAGED);
}
} else if (data.isLoaded() == false && status == Status.LOADED) {
if (data.isStaged()) {
setStatus(Status.STAGED);
} else {
setStatus(Status.UNLOADED);
}
} else if (data.isStaged() == false && status == Status.STAGED) {
setStatus(Status.UNLOADED);
}
return super.getStatus();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getTextureCoords()
*/
@Override
public TextureCoords getTextureCoords() {
return new TextureCoords(0, 1, 1, 0);
}
}

View file

@ -41,7 +41,8 @@ import com.sun.opengl.util.texture.TextureCoords;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 2, 2011 bsteffen Initial creation
* Aug 2, 2011 bsteffen Initial creation
* Oct 16, 2013 2333 mschenke Cleaned up usaAsFrameBuffer for clearer logic
*
* </pre>
*
@ -171,55 +172,61 @@ public abstract class AbstractGLImage implements IImage {
public void usaAsFrameBuffer() throws VizException {
GL gl = GLU.getCurrentGL();
if (fbo != null && fbo.isValid()) {
fbo.bind(gl);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
if (rbuf != null && rbuf.isValid()) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
if (fbo == null || fbo.isValid() == false) {
gl.glBindTexture(getTextureStorageType(), 0);
fbo = new GLFrameBufferObject(this);
if (fbo.isValid()) {
fbo.bind(gl);
if ((rbuf == null || rbuf.isValid() == false)
&& gl.glIsEnabled(GL.GL_DEPTH_TEST)) {
// Generate and bind a render buffer for the depth component
rbuf = new GLRenderBuffer(this);
rbuf.bind(gl);
rbuf.createStorage(gl, GL.GL_DEPTH_COMPONENT, getWidth(),
getHeight());
gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
// Attach render buffer to depth of fbo
gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT,
GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT,
rbuf.getId());
}
// Attach texture to color attachement on fbo
gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
GL.GL_COLOR_ATTACHMENT0_EXT, getTextureStorageType(),
getTextureid(), 0);
String errorMessage = fbo.checkStatus(gl);
// use the window buffer
if (errorMessage != null) {
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
if (fbo != null) {
fbo.dispose();
fbo = null;
}
if (rbuf != null) {
rbuf.dispose();
rbuf = null;
}
throw new VizException(errorMessage);
}
} else {
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
throw new VizException("Error generating Frame Buffer Object");
}
return;
} else {
// Bind the fbo for use
fbo.bind(gl);
}
gl = GLU.getCurrentGL();
gl.glBindTexture(getTextureStorageType(), 0);
fbo = new GLFrameBufferObject(this);
fbo.bind(gl);
if (gl.glIsEnabled(GL.GL_DEPTH_TEST)) {
// Generate and bind a render buffer for the depth component
rbuf = new GLRenderBuffer(this);
rbuf.bind(gl);
rbuf.createStorage(gl, GL.GL_DEPTH_COMPONENT, getWidth(),
getHeight());
gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
// Attach render buffer to depth of fbo
gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT,
GL.GL_DEPTH_ATTACHMENT_EXT, GL.GL_RENDERBUFFER_EXT,
rbuf.getId());
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
if (rbuf != null && rbuf.isValid()) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
} else {
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
}
// Attach texture to color attachement on fbo
gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
GL.GL_COLOR_ATTACHMENT0_EXT, getTextureStorageType(),
getTextureid(), 0);
String errorMessage = fbo.checkStatus(gl);
// use the window buffer
if (errorMessage != null) {
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
if (fbo != null) {
fbo.dispose();
fbo = null;
}
if (rbuf != null) {
rbuf.dispose();
rbuf = null;
}
throw new VizException(errorMessage);
}
}
/*
@ -265,7 +272,7 @@ public abstract class AbstractGLImage implements IImage {
}
return false;
}
/*
* (non-Javadoc)
*

View file

@ -19,29 +19,15 @@
**/
package com.raytheon.viz.core.gl.images;
import java.nio.Buffer;
import java.util.HashMap;
import java.util.Map;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.core.gl.GLContextBridge;
import com.raytheon.viz.core.gl.dataformat.GLColorMapData;
import com.raytheon.viz.core.gl.dataformat.IGLColorMapDataFormatProvider;
import com.raytheon.viz.core.gl.internal.cache.IImageCacheable;
import com.raytheon.viz.core.gl.internal.cache.ImageCache;
import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
import com.raytheon.viz.core.gl.objects.GLTextureObject;
/**
*
* TODO Make use new ColorMapData retrieval callback stuff.... Keep old
* CMDataPreparer stuff working
* Colormappable texture data object. Does not provide source of data
*
* <pre>
*
@ -49,87 +35,77 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 2, 2011 bsteffen Initial creation
* Aug 2, 2011 bsteffen Initial creation
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
* format for offscreen textures.
* Oct 16, 2013 2333 mschenke Moved retrievable/Buffer parts out and
* into separate class.
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class GLCMTextureData implements IImageCacheable {
public class GLCMTextureData {
private GLTextureObject tex;
protected GLTextureObject tex;
private final IColorMapDataRetrievalCallback callback;
protected GLColorMapData data;
private int refCount = 0;
private GLColorMapData data = null;
private GLCMTextureData(IColorMapDataRetrievalCallback callback) {
this.callback = callback;
}
public void use() {
refCount += 1;
}
public void dispose() {
synchronized (texMap) {
refCount -= 1;
if (refCount == 0) {
texMap.remove(callback);
ImageCache.getInstance(CacheType.MEMORY).remove(this);
ImageCache.getInstance(CacheType.TEXTURE).remove(this);
}
/**
* Constructs a GLCMTextureData with the specified GLColorMapData.
*
* @param data
*/
public GLCMTextureData(GLColorMapData data) {
this.data = data;
if (data == null && getClass().equals(GLCMTextureData.class)) {
// If null data and class is not overridden, throw exception
throw new IllegalArgumentException(
"null GLColorMapData is not allowed for GLCMTextureData");
}
}
public synchronized void disposeTexture(GL gl) {
protected GLColorMapData getDataObject() {
return data;
}
/**
* Disposes the texture data object
*/
public void dispose() {
// Dispose the texture
disposeTexture();
}
/**
* Disposes the underlying texture in the texture data
*/
public synchronized void disposeTexture() {
if (isLoaded()) {
tex.dispose();
tex = null;
}
ImageCache.getInstance(CacheType.TEXTURE).remove(this);
}
public synchronized void disposeTextureData() {
if (isStaged()) {
data.setData(null);
}
ImageCache.getInstance(CacheType.MEMORY).remove(this);
}
/**
* Stages the texture data for use.
*
* @return true if successfully staged, false otherwise
* @throws VizException
*/
public synchronized boolean stageTexture() throws VizException {
// Don't need to stage if we are already in gpu
if (isLoaded()) {
return true;
}
// Don't need to stage if we already have data
if (isStaged()) {
return true;
}
// OK, Fetch the data
ColorMapData cmData = callback.getColorMapData();
if (cmData != null) {
IGLColorMapDataFormatProvider glDataFormatCallback = IGLColorMapDataFormatProvider.defaultCallback;
if (callback instanceof IGLColorMapDataFormatProvider) {
glDataFormatCallback = (IGLColorMapDataFormatProvider) callback;
}
data = new GLColorMapData(cmData,
glDataFormatCallback.getGLColorMapDataFormat(cmData));
if (isStaged()) {
ImageCache.getInstance(CacheType.MEMORY).put(this);
return true;
}
}
// The data fetch didn't go well
return false;
// There is no data to stage
return isStaged();
}
/**
* Loads the texture object into GL
*
* @param gl
* @return true if texture is loaded, false otherwise
* @throws VizException
*/
public synchronized boolean loadTexture(GL gl) throws VizException {
// Don't need to load if we are already loaded
if (isLoaded()) {
@ -149,8 +125,7 @@ public class GLCMTextureData implements IImageCacheable {
gl.glTexParameteri(type, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(type, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
if (getTextureType() == GL.GL_SHORT || getTextureType() == GL.GL_INT
|| getTextureType() == GL.GL_BYTE) {
if (isDataFormatScaled() && isDataFormatSigned()) {
// GL maps signed data into the range -1 to 1, but gl trims
// this to a valid range of 0 to 1, essentially removing
// negative values. Adding a scale and bias remaps this from
@ -160,120 +135,156 @@ public class GLCMTextureData implements IImageCacheable {
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.5f);
}
int w = data.getDimensionSize(0);
int h = data.getDimensionSize(1);
int w = getDimensionSize(0);
int h = getDimensionSize(1);
createTexture2D(gl, type, w, h);
gl.glTexImage2D(type, 0, getTextureInternalFormat(), w, h, 0,
getTextureFormat(), getTextureType(), data.getData().rewind());
gl.glPixelTransferf(GL.GL_RED_SCALE, 1.0f);
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.0f);
ImageCache.getInstance(CacheType.TEXTURE).put(this);
return true;
}
public boolean isStaged() {
return data != null && data.getData() != null;
/**
* Creates a 2D texture for type, with width/height w/h. Texture object must
* be bound for this call to work using
* {@link GLTextureObject#bind(GL, int)}
*
* @param gl
* @param type
* @param w
* @param h
*/
protected void createTexture2D(GL gl, int type, int w, int h) {
// Allocate our space on the graphics card, no buffer to upload so it
// will be filled with default values initially (0s)
gl.glTexImage2D(type, 0, getTextureInternalFormat(), w, h, 0,
getTextureFormat(), getTextureType(), null);
}
/**
* Checks if texture data is staged. If false, a call to
* {@link #stageTexture()} is needed before texture can be loaded
*
* @return true if staged
*/
public boolean isStaged() {
// There is nothing to stage, so we are good if data != null
return getDataObject() != null;
}
/**
* Checks if texture data is loaded. If false, a call to
* {@link #loadTexture(GL)} is needed before the texture can be used in GL
*
* @return true if staged
*/
public boolean isLoaded() {
return tex != null && tex.isValid();
}
/**
* Returns the size of the dimension index passed in (0=width,1=height)
*
* @param dimension
* @return
*/
public int getDimensionSize(int dimension) {
return data.getDimensionSize(dimension);
}
/**
* Returns the texture type of the data (FLOAT,INT,SHORT,etc).
*
* @return
*/
public int getTextureType() {
return data.getTextureType();
}
/**
* Returns texture format (LUMINANCE,RGB)
*
* @return
*/
public int getTextureFormat() {
return data.getTextureFormat();
}
/**
* Returns texture gl internal format (number of bits: LUMINANCE8/16/32)
*
* @return
*/
public int getTextureInternalFormat() {
return data.getTextureInternalFormat();
}
/**
* Returns the minimum valid data value for the texture format. (0 for
* unsigned byte, -128 for signed byte, etc)
*
* @return
*/
public double getDataMin() {
return data.getDataFormatMin();
}
/**
* Returns the maximium valid data value for the texture format. ( 255 for
* usnigned byte, 127 for signed byte, etc)
*
* @return
*/
public double getDataMax() {
return data.getDataFormatMax();
}
/**
* Returns true if the data values when uploaded to GL are in a scaled
* format and need to be converted to get actual data value
*
* @return
*/
public boolean isDataFormatScaled() {
return data.isDataFormatScaled();
}
/**
* Returns true if the data format is a signed data format (values in format
* can be less than 0), false otherwise
*
* @return true if signed format
*/
public boolean isDataFormatSigned() {
return data.isDataFormatSigned();
}
/**
* The id of the texture in GL. Will not work if {@link #isLoaded()} returns
* false
*
* @return
*/
public int getTexId() {
if (isLoaded()) {
ImageCache.getInstance(CacheType.TEXTURE).put(this);
}
return tex.getId();
}
/**
* The texture storage type of the data (TEXTURE_2D)
*
* @return
*/
public int getTextureStorageType() {
return GL.GL_TEXTURE_2D;
}
public double getValue(int x, int y) {
double value = Double.NaN;
if (!isStaged() && isLoaded()) {
GLContextBridge.makeMasterContextCurrent();
GL gl = GLU.getCurrentGL();
int textureStorageType = getTextureStorageType();
int copybackTextureType = data.getCopyBackTextureType();
Buffer copybackBuffer = data.getCopybackBuffer();
gl.glEnable(textureStorageType);
gl.glActiveTexture(GL.GL_TEXTURE0);
tex.bind(gl, textureStorageType);
gl.glGetTexImage(textureStorageType, 0, getTextureFormat(),
copybackTextureType, copybackBuffer.rewind());
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(textureStorageType, 0);
gl.glDisable(textureStorageType);
data.setTextureType(copybackTextureType);
data.setData(copybackBuffer);
GLContextBridge.releaseMasterContext();
}
if (data != null) {
ImageCache.getInstance(CacheType.MEMORY).put(this);
value = data.getValue(x, y).doubleValue();
}
return value;
}
private static Map<IColorMapDataRetrievalCallback, GLCMTextureData> texMap = new HashMap<IColorMapDataRetrievalCallback, GLCMTextureData>();
public static GLCMTextureData getGlTextureId(
IColorMapDataRetrievalCallback callback) {
synchronized (texMap) {
GLCMTextureData data = texMap.get(callback);
if (data == null) {
data = new GLCMTextureData(callback);
texMap.put(callback, data);
}
data.use();
return data;
}
}
@Override
public int getSize() {
if (data != null) {
int[] dimensions = data.getDimensions();
int totalSize = data.getBytesPerPixel();
for (int i = 0; i < dimensions.length; ++i) {
totalSize *= dimensions[i];
}
return totalSize;
}
return 0;
}
/**
* Returns the {@link ColorMapDataType} for the texture
*
* @return
*/
public ColorMapDataType getColorMapDataType() {
return data.getDataType();
}

View file

@ -24,10 +24,8 @@ import javax.media.opengl.GL;
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
import com.raytheon.uf.viz.core.exception.VizException;
import com.sun.opengl.util.texture.TextureCoords;
/**
*
@ -39,46 +37,25 @@ import com.sun.opengl.util.texture.TextureCoords;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 27, 2009 mschenke Initial creation
* Jul 27, 2009 mschenke Initial creation
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
* format for offscreen textures.
* Oct 16, 2013 2333 mschenke Moved shared logic into base class
*
* </pre>
*
* @author mschenke
*/
public class GLColormappedImage extends AbstractGLImage implements
IColormappedImage {
public class GLColormappedImage extends AbstractGLColormappedImage {
protected ColorMapParameters colorMapParameters;
protected GLCMTextureData data;
protected GLRetrievableCMTextureData data;
public GLColormappedImage(IColorMapDataRetrievalCallback dataCallback,
ColorMapParameters params,
Class<? extends IImagingExtension> extensionClass) {
super(extensionClass);
this.data = GLCMTextureData.getGlTextureId(dataCallback);
this.colorMapParameters = params;
if (data.isLoaded()) {
setStatus(Status.LOADED);
} else if (data.isStaged()) {
setStatus(Status.STAGED);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#stageTexture()
*/
@Override
public boolean stageTexture() throws VizException {
if (data == null) {
throw new VizException(
"Cannot stage texture, image has been disposed");
}
return data.stageTexture();
super(GLRetrievableCMTextureData.getGlTextureId(dataCallback), params,
extensionClass);
this.data = (GLRetrievableCMTextureData) super.data;
}
/*
@ -90,117 +67,15 @@ public class GLColormappedImage extends AbstractGLImage implements
*/
@Override
public void loadTexture(GL gl) throws VizException {
if (data.loadTexture(gl)) {
// Add to texture cache
setStatus(Status.LOADED);
data.disposeTextureData();
} else {
setStatus(Status.FAILED);
data.disposeTextureData();
}
}
/**
* Return the texture's data type
*
* Example: GL.GL_FLOAT
*
* @return the data type of the texture
*
*/
public int getTextureType() {
return data.getTextureType();
super.loadTexture(gl);
// No need to keep around texture data after loading
data.disposeTextureData();
}
public ColorMapDataType getColorMapDataType() {
return data.getColorMapDataType();
}
/**
* Return the texture's format
*
* Example: GL.GL_LUMINANCE
*
* @return the texture format
*/
public int getTextureFormat() {
return data.getTextureFormat();
}
/**
* Return the texture's internal format
*
* This is the format of the texture after driver manipulation
*
* Example: GL.GL_LUMINANCE8
*
* @return the texture internal format
*/
public int getTextureInternalFormat() {
return data.getTextureInternalFormat();
}
/**
* @return the textureid
*/
public int getTextureid() {
return data.getTexId();
}
/**
* the absolute minimum value of a pixel in this image. {@link Double#NaN}
* if no absolute minimum exists
*
* @return
*/
public double getDataMin() {
return data.getDataMin();
}
/**
* the absolute maximum value of a pixel in this image. {@link Double#NaN}
* if no absolute maximum exists
*
* @return
*/
public double getDataMax() {
return data.getDataMax();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.drawables.IColormappedImage#getColorMapParameters()
*/
@Override
public ColorMapParameters getColorMapParameters() {
return this.colorMapParameters;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.drawables.IColormappedImage#setColorMapParameters
* (com.raytheon.viz.core.drawables.ColorMapParameters)
*/
@Override
public void setColorMapParameters(ColorMapParameters params) {
this.colorMapParameters = params;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.internal.images.GLImage#getTextureStorageType()
*/
@Override
public int getTextureStorageType() {
return data.getTextureStorageType();
}
@Override
public double getValue(int x, int y) {
double val = Double.NaN;
@ -210,33 +85,10 @@ public class GLColormappedImage extends AbstractGLImage implements
return val;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.internal.images.GLImage#getHeight()
*/
@Override
public int getHeight() {
return data.getDimensionSize(1);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.internal.images.GLImage#getWidth()
*/
@Override
public int getWidth() {
return data.getDimensionSize(0);
}
@Override
public void dispose() {
super.dispose();
if (data != null) {
data.dispose();
data = null;
}
data = null;
}
/*
@ -250,46 +102,4 @@ public class GLColormappedImage extends AbstractGLImage implements
super.usaAsFrameBuffer();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getStatus()
*/
@Override
public Status getStatus() {
Status status = super.getStatus();
if (data == null) {
if (status != Status.UNLOADED) {
setStatus(Status.UNLOADED);
}
} else if (data.isLoaded()) {
if (status != Status.LOADED) {
setStatus(Status.LOADED);
}
} else if (data.isStaged()) {
if (status != Status.STAGED) {
setStatus(Status.STAGED);
}
} else if (data.isLoaded() == false && status == Status.LOADED) {
if (data.isStaged()) {
setStatus(Status.STAGED);
} else {
setStatus(Status.UNLOADED);
}
} else if (data.isStaged() == false && status == Status.STAGED) {
setStatus(Status.UNLOADED);
}
return super.getStatus();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.AbstractGLImage#getTextureCoords()
*/
@Override
public TextureCoords getTextureCoords() {
return new TextureCoords(0, 1, 1, 0);
}
}

View file

@ -105,7 +105,7 @@ public class GLImage extends AbstractGLImage implements IImageCacheable {
ImageCache.getInstance(CacheType.TEXTURE).remove(this);
}
public void disposeTexture(GL gl) {
public void disposeTexture() {
synchronized (this) {
if (theTexture == null) {
return;

View file

@ -0,0 +1,69 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.gl.images;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
import com.raytheon.viz.core.gl.dataformat.GLColorMapData;
/**
* Colormappable image that is writeable to in GL/GLSL but is not back by a
* Buffer and therefore not preinitialized or inspectable
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 16, 2013 2333 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class GLOffscreenColormappedImage extends AbstractGLColormappedImage {
/**
* @param data
* @param params
* @param extensionClass
*/
public GLOffscreenColormappedImage(GLColorMapData data,
ColorMapParameters params,
Class<? extends IImagingExtension> extensionClass) {
super(new GLCMTextureData(data), params, extensionClass);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.drawables.IColormappedImage#getValue(int,
* int)
*/
@Override
public double getValue(int x, int y) {
// TODO: Read value off of graphics card?
return Double.NaN;
}
}

View file

@ -0,0 +1,291 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.core.gl.images;
import java.nio.Buffer;
import java.util.HashMap;
import java.util.Map;
import javax.measure.unit.Unit;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import com.raytheon.uf.common.colormap.image.ColorMapData;
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.core.gl.GLContextBridge;
import com.raytheon.viz.core.gl.dataformat.GLBufferColorMapData;
import com.raytheon.viz.core.gl.dataformat.IGLColorMapDataFormatProvider;
import com.raytheon.viz.core.gl.internal.cache.IImageCacheable;
import com.raytheon.viz.core.gl.internal.cache.ImageCache;
import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
/**
* Object that represents a colormapped texture that can be unloaded and
* reloaded from main/graphics memory using a retrieval callback
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 24, 2013 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class GLRetrievableCMTextureData extends GLCMTextureData implements
IImageCacheable {
private static Map<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData> texMap = new HashMap<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData>();
/**
* Gets a {@link GLRetrievableCMTextureData} for the callback. These
* TextureData objects can be shared among callbacks
*
* @param callback
* @return
*/
public static GLRetrievableCMTextureData getGlTextureId(
IColorMapDataRetrievalCallback callback) {
synchronized (texMap) {
GLRetrievableCMTextureData data = texMap.get(callback);
if (data == null) {
data = new GLRetrievableCMTextureData(callback);
texMap.put(callback, data);
}
data.use();
return data;
}
}
private final IColorMapDataRetrievalCallback callback;
private int refCount = 0;
/**
* Private constructor, access only allowed through
* {@link #getGlTextureId(IColorMapDataRetrievalCallback)}
*
* @param callback
*/
private GLRetrievableCMTextureData(IColorMapDataRetrievalCallback callback) {
super(null);
this.callback = callback;
}
@Override
protected GLBufferColorMapData getDataObject() {
return (GLBufferColorMapData) super.getDataObject();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#stageTexture()
*/
@Override
public synchronized boolean stageTexture() throws VizException {
// Don't need to stage if we are already in GL
if (isLoaded()) {
return true;
}
// Don't need to stage if we already have data locally
if (isStaged()) {
return true;
}
// OK, Fetch the data
ColorMapData cmData = callback.getColorMapData();
if (cmData != null) {
IGLColorMapDataFormatProvider glDataFormatCallback = IGLColorMapDataFormatProvider.defaultCallback;
if (callback instanceof IGLColorMapDataFormatProvider) {
glDataFormatCallback = (IGLColorMapDataFormatProvider) callback;
}
this.data = new GLBufferColorMapData(cmData,
glDataFormatCallback.getGLColorMapDataFormat(cmData));
if (isStaged()) {
ImageCache.getInstance(CacheType.MEMORY).put(this);
return true;
}
}
// The data fetch didn't go well
return false;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.images.GLCMTextureData#loadTexture(javax.media
* .opengl.GL)
*/
@Override
public synchronized boolean loadTexture(GL gl) throws VizException {
if (super.loadTexture(gl)) {
ImageCache.getInstance(CacheType.TEXTURE).put(this);
return true;
}
return false;
}
@Override
public synchronized void disposeTexture() {
super.disposeTexture();
ImageCache.getInstance(CacheType.TEXTURE).remove(this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.internal.cache.IImageCacheable#disposeTextureData
* ()
*/
@Override
public void disposeTextureData() {
if (isStaged()) {
getDataObject().setData(null);
}
ImageCache.getInstance(CacheType.MEMORY).remove(this);
}
public void use() {
refCount += 1;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#dispose()
*/
@Override
public void dispose() {
synchronized (texMap) {
refCount -= 1;
if (refCount == 0) {
texMap.remove(callback);
ImageCache.getInstance(CacheType.TEXTURE).remove(this);
ImageCache.getInstance(CacheType.MEMORY).remove(this);
}
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#getTexId()
*/
@Override
public int getTexId() {
if (isLoaded()) {
ImageCache.getInstance(CacheType.TEXTURE).put(this);
}
return super.getTexId();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.util.cache.ICacheObject#getSize()
*/
@Override
public int getSize() {
GLBufferColorMapData data = getDataObject();
if (data != null) {
int[] dimensions = data.getDimensions();
int totalSize = data.getBytesPerPixel();
for (int i = 0; i < dimensions.length; ++i) {
totalSize *= dimensions[i];
}
return totalSize;
}
return 0;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#isStaged()
*/
@Override
public boolean isStaged() {
GLBufferColorMapData data = getDataObject();
// Override since we have our required data
return data != null && data.getData() != null;
}
public double getValue(int x, int y) {
GLBufferColorMapData data = getDataObject();
double value = Double.NaN;
if (!isStaged() && isLoaded()) {
GLContextBridge.makeMasterContextCurrent();
GL gl = GLU.getCurrentGL();
int textureStorageType = getTextureStorageType();
int copybackTextureType = data.getCopyBackTextureType();
Buffer copybackBuffer = data.getCopybackBuffer();
gl.glEnable(textureStorageType);
gl.glActiveTexture(GL.GL_TEXTURE0);
tex.bind(gl, textureStorageType);
gl.glGetTexImage(textureStorageType, 0, getTextureFormat(),
copybackTextureType, copybackBuffer.rewind());
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(textureStorageType, 0);
gl.glDisable(textureStorageType);
data.setTextureType(copybackTextureType);
data.setData(copybackBuffer);
GLContextBridge.releaseMasterContext();
}
if (data != null) {
ImageCache.getInstance(CacheType.MEMORY).put(this);
value = data.getValue(x, y).doubleValue();
}
return value;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.core.gl.images.GLCMTextureData#uploadTexture2D(javax
* .media.opengl.GL, int, int, int)
*/
@Override
protected void createTexture2D(GL gl, int type, int w, int h) {
gl.glTexImage2D(type, 0, getTextureInternalFormat(), w, h, 0,
getTextureFormat(), getTextureType(), getDataObject().getData()
.rewind());
}
/**
* Returns the {@link Unit} associated with the data
*
* @return the dataUnit
*/
public Unit<?> getDataUnit() {
GLBufferColorMapData data = getDataObject();
return data != null ? data.getDataUnit() : null;
}
}

View file

@ -19,8 +19,6 @@
**/
package com.raytheon.viz.core.gl.internal.cache;
import javax.media.opengl.GL;
import com.raytheon.uf.common.util.cache.ICacheObject;
/**
@ -44,6 +42,6 @@ public interface IImageCacheable extends ICacheObject {
public abstract void disposeTextureData();
public abstract void disposeTexture(GL gl);
public abstract void disposeTexture();
}

View file

@ -130,7 +130,7 @@ public class ImageCache extends LRUCache<Object, IImageCacheable> implements
new GLDisposer() {
@Override
protected void dispose(GL gl) {
i.disposeTexture(gl);
i.disposeTexture();
}
}.dispose();
}

View file

@ -24,8 +24,8 @@ import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension;
import com.raytheon.uf.viz.core.drawables.ext.IMosaicImageExtension.IMosaicImage;
import com.raytheon.viz.core.gl.images.GLColormappedImage;
import com.raytheon.viz.core.gl.images.GLDelegateImage;
import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
/**
* GL implementation of IMosaicImage, wraps an offscreen image and contains
@ -47,7 +47,7 @@ import com.raytheon.viz.core.gl.images.GLDelegateImage;
* @version 1.0
*/
public class GLMosaicImage extends GLDelegateImage<GLColormappedImage>
public class GLMosaicImage extends GLDelegateImage<GLOffscreenColormappedImage>
implements IMosaicImage {
private DrawableImage[] images;
@ -63,7 +63,7 @@ public class GLMosaicImage extends GLDelegateImage<GLColormappedImage>
* @param image
* @param extensionClass
*/
public GLMosaicImage(GLColormappedImage image, int[] bounds,
public GLMosaicImage(GLOffscreenColormappedImage image, int[] bounds,
IExtent imageExtent,
Class<? extends IMosaicImageExtension> extensionClass) {
super(image, extensionClass);
@ -167,7 +167,7 @@ public class GLMosaicImage extends GLDelegateImage<GLColormappedImage>
return image.getValue(x, y);
}
public void setWrappedImage(GLColormappedImage wrappedImage) {
public void setWrappedImage(GLOffscreenColormappedImage wrappedImage) {
this.image.dispose();
this.image = wrappedImage;
}

View file

@ -37,6 +37,7 @@ import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
import com.raytheon.viz.core.gl.images.AbstractGLImage;
import com.raytheon.viz.core.gl.images.GLColormappedImage;
import com.raytheon.viz.core.gl.images.GLOffscreenColormappedImage;
/**
* Extension used for rendering radar mosaic images
@ -47,9 +48,11 @@ import com.raytheon.viz.core.gl.images.GLColormappedImage;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 16, 2011 mschenke Initial creation
* Dec 16, 2011 mschenke Initial creation
* Mar 21, 2013 1806 bsteffen Update GL mosaicing to use dynamic data
* format for offscreen textures.
* Oct 16, 2013 2333 mschenke Cleaned up render logic, switched to
* use GLOffscreenColormappedImage
*
* </pre>
*
@ -60,11 +63,12 @@ import com.raytheon.viz.core.gl.images.GLColormappedImage;
public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
implements IMosaicImageExtension {
private GLColormappedImage writeToImage;
private GLOffscreenColormappedImage writeToImage;
public GLMosaicImage initializeRaster(int[] imageBounds,
IExtent imageExtent, ColorMapParameters params) throws VizException {
// Since byte is the most common type of mosaic start with a byte image. It might switch later if needed.
// Since byte is the most common type of mosaic start with a byte image.
// It might switch later if needed when images to mosaic are set
return new GLMosaicImage(target.getExtension(
GLOffscreenRenderingExtension.class).constructOffscreenImage(
ColorMapDataType.BYTE, imageBounds, params), imageBounds,
@ -80,6 +84,7 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
*/
@Override
public String getShaderProgramName() {
// Default mosaicing algorithm glsl program
return "mosaicOrdered";
}
@ -96,36 +101,47 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
AbstractGLImage image, PixelCoverage coverage) throws VizException {
if (image instanceof GLMosaicImage) {
GLMosaicImage mosaicImage = (GLMosaicImage) image;
boolean drawMosaic = true;
if (mosaicImage.isRepaint()) {
writeToImage = getWriteToImage(mosaicImage);
GLOffscreenRenderingExtension extension = target
.getExtension(GLOffscreenRenderingExtension.class);
try {
extension.renderOffscreen(mosaicImage,
mosaicImage.getImageExtent());
DrawableImage[] imagesToMosaic = mosaicImage
.getImagesToMosaic();
// Make sure images are staged before we mosaic them
ImagingSupport.prepareImages(target, imagesToMosaic);
DrawableImage[] imagesToMosaic = mosaicImage
.getImagesToMosaic();
// Make sure images are staged before we mosaic them
ImagingSupport.prepareImages(target, imagesToMosaic);
boolean allPainted = true;
// Each image needs to draw separately due to gl issues when
// zoomed in very far, rendered parts near the corners don't
// show all the pixels for each image. Pushing and popping
// GL_TEXTURE_BIT before/after each render fixes this issue
for (DrawableImage di : imagesToMosaic) {
allPainted &= drawRasters(paintProps, di);
writeToImage = getWriteToImage(mosaicImage);
if (writeToImage != null) {
GLOffscreenRenderingExtension extension = target
.getExtension(GLOffscreenRenderingExtension.class);
try {
extension.beginOffscreenRendering(mosaicImage,
mosaicImage.getImageExtent());
boolean allPainted = true;
// Each image needs to draw separately due to gl issues
// when zoomed in very far, rendered parts near the
// corners don't show all the pixels for each image.
// Pushing and popping GL_TEXTURE_BIT before/after each
// render fixes this issue
for (DrawableImage di : imagesToMosaic) {
allPainted &= drawRasters(paintProps, di);
}
// Need to set repaint based on if drawing completed.
mosaicImage.setRepaint(allPainted == false);
} finally {
extension.endOffscreenRendering();
}
// Need to set repaint based on if drawing completed.
mosaicImage.setRepaint(allPainted == false);
} finally {
extension.renderOnscreen();
writeToImage = null;
} else {
drawMosaic = false;
mosaicImage.setRepaint(true);
}
writeToImage = null;
}
target.drawRasters(paintProps,
new DrawableImage(mosaicImage.getWrappedImage(), coverage));
if (drawMosaic) {
target.drawRasters(paintProps,
new DrawableImage(mosaicImage.getWrappedImage(),
coverage));
}
// Don't actually render this image now since we just did it
return null;
} else {
@ -138,12 +154,13 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
}
}
private GLColormappedImage getWriteToImage(GLMosaicImage mosaicImage)
throws VizException {
private GLOffscreenColormappedImage getWriteToImage(
GLMosaicImage mosaicImage) throws VizException {
ColorMapDataType neededType = null;
for (DrawableImage di : mosaicImage.getImagesToMosaic()) {
IImage image = di.getImage();
if (image.getStatus() != Status.LOADED) {
if (image.getStatus() != Status.LOADED
&& image.getStatus() != Status.STAGED) {
continue;
}
if (image instanceof GLColormappedImage) {
@ -158,11 +175,17 @@ public class GLMosaicImageExtension extends AbstractGLSLImagingExtension
}
}
}
GLColormappedImage writeTo = mosaicImage.getWrappedImage();
if (neededType == null) {
return null;
}
GLOffscreenColormappedImage writeTo = mosaicImage.getWrappedImage();
if (neededType != null && neededType != writeTo.getColorMapDataType()) {
GLOffscreenRenderingExtension offscreenExt = target
.getExtension(GLOffscreenRenderingExtension.class);
int[] dimensions = { writeTo.getWidth(), writeTo.getHeight() };
writeTo.dispose();
writeTo = offscreenExt.constructOffscreenImage(neededType,
dimensions, writeTo.getColorMapParameters());
mosaicImage.setWrappedImage(writeTo);

View file

@ -220,8 +220,8 @@ public class SatResource extends
InterrogationResult result = null;
synchronized (tileMap) {
for (SatTileSetRenderable renderable : tileMap.values()) {
double rValue = renderable.interrogate(latLon);
if (Double.isNaN(rValue) == false && rValue != fillValue) {
double rValue = renderable.interrogate(latLon, fillValue);
if (Double.isNaN(rValue) == false) {
result = new InterrogationResult(
renderable.getSatelliteRecord(), rValue);
}

View file

@ -25,6 +25,8 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.measure.unit.Unit;
/**
*
* Container for colormap data.
@ -36,6 +38,7 @@ import java.nio.ShortBuffer;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 28, 2013 bsteffen Seperate from IColorMapDataRetrievalCallback
* Oct 16, 2013 2333 mschenke Added field for specifying the unit of the data
*
* </pre>
*
@ -48,11 +51,13 @@ public class ColorMapData {
BYTE, SIGNED_BYTE, UNSIGNED_SHORT, SHORT, INT, FLOAT;
}
private Buffer buffer;
private final Buffer buffer;
private int[] dimensions;
private final int[] dimensions;
private ColorMapData.ColorMapDataType dataType;
private final ColorMapData.ColorMapDataType dataType;
private final Unit<?> dataUnit;
/**
*
@ -63,6 +68,14 @@ public class ColorMapData {
this(buffer, dimensions, getDataType(buffer));
}
/**
* @param dataType
* @param dataBounds
*/
public ColorMapData(ColorMapDataType dataType, int[] dimensions) {
this(getBuffer(dataType, dimensions), dimensions, dataType);
}
/**
* @param buffer
* @param dataBounds
@ -70,19 +83,20 @@ public class ColorMapData {
*/
public ColorMapData(Buffer buffer, int[] dimensions,
ColorMapData.ColorMapDataType dataType) {
this.buffer = buffer;
this.dimensions = dimensions;
this.dataType = dataType;
this(buffer, dimensions, dataType, null);
}
/**
* @param dataType
* @param buffer
* @param dataBounds
* @param dataType
*/
public ColorMapData(ColorMapDataType dataType, int[] dimensions) {
this.buffer = getBuffer(dataType, dimensions);
public ColorMapData(Buffer buffer, int[] dimensions,
ColorMapData.ColorMapDataType dataType, Unit<?> dataUnit) {
this.buffer = buffer;
this.dimensions = dimensions;
this.dataType = dataType;
this.dataUnit = dataUnit;
}
public Buffer getBuffer() {
@ -97,6 +111,10 @@ public class ColorMapData {
return dataType;
}
public Unit<?> getDataUnit() {
return dataUnit;
}
public static ColorMapData.ColorMapDataType getDataType(Buffer buffer) {
if (buffer instanceof FloatBuffer) {
return ColorMapData.ColorMapDataType.FLOAT;

View file

@ -80,6 +80,8 @@ import com.raytheon.uf.common.datastorage.records.AbstractStorageRecord;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialEnabled;
import com.raytheon.uf.common.geospatial.interpolation.data.ByteBufferWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.UnsignedByteBufferWrapper;
//import com.raytheon.viz.core.gl.dataprep.ByteDataPreparer;
//import com.raytheon.viz.core.gl.dataprep.GlNumericImageData;
import com.raytheon.viz.core.gl.dataformat.GLByteDataFormat;
@ -845,15 +847,11 @@ SoundingModelReader sndingMdlRdr = new SoundingModelReader(
double tempDbl = Double.NaN;
if (retriever != null ){
/* Wrap the raw data of bytes into a GLByteDataFormat object */
//TODO? GLColorMapDataFormatFactory bdff = new GLColorMapDataFormatFactory();
//TODO? GLByteDataFormat bdf = bdff.getGLColorMapDataFormat(byteBuffer, retriever, rectangle, new int[] {maxX,maxY});
GLByteDataFormat bdf = new GLByteDataFormat();
ColorMapData cmd = new ColorMapData(byteBuffer, new int[] {maxX,maxY});
GLColorMapData glColorMapData = new GLColorMapData(cmd, bdf);
/* Wrap the raw data of bytes into a ByteBufferWrapper object */
UnsignedByteBufferWrapper bdf = new UnsignedByteBufferWrapper(byteBuffer, maxX, maxY);
/*Get the actual pixel value information from the byte array */
tempDbl = bdf.getValue( ( int )( outCoord[ 0 ] ), ( int ) ( outCoord[ 1 ] ), glColorMapData );
tempDbl = bdf.getDataValue( ( int )( outCoord[ 0 ] ), ( int ) ( outCoord[ 1 ] ));
if ( isSinglePixelNeeded ){
pixVal = new Double( (tempDbl) );
@ -880,7 +878,7 @@ SoundingModelReader sndingMdlRdr = new SoundingModelReader(
/*Generate the NxN array of pixel values*/
for ( int i = 0 ; i < newArrDimensions ; i++){
for ( int j = 0 ; j < newArrDimensions ; j++){
arrayOfPixVal[i][j] = bdf.getValue( ( int )( squarePixelArea[i][j].xCoord ), ( int ) ( squarePixelArea[i][j].yCoord ), glColorMapData );
arrayOfPixVal[i][j] = bdf.getDataValue( ( int )( squarePixelArea[i][j].xCoord ), ( int ) ( squarePixelArea[i][j].yCoord ));
}
}