1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.camera.ui; 18 19import android.graphics.Bitmap; 20import android.graphics.Bitmap.Config; 21import android.opengl.GLUtils; 22 23import com.android.camera.Util; 24 25import javax.microedition.khronos.opengles.GL11; 26import javax.microedition.khronos.opengles.GL11Ext; 27 28public abstract class Texture { 29 30 @SuppressWarnings("unused") 31 private static final String TAG = "Texture"; 32 protected static final int UNSPECIFIED = -1; 33 34 public static final int STATE_UNLOADED = 0; 35 public static final int STATE_LOADED = 1; 36 public static final int STATE_ERROR = -1; 37 38 protected GL11 mGL; 39 40 protected int mId; 41 protected int mState; 42 43 protected int mWidth = UNSPECIFIED; 44 protected int mHeight = UNSPECIFIED; 45 46 private float mTexCoordWidth = 1.0f; 47 private float mTexCoordHeight = 1.0f; 48 49 protected Texture(GL11 gl, int id, int state) { 50 mGL = gl; 51 mId = id; 52 mState = state; 53 } 54 55 protected Texture() { 56 this(null, 0, STATE_UNLOADED); 57 } 58 59 protected void setSize(int width, int height) { 60 mWidth = width; 61 mHeight = height; 62 } 63 64 protected void setTexCoordSize(float width, float height) { 65 mTexCoordWidth = width; 66 mTexCoordHeight = height; 67 } 68 69 public int getId() { 70 return mId; 71 } 72 73 public int getWidth() { 74 return mWidth; 75 } 76 77 public int getHeight() { 78 return mHeight; 79 } 80 81 protected abstract Bitmap getBitmap(); 82 83 protected abstract void freeBitmap(Bitmap bitmap); 84 85 public void deleteFromGL() { 86 if (mState == STATE_LOADED) { 87 mGL.glDeleteTextures(1, new int[]{mId}, 0); 88 } 89 mState = STATE_UNLOADED; 90 } 91 92 private void uploadToGL(GL11 gl) throws GLOutOfMemoryException { 93 Bitmap bitmap = getBitmap(); 94 int glError = GL11.GL_NO_ERROR; 95 if (bitmap != null) { 96 int[] textureId = new int[1]; 97 try { 98 // Define a vertically flipped crop rectangle for 99 // OES_draw_texture. 100 int[] cropRect = {0, mHeight, mWidth, - mHeight}; 101 102 // Upload the bitmap to a new texture. 103 gl.glGenTextures(1, textureId, 0); 104 gl.glBindTexture(GL11.GL_TEXTURE_2D, textureId[0]); 105 gl.glTexParameteriv(GL11.GL_TEXTURE_2D, 106 GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); 107 gl.glTexParameteri(GL11.GL_TEXTURE_2D, 108 GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); 109 gl.glTexParameteri(GL11.GL_TEXTURE_2D, 110 GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); 111 gl.glTexParameterf(GL11.GL_TEXTURE_2D, 112 GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); 113 gl.glTexParameterf(GL11.GL_TEXTURE_2D, 114 GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); 115 GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0); 116 } finally { 117 freeBitmap(bitmap); 118 } 119 if (glError == GL11.GL_OUT_OF_MEMORY) { 120 throw new GLOutOfMemoryException(); 121 } 122 if (glError != GL11.GL_NO_ERROR) { 123 mId = 0; 124 mState = STATE_UNLOADED; 125 throw new RuntimeException( 126 "Texture upload fail, glError " + glError); 127 } else { 128 // Update texture state. 129 mGL = gl; 130 mId = textureId[0]; 131 mState = Texture.STATE_LOADED; 132 } 133 } else { 134 mState = STATE_ERROR; 135 throw new RuntimeException("Texture load fail, no bitmap"); 136 } 137 } 138 139 public void draw(GLRootView root, int x, int y) { 140 root.drawTexture(this, x, y, mWidth, mHeight); 141 } 142 143 public void draw(GLRootView root, int x, int y, int w, int h, float alpha) { 144 root.drawTexture(this, x, y, w, h, alpha); 145 } 146 147 protected boolean bind(GLRootView root, GL11 gl) { 148 if (mState == Texture.STATE_UNLOADED || mGL != gl) { 149 mState = Texture.STATE_UNLOADED; 150 try { 151 uploadToGL(gl); 152 } catch (GLOutOfMemoryException e) { 153 root.handleLowMemory(); 154 return false; 155 } 156 } else { 157 gl.glBindTexture(GL11.GL_TEXTURE_2D, getId()); 158 } 159 return true; 160 } 161 162 public void getTextureCoords(float coord[], int offset) { 163 float w = mTexCoordWidth; 164 float h = mTexCoordHeight; 165 166 coord[offset++] = 0; 167 coord[offset++] = 0; 168 coord[offset++] = w; 169 coord[offset++] = 0; 170 coord[offset++] = 0; 171 coord[offset++] = h; 172 coord[offset++] = w; 173 coord[offset] = h; 174 } 175 176 protected Bitmap generateGLCompatibleBitmap(int width, int height) { 177 int newWidth = Util.nextPowerOf2(width); 178 int newHeight = Util.nextPowerOf2(height); 179 mTexCoordWidth = (float) width / newWidth; 180 mTexCoordHeight = (float) height / newHeight; 181 return Bitmap.createBitmap(newWidth, newHeight, Config.ARGB_8888); 182 } 183} 184