diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/TexImageTransform.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/TexImageTransform.java | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/TexImageTransform.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/TexImageTransform.java deleted file mode 100644 index dde89eae6..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/TexImageTransform.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.gltrace.state.transforms; - -import com.android.ide.eclipse.gltrace.FileUtils; -import com.android.ide.eclipse.gltrace.GLEnum; -import com.android.ide.eclipse.gltrace.state.GLStringProperty; -import com.android.ide.eclipse.gltrace.state.IGLProperty; -import com.google.common.io.Files; -import com.google.common.primitives.UnsignedBytes; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; - -import javax.imageio.ImageIO; - -/** - * {@link TexImageTransform} transforms the state to reflect the effect of a - * glTexImage2D or glTexSubImage2D GL call. - */ -public class TexImageTransform implements IStateTransform { - private static final String PNG_IMAGE_FORMAT = "PNG"; - private static final String TEXTURE_FILE_PREFIX = "tex"; - private static final String TEXTURE_FILE_SUFFIX = ".png"; - - private final IGLPropertyAccessor mAccessor; - private final File mTextureDataFile; - - private final int mxOffset; - private final int myOffset; - private final int mWidth; - private final int mHeight; - - private String mOldValue; - private String mNewValue; - private GLEnum mFormat; - private GLEnum mType; - - /** - * Construct a texture image transformation. - * @param accessor accessor to obtain the GL state variable to modify - * @param textureData texture data passed in by the call. Could be null. - * @param format format of the source texture data - * @param xOffset x offset for the source data (used only in glTexSubImage2D) - * @param yOffset y offset for the source data (used only in glTexSubImage2D) - * @param width width of the texture - * @param height height of the texture - */ - public TexImageTransform(IGLPropertyAccessor accessor, File textureData, GLEnum format, - GLEnum type, int xOffset, int yOffset, int width, int height) { - mAccessor = accessor; - mTextureDataFile = textureData; - mFormat = format; - mType = type; - - mxOffset = xOffset; - myOffset = yOffset; - mWidth = width; - mHeight = height; - } - - @Override - public void apply(IGLProperty currentState) { - assert mOldValue == null : "Transform cannot be applied multiple times"; //$NON-NLS-1$ - - IGLProperty property = mAccessor.getProperty(currentState); - if (!(property instanceof GLStringProperty)) { - return; - } - - GLStringProperty prop = (GLStringProperty) property; - mOldValue = prop.getStringValue(); - - // Applying texture transformations is a heavy weight process. So we perform - // it only once and save the result in a temporary file. The property is actually - // the path to the file. - if (mNewValue == null) { - try { - if (mOldValue == null) { - mNewValue = createTexture(mTextureDataFile, mWidth, mHeight); - } else { - mNewValue = updateTextureData(mOldValue, mTextureDataFile, mxOffset, myOffset, - mWidth, mHeight); - } - } catch (IOException e) { - throw new RuntimeException(e); - } catch (RuntimeException e) { - throw e; - } - } - - prop.setValue(mNewValue); - } - - @Override - public void revert(IGLProperty state) { - if (mOldValue != null) { - IGLProperty property = mAccessor.getProperty(state); - property.setValue(mOldValue); - mOldValue = null; - } - } - - @Override - public IGLProperty getChangedProperty(IGLProperty state) { - return mAccessor.getProperty(state); - } - - /** - * Creates a texture of provided width and height. If the texture data file is provided, - * then the texture is initialized with the contents of that file, otherwise an empty - * image is created. - * @param textureDataFile path to texture data, could be null. - * @param width width of texture - * @param height height of texture - * @return path to cached texture - */ - private String createTexture(File textureDataFile, int width, int height) throws IOException { - File f = FileUtils.createTempFile(TEXTURE_FILE_PREFIX, TEXTURE_FILE_SUFFIX); - - BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); - - if (textureDataFile != null) { - byte[] initialData = Files.toByteArray(textureDataFile); - img.getRaster().setDataElements(0, 0, width, height, - formatSourceData(initialData, width, height)); - } - - ImageIO.write(img, PNG_IMAGE_FORMAT, f); - - return f.getAbsolutePath(); - } - - /** - * Update part of an existing texture. - * @param currentImagePath current texture image. - * @param textureDataFile new data to update the current texture with - * @param xOffset x offset for the update region - * @param yOffset y offset for the update region - * @param width width of the update region - * @param height height of the update region - * @return path to the updated texture - */ - private String updateTextureData(String currentImagePath, File textureDataFile, - int xOffset, int yOffset, int width, int height) throws IOException { - assert currentImagePath != null : "Attempt to update a null texture"; - - if (textureDataFile == null) { - // Do not perform any updates if we don't have the actual data. - return currentImagePath; - } - - File f = FileUtils.createTempFile(TEXTURE_FILE_PREFIX, TEXTURE_FILE_SUFFIX); - BufferedImage image = null; - image = ImageIO.read(new File(currentImagePath)); - - byte[] subImageData = Files.toByteArray(textureDataFile); - image.getRaster().setDataElements(xOffset, yOffset, width, height, - formatSourceData(subImageData, width, height)); - ImageIO.write(image, PNG_IMAGE_FORMAT, f); - - return f.getAbsolutePath(); - } - - private byte[] formatSourceData(byte[] subImageData, int width, int height) { - if (mType != GLEnum.GL_UNSIGNED_BYTE) { - subImageData = unpackData(subImageData, mType); - } - - switch (mFormat) { - case GL_RGBA: - // no conversions necessary - return subImageData; - case GL_RGB: - return addAlphaChannel(subImageData, width, height); - case GL_RED: - case GL_GREEN: - case GL_BLUE: - // GL_RED, GL_GREEN and GL_BLUE are all supposed to fill those respective - // channels, but we assume that the programmers intent was to use GL_ALPHA in order - // to overcome the issue that GL_ALPHA cannot be used with float data. - if (mType != GLEnum.GL_FLOAT) { - throw new RuntimeException(); - } else { - // fall through - assume that it is GL_ALPHA - } - //$FALL-THROUGH$ - case GL_ALPHA: - return addRGBChannels(subImageData, width, height); - case GL_LUMINANCE: - return createRGBAFromLuminance(subImageData, width, height); - case GL_LUMINANCE_ALPHA: - return createRGBAFromLuminanceAlpha(subImageData, width, height); - default: - throw new RuntimeException(); - } - } - - private byte[] unpackData(byte[] data, GLEnum type) { - switch (type) { - case GL_UNSIGNED_BYTE: - return data; - case GL_UNSIGNED_SHORT_4_4_4_4: - return convertShortToUnsigned(data, 0xf000, 12, 0x0f00, 8, 0x00f0, 4, 0x000f, 0, - true); - case GL_UNSIGNED_SHORT_5_6_5: - return convertShortToUnsigned(data, 0xf800, 11, 0x07e0, 5, 0x001f, 0, 0, 0, - false); - case GL_UNSIGNED_SHORT_5_5_5_1: - return convertShortToUnsigned(data, 0xf800, 11, 0x07c0, 6, 0x003e, 1, 0x1, 0, - true); - case GL_FLOAT: - return convertFloatToUnsigned(data); - default: - return data; - } - } - - private byte[] convertFloatToUnsigned(byte[] data) { - byte[] unsignedData = new byte[data.length]; - ByteBuffer floatBuffer = ByteBuffer.wrap(data); - for (int i = 0; i < data.length / 4; i++) { - float v = floatBuffer.getFloat(i); - byte alpha = (byte)(v * 255); - unsignedData[i*4 + 3] = alpha; - } - return unsignedData; - } - - private byte[] convertShortToUnsigned(byte[] shortData, - int rmask, int rshift, - int gmask, int gshift, - int bmask, int bshift, - int amask, int ashift, - boolean includeAlpha) { - int numChannels = includeAlpha ? 4 : 3; - byte[] unsignedData = new byte[(shortData.length/2) * numChannels]; - - for (int i = 0; i < (shortData.length / 2); i++) { - int hi = UnsignedBytes.toInt(shortData[i*2 + 0]); - int lo = UnsignedBytes.toInt(shortData[i*2 + 1]); - - int x = hi << 8 | lo; - - int r = (x & rmask) >>> rshift; - int g = (x & gmask) >>> gshift; - int b = (x & bmask) >>> bshift; - int a = (x & amask) >>> ashift; - - unsignedData[i * numChannels + 0] = UnsignedBytes.checkedCast(r); - unsignedData[i * numChannels + 1] = UnsignedBytes.checkedCast(g); - unsignedData[i * numChannels + 2] = UnsignedBytes.checkedCast(b); - - if (includeAlpha) { - unsignedData[i * numChannels + 3] = UnsignedBytes.checkedCast(a); - } - } - - return unsignedData; - } - - private byte[] addAlphaChannel(byte[] sourceData, int width, int height) { - assert sourceData.length == 3 * width * height; // should have R, G & B channels - - byte[] data = new byte[4 * width * height]; - - for (int src = 0, dst = 0; src < sourceData.length; src += 3, dst += 4) { - data[dst + 0] = sourceData[src + 0]; // copy R byte - data[dst + 1] = sourceData[src + 1]; // copy G byte - data[dst + 2] = sourceData[src + 2]; // copy B byte - data[dst + 3] = 1; // add alpha = 1 - } - - return data; - } - - private byte[] addRGBChannels(byte[] sourceData, int width, int height) { - assert sourceData.length == width * height; // should have a single alpha channel - - byte[] data = new byte[4 * width * height]; - - for (int src = 0, dst = 0; src < sourceData.length; src++, dst += 4) { - data[dst + 0] = data[dst + 1] = data[dst + 2] = 0; // set R = G = B = 0 - data[dst + 3] = sourceData[src]; // copy over alpha - } - - return data; - } - - private byte[] createRGBAFromLuminance(byte[] sourceData, int width, int height) { - assert sourceData.length == width * height; // should have a single luminance channel - - byte[] data = new byte[4 * width * height]; - - for (int src = 0, dst = 0; src < sourceData.length; src++, dst += 4) { - int l = sourceData[src] * 3; - if (l > 255) { // clamp to 255 - l = 255; - } - - data[dst + 0] = data[dst + 1] = data[dst + 2] = (byte) l; // set R = G = B = L * 3 - data[dst + 3] = 1; // set alpha = 1 - } - - return data; - } - - private byte[] createRGBAFromLuminanceAlpha(byte[] sourceData, int width, int height) { - assert sourceData.length == 2 * width * height; // should have luminance & alpha channels - - byte[] data = new byte[4 * width * height]; - - for (int src = 0, dst = 0; src < sourceData.length; src += 2, dst += 4) { - int l = sourceData[src] * 3; - if (l > 255) { // clamp to 255 - l = 255; - } - - data[dst + 0] = data[dst + 1] = data[dst + 2] = (byte) l; // set R = G = B = L * 3 - data[dst + 3] = sourceData[src + 1]; // copy over alpha - } - - return data; - } -} |