Inline hippo's all libs

* These dependencies are outdated and lack of maintenance
This commit is contained in:
tarsin committed 2022-06-13 13:04:50 +08:00
1 parent edd1ec2cc1
commit 850a8fb35c
35 files changed
+5221 -3

No files matched your search

@@ -0,0 +1,686 @@
/*
* 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<GLStuff> 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<Runnable> 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<GLStuff> mGLStuffWeakRef;
}