/* * Copyright (C) 2010 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 org.ebookdroid.common.bitmaps; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import org.emdev.common.log.LogContext; import org.emdev.common.log.LogManager; import org.emdev.ui.gl.BasicTexture; import org.emdev.ui.gl.GLCanvas; import org.emdev.ui.gl.GLId; // UploadedTextures use a Bitmap for the content of the texture. // // Subclasses should implement onGetBitmap() to provide the Bitmap and // implement onFreeBitmap(mBitmap) which will be called when the Bitmap // is not needed anymore. // // isContentValid() is meaningful only when the isLoaded() returns true. // It means whether the content needs to be updated. // // The user of this class should call recycle() when the texture is not // needed anymore. // // By default an UploadedTexture is opaque (so it can be drawn faster without // blending). The user or subclass can override it using setOpaque(). public class ByteBufferTexture extends BasicTexture { @SuppressWarnings("unused") private static final LogContext LCTX = LogManager.root().lctx("Texture"); private static int[] sTextureId = new int[1]; private static float[] sCropRect = new float[4]; private boolean mOpaque = true; protected ByteBufferBitmap mBitmap; public ByteBufferTexture(final ByteBufferBitmap bitmap) { super(null, 0, STATE_UNLOADED); this.mBitmap = bitmap; setSize(mBitmap.getWidth(), mBitmap.getHeight()); } protected void freeBitmap() { if (mBitmap != null) { mBitmap = null; } } @Override public int getWidth() { return mWidth; } @Override public int getHeight() { return mHeight; } /** * Updates the content on GPU's memory. * * @param canvas */ public void updateContent(final GLCanvas canvas) { if (!isLoaded()) { uploadToCanvas(canvas); } } private void uploadToCanvas(final GLCanvas canvas) { final GL11 gl = canvas.getGLInstance(); if (mBitmap != null) { try { final int bWidth = mBitmap.getWidth(); final int bHeight = mBitmap.getHeight(); final int texWidth = getTextureWidth(); final int texHeight = getTextureHeight(); // Define a vertically flipped crop rectangle for // OES_draw_texture. // The four values in sCropRect are: left, bottom, width, and // height. Negative value of width or height means flip. sCropRect[0] = 0; sCropRect[1] = bHeight; sCropRect[2] = bWidth; sCropRect[3] = -bHeight; // Upload the bitmap to a new texture. GLId.glGenTextures(1, sTextureId, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, sTextureId[0]); gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); if (bWidth == texWidth && bHeight == texHeight) { gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texWidth, texHeight, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, mBitmap.getPixels()); } else { gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texWidth, texHeight, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null); gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, bWidth, bHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, mBitmap.getPixels()); } } finally { freeBitmap(); } // Update texture state. setAssociatedCanvas(canvas); mId = sTextureId[0]; mState = STATE_LOADED; } else { mState = STATE_ERROR; LCTX.e("Texture load fail, no bitmap"); } } @Override protected boolean onBind(final GLCanvas canvas) { updateContent(canvas); return isLoaded(); } @Override protected int getTarget() { return GL10.GL_TEXTURE_2D; } public void setOpaque(final boolean isOpaque) { mOpaque = isOpaque; } @Override public boolean isOpaque() { return mOpaque; } @Override public void recycle() { super.recycle(); if (mBitmap != null) { freeBitmap(); } } }