From f257c936bae9a10a539a225bd28d27bc52c44604 Mon Sep 17 00:00:00 2001 From: tarsin Date: Mon, 18 Jul 2022 16:57:43 +0800 Subject: [PATCH] Use fwb's glSurfaceView --- .../com/hippo/glview/view/GLRootView.java | 89 +-- .../com/hippo/tuxiang/BaseConfigChooser.java | 85 --- .../hippo/tuxiang/ComponentSizeChooser.java | 94 --- .../hippo/tuxiang/DefaultContextFactory.java | 58 -- .../tuxiang/DefaultWindowSurfaceFactory.java | 53 -- .../com/hippo/tuxiang/EGLConfigChooser.java | 43 -- .../com/hippo/tuxiang/EGLContextFactory.java | 38 - .../tuxiang/EGLWindowSurfaceFactory.java | 39 - .../java/com/hippo/tuxiang/EglHelper.java | 298 -------- .../main/java/com/hippo/tuxiang/GLStuff.java | 320 -------- .../java/com/hippo/tuxiang/GLSurfaceView.java | 434 ----------- .../java/com/hippo/tuxiang/GLTextureView.java | 292 -------- .../main/java/com/hippo/tuxiang/GLThread.java | 686 ------------------ .../com/hippo/tuxiang/GLThreadManager.java | 41 -- .../java/com/hippo/tuxiang/GLWrapper.java | 50 -- .../main/java/com/hippo/tuxiang/Renderer.java | 160 ---- .../hippo/tuxiang/SimpleEGLConfigChooser.java | 29 - 17 files changed, 29 insertions(+), 2780 deletions(-) delete mode 100644 app/src/main/java/com/hippo/tuxiang/BaseConfigChooser.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/ComponentSizeChooser.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/DefaultContextFactory.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/DefaultWindowSurfaceFactory.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/EGLConfigChooser.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/EGLContextFactory.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/EGLWindowSurfaceFactory.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/EglHelper.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLStuff.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLSurfaceView.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLTextureView.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLThread.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLThreadManager.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/GLWrapper.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/Renderer.java delete mode 100644 app/src/main/java/com/hippo/tuxiang/SimpleEGLConfigChooser.java diff --git a/app/src/main/java/com/hippo/glview/view/GLRootView.java b/app/src/main/java/com/hippo/glview/view/GLRootView.java index 66b2b8f90..762930603 100644 --- a/app/src/main/java/com/hippo/glview/view/GLRootView.java +++ b/app/src/main/java/com/hippo/glview/view/GLRootView.java @@ -16,12 +16,11 @@ package com.hippo.glview.view; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; +import android.opengl.GLSurfaceView; import android.opengl.GLUtils; -import android.os.Build; import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; @@ -42,10 +41,6 @@ import com.hippo.glview.glrenderer.UploadedTexture; import com.hippo.glview.util.ApiHelper; import com.hippo.glview.util.GalleryUtils; import com.hippo.glview.util.MotionEventHelper; -import com.hippo.tuxiang.EGLConfigChooser; -import com.hippo.tuxiang.EGLContextFactory; -import com.hippo.tuxiang.GLSurfaceView; -import com.hippo.tuxiang.Renderer; import com.hippo.yorozuya.AssertUtils; import java.util.ArrayDeque; @@ -89,12 +84,7 @@ public class GLRootView extends GLSurfaceView private final ReentrantLock mRenderLock = new ReentrantLock(); private final Condition mFreezeCondition = mRenderLock.newCondition(); - private final Runnable mRequestRenderOnAnimationFrame = new Runnable() { - @Override - public void run() { - superRequestRender(); - } - }; + private final Runnable mRequestRenderOnAnimationFrame = this::superRequestRender; private int mFrameCount = 0; private long mFrameCountingStart = 0; private int mInvalidateColor = 0; @@ -187,11 +177,7 @@ public class GLRootView extends GLSurfaceView } if (mRenderRequested) return; mRenderRequested = true; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - postOnAnimation(mRequestRenderOnAnimationFrame); - } else { - super.requestRender(); - } + postOnAnimation(mRequestRenderOnAnimationFrame); } private void superRequestRender() { @@ -281,7 +267,7 @@ public class GLRootView extends GLSurfaceView ++mFrameCount; } - private void onDrawFrameLocked(GL10 gl) { + private void onDrawFrameLocked() { if (DEBUG_FPS) outputFps(); // release the unbound textures and deleted buffers. mCanvas.deleteRecycledResources(); @@ -391,9 +377,20 @@ public class GLRootView extends GLSurfaceView @Override public void onPause() { unfreeze(); + if (mContentView != null) { + mContentView.pause(); + } super.onPause(); } + @Override + public void onResume() { + if (mContentView != null) { + mContentView.resume(); + } + super.onResume(); + } + @Override public void setOrientationSource(OrientationSource source) { mOrientationSource = source; @@ -430,7 +427,6 @@ public class GLRootView extends GLSurfaceView } @Override - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void setLightsOutMode(boolean enabled) { if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return; @@ -503,7 +499,7 @@ public class GLRootView extends GLSurfaceView } } - private class GLRootRenderer implements Renderer { + private class GLRootRenderer implements GLSurfaceView.Renderer { /** * Called when the context is created, possibly after automatic destruction. @@ -547,7 +543,7 @@ public class GLRootView extends GLSurfaceView } @Override - public boolean onDrawFrame(GL10 gl) { + public void onDrawFrame(GL10 gl) { AnimationTime.update(); long t0 = System.nanoTime(); @@ -559,7 +555,7 @@ public class GLRootView extends GLSurfaceView } try { - onDrawFrameLocked(gl); + onDrawFrameLocked(); } finally { mRenderLock.unlock(); } @@ -570,33 +566,6 @@ public class GLRootView extends GLSurfaceView if (duration > 8) { Log.v(TAG, "--- " + duration + " ---"); } - - return true; - } - - @Override - public void onGLThreadStart() { - } - - @Override - public void onGLThreadExit() { - if (mContentView != null && mContentView.isAttachedToRoot()) { - mContentView.detachFromRoot(); - } - } - - @Override - public void onGLThreadPause() { - if (mContentView != null) { - mContentView.pause(); - } - } - - @Override - public void onGLThreadResume() { - if (mContentView != null) { - mContentView.resume(); - } } } @@ -662,7 +631,7 @@ public class GLRootView extends GLSurfaceView throw new IllegalArgumentException("No config chosen"); } - int renderableType = findConfigAttrib(egl, display, config, EGL10.EGL_RENDERABLE_TYPE, 0); + int renderableType = findConfigAttrib(egl, display, config, EGL10.EGL_RENDERABLE_TYPE); if ((renderableType & 0x0004) == 0x0004 /* EGL_OPENGL_ES2_BIT */) { mEGLContextClientVersion = 2; } else { @@ -680,21 +649,21 @@ public class GLRootView extends GLSurfaceView for (int i = 0, n = configs.length; i < n; i++) { final EGLConfig config = configs[i]; final int redSize = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); + EGL10.EGL_RED_SIZE); final int greenSize = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); + EGL10.EGL_GREEN_SIZE); final int blueSize = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); + EGL10.EGL_BLUE_SIZE); final int alphaSize = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); + EGL10.EGL_ALPHA_SIZE); final int sampleBuffers = findConfigAttrib(egl, display, config, - EGL10.EGL_SAMPLE_BUFFERS, 0); + EGL10.EGL_SAMPLE_BUFFERS); final int samples = findConfigAttrib(egl, display, config, - EGL10.EGL_SAMPLES, 0); + EGL10.EGL_SAMPLES); final int depth = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); + EGL10.EGL_DEPTH_SIZE); final int stencil = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); + EGL10.EGL_STENCIL_SIZE); final int score = redSize + greenSize + blueSize + alphaSize + sampleBuffers + samples - depth - stencil; @@ -709,11 +678,11 @@ public class GLRootView extends GLSurfaceView } private int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { + EGLConfig config, int attribute) { if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { return mValue[0]; } - return defaultValue; + return 0; } } diff --git a/app/src/main/java/com/hippo/tuxiang/BaseConfigChooser.java b/app/src/main/java/com/hippo/tuxiang/BaseConfigChooser.java deleted file mode 100644 index 2932657eb..000000000 --- a/app/src/main/java/com/hippo/tuxiang/BaseConfigChooser.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; - -// android-9.0.0_r30 - -public abstract class BaseConfigChooser implements EGLConfigChooser { - - private final int mEGLContextClientVersion; - - public BaseConfigChooser(int eglContextClientVersion, int[] configSpec) { - mEGLContextClientVersion = eglContextClientVersion; - mConfigSpec = filterConfigSpec(configSpec); - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - final int[] num_config = new int[1]; - if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, - num_config)) { - throw new IllegalArgumentException("eglChooseConfig failed"); - } - - final int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException( - "No configs match configSpec"); - } - - final EGLConfig[] configs = new EGLConfig[numConfigs]; - if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config)) { - throw new IllegalArgumentException("eglChooseConfig#2 failed"); - } - final EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - public abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - - private int[] filterConfigSpec(int[] configSpec) { - if (mEGLContextClientVersion != 2 && mEGLContextClientVersion != 3) { - return configSpec; - } - /* We know none of the subclasses define EGL_RENDERABLE_TYPE. - * And we know the configSpec is well formed. - */ - final int len = configSpec.length; - final int[] newConfigSpec = new int[len + 2]; - System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); - newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; - if (mEGLContextClientVersion == 2) { - newConfigSpec[len] = 0x0004; /* EGL_OPENGL_ES2_BIT */ - } else { - newConfigSpec[len] = 0x0040; /* EGL_OPENGL_ES3_BIT_KHR */ - } - newConfigSpec[len+1] = EGL10.EGL_NONE; - return newConfigSpec; - } -} diff --git a/app/src/main/java/com/hippo/tuxiang/ComponentSizeChooser.java b/app/src/main/java/com/hippo/tuxiang/ComponentSizeChooser.java deleted file mode 100644 index d9487eac2..000000000 --- a/app/src/main/java/com/hippo/tuxiang/ComponentSizeChooser.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; - -// android-9.0.0_r30 - -/** - * Choose a configuration with exactly the specified r,g,b,a sizes, - * and at least the specified depth and stencil sizes. - */ -public class ComponentSizeChooser extends BaseConfigChooser { - - public ComponentSizeChooser(int eglContextClientVersion, - int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize) { - super(eglContextClientVersion, new int[] { - EGL10.EGL_RED_SIZE, redSize, - EGL10.EGL_GREEN_SIZE, greenSize, - EGL10.EGL_BLUE_SIZE, blueSize, - EGL10.EGL_ALPHA_SIZE, alphaSize, - EGL10.EGL_DEPTH_SIZE, depthSize, - EGL10.EGL_STENCIL_SIZE, stencilSize, - EGL10.EGL_NONE}); - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - for (final EGLConfig config : configs) { - final int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - final int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - if ((d >= mDepthSize) && (s >= mStencilSize)) { - final int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - final int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - final int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - final int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - if ((r == mRedSize) && (g == mGreenSize) - && (b == mBlueSize) && (a == mAlphaSize)) { - return config; - } - } - } - return null; - } - - private int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { - - if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { - return mValue[0]; - } - return defaultValue; - } - - private final int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; -} diff --git a/app/src/main/java/com/hippo/tuxiang/DefaultContextFactory.java b/app/src/main/java/com/hippo/tuxiang/DefaultContextFactory.java deleted file mode 100644 index 621cc0c95..000000000 --- a/app/src/main/java/com/hippo/tuxiang/DefaultContextFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.util.Log; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; - -// android-9.0.0_r30 - -public class DefaultContextFactory implements EGLContextFactory { - - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - - private final int mEGLContextClientVersion; - - public DefaultContextFactory(int eglContextClientVersion) { - mEGLContextClientVersion = eglContextClientVersion; - } - - @Override - public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) { - final int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion, - EGL10.EGL_NONE }; - - return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, - mEGLContextClientVersion != 0 ? attrib_list : null); - } - - @Override - public void destroyContext(EGL10 egl, EGLDisplay display, - EGLContext context) { - if (!egl.eglDestroyContext(display, context)) { - Log.e("DefaultContextFactory", "display:" + display + " context: " + context); - if (GLStuff.LOG_THREADS) { - Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId()); - } - EglHelper.throwEglException("eglDestroyContex", egl.eglGetError()); - } - } -} diff --git a/app/src/main/java/com/hippo/tuxiang/DefaultWindowSurfaceFactory.java b/app/src/main/java/com/hippo/tuxiang/DefaultWindowSurfaceFactory.java deleted file mode 100644 index 817a00787..000000000 --- a/app/src/main/java/com/hippo/tuxiang/DefaultWindowSurfaceFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.util.Log; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; - -// android-9.0.0_r30 - -public class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { - - @Override - public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, - EGLConfig config, Object nativeWindow) { - EGLSurface result = null; - try { - result = egl.eglCreateWindowSurface(display, config, nativeWindow, null); - } catch (IllegalArgumentException e) { - // This exception indicates that the surface flinger surface - // is not valid. This can happen if the surface flinger surface has - // been torn down, but the application has not yet been - // notified via SurfaceHolder.Callback.surfaceDestroyed. - // In theory the application should be notified first, - // but in practice sometimes it is not. See b/4588890 - Log.e("DefWinSurfaceFactory", "eglCreateWindowSurface", e); - } - return result; - } - - @Override - public void destroySurface(EGL10 egl, EGLDisplay display, - EGLSurface surface) { - egl.eglDestroySurface(display, surface); - } -} diff --git a/app/src/main/java/com/hippo/tuxiang/EGLConfigChooser.java b/app/src/main/java/com/hippo/tuxiang/EGLConfigChooser.java deleted file mode 100644 index 5b7ce9827..000000000 --- a/app/src/main/java/com/hippo/tuxiang/EGLConfigChooser.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; - -// android-9.0.0_r30 - -/** - * An interface for choosing an EGLConfig configuration from a list of - * potential configurations. - *

