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
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap.Config;
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.opengl.GLUtils;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
232b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils;
242b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap;
262b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11;
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport javax.microedition.khronos.opengles.GL11Ext;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// UploadedTextures use a Bitmap for the content of the texture.
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// Subclasses should implement onGetBitmap() to provide the Bitmap and
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// implement onFreeBitmap(mBitmap) which will be called when the Bitmap
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// is not needed anymore.
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// isContentValid() is meaningful only when the isLoaded() returns true.
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// It means whether the content needs to be updated.
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// The user of this class should call recycle() when the texture is not
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// needed anymore.
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin//
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// By default an UploadedTexture is opaque (so it can be drawn faster without
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin// blending). The user or subclass can override it using setOpaque().
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linabstract class UploadedTexture extends BasicTexture {
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // To prevent keeping allocation the borders, we store those used borders here.
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Since the length will be power of two, it won't use too much memory.
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static HashMap<BorderKey, Bitmap> sBorderLines =
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            new HashMap<BorderKey, Bitmap>();
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static BorderKey sBorderKey = new BorderKey();
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @SuppressWarnings("unused")
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "Texture";
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mContentValid = true;
5537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
5637c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    // indicate this textures is being uploaded in background
5737c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    private boolean mIsUploading = false;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mOpaque = true;
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mThrottled = false;
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int sUploadedCount;
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int UPLOAD_LIMIT = 100;
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected Bitmap mBitmap;
641a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    private int mBorder;
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected UploadedTexture() {
671a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        this(false);
681a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    }
691a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
701a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang    protected UploadedTexture(boolean hasBorder) {
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super(null, 0, STATE_UNLOADED);
721a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        if (hasBorder) {
731a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            setBorder(true);
741a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            mBorder = 1;
751a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang        }
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
7837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    protected void setIsUploading(boolean uploading) {
7937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        mIsUploading = uploading;
8037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    }
8137c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
8237c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    public boolean isUploading() {
8337c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return mIsUploading;
8437c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    }
8537c605949219b8bf54c165c34d6405f5f2989f50Owen Lin
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static class BorderKey implements Cloneable {
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean vertical;
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Config config;
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int length;
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int hashCode() {
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int x = config.hashCode() ^ length;
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return vertical ? x : -x;
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public boolean equals(Object object) {
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (!(object instanceof BorderKey)) return false;
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            BorderKey o = (BorderKey) object;
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return vertical == o.vertical
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    && config == o.config && length == o.length;
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public BorderKey clone() {
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return (BorderKey) super.clone();
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } catch (CloneNotSupportedException e) {
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                throw new AssertionError(e);
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void setThrottled(boolean throttled) {
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mThrottled = throttled;
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static Bitmap getBorderLine(
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            boolean vertical, Config config, int length) {
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        BorderKey key = sBorderKey;
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.vertical = vertical;
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.config = config;
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        key.length = length;
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Bitmap bitmap = sBorderLines.get(key);
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (bitmap == null) {
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            bitmap = vertical
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    ? Bitmap.createBitmap(1, length, config)
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    : Bitmap.createBitmap(length, 1, config);
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            sBorderLines.put(key.clone(), bitmap);
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return bitmap;
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Bitmap getBitmap() {
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap == null) {
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mBitmap = onGetBitmap();
1381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            int w = mBitmap.getWidth() + mBorder * 2;
1391a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            int h = mBitmap.getHeight() + mBorder * 2;
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mWidth == UNSPECIFIED) {
1411a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                setSize(w, h);
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mBitmap;
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void freeBitmap() {
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Utils.assertTrue(mBitmap != null);
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        onFreeBitmap(mBitmap);
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mBitmap = null;
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int getWidth() {
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mWidth == UNSPECIFIED) getBitmap();
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mWidth;
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int getHeight() {
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mWidth == UNSPECIFIED) getBitmap();
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mHeight;
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected abstract Bitmap onGetBitmap();
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected abstract void onFreeBitmap(Bitmap bitmap);
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void invalidateContent() {
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap != null) freeBitmap();
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentValid = false;
172cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang        mWidth = UNSPECIFIED;
173cb4fb7c19f20405fb5e08513e6297dffce824118Chih-Chung Chang        mHeight = UNSPECIFIED;
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Whether the content on GPU is valid.
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
17937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin    public boolean isContentValid() {
18037c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return isLoaded() && mContentValid;
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    /**
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * Updates the content on GPU's memory.
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     * @param canvas
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin     */
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void updateContent(GLCanvas canvas) {
18837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        if (!isLoaded()) {
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) {
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return;
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            uploadToCanvas(canvas);
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (!mContentValid) {
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Bitmap bitmap = getBitmap();
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int format = GLUtils.getInternalFormat(bitmap);
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int type = GLUtils.getType(bitmap);
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.getGLInstance().glBindTexture(GL11.GL_TEXTURE_2D, mId);
1981a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang            GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, mBorder, mBorder,
1991a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    bitmap, format, type);
200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            freeBitmap();
201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mContentValid = true;
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static void resetUploadLimit() {
206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        sUploadedCount = 0;
207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static boolean uploadLimitReached() {
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return sUploadedCount > UPLOAD_LIMIT;
211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    static int[] sTextureId = new int[1];
214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    static float[] sCropRect = new float[4];
215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void uploadToCanvas(GLCanvas canvas) {
217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        GL11 gl = canvas.getGLInstance();
218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Bitmap bitmap = getBitmap();
220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (bitmap != null) {
221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            try {
2221a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int bWidth = bitmap.getWidth();
2231a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int bHeight = bitmap.getHeight();
2241a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int width = bWidth + mBorder * 2;
2251a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int height = bHeight + mBorder * 2;
2261a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int texWidth = getTextureWidth();
2271a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                int texHeight = getTextureHeight();
228c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin
229c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin                Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
230c2c0b01fbbf243eee1a11c33ba6dd1ce918a9ce5Owen Lin
231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                // Define a vertically flipped crop rectangle for
232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                // OES_draw_texture.
2331a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                // The four values in sCropRect are: left, bottom, width, and
2341a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                // height. Negative value of width or height means flip.
2351a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                sCropRect[0] = mBorder;
2361a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                sCropRect[1] = mBorder + bHeight;
2371a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                sCropRect[2] = bWidth;
2381a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                sCropRect[3] = -bHeight;
239f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
240f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                // Upload the bitmap to a new texture.
241b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang                GLId.glGenTextures(1, sTextureId, 0);
242f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glBindTexture(GL11.GL_TEXTURE_2D, sTextureId[0]);
243f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glTexParameterfv(GL11.GL_TEXTURE_2D,
244f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0);
245f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glTexParameteri(GL11.GL_TEXTURE_2D,
246f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE);
247f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glTexParameteri(GL11.GL_TEXTURE_2D,
248f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE);
249f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glTexParameterf(GL11.GL_TEXTURE_2D,
250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                gl.glTexParameterf(GL11.GL_TEXTURE_2D,
252f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
253f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2541a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                if (bWidth == texWidth && bHeight == texHeight) {
255f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
256f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                } else {
257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    int format = GLUtils.getInternalFormat(bitmap);
258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    int type = GLUtils.getType(bitmap);
259f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Config config = bitmap.getConfig();
260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format,
2621a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                            texWidth, texHeight, 0, format, type, null);
2631a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0,
2641a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                            mBorder, mBorder, bitmap, format, type);
2651a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
2661a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder > 0) {
2671a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        // Left border
2681a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(true, config, texHeight);
2691a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0,
2701a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                                0, 0, line, format, type);
2711a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang
2721a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        // Top border
2731a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        line = getBorderLine(false, config, texWidth);
2741a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0,
2751a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                                0, 0, line, format, type);
276f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2781a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    // Right border
2791a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder + bWidth < texWidth) {
2801a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(true, config, texHeight);
2811a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0,
2821a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                                mBorder + bWidth, 0, line, format, type);
283f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
284f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2851a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    // Bottom border
2861a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    if (mBorder + bHeight < texHeight) {
2871a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        Bitmap line = getBorderLine(false, config, texWidth);
2881a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                        GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0,
2891a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                                0, mBorder + bHeight, line, format, type);
2901a088db165c138f57d9445ca0b7e50fe90d3ad1dChih-Chung Chang                    }
291f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
292f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } finally {
293f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeBitmap();
294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            // Update texture state.
296f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            setAssociatedCanvas(canvas);
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mId = sTextureId[0];
29837c605949219b8bf54c165c34d6405f5f2989f50Owen Lin            mState = STATE_LOADED;
299f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mContentValid = true;
300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mState = STATE_ERROR;
302f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            throw new RuntimeException("Texture load fail, no bitmap");
303f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
304f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
305f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
306f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
307f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected boolean onBind(GLCanvas canvas) {
308f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        updateContent(canvas);
30937c605949219b8bf54c165c34d6405f5f2989f50Owen Lin        return isContentValid();
310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
312b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
313b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    protected int getTarget() {
314b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        return GL11.GL_TEXTURE_2D;
315b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
316b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
317f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setOpaque(boolean isOpaque) {
318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mOpaque = isOpaque;
319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean isOpaque() {
322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mOpaque;
323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
326f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void recycle() {
327f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.recycle();
328f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBitmap != null) freeBitmap();
329f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
330f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
331