1b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang/*
2b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * Copyright (C) 2012 The Android Open Source Project
3b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang *
4b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License");
5b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * you may not use this file except in compliance with the License.
6b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * You may obtain a copy of the License at
7b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang *
8b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang *      http://www.apache.org/licenses/LICENSE-2.0
9b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang *
10b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * Unless required by applicable law or agreed to in writing, software
11b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS,
12b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * See the License for the specific language governing permissions and
14b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang * limitations under the License.
15b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang */
16b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
17b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Changpackage com.android.gallery3d.ui;
18b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
196772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport android.annotation.TargetApi;
20b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Changimport android.graphics.RectF;
21b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Changimport android.graphics.SurfaceTexture;
22b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
236772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Changimport com.android.gallery3d.common.ApiHelper;
24a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.ExtTexture;
25a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.GLCanvas;
266772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang
27a9fb0f51165bf1ba8287f4abaf5319efaf2cae84Wu-cheng Li@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
28b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Changpublic abstract class SurfaceTextureScreenNail implements ScreenNail,
29b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        SurfaceTexture.OnFrameAvailableListener {
307817979db0c52ffeacb951625b1e821eba303285Ahbong Chang    @SuppressWarnings("unused")
31b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    private static final String TAG = "SurfaceTextureScreenNail";
326772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    // This constant is not available in API level before 15, but it was just an
336772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    // oversight.
346772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
356772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang
36ffc2a4a77f7164dd435d07c11a3df290c4b64079Angus Kong    protected ExtTexture mExtTexture;
37b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    private SurfaceTexture mSurfaceTexture;
38b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    private int mWidth, mHeight;
39b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    private float[] mTransform = new float[16];
40b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    private boolean mHasTexture = false;
41b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
42b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public SurfaceTextureScreenNail() {
43b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
44b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
4550b33abe053ccab7be3d1bca2328e792507963d4George Mount    public void acquireSurfaceTexture(GLCanvas canvas) {
4650b33abe053ccab7be3d1bca2328e792507963d4George Mount        mExtTexture = new ExtTexture(canvas, GL_TEXTURE_EXTERNAL_OES);
47b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mExtTexture.setSize(mWidth, mHeight);
48b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mSurfaceTexture = new SurfaceTexture(mExtTexture.getId());
496772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang        setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
50b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mSurfaceTexture.setOnFrameAvailableListener(this);
51b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        synchronized (this) {
52b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            mHasTexture = true;
53b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        }
54b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
55b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
566772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
576772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    private static void setDefaultBufferSize(SurfaceTexture st, int width, int height) {
586772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang        if (ApiHelper.HAS_SET_DEFALT_BUFFER_SIZE) {
596772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang            st.setDefaultBufferSize(width, height);
606772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang        }
616772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang    }
626772173d2a49b87a1d209f42fe52b5f830596f99Chih-Chung Chang
63840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
64840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang    private static void releaseSurfaceTexture(SurfaceTexture st) {
6571ba6e959569cb90f415490e40bd95855f894cc5John Reck        st.setOnFrameAvailableListener(null);
66840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang        if (ApiHelper.HAS_RELEASE_SURFACE_TEXTURE) {
67840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang            st.release();
68840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang        }
69840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang    }
70840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang
71b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public SurfaceTexture getSurfaceTexture() {
72b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        return mSurfaceTexture;
73b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
74b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
75b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public void releaseSurfaceTexture() {
76b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        synchronized (this) {
77b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            mHasTexture = false;
78b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        }
79b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mExtTexture.recycle();
80b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mExtTexture = null;
81840ae396bac4ff8ff34e88c8d2a1773cb112a4b6Chih-Chung Chang        releaseSurfaceTexture(mSurfaceTexture);
82b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mSurfaceTexture = null;
83b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
84b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
85b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public void setSize(int width, int height) {
86b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mWidth = width;
87b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        mHeight = height;
88b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
89b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
90b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount    public void resizeTexture() {
91b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount        if (mExtTexture != null) {
92b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount            mExtTexture.setSize(mWidth, mHeight);
93b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount            setDefaultBufferSize(mSurfaceTexture, mWidth, mHeight);
94b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount        }
95b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount    }
96b6d494925ea14a02ef75f58d5d969d7586914ef7George Mount
97b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
98b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public int getWidth() {
99b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        return mWidth;
100b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
101b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
102b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
103b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public int getHeight() {
104b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        return mHeight;
105b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
106b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
107b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
108b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public void draw(GLCanvas canvas, int x, int y, int width, int height) {
109b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        synchronized (this) {
110b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            if (!mHasTexture) return;
111b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            mSurfaceTexture.updateTexImage();
112b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            mSurfaceTexture.getTransformMatrix(mTransform);
113b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
114b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            // Flip vertically.
115b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
116b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            int cx = x + width / 2;
117b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            int cy = y + height / 2;
118b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.translate(cx, cy);
119b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.scale(1, -1, 1);
120b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.translate(-cx, -cy);
1214ce48412b86ac28042bf70e4cbe051ffc3dd489dJohn Reck            updateTransformMatrix(mTransform);
122b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.drawTexture(mExtTexture, mTransform, x, y, width, height);
123b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang            canvas.restore();
124b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        }
125b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
126b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
127b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
128b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    public void draw(GLCanvas canvas, RectF source, RectF dest) {
129b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang        throw new UnsupportedOperationException();
130b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    }
131b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
1324ce48412b86ac28042bf70e4cbe051ffc3dd489dJohn Reck    protected void updateTransformMatrix(float[] matrix) {}
1334ce48412b86ac28042bf70e4cbe051ffc3dd489dJohn Reck
134b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
135b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    abstract public void noDraw();
136b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
137b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
138b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang    abstract public void recycle();
139b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang
140b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    @Override
141b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang    abstract public void onFrameAvailable(SurfaceTexture surfaceTexture);
142b29a27f475a2c449abdda8d4e03d30914feed8c6Chih-Chung Chang}
143