- * This interface must be implemented by clients wishing to call - * {@link GLStuff#setEGLConfigChooser(EGLConfigChooser)} - */ -public interface EGLConfigChooser { - /** - * Choose a configuration from the list. Implementors typically - * implement this method by calling - * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the - * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. - * @param egl the EGL10 for the current display. - * @param display the current display. - * @return the chosen configuration. - */ - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); -} diff --git a/app/src/main/java/com/hippo/tuxiang/EGLContextFactory.java b/app/src/main/java/com/hippo/tuxiang/EGLContextFactory.java deleted file mode 100644 index d05a574bf..000000000 --- a/app/src/main/java/com/hippo/tuxiang/EGLContextFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * An interface for customizing the eglCreateContext and eglDestroyContext calls. - */ -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; - -// android-9.0.0_r30 - -/** - * An interface for customizing the eglCreateContext and eglDestroyContext calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLStuff#setEGLContextFactory(EGLContextFactory)} - */ -public interface EGLContextFactory { - EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); - void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); -} diff --git a/app/src/main/java/com/hippo/tuxiang/EGLWindowSurfaceFactory.java b/app/src/main/java/com/hippo/tuxiang/EGLWindowSurfaceFactory.java deleted file mode 100644 index c2a83dc4e..000000000 --- a/app/src/main/java/com/hippo/tuxiang/EGLWindowSurfaceFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; - -// android-9.0.0_r30 - -/** - * An interface for customizing the eglCreateWindowSurface and eglDestroySurface calls. - *

- * This interface must be implemented by clients wishing to call - * {@link GLStuff#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} - */ -public interface EGLWindowSurfaceFactory { - /** - * @return null if the surface cannot be constructed. - */ - EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, EGLConfig config, - Object nativeWindow); - void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); -} diff --git a/app/src/main/java/com/hippo/tuxiang/EglHelper.java b/app/src/main/java/com/hippo/tuxiang/EglHelper.java deleted file mode 100644 index bab12e2fb..000000000 --- a/app/src/main/java/com/hippo/tuxiang/EglHelper.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.opengl.GLDebugHelper; -import android.opengl.GLUtils; -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.io.Writer; -import java.lang.ref.WeakReference; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL; - -// android-9.0.0_r30 - -/** - * An EGL helper class. - */ -class EglHelper { - public EglHelper(WeakReference glStuffWeakRef) { - mGLStuffViewWeakRef = glStuffWeakRef; - } - - /** - * Initialize EGL for a given configuration spec. - */ - public void start() { - if (GLStuff.LOG_EGL) { - Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId()); - } - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("eglGetDisplay failed"); - } - - /* - * We can now initialize EGL for that display - */ - final int[] version = new int[2]; - if(!mEgl.eglInitialize(mEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed"); - } - final GLStuff stuff = mGLStuffViewWeakRef.get(); - if (stuff == null) { - mEglConfig = null; - mEglContext = null; - } else { - mEglConfig = stuff.getEGLConfigChooser().chooseConfig(mEgl, mEglDisplay); - - /* - * Create an EGL context. We want to do this as rarely as we can, because an - * EGL context is a somewhat heavy object. - */ - mEglContext = stuff.getEGLContextFactory().createContext(mEgl, mEglDisplay, mEglConfig); - } - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - mEglContext = null; - throwEglException("createContext"); - } - if (GLStuff.LOG_EGL) { - Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId()); - } - - mEglSurface = null; - } - - /** - * Create an egl surface for the current SurfaceHolder surface. If a surface - * already exists, destroy it before creating the new surface. - * - * @return true if the surface was created successfully. - */ - public boolean createSurface() { - if (GLStuff.LOG_EGL) { - Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId()); - } - /* - * Check preconditions. - */ - if (mEgl == null) { - throw new RuntimeException("egl not initialized"); - } - if (mEglDisplay == null) { - throw new RuntimeException("eglDisplay not initialized"); - } - if (mEglConfig == null) { - throw new RuntimeException("mEglConfig not initialized"); - } - - /* - * The window size has changed, so we need to create a new - * surface. - */ - destroySurfaceImp(); - - /* - * Create an EGL surface we can render into. - */ - final GLStuff stuff = mGLStuffViewWeakRef.get(); - if (stuff != null) { - mEglSurface = stuff.getEGLWindowSurfaceFactory().createWindowSurface(mEgl, - mEglDisplay, mEglConfig, stuff.getNativeWindow()); - } else { - mEglSurface = null; - } - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - final int error = mEgl.eglGetError(); - if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { - Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); - } - return false; - } - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - /* - * Could not make the context current, probably because the underlying - * SurfaceView surface has been destroyed. - */ - logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); - return false; - } - - return true; - } - - /** - * Create a GL object for the current EGL context. - */ - GL createGL() { - - GL gl = mEglContext.getGL(); - final GLStuff stuff = mGLStuffViewWeakRef.get(); - if (stuff != null) { - final GLWrapper glWrapper = stuff.getGLWrapper(); - if (glWrapper != null) { - gl = glWrapper.wrap(gl); - } - - final int debugFlags = stuff.getDebugFlags(); - if ((debugFlags & (GLStuff.DEBUG_CHECK_GL_ERROR | GLStuff.DEBUG_LOG_GL_CALLS)) != 0) { - int configFlags = 0; - Writer log = null; - if ((debugFlags & GLStuff.DEBUG_CHECK_GL_ERROR) != 0) { - configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR; - } - if ((debugFlags & GLStuff.DEBUG_LOG_GL_CALLS) != 0) { - log = new LogWriter(); - } - gl = GLDebugHelper.wrap(gl, configFlags, log); - } - } - return gl; - } - - /** - * Display the current render surface. - * @return the EGL error code from eglSwapBuffers. - */ - public int swap() { - if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { - return mEgl.eglGetError(); - } - return EGL10.EGL_SUCCESS; - } - - public void destroySurface() { - if (GLStuff.LOG_EGL) { - Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId()); - } - destroySurfaceImp(); - } - - private void destroySurfaceImp() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - final GLStuff stuff = mGLStuffViewWeakRef.get(); - if (stuff != null) { - stuff.getEGLWindowSurfaceFactory().destroySurface(mEgl, mEglDisplay, mEglSurface); - } - mEglSurface = null; - } - } - - public void finish() { - if (GLStuff.LOG_EGL) { - Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId()); - } - if (mEglContext != null) { - final GLStuff stuff = mGLStuffViewWeakRef.get(); - if (stuff != null) { - stuff.getEGLContextFactory().destroyContext(mEgl, mEglDisplay, mEglContext); - } - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - private void throwEglException(String function) { - throwEglException(function, mEgl.eglGetError()); - } - - public static void throwEglException(String function, int error) { - final String message = formatEglError(function, error); - if (GLStuff.LOG_THREADS) { - Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " - + message); - } - throw new RuntimeException(message); - } - - public static void logEglErrorAsWarning(String tag, String function, int error) { - Log.w(tag, formatEglError(function, error)); - } - - public static String formatEglError(String function, int error) { - return function + " failed: " + GLUtils.getEGLErrorString(error); - } - - private final WeakReference mGLStuffViewWeakRef; - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - - - static class LogWriter extends Writer { - - @Override public void close() { - flushBuilder(); - } - - @Override public void flush() { - flushBuilder(); - } - - @Override public void write(@NonNull char[] buf, int offset, int count) { - for(int i = 0; i < count; i++) { - final char c = buf[offset + i]; - if ( c == '\n') { - flushBuilder(); - } - else { - mBuilder.append(c); - } - } - } - - private void flushBuilder() { - if (mBuilder.length() > 0) { - Log.v("GLSurfaceView", mBuilder.toString()); - mBuilder.delete(0, mBuilder.length()); - } - } - - private final StringBuilder mBuilder = new StringBuilder(); - } -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLStuff.java b/app/src/main/java/com/hippo/tuxiang/GLStuff.java deleted file mode 100644 index d342232c8..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLStuff.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.opengles.GL; - -// android-9.0.0_r30 - -public interface GLStuff { - - boolean LOG_ATTACH_DETACH = false; - boolean LOG_THREADS = false; - boolean LOG_PAUSE_RESUME = false; - boolean LOG_SURFACE = false; - boolean LOG_RENDERER = false; - boolean LOG_RENDERER_DRAW_FRAME = false; - boolean LOG_EGL = false; - - /** - * The renderer only renders - * when the surface is created, or when {@link #requestRender} is called. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - * @see #requestRender() - */ - int RENDERMODE_WHEN_DIRTY = 0; - - /** - * The renderer is called - * continuously to re-render the scene. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - */ - int RENDERMODE_CONTINUOUSLY = 1; - - /** - * Check glError() after every GL call and throw an exception if glError indicates - * that an error has occurred. This can be used to help track down which OpenGL ES call - * is causing an error. - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - int DEBUG_CHECK_GL_ERROR = 1; - - /** - * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - int DEBUG_LOG_GL_CALLS = 2; - - /** - * Get the native window object - */ - Object getNativeWindow(); - - /** - * Set the glWrapper. If the glWrapper is not null, its - * {@link GLWrapper#wrap(GL)} method is called - * whenever a surface is created. A GLWrapper can be used to wrap - * the GL object that's passed to the renderer. Wrapping a GL - * object enables examining and modifying the behavior of the - * GL calls made by the renderer. - *

- * Wrapping is typically used for debugging purposes. - *

- * The default value is null. - * @param glWrapper the new GLWrapper - */ - void setGLWrapper(GLWrapper glWrapper); - - /** - * @return Returns the {@code GLWrapper} - */ - GLWrapper getGLWrapper(); - - /** - * Set the debug flags to a new value. The value is - * constructed by OR-together zero or more - * of the DEBUG_CHECK_* constants. The debug flags take effect - * whenever a surface is created. The default value is zero. - * @param debugFlags the new debug flags - * @see #DEBUG_CHECK_GL_ERROR - * @see #DEBUG_LOG_GL_CALLS - */ - void setDebugFlags(int debugFlags); - - /** - * Get the current value of the debug flags. - * @return the current value of the debug flags. - */ - int getDebugFlags(); - - /** - * Control whether the EGL context is preserved when the GLSurfaceView is paused and - * resumed. - *

- * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. - *

- * Prior to API level 11, whether the EGL context is actually preserved or not - * depends upon whether the Android device can support an arbitrary number of - * EGL contexts or not. Devices that can only support a limited number of EGL - * contexts must release the EGL context in order to allow multiple applications - * to share the GPU. - *

- * If set to false, the EGL context will be released when the GLSurfaceView is paused, - * and recreated when the GLSurfaceView is resumed. - *

- * - * The default is false. - * - * @param preserveOnPause preserve the EGL context when paused - */ - void setPreserveEGLContextOnPause(boolean preserveOnPause); - - /** - * @return true if the EGL context will be preserved when paused - */ - boolean getPreserveEGLContextOnPause(); - - /** - * Set the renderer associated with this view. Also starts the thread that - * will call the renderer, which in turn causes the rendering to start. - *

This method should be called once and only once in the life-cycle of - * a GLSurfaceView. - *

The following GLSurfaceView methods can only be called before - * setRenderer is called: - *

- *

- * The following GLSurfaceView methods can only be called after - * setRenderer is called: - *

- * - * @param renderer the renderer to use to perform OpenGL drawing. - */ - void setRenderer(Renderer renderer); - - /** - * @return Returns the {@code Renderer} - */ - Renderer getRenderer(); - - /** - * Install a custom EGLContextFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a context will be created with no shared context and - * with a null attribute list. - */ - void setEGLContextFactory(EGLContextFactory factory); - - /** - * @return Returns the {@code EGLWindowSurfaceFactory} - */ - EGLWindowSurfaceFactory getEGLWindowSurfaceFactory(); - - /** - * Install a custom EGLWindowSurfaceFactory. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If this method is not called, then by default - * a window surface will be created with a null attribute list. - */ - void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory); - - /** - * @return Returns the {@code EGLContextFactory} - */ - EGLContextFactory getEGLContextFactory(); - - /** - * Install a custom EGLConfigChooser. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose an EGLConfig that is compatible with the current - * android.view.Surface, with a depth buffer depth of - * at least 16 bits. - */ - void setEGLConfigChooser(EGLConfigChooser configChooser); - - /** - * @return Returns the {@code EGLConfigChooser} - */ - EGLConfigChooser getEGLConfigChooser(); - - /** - * Inform the default EGLContextFactory and default EGLConfigChooser - * which EGLContext client version to pick. - *

Use this method to create an OpenGL ES 2.0-compatible context. - * Example: - *

-     *     public MyView(Context context) {
-     *         super(context);
-     *         setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
-     *         setRenderer(new MyRenderer());
-     *     }
-     * 
- *

Note: Activities which require OpenGL ES 2.0 should indicate this by - * setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's - * AndroidManifest.xml file. - *

If this method is called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

This method only affects the behavior of the default EGLContexFactory and the - * default EGLConfigChooser. If - * {@link #setEGLContextFactory(EGLContextFactory)} has been called, then the supplied - * EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. - * If - * {@link #setEGLConfigChooser(EGLConfigChooser)} has been called, then the supplied - * EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config. - * @param version The EGLContext client version to choose. Use 2 for OpenGL ES 2.0 - */ - void setEGLContextClientVersion(int version); - - /** - * Get EGLContextClientVersion - */ - int getEGLContextClientVersion(); - - /** - * Set the rendering mode. When renderMode is - * RENDERMODE_CONTINUOUSLY, the renderer is called - * repeatedly to re-render the scene. When renderMode - * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface - * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. - *

- * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance - * by allowing the GPU and CPU to idle when the view does not need to be updated. - *

- * This method can only be called after {@link #setRenderer(Renderer)} - * - * @param renderMode one of the RENDERMODE_X constants - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - void setRenderMode(int renderMode); - - /** - * Get the current rendering mode. May be called - * from any thread. Must not be called before a renderer has been set. - * @return the current rendering mode. - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - int getRenderMode(); - - /** - * Request that the renderer render a frame. - * This method is typically used when the render mode has been set to - * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. - * May be called - * from any thread. Must not be called before a renderer has been set. - */ - void requestRender(); - - /** - * Pause the rendering thread, optionally tearing down the EGL context - * depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}. - * - * This method should be called when it is no longer desirable for the - * GLSurfaceView to continue rendering, such as in response to - * {@link android.app.Activity#onStop Activity.onStop}. - * - * Must not be called before a renderer has been set. - */ - void onPause(); - - /** - * Resumes the rendering thread, re-creating the OpenGL context if necessary. It - * is the counterpart to {@link #onPause()}. - * - * This method should typically be called in - * {@link android.app.Activity#onStart Activity.onStart}. - * - * Must not be called before a renderer has been set. - */ - void onResume(); - - /** - * Queue a runnable to be run on the GL rendering thread. This can be used - * to communicate with the Renderer on the rendering thread. - * Must not be called before a renderer has been set. - * @param r the runnable to be run on the GL rendering thread. - */ - void queueEvent(Runnable r); -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLSurfaceView.java b/app/src/main/java/com/hippo/tuxiang/GLSurfaceView.java deleted file mode 100644 index ffc5b6c38..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLSurfaceView.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -import java.lang.ref.WeakReference; - -// android-9.0.0_r30 - -/** - * An implementation of SurfaceView that uses the dedicated surface for - * displaying OpenGL rendering. - *

- * A GLSurfaceView provides the following features: - *

- *

- * - *
- *

Developer Guides

- *

For more information about how to use OpenGL, read the - * OpenGL developer guide.

- *
- * - *

Using GLSurfaceView

- *

- * Typically you use GLSurfaceView by subclassing it and overriding one or more of the - * View system input event methods. If your application does not need to override event - * methods then GLSurfaceView can be used as-is. For the most part - * GLSurfaceView behavior is customized by calling "set" methods rather than by subclassing. - * For example, unlike a regular View, drawing is delegated to a separate Renderer object which - * is registered with the GLSurfaceView - * using the {@link #setRenderer(Renderer)} call. - *

- *

Initializing GLSurfaceView

- * All you have to do to initialize a GLSurfaceView is call {@link #setRenderer(Renderer)}. - * However, if desired, you can modify the default behavior of GLSurfaceView by calling one or - * more of these methods before calling setRenderer: - * - *

- *

Specifying the android.view.Surface

- * By default GLSurfaceView will create a PixelFormat.RGB_888 format surface. If a translucent - * surface is required, call getHolder().setFormat(PixelFormat.TRANSLUCENT). - * The exact format of a TRANSLUCENT surface is device dependent, but it will be - * a 32-bit-per-pixel surface with 8 bits per component. - *

- *

Choosing an EGL Configuration

- * A given Android device may support multiple EGLConfig rendering configurations. - * The available configurations may differ in how many channels of data are present, as - * well as how many bits are allocated to each channel. Therefore, the first thing - * GLSurfaceView has to do when starting to render is choose what EGLConfig to use. - *

- * By default GLSurfaceView chooses a EGLConfig that has an RGB_888 pixel format, - * with at least a 16-bit depth buffer and no stencil. - *

- * If you would prefer a different EGLConfig - * you can override the default behavior by calling one of the - * setEGLConfigChooser methods. - *

- *

Debug Behavior

- * You can optionally modify the behavior of GLSurfaceView by calling - * one or more of the debugging methods {@link #setDebugFlags(int)}, - * and {@link #setGLWrapper}. These methods may be called before and/or after setRenderer, but - * typically they are called before setRenderer so that they take effect immediately. - *

- *

Setting a Renderer

- * Finally, you must call {@link #setRenderer} to register a {@link Renderer}. - * The renderer is - * responsible for doing the actual OpenGL rendering. - *

- *

Rendering Mode

- * Once the renderer is set, you can control whether the renderer draws - * continuously or on-demand by calling - * {@link #setRenderMode}. The default is continuous rendering. - *

- *

Activity Life-cycle

- * A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity stops and - * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to - * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate - * the OpenGL display. - *

- *

Handling events

- *

- * To handle an event you will typically subclass GLSurfaceView and override the - * appropriate method, just as you would with any other View. However, when handling - * the event, you may need to communicate with the Renderer object - * that's running in the rendering thread. You can do this using any - * standard Java cross-thread communication mechanism. In addition, - * one relatively easy way to communicate with your renderer is - * to call - * {@link #queueEvent(Runnable)}. For example: - *

- * class MyGLSurfaceView extends GLSurfaceView {
- *
- *     private MyRenderer mMyRenderer;
- *
- *     public void start() {
- *         mMyRenderer = ...;
- *         setRenderer(mMyRenderer);
- *     }
- *
- *     public boolean onKeyDown(int keyCode, KeyEvent event) {
- *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- *             queueEvent(new Runnable() {
- *                 // This method will be called on the rendering
- *                 // thread:
- *                 public void run() {
- *                     mMyRenderer.handleDpadCenter();
- *                 }});
- *             return true;
- *         }
- *         return super.onKeyDown(keyCode, event);
- *     }
- * }
- * 
- * - */ -public class GLSurfaceView extends SurfaceView implements GLStuff, SurfaceHolder.Callback2 { - private final static String TAG = "GLSurfaceView"; - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView(Context context) { - super(context); - init(); - } - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mGLThread != null) { - // GLThread may still be running if this view was never - // attached to a window. - mGLThread.requestExitAndWait(); - } - } finally { - super.finalize(); - } - } - - private void init() { - // Install a SurfaceHolder.Callback so we get notified when the - // underlying surface is created and destroyed - SurfaceHolder holder = getHolder(); - holder.addCallback(this); - // setFormat is done by SurfaceView in SDK 2.3 and newer. Uncomment - // this statement if back-porting to 2.2 or older: - // holder.setFormat(PixelFormat.RGB_565); - // - // setType is not needed for SDK 2.0 or newer. Uncomment this - // statement if back-porting this code to older SDKs. - // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); - } - - @Override - public Object getNativeWindow() { - return getHolder(); - } - - @Override - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - @Override - public GLWrapper getGLWrapper() { - return mGLWrapper; - } - - @Override - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - @Override - public int getDebugFlags() { - return mDebugFlags; - } - - @Override - public void setPreserveEGLContextOnPause(boolean preserveOnPause) { - mPreserveEGLContextOnPause = preserveOnPause; - } - - @Override - public boolean getPreserveEGLContextOnPause() { - return mPreserveEGLContextOnPause; - } - - private void checkRenderThreadState() { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - } - - @Override - public void setRenderer(Renderer renderer) { - checkRenderThreadState(); - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(mEGLContextClientVersion, true); - } - if (mEGLContextFactory == null) { - mEGLContextFactory = new DefaultContextFactory(mEGLContextClientVersion); - } - if (mEGLWindowSurfaceFactory == null) { - mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); - } - mRenderer = renderer; - mGLThread = new GLThread(mThisWeakRef); - mGLThread.start(); - } - - @Override - public Renderer getRenderer() { - return mRenderer; - } - - @Override - public void setEGLContextFactory(EGLContextFactory factory) { - checkRenderThreadState(); - mEGLContextFactory = factory; - } - - @Override - public EGLContextFactory getEGLContextFactory() { - return mEGLContextFactory; - } - - @Override - public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { - checkRenderThreadState(); - mEGLWindowSurfaceFactory = factory; - } - - @Override - public EGLWindowSurfaceFactory getEGLWindowSurfaceFactory() { - return mEGLWindowSurfaceFactory; - } - - @Override - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - checkRenderThreadState(); - mEGLConfigChooser = configChooser; - } - - @Override - public EGLConfigChooser getEGLConfigChooser() { - return mEGLConfigChooser; - } - - @Override - public void setEGLContextClientVersion(int version) { - checkRenderThreadState(); - mEGLContextClientVersion = version; - } - - @Override - public int getEGLContextClientVersion() { - return mEGLContextClientVersion; - } - - @Override - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - @Override - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - @Override - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the SurfaceHolder.Callback2 interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - @Override - public void surfaceCreated(SurfaceHolder holder) { - mGLThread.surfaceCreated(); - } - - /** - * This method is part of the SurfaceHolder.Callback2 interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - } - - /** - * This method is part of the SurfaceHolder.Callback2 interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - mGLThread.onWindowResize(w, h); - } - - /** - * This method is part of the SurfaceHolder.Callback2 interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - @Override - public void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable finishDrawing) { - if (mGLThread != null) { - mGLThread.requestRenderAndNotify(finishDrawing); - } - } - - /** - * This method is part of the SurfaceHolder.Callback2 interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - @Override - public void surfaceRedrawNeeded(SurfaceHolder holder) { - if (mGLThread != null) { - mGLThread.requestRenderAndWait(); - } - } - - @Override - public void onPause() { - mGLThread.onPause(); - } - - @Override - public void onResume() { - mGLThread.onResume(); - } - - @Override - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLSurfaceView. - */ - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onAttachedToWindow reattach =" + mDetached); - } - if (mDetached && (mRenderer != null)) { - int renderMode = RENDERMODE_CONTINUOUSLY; - if (mGLThread != null) { - renderMode = mGLThread.getRenderMode(); - } - mGLThread = new GLThread(mThisWeakRef); - if (renderMode != RENDERMODE_CONTINUOUSLY) { - mGLThread.setRenderMode(renderMode); - } - mGLThread.start(); - } - mDetached = false; - } - - @Override - protected void onDetachedFromWindow() { - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onDetachedFromWindow"); - } - if (mGLThread != null) { - mGLThread.requestExitAndWait(); - } - mDetached = true; - super.onDetachedFromWindow(); - } - - private final WeakReference mThisWeakRef = - new WeakReference<>((GLStuff) this); - private GLThread mGLThread; - private Renderer mRenderer; - private boolean mDetached; - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - private GLWrapper mGLWrapper; - private int mDebugFlags; - private int mEGLContextClientVersion; - private boolean mPreserveEGLContextOnPause; -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLTextureView.java b/app/src/main/java/com/hippo/tuxiang/GLTextureView.java deleted file mode 100644 index 14e5963e1..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLTextureView.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2022 Tarsin Norbin - * - * This file is part of EhViewer - * - * EhViewer is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * EhViewer is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with EhViewer. - * If not, see . - */ - -package com.hippo.tuxiang; - -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.util.AttributeSet; -import android.util.Log; -import android.view.TextureView; - -import java.lang.ref.WeakReference; - -/** - * TextureView version {@link GLSurfaceView} - */ -public class GLTextureView extends TextureView implements GLStuff, TextureView.SurfaceTextureListener { - private final static String TAG = "GLSurfaceView"; - - public GLTextureView(Context context) { - super(context); - init(); - } - - public GLTextureView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public GLTextureView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mGLThread != null) { - // GLThread may still be running if this view was never - // attached to a window. - mGLThread.requestExitAndWait(); - } - } finally { - super.finalize(); - } - } - - private void init() { - setSurfaceTextureListener(this); - } - - @Override - public Object getNativeWindow() { - return getSurfaceTexture(); - } - - @Override - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - @Override - public GLWrapper getGLWrapper() { - return mGLWrapper; - } - - @Override - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - @Override - public int getDebugFlags() { - return mDebugFlags; - } - - @Override - public void setPreserveEGLContextOnPause(boolean preserveOnPause) { - mPreserveEGLContextOnPause = preserveOnPause; - } - - @Override - public boolean getPreserveEGLContextOnPause() { - return mPreserveEGLContextOnPause; - } - - private void checkRenderThreadState() { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - } - - @Override - public void setRenderer(Renderer renderer) { - checkRenderThreadState(); - if (mEGLConfigChooser == null) { - mEGLConfigChooser = new SimpleEGLConfigChooser(mEGLContextClientVersion, true); - } - if (mEGLContextFactory == null) { - mEGLContextFactory = new DefaultContextFactory(mEGLContextClientVersion); - } - if (mEGLWindowSurfaceFactory == null) { - mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); - } - mRenderer = renderer; - mGLThread = new GLThread(mThisWeakRef); - mGLThread.start(); - } - - @Override - public Renderer getRenderer() { - return mRenderer; - } - - @Override - public void setEGLContextFactory(EGLContextFactory factory) { - checkRenderThreadState(); - mEGLContextFactory = factory; - } - - @Override - public EGLContextFactory getEGLContextFactory() { - return mEGLContextFactory; - } - - @Override - public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { - checkRenderThreadState(); - mEGLWindowSurfaceFactory = factory; - } - - @Override - public EGLWindowSurfaceFactory getEGLWindowSurfaceFactory() { - return mEGLWindowSurfaceFactory; - } - - @Override - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - checkRenderThreadState(); - mEGLConfigChooser = configChooser; - } - - @Override - public EGLConfigChooser getEGLConfigChooser() { - return mEGLConfigChooser; - } - - @Override - public void setEGLContextClientVersion(int version) { - checkRenderThreadState(); - mEGLContextClientVersion = version; - } - - @Override - public int getEGLContextClientVersion() { - return mEGLContextClientVersion; - } - - @Override - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - @Override - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - @Override - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the {@link android.view.TextureView.SurfaceTextureListener} - * interface, and is not normally called or subclassed by clients of GLTextureView. - */ - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - mGLThread.surfaceCreated(); - mGLThread.onWindowResize(width, height); - } - - /** - * This method is part of the {@link android.view.TextureView.SurfaceTextureListener} - * interface, and is not normally called or subclassed by clients of GLTextureView. - */ - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - mGLThread.onWindowResize(width, height); - } - - /** - * This method is part of the {@link android.view.TextureView.SurfaceTextureListener} - * interface, and is not normally called or subclassed by clients of GLTextureView. - */ - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - return true; - } - - /** - * This method is part of the {@link android.view.TextureView.SurfaceTextureListener} - * interface, and is not normally called or subclassed by clients of GLTextureView. - */ - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - requestRender(); - } - - @Override - public void onPause() { - mGLThread.onPause(); - } - - @Override - public void onResume() { - mGLThread.onResume(); - } - - @Override - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLTextureView. - */ - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onAttachedToWindow reattach =" + mDetached); - } - if (mDetached && (mRenderer != null)) { - int renderMode = RENDERMODE_CONTINUOUSLY; - if (mGLThread != null) { - renderMode = mGLThread.getRenderMode(); - } - mGLThread = new GLThread(mThisWeakRef); - if (renderMode != RENDERMODE_CONTINUOUSLY) { - mGLThread.setRenderMode(renderMode); - } - mGLThread.start(); - } - mDetached = false; - } - - @Override - protected void onDetachedFromWindow() { - if (LOG_ATTACH_DETACH) { - Log.d(TAG, "onDetachedFromWindow"); - } - if (mGLThread != null) { - mGLThread.requestExitAndWait(); - } - mDetached = true; - super.onDetachedFromWindow(); - } - - private final WeakReference mThisWeakRef = - new WeakReference<>((GLStuff) this); - private GLThread mGLThread; - private Renderer mRenderer; - private boolean mDetached; - private EGLConfigChooser mEGLConfigChooser; - private EGLContextFactory mEGLContextFactory; - private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; - private GLWrapper mGLWrapper; - private int mDebugFlags; - private int mEGLContextClientVersion; - private boolean mPreserveEGLContextOnPause; -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLThread.java b/app/src/main/java/com/hippo/tuxiang/GLThread.java deleted file mode 100644 index e6dacd644..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLThread.java +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.util.Log; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; -import javax.microedition.khronos.opengles.GL10; - -// android-9.0.0_r30 - -/** - * A generic GL Thread. Takes care of initializing EGL and GL. Delegates - * to a Renderer instance to do the actual drawing. Can be configured to - * render continuously or on request. - * - * All potentially blocking synchronization is done through the - * sGLThreadManager object. This avoids multiple-lock ordering issues. - * - */ -class GLThread extends Thread { - GLThread(WeakReference glStuffWeakRef) { - super(); - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = GLStuff.RENDERMODE_CONTINUOUSLY; - mWantRenderNotification = false; - mGLStuffWeakRef = glStuffWeakRef; - } - - @Override - public void run() { - setName("GLThread " + getId()); - if (GLStuff.LOG_THREADS) { - Log.i("GLThread", "starting tid=" + getId()); - } - - GLStuff stuff; - - stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - stuff.getRenderer().onGLThreadStart(); - stuff = null; - } - - try { - guardedRun(); - } catch (InterruptedException e) { - // fall thru and exit normally - } finally { - stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - stuff.getRenderer().onGLThreadExit(); - stuff = null; - } - sGLThreadManager.threadExiting(this); - } - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglSurfaceLocked() { - if (mHaveEglSurface) { - mHaveEglSurface = false; - mEglHelper.destroySurface(); - } - } - - /* - * This private method should only be called inside a - * synchronized(sGLThreadManager) block. - */ - private void stopEglContextLocked() { - if (mHaveEglContext) { - mEglHelper.finish(); - mHaveEglContext = false; - sGLThreadManager.releaseEglContextLocked(this); - } - } - - private void guardedRun() throws InterruptedException { - mEglHelper = new EglHelper(mGLStuffWeakRef); - mHaveEglContext = false; - mHaveEglSurface = false; - mWantRenderNotification = false; - - try { - GL10 gl = null; - boolean createEglContext = false; - boolean createEglSurface = false; - boolean createGlInterface = false; - boolean lostEglContext = false; - boolean sizeChanged = false; - boolean wantRenderNotification = false; - boolean doRenderNotification = false; - boolean askedToReleaseEglContext = false; - int w = 0; - int h = 0; - Runnable event = null; - Runnable finishDrawingRunnable = null; - - while (true) { - synchronized (sGLThreadManager) { - while (true) { - if (mShouldExit) { - return; - } - - if (! mEventQueue.isEmpty()) { - event = mEventQueue.remove(0); - break; - } - - // Update the pause state. - boolean pausing = false; - if (mPaused != mRequestPaused) { - pausing = mRequestPaused; - mPaused = mRequestPaused; - sGLThreadManager.notifyAll(); - if (GLStuff.LOG_PAUSE_RESUME) { - Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId()); - } - GLStuff stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - if (pausing) { - stuff.getRenderer().onGLThreadPause(); - } else { - stuff.getRenderer().onGLThreadResume(); - } - stuff = null; - } - } - - // Do we need to give up the EGL context? - if (mShouldReleaseEglContext) { - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "releasing EGL context because asked to tid=" + getId()); - } - stopEglSurfaceLocked(); - stopEglContextLocked(); - mShouldReleaseEglContext = false; - askedToReleaseEglContext = true; - } - - // Have we lost the EGL context? - if (lostEglContext) { - stopEglSurfaceLocked(); - stopEglContextLocked(); - lostEglContext = false; - } - - // When pausing, release the EGL surface: - if (pausing && mHaveEglSurface) { - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "releasing EGL surface because paused tid=" + getId()); - } - stopEglSurfaceLocked(); - } - - // When pausing, optionally release the EGL Context: - if (pausing && mHaveEglContext) { - GLStuff stuff = mGLStuffWeakRef.get(); - boolean preserveEglContextOnPause = stuff == null ? - false : stuff.getPreserveEGLContextOnPause(); - if (!preserveEglContextOnPause) { - stopEglContextLocked(); - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); - } - } - } - - // Have we lost the SurfaceView surface? - if ((! mHasSurface) && (! mWaitingForSurface)) { - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId()); - } - if (mHaveEglSurface) { - stopEglSurfaceLocked(); - } - mWaitingForSurface = true; - mSurfaceIsBad = false; - sGLThreadManager.notifyAll(); - } - - // Have we acquired the surface view surface? - if (mHasSurface && mWaitingForSurface) { - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId()); - } - mWaitingForSurface = false; - sGLThreadManager.notifyAll(); - } - - if (doRenderNotification) { - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "sending render notification tid=" + getId()); - } - mWantRenderNotification = false; - doRenderNotification = false; - mRenderComplete = true; - sGLThreadManager.notifyAll(); - } - - if (mFinishDrawingRunnable != null) { - finishDrawingRunnable = mFinishDrawingRunnable; - mFinishDrawingRunnable = null; - } - - // Ready to draw? - if (readyToDraw()) { - - // If we don't have an EGL context, try to acquire one. - if (! mHaveEglContext) { - if (askedToReleaseEglContext) { - askedToReleaseEglContext = false; - } else { - try { - mEglHelper.start(); - } catch (RuntimeException t) { - sGLThreadManager.releaseEglContextLocked(this); - throw t; - } - mHaveEglContext = true; - createEglContext = true; - - sGLThreadManager.notifyAll(); - } - } - - if (mHaveEglContext && !mHaveEglSurface) { - mHaveEglSurface = true; - createEglSurface = true; - createGlInterface = true; - sizeChanged = true; - } - - if (mHaveEglSurface) { - if (mSizeChanged) { - sizeChanged = true; - w = mWidth; - h = mHeight; - mWantRenderNotification = true; - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", - "noticing that we want render notification tid=" - + getId()); - } - - // Destroy and recreate the EGL surface. - createEglSurface = true; - - mSizeChanged = false; - } - mRequestRender = false; - sGLThreadManager.notifyAll(); - if (mWantRenderNotification) { - wantRenderNotification = true; - } - break; - } - } else { - if (finishDrawingRunnable != null) { - Log.w("GLThread", "Warning, !readyToDraw() but waiting for " + - "draw finished! Early reporting draw finished."); - finishDrawingRunnable.run(); - finishDrawingRunnable = null; - } - } - - // By design, this is the only place in a GLThread thread where we wait(). - if (GLStuff.LOG_THREADS) { - Log.i("GLThread", "waiting tid=" + getId() - + " mHaveEglContext: " + mHaveEglContext - + " mHaveEglSurface: " + mHaveEglSurface - + " mFinishedCreatingEglSurface: " + mFinishedCreatingEglSurface - + " mPaused: " + mPaused - + " mHasSurface: " + mHasSurface - + " mSurfaceIsBad: " + mSurfaceIsBad - + " mWaitingForSurface: " + mWaitingForSurface - + " mWidth: " + mWidth - + " mHeight: " + mHeight - + " mRequestRender: " + mRequestRender - + " mRenderMode: " + mRenderMode); - } - sGLThreadManager.wait(); - } - } // end of synchronized(sGLThreadManager) - - if (event != null) { - event.run(); - event = null; - continue; - } - - if (createEglSurface) { - if (GLStuff.LOG_SURFACE) { - Log.w("GLThread", "egl createSurface"); - } - if (mEglHelper.createSurface()) { - synchronized(sGLThreadManager) { - mFinishedCreatingEglSurface = true; - sGLThreadManager.notifyAll(); - } - } else { - synchronized(sGLThreadManager) { - mFinishedCreatingEglSurface = true; - mSurfaceIsBad = true; - sGLThreadManager.notifyAll(); - } - continue; - } - createEglSurface = false; - } - - if (createGlInterface) { - gl = (GL10) mEglHelper.createGL(); - - createGlInterface = false; - } - - if (createEglContext) { - if (GLStuff.LOG_RENDERER) { - Log.w("GLThread", "onSurfaceCreated"); - } - GLStuff stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - stuff.getRenderer().onSurfaceCreated(gl, mEglHelper.mEglConfig); - stuff = null; - } - createEglContext = false; - } - - if (sizeChanged) { - if (GLStuff.LOG_RENDERER) { - Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")"); - } - GLStuff stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - stuff.getRenderer().onSurfaceChanged(gl, w, h); - stuff = null; - } - sizeChanged = false; - } - - if (GLStuff.LOG_RENDERER_DRAW_FRAME) { - Log.w("GLThread", "onDrawFrame tid=" + getId()); - } - boolean drew = false; - { - GLStuff stuff = mGLStuffWeakRef.get(); - if (stuff != null) { - drew = stuff.getRenderer().onDrawFrame(gl); - stuff = null; - if (finishDrawingRunnable != null) { - finishDrawingRunnable.run(); - finishDrawingRunnable = null; - } - } - } - if (drew) { - final int swapError = mEglHelper.swap(); - switch (swapError) { - case EGL10.EGL_SUCCESS: - break; - case EGL11.EGL_CONTEXT_LOST: - if (GLStuff.LOG_SURFACE) { - Log.i("GLThread", "egl context lost tid=" + getId()); - } - lostEglContext = true; - break; - default: - // Other errors typically mean that the current surface is bad, - // probably because the SurfaceView surface has been destroyed, - // but we haven't been notified yet. - // Log the error to help developers understand why rendering stopped. - EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError); - - synchronized (sGLThreadManager) { - mSurfaceIsBad = true; - sGLThreadManager.notifyAll(); - } - break; - } - } - - if (wantRenderNotification) { - doRenderNotification = true; - wantRenderNotification = false; - } - } - - } finally { - /* - * clean-up everything... - */ - synchronized (sGLThreadManager) { - stopEglSurfaceLocked(); - stopEglContextLocked(); - } - } - } - - public boolean ableToDraw() { - return mHaveEglContext && mHaveEglSurface && readyToDraw(); - } - - private boolean readyToDraw() { - return (!mPaused) && mHasSurface && (!mSurfaceIsBad) - && (mWidth > 0) && (mHeight > 0) - && (mRequestRender || (mRenderMode == GLStuff.RENDERMODE_CONTINUOUSLY)); - } - - public void setRenderMode(int renderMode) { - if ( !((GLStuff.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLStuff.RENDERMODE_CONTINUOUSLY)) ) { - throw new IllegalArgumentException("renderMode"); - } - synchronized(sGLThreadManager) { - mRenderMode = renderMode; - sGLThreadManager.notifyAll(); - } - } - - public int getRenderMode() { - synchronized(sGLThreadManager) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized(sGLThreadManager) { - mRequestRender = true; - sGLThreadManager.notifyAll(); - } - } - - public void requestRenderAndNotify(Runnable finishDrawing) { - synchronized(sGLThreadManager) { - // If we are already on the GL thread, this means a client callback - // has caused reentrancy, for example via updating the SurfaceView parameters. - // We will return to the client rendering code, so here we don't need to - // do anything. - if (Thread.currentThread() == this) { - return; - } - - mWantRenderNotification = true; - mRequestRender = true; - mRenderComplete = false; - mFinishDrawingRunnable = finishDrawing; - - sGLThreadManager.notifyAll(); - } - } - - public void requestRenderAndWait() { - synchronized(sGLThreadManager) { - // If we are already on the GL thread, this means a client callback - // has caused reentrancy, for example via updating the SurfaceView parameters. - // We will return to the client rendering code, so here we don't need to - // do anything. - if (Thread.currentThread() == this) { - return; - } - - mWantRenderNotification = true; - mRequestRender = true; - mRenderComplete = false; - - sGLThreadManager.notifyAll(); - - while (!mExited && !mPaused && !mRenderComplete && ableToDraw()) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void surfaceCreated() { - synchronized(sGLThreadManager) { - if (GLStuff.LOG_THREADS) { - Log.i("GLThread", "surfaceCreated tid=" + getId()); - } - mHasSurface = true; - mFinishedCreatingEglSurface = false; - sGLThreadManager.notifyAll(); - while (mWaitingForSurface - && !mFinishedCreatingEglSurface - && !mExited) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void surfaceDestroyed() { - synchronized(sGLThreadManager) { - if (GLStuff.LOG_THREADS) { - Log.i("GLThread", "surfaceDestroyed tid=" + getId()); - } - mHasSurface = false; - sGLThreadManager.notifyAll(); - while((!mWaitingForSurface) && (!mExited)) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onPause() { - synchronized (sGLThreadManager) { - if (GLStuff.LOG_PAUSE_RESUME) { - Log.i("GLThread", "onPause tid=" + getId()); - } - mRequestPaused = true; - sGLThreadManager.notifyAll(); - while ((! mExited) && (! mPaused)) { - if (GLStuff.LOG_PAUSE_RESUME) { - Log.i("Main thread", "onPause waiting for mPaused."); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onResume() { - synchronized (sGLThreadManager) { - if (GLStuff.LOG_PAUSE_RESUME) { - Log.i("GLThread", "onResume tid=" + getId()); - } - mRequestPaused = false; - mRequestRender = true; - mRenderComplete = false; - sGLThreadManager.notifyAll(); - while ((! mExited) && mPaused && (!mRenderComplete)) { - if (GLStuff.LOG_PAUSE_RESUME) { - Log.i("Main thread", "onResume waiting for !mPaused."); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void onWindowResize(int w, int h) { - synchronized (sGLThreadManager) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - mRequestRender = true; - mRenderComplete = false; - - // If we are already on the GL thread, this means a client callback - // has caused reentrancy, for example via updating the SurfaceView parameters. - // We need to process the size change eventually though and update our EGLSurface. - // So we set the parameters and return so they can be processed on our - // next iteration. - if (Thread.currentThread() == this) { - return; - } - - sGLThreadManager.notifyAll(); - - // Wait for thread to react to resize and render a frame - while (! mExited && !mPaused && !mRenderComplete - && ableToDraw()) { - if (GLStuff.LOG_SURFACE) { - Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId()); - } - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - synchronized(sGLThreadManager) { - mShouldExit = true; - sGLThreadManager.notifyAll(); - while (! mExited) { - try { - sGLThreadManager.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - } - - public void requestReleaseEglContextLocked() { - mShouldReleaseEglContext = true; - sGLThreadManager.notifyAll(); - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - if (r == null) { - throw new IllegalArgumentException("r must not be null"); - } - synchronized(sGLThreadManager) { - mEventQueue.add(r); - sGLThreadManager.notifyAll(); - } - } - - private static final GLThreadManager sGLThreadManager = new GLThreadManager(); - - // Once the thread is started, all accesses to the following member - // variables are protected by the sGLThreadManager monitor - private boolean mShouldExit; - boolean mExited; - private boolean mRequestPaused; - private boolean mPaused; - private boolean mHasSurface; - private boolean mSurfaceIsBad; - private boolean mWaitingForSurface; - private boolean mHaveEglContext; - private boolean mHaveEglSurface; - private boolean mFinishedCreatingEglSurface; - private boolean mShouldReleaseEglContext; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private boolean mWantRenderNotification; - private boolean mRenderComplete; - private final ArrayList mEventQueue = new ArrayList<>(); - private boolean mSizeChanged = true; - private Runnable mFinishDrawingRunnable = null; - - // End of member variables protected by the sGLThreadManager monitor. - - private EglHelper mEglHelper; - - /** - * Set once at thread construction time, nulled out when the parent view is garbage - * called. This weak reference allows the GLSurfaceView to be garbage collected while - * the GLThread is still alive. - */ - private final WeakReference mGLStuffWeakRef; -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLThreadManager.java b/app/src/main/java/com/hippo/tuxiang/GLThreadManager.java deleted file mode 100644 index e6a8ff19f..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLThreadManager.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import android.util.Log; - -// android-9.0.0_r30 - -final class GLThreadManager { - private static final String TAG = "GLThreadManager"; - - public synchronized void threadExiting(GLThread thread) { - if (GLStuff.LOG_THREADS) { - Log.i("GLThread", "exiting tid=" + thread.getId()); - } - thread.mExited = true; - notifyAll(); - } - - /* - * Releases the EGL context. Requires that we are already in the - * sGLThreadManager monitor when this is called. - */ - public void releaseEglContextLocked(GLThread thread) { - notifyAll(); - } -} diff --git a/app/src/main/java/com/hippo/tuxiang/GLWrapper.java b/app/src/main/java/com/hippo/tuxiang/GLWrapper.java deleted file mode 100644 index 9f6a8a9f9..000000000 --- a/app/src/main/java/com/hippo/tuxiang/GLWrapper.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.opengles.GL; - -// android-9.0.0_r30 - -/** - * An interface used to wrap a GL interface. - *

Typically - * used for implementing debugging and tracing on top of the default - * GL interface. You would typically use this by creating your own class - * that implemented all the GL methods by delegating to another GL instance. - * Then you could add your own behavior before or after calling the - * delegate. All the GLWrapper would do was instantiate and return the - * wrapper GL instance: - *

- * class MyGLWrapper implements GLWrapper {
- *     GL wrap(GL gl) {
- *         return new MyGLImplementation(gl);
- *     }
- *     static class MyGLImplementation implements GL,GL10,GL11,... {
- *         ...
- *     }
- * }
- * 
- */ -public interface GLWrapper { - /** - * Wraps a gl interface in another gl interface. - * @param gl a GL interface that is to be wrapped. - * @return either the input argument or another GL object that wraps the input argument. - */ - GL wrap(GL gl); -} diff --git a/app/src/main/java/com/hippo/tuxiang/Renderer.java b/app/src/main/java/com/hippo/tuxiang/Renderer.java deleted file mode 100644 index 4c7239b0b..000000000 --- a/app/src/main/java/com/hippo/tuxiang/Renderer.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -// android-9.0.0_r30 - -/** - * A generic renderer interface. - *

- * The renderer is responsible for making OpenGL calls to render a frame. - *

- * GLSurfaceView clients typically create their own classes that implement - * this interface, and then call {@link GLStuff#setRenderer} to - * register the renderer with the GLSurfaceView. - *

- * - *

- *

Developer Guides

- *

For more information about how to use OpenGL, read the - * OpenGL developer guide.

- *
- * - *

Threading

- * The renderer will be called on a separate thread, so that rendering - * performance is decoupled from the UI thread. Clients typically need to - * communicate with the renderer from the UI thread, because that's where - * input events are received. Clients can communicate using any of the - * standard Java techniques for cross-thread communication, or they can - * use the {@link GLStuff#queueEvent(Runnable)} convenience method. - *

- *

EGL Context Lost

- * There are situations where the EGL rendering context will be lost. This - * typically happens when device wakes up after going to sleep. When - * the EGL context is lost, all OpenGL resources (such as textures) that are - * associated with that context will be automatically deleted. In order to - * keep rendering correctly, a renderer must recreate any lost resources - * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method - * is a convenient place to do this. - * - * @see GLStuff#setRenderer(Renderer) - */ -public interface Renderer { - /** - * Called when the surface is created or recreated. - *

- * Called when the rendering thread - * starts and whenever the EGL context is lost. The EGL context will typically - * be lost when the Android device awakes after going to sleep. - *

- * Since this method is called at the beginning of rendering, as well as - * every time the EGL context is lost, this method is a convenient place to put - * code to create resources that need to be created when the rendering - * starts, and that need to be recreated when the EGL context is lost. - * Textures are an example of a resource that you might want to create - * here. - *

- * Note that when the EGL context is lost, all OpenGL resources associated - * with that context will be automatically deleted. You do not need to call - * the corresponding "glDelete" methods such as glDeleteTextures to - * manually delete these lost resources. - *

- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param config the EGLConfig of the created surface. Can be used - * to create matching pbuffers. - */ - void onSurfaceCreated(GL10 gl, EGLConfig config); - - /** - * Called when the surface changed size. - *

- * Called after the surface is created and whenever - * the OpenGL ES surface size changes. - *

- * Typically you will set your viewport here. If your camera - * is fixed then you could also set your projection matrix here: - *

-     * void onSurfaceChanged(GL10 gl, int width, int height) {
-     *     gl.glViewport(0, 0, width, height);
-     *     // for a fixed camera, set the projection too
-     *     float ratio = (float) width / height;
-     *     gl.glMatrixMode(GL10.GL_PROJECTION);
-     *     gl.glLoadIdentity();
-     *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
-     * }
-     * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - */ - void onSurfaceChanged(GL10 gl, int width, int height); - - /** - * Called to draw the current frame. - *

- * This method is responsible for drawing the current frame. - *

- * The implementation of this method typically looks like this: - *

-     * void onDrawFrame(GL10 gl) {
-     *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-     *     //... other gl calls to render the scene ...
-     * }
-     * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @return {@code false} for not drew, will not swap buffers. - */ - boolean onDrawFrame(GL10 gl); - - /** - * Called when the GL thread exits. - *

- * GL thread starts after {@link GLStuff#setRenderer(Renderer)} called, and - * after {@link android.view.View#onDetachedFromWindow} called except - * the first time. - *

- * It is a good time to prepare resources. - */ - void onGLThreadStart(); - - /** - * Called when the GL thread exits. - *

- * GL thread ends after {@link android.view.View#onDetachedFromWindow} called. - *

- * It is a good time to release resources. - */ - void onGLThreadExit(); - - /** - * Called after {@link GLStuff#onPause()} called. - *

- * It is a good time to stop animations. - */ - void onGLThreadPause(); - - /** - * Called after {@link GLStuff#onResume()} called. - *

- * It is a good time to restart animations. - */ - void onGLThreadResume(); -} diff --git a/app/src/main/java/com/hippo/tuxiang/SimpleEGLConfigChooser.java b/app/src/main/java/com/hippo/tuxiang/SimpleEGLConfigChooser.java deleted file mode 100644 index 9a94281fa..000000000 --- a/app/src/main/java/com/hippo/tuxiang/SimpleEGLConfigChooser.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.tuxiang; - -// android-9.0.0_r30 - -/** - * This class will choose a RGB_888 surface with - * or without a depth buffer. - */ -public class SimpleEGLConfigChooser extends ComponentSizeChooser { - public SimpleEGLConfigChooser(int eglContextClientVersion, boolean withDepthBuffer) { - super(eglContextClientVersion, 8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0); - } -}