14fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong/*
24fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * Copyright (C) 2011 The Android Open Source Project
34fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong *
44fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * Licensed under the Apache License, Version 2.0 (the "License");
54fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * you may not use this file except in compliance with the License.
64fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * You may obtain a copy of the License at
74fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong *
84fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong *      http://www.apache.org/licenses/LICENSE-2.0
94fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong *
104fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * Unless required by applicable law or agreed to in writing, software
114fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * distributed under the License is distributed on an "AS IS" BASIS,
124fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * See the License for the specific language governing permissions and
144fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong * limitations under the License.
154fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong */
164fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
174fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongpackage com.android.camera;
184fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
19c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Liimport android.annotation.TargetApi;
204fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.graphics.SurfaceTexture;
214fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.os.ConditionVariable;
224fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.os.Handler;
234fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.os.HandlerThread;
244fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.os.Looper;
254fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.os.Message;
264fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport android.util.Log;
274fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
28c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Liimport com.android.gallery3d.common.ApiHelper;
29c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li
304fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.egl.EGL10;
314fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.egl.EGLConfig;
324fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.egl.EGLContext;
334fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.egl.EGLDisplay;
344fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.egl.EGLSurface;
354fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongimport javax.microedition.khronos.opengles.GL10;
364fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
37c82461e017eed0c8bf73a646d782be3bb4f8d817Wu-cheng Li@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) // uses SurfaceTexture
384fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kongpublic class MosaicPreviewRenderer {
394fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static final String TAG = "MosaicPreviewRenderer";
404fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
414fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static final boolean DEBUG = false;
424fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
43553ebe08a5fd329178a44ea0d316df5d5551c92bWu-cheng Li    private int mWidth; // width of the view in UI
44553ebe08a5fd329178a44ea0d316df5d5551c92bWu-cheng Li    private int mHeight; // height of the view in UI
454fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
464fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private boolean mIsLandscape = true;
474fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private final float[] mTransformMatrix = new float[16];
484fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
494fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private ConditionVariable mEglThreadBlockVar = new ConditionVariable();
504fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private HandlerThread mEglThread;
514fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGLHandler mEglHandler;
524fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
534fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGLConfig mEglConfig;
544fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGLDisplay mEglDisplay;
554fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGLContext mEglContext;
564fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGLSurface mEglSurface;
574fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private SurfaceTexture mMosaicOutputSurfaceTexture;
584fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private SurfaceTexture mInputSurfaceTexture;
594fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private EGL10 mEgl;
604fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private GL10 mGl;
614fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
624fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private class EGLHandler extends Handler {
634fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        public static final int MSG_INIT_EGL_SYNC = 0;
647b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong        public static final int MSG_SHOW_PREVIEW_FRAME_SYNC = 1;
65252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        public static final int MSG_SHOW_PREVIEW_FRAME = 2;
668ed91ce2179d82e80437339fd17da7a3a8366b29Wu-cheng Li        public static final int MSG_ALIGN_FRAME_SYNC = 3;
67252da3c55a35c77fa4be4d51f79dac4aaf7cdb77Pin Ting        public static final int MSG_RELEASE = 4;
684fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
694fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        public EGLHandler(Looper looper) {
704fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            super(looper);
714fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
724fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
734fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        @Override
744fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        public void handleMessage(Message msg) {
754fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            switch (msg.what) {
764fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                case MSG_INIT_EGL_SYNC:
774fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    doInitGL();
784fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    mEglThreadBlockVar.open();
794fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    break;
807b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong                case MSG_SHOW_PREVIEW_FRAME_SYNC:
817b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong                    doShowPreviewFrame();
827b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong                    mEglThreadBlockVar.open();
837b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong                    break;
844fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                case MSG_SHOW_PREVIEW_FRAME:
854fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    doShowPreviewFrame();
864fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    break;
878ed91ce2179d82e80437339fd17da7a3a8366b29Wu-cheng Li                case MSG_ALIGN_FRAME_SYNC:
884fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    doAlignFrame();
898ed91ce2179d82e80437339fd17da7a3a8366b29Wu-cheng Li                    mEglThreadBlockVar.open();
904fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    break;
914fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                case MSG_RELEASE:
924fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    doRelease();
934fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    break;
944fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
954fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
964fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
974fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        private void doAlignFrame() {
984fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mInputSurfaceTexture.updateTexImage();
994fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);
1004fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1014fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.setWarping(true);
1024fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            // Call preprocess to render it to low-res and high-res RGB textures.
1034fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.preprocess(mTransformMatrix);
1044fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            // Now, transfer the textures from GPU to CPU memory for processing
1054fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.transferGPUtoCPU();
1064fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.updateMatrix();
1074fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            draw();
1084fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
1094fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
1104fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1114fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        private void doShowPreviewFrame() {
1124fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mInputSurfaceTexture.updateTexImage();
1134fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);
1144fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1154fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.setWarping(false);
1164fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            // Call preprocess to render it to low-res and high-res RGB textures.
1174fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.preprocess(mTransformMatrix);
1184fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.updateMatrix();
1194fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            draw();
1204fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
1214fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
1224fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1234fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        private void doInitGL() {
1244fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            // These are copied from GLSurfaceView
1254fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl = (EGL10) EGLContext.getEGL();
1264fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
1274fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
1284fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                throw new RuntimeException("eglGetDisplay failed");
1294fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
1304fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            int[] version = new int[2];
1314fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            if (!mEgl.eglInitialize(mEglDisplay, version)) {
1324fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                throw new RuntimeException("eglInitialize failed");
1334fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            } else {
1344fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                Log.v(TAG, "EGL version: " + version[0] + '.' + version[1]);
1354fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
1364fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            int[] attribList = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
1374fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglConfig = chooseConfig(mEgl, mEglDisplay);
1384fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT,
1394fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                                                attribList);
1404fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1414fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
1424fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                throw new RuntimeException("failed to createContext");
1434fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
1444fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglSurface = mEgl.eglCreateWindowSurface(
1454fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    mEglDisplay, mEglConfig, mMosaicOutputSurfaceTexture, null);
1464fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
1474fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                throw new RuntimeException("failed to createWindowSurface");
1484fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
1494fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1504fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
1514fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                throw new RuntimeException("failed to eglMakeCurrent");
1524fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            }
1534fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1544fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mGl = (GL10) mEglContext.getGL();
1554fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1564fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mInputSurfaceTexture = new SurfaceTexture(MosaicRenderer.init());
1574fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            MosaicRenderer.reset(mWidth, mHeight, mIsLandscape);
1584fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
1594fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1604fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        private void doRelease() {
1614fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
1624fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
1634fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
1644fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                    EGL10.EGL_NO_CONTEXT);
1654fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEgl.eglTerminate(mEglDisplay);
1664fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglSurface = null;
1674fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglContext = null;
1684fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglDisplay = null;
1691baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li            releaseSurfaceTexture(mInputSurfaceTexture);
1704fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglThread.quit();
1714fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
1724fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1731baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li        @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
1741baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li        private void releaseSurfaceTexture(SurfaceTexture st) {
1751baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li            if (ApiHelper.HAS_RELEASE_SURFACE_TEXTURE) {
1761baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li                st.release();
1771baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li            }
1781baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li        }
1791baf539a75dd8c987ad496330160ba4e2d87473aWu-cheng Li
1804fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        // Should be called from other thread.
1814fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        public void sendMessageSync(int msg) {
1824fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglThreadBlockVar.close();
1834fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            sendEmptyMessage(msg);
1844fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            mEglThreadBlockVar.block();
1854fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
1864fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1874fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
1884fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1894fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    public MosaicPreviewRenderer(SurfaceTexture tex, int w, int h, boolean isLandscape) {
1904fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mMosaicOutputSurfaceTexture = tex;
1914fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mWidth = w;
1924fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mHeight = h;
1934fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mIsLandscape = isLandscape;
1944fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1954fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglThread = new HandlerThread("PanoramaRealtimeRenderer");
1964fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglThread.start();
1974fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglHandler = new EGLHandler(mEglThread.getLooper());
1984fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
1994fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        // We need to sync this because the generation of surface texture for input is
2004fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        // done here and the client will continue with the assumption that the
2014fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        // generation is completed.
2024fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglHandler.sendMessageSync(EGLHandler.MSG_INIT_EGL_SYNC);
2034fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2044fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2054fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    public void release() {
2064fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglHandler.sendEmptyMessage(EGLHandler.MSG_RELEASE);
2074fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2084fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2097b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong    public void showPreviewFrameSync() {
2107b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong        mEglHandler.sendMessageSync(EGLHandler.MSG_SHOW_PREVIEW_FRAME_SYNC);
2117b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong    }
2127b91d89f6f8a07dcdd630ff9b8b4413adcaee3fbAngus Kong
2134fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    public void showPreviewFrame() {
2144fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        mEglHandler.sendEmptyMessage(EGLHandler.MSG_SHOW_PREVIEW_FRAME);
2154fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2164fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2178ed91ce2179d82e80437339fd17da7a3a8366b29Wu-cheng Li    public void alignFrameSync() {
2188ed91ce2179d82e80437339fd17da7a3a8366b29Wu-cheng Li        mEglHandler.sendMessageSync(EGLHandler.MSG_ALIGN_FRAME_SYNC);
2194fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2204fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2214fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    public SurfaceTexture getInputSurfaceTexture() {
2224fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        return mInputSurfaceTexture;
2234fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2244fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2254fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private void draw() {
2264fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        MosaicRenderer.step();
2274fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2284fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2294fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static void checkEglError(String prompt, EGL10 egl) {
2304fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        int error;
2314fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
2324fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
2334fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
2344fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2354fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2364fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static final int EGL_OPENGL_ES2_BIT = 4;
2374fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static final int[] CONFIG_SPEC = new int[] {
2384fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2394fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            EGL10.EGL_RED_SIZE, 8,
2404fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            EGL10.EGL_GREEN_SIZE, 8,
2414fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            EGL10.EGL_BLUE_SIZE, 8,
2424fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            EGL10.EGL_NONE
2434fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    };
2444fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2454fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    private static EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
2464fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        int[] numConfig = new int[1];
2474fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        if (!egl.eglChooseConfig(display, CONFIG_SPEC, null, 0, numConfig)) {
2484fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            throw new IllegalArgumentException("eglChooseConfig failed");
2494fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
2504fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2514fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        int numConfigs = numConfig[0];
2524fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        if (numConfigs <= 0) {
2534fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            throw new IllegalArgumentException("No configs match configSpec");
2544fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
2554fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2564fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        EGLConfig[] configs = new EGLConfig[numConfigs];
2574fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        if (!egl.eglChooseConfig(
2584fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong                display, CONFIG_SPEC, configs, numConfigs, numConfig)) {
2594fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong            throw new IllegalArgumentException("eglChooseConfig#2 failed");
2604fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        }
2614fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong
2624fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong        return configs[0];
2634fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong    }
2644fabf52f7e8b2419749f5cdc03925d5f8b1c0199Angus Kong}
265