1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17a4eae1abb4f2547dfbda84301ee764ce35464881John Reckpackage com.android.gallery3d.glrenderer;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap.Config;
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.opengl.GLUtils;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
23a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport junit.framework.Assert;
242b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap;
262b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// UploadedTextures use a Bitmap for the content of the texture.
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// Subclasses should implement onGetBitmap() to provide the Bitmap and
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// implement onFreeBitmap(mBitmap) which will be called when the Bitmap
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// is not needed anymore.
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// isContentValid() is meaningful only when the isLoaded() returns true.
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// It means whether the content needs to be updated.
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The user of this class should call recycle() when the texture is not
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// needed anymore.
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// By default an UploadedTexture is opaque (so it can be drawn faster without
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// blending). The user or subclass can override it using setOpaque().
43a4eae1abb4f2547dfbda84301ee764ce35464881John Reckpublic abstract class UploadedTexture extends BasicTexture {
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // To prevent keeping allocation the borders, we store those used borders here.
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Since the length will be power of two, it won't use too much memory.
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static HashMap<BorderKey, Bitmap> sBorderLines =
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            new HashMap<BorderKey, Bitmap>();
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static BorderKey sBorderKey = new BorderKey();
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @SuppressWarnings("unused")
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "Texture";
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mContentValid = true;
5437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
5537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    // indicate this textures is being uploaded in background
5637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    private boolean mIsUploading = false;
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mOpaque = true;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mThrottled = false;
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int sUploadedCount;
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int UPLOAD_LIMIT = 100;
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected Bitmap mBitmap;
631a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    private int mBorder;
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected UploadedTexture() {
661a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        this(false);
671a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    }
681a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
691a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    protected UploadedTexture(boolean hasBorder) {
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super(null, 0, STATE_UNLOADED);
711a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        if (hasBorder) {
721a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            setBorder(true);
731a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            mBorder = 1;
741a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        }
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
7737c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    protected void setIsUploading(boolean uploading) {
7837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        mIsUploading = uploading;
7937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    }
8037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
8137c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    public boolean isUploading() {
8237c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return mIsUploading;
8337c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    }
8437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class BorderKey implements Cloneable {
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean vertical;
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Config config;
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int length;
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int hashCode() {
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int x = config.hashCode() ^ length;
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return vertical ? x : -x;
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean equals(Object object) {
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (!(object instanceof BorderKey)) return false;
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            BorderKey o = (BorderKey) object;
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return vertical == o.vertical
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    && config == o.config && length == o.length;
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public BorderKey clone() {
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return (BorderKey) super.clone();
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } catch (CloneNotSupportedException e) {
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                throw new AssertionError(e);
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void setThrottled(boolean throttled) {
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mThrottled = throttled;
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static Bitmap getBorderLine(
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean vertical, Config config, int length) {
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        BorderKey key = sBorderKey;
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.vertical = vertical;
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.config = config;
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.length = length;
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Bitmap bitmap = sBorderLines.get(key);
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (bitmap == null) {
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            bitmap = vertical
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    ? Bitmap.createBitmap(1, length, config)
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    : Bitmap.createBitmap(length, 1, config);
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            sBorderLines.put(key.clone(), bitmap);
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return bitmap;
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Bitmap getBitmap() {
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap == null) {
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mBitmap = onGetBitmap();
1371a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            int w = mBitmap.getWidth() + mBorder * 2;
1381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            int h = mBitmap.getHeight() + mBorder * 2;
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mWidth == UNSPECIFIED) {
1401a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                setSize(w, h);
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mBitmap;
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void freeBitmap() {
147a4eae1abb4f2547dfbda84301ee764ce35464881John Reck        Assert.assertTrue(mBitmap != null);
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        onFreeBitmap(mBitmap);
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mBitmap = null;
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int getWidth() {
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mWidth == UNSPECIFIED) getBitmap();
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mWidth;
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int getHeight() {
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mWidth == UNSPECIFIED) getBitmap();
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mHeight;
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected abstract Bitmap onGetBitmap();
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected abstract void onFreeBitmap(Bitmap bitmap);
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void invalidateContent() {
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap != null) freeBitmap();
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentValid = false;
171cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang        mWidth = UNSPECIFIED;
172cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang        mHeight = UNSPECIFIED;
173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Whether the content on GPU is valid.
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
17837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    public boolean isContentValid() {
17937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return isLoaded() && mContentValid;
180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Updates the content on GPU's memory.
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * @param canvas
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void updateContent(GLCanvas canvas) {
18737c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        if (!isLoaded()) {
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) {
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return;
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            uploadToCanvas(canvas);
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (!mContentValid) {
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Bitmap bitmap = getBitmap();
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int format = GLUtils.getInternalFormat(bitmap);
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int type = GLUtils.getType(bitmap);
1967da54d7e41e04ea5122009b40de19be0724e1ca4George Mount            canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            freeBitmap();
198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mContentValid = true;
199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static void resetUploadLimit() {
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        sUploadedCount = 0;
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static boolean uploadLimitReached() {
207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return sUploadedCount > UPLOAD_LIMIT;
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void uploadToCanvas(GLCanvas canvas) {
211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Bitmap bitmap = getBitmap();
213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (bitmap != null) {
214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
2151a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int bWidth = bitmap.getWidth();
2161a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int bHeight = bitmap.getHeight();
2171a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int width = bWidth + mBorder * 2;
2181a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int height = bHeight + mBorder * 2;
2191a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int texWidth = getTextureWidth();
2201a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int texHeight = getTextureHeight();
221c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin
222a4eae1abb4f2547dfbda84301ee764ce35464881John Reck                Assert.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
223c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin
224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                // Upload the bitmap to a new texture.
22550b33abe053ccab7be3d1bca2328e792507963d4George Mount                mId = canvas.getGLId().generateTexture();
2267da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                canvas.setTextureParameters(this);
227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2281a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                if (bWidth == texWidth && bHeight == texHeight) {
2297da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                    canvas.initializeTexture(this, bitmap);
230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                } else {
231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    int format = GLUtils.getInternalFormat(bitmap);
232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    int type = GLUtils.getType(bitmap);
233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Config config = bitmap.getConfig();
234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2357da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                    canvas.initializeTextureSize(this, format, type);
2367da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                    canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
2371a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
2381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder > 0) {
2391a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        // Left border
2401a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(true, config, texHeight);
2417da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                        canvas.texSubImage2D(this, 0, 0, line, format, type);
2421a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
2431a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        // Top border
2441a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        line = getBorderLine(false, config, texWidth);
2457da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                        canvas.texSubImage2D(this, 0, 0, line, format, type);
246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2481a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    // Right border
2491a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder + bWidth < texWidth) {
2501a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(true, config, texHeight);
2517da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                        canvas.texSubImage2D(this, mBorder + bWidth, 0, line, format, type);
252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2541a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    // Bottom border
2551a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder + bHeight < texHeight) {
2561a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(false, config, texWidth);
2577da54d7e41e04ea5122009b40de19be0724e1ca4George Mount                        canvas.texSubImage2D(this, 0, mBorder + bHeight, line, format, type);
2581a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    }
259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } finally {
261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeBitmap();
262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // Update texture state.
264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            setAssociatedCanvas(canvas);
26537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            mState = STATE_LOADED;
266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mContentValid = true;
267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mState = STATE_ERROR;
269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            throw new RuntimeException("Texture load fail, no bitmap");
270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
273f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected boolean onBind(GLCanvas canvas) {
275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        updateContent(canvas);
27637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return isContentValid();
277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
278f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
279b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
280b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    protected int getTarget() {
281b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        return GL11.GL_TEXTURE_2D;
282b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
283b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setOpaque(boolean isOpaque) {
285f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mOpaque = isOpaque;
286f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
287f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2887817979db0c52ffeacb951625b1e821eba303285Ahbong Chang    @Override
289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean isOpaque() {
290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mOpaque;
291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void recycle() {
295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.recycle();
296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap != null) freeBitmap();
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
299