Esempio n. 1
0
    public void onWindowResize(int w, int h) {
      synchronized (GL_THREAD_MANAGER) {
        mWidth = w;
        mHeight = h;
        mSizeChanged = true;
        mRequestRender = true;
        mSurfaceTextureReady = true;
        mRenderComplete = false;
        GL_THREAD_MANAGER.notifyAll();

        // Wait for thread to react to resize and render a frame
        while (!mExited
            && !mPaused
            && !mRenderComplete
            && (mGLThread != null && mGLThread.ableToDraw())) {
          if (LOG_SURFACE) {
            Log.i(
                "Main thread",
                "onWindowResize waiting for render complete from tid=" + mGLThread.getId());
          }
          try {
            GL_THREAD_MANAGER.wait();
          } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
          }
        }
      }
    }
Esempio n. 2
0
 /*
  * This private method should only be called inside a
  * synchronized(GL_THREAD_MANAGER) block.
  */
 private void stopEglContextLocked() {
   if (mHaveEglContext) {
     mEglHelper.finish();
     mHaveEglContext = false;
     GL_THREAD_MANAGER.releaseEglContextLocked(this);
   }
 }
Esempio n. 3
0
 public void requestExitAndWait() {
   // don't call this from GLThread thread or it is a guaranteed
   // deadlock!
   synchronized (GL_THREAD_MANAGER) {
     mShouldExit = true;
     GL_THREAD_MANAGER.notifyAll();
     while (!mExited) {
       try {
         GL_THREAD_MANAGER.wait();
       } catch (InterruptedException ex) {
         Thread.currentThread().interrupt();
       }
     }
   }
   mSurface = null;
 }
Esempio n. 4
0
 /**
  * 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 (GL_THREAD_MANAGER) {
     mEventQueue.add(r);
     GL_THREAD_MANAGER.notifyAll();
   }
 }
Esempio n. 5
0
    public void surfaceDestroyed() {
      synchronized (GL_THREAD_MANAGER) {
        if (LOG_THREADS) {
          Log.i("GLThread", "surfaceDestroyed tid=" + getId());
        }

        mHasSurface = false;
        mSurfaceTextureReady = false;
        GL_THREAD_MANAGER.notifyAll();
        while ((!mWaitingForSurface) && (!mExited)) {
          Log.i("Main thread", "surfaceDestroyed waiting for !mWaitingForSurface.");
          try {
            GL_THREAD_MANAGER.wait();
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
          }
        }
      }
    }
Esempio n. 6
0
    public void setRenderMode(int renderMode) {
      if (!((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY))) {
        throw new IllegalArgumentException("renderMode");
      }

      synchronized (GL_THREAD_MANAGER) {
        mRenderMode = renderMode;
        GL_THREAD_MANAGER.notifyAll();
      }
    }
Esempio n. 7
0
 public void onPause() {
   synchronized (GL_THREAD_MANAGER) {
     if (LOG_PAUSE_RESUME) {
       Log.i("GLThread", "onPause tid=" + getId());
     }
     mSurfaceTextureReady = true;
     mRequestPaused = true;
     GL_THREAD_MANAGER.notifyAll();
     while ((!mExited) && (!mPaused)) {
       if (LOG_PAUSE_RESUME) {
         Log.i("Main thread", "onPause waiting for mPaused.");
       }
       try {
         GL_THREAD_MANAGER.wait();
       } catch (InterruptedException ex) {
         Thread.currentThread().interrupt();
       }
     }
   }
 }
Esempio n. 8
0
 public void surfaceCreated(SurfaceTexture surfaceTexture, int width, int height) {
   synchronized (GL_THREAD_MANAGER) {
     if (LOG_THREADS) {
       Log.i("GLThread", "surfaceCreated tid=" + getId());
     }
     mWidth = width;
     mHeight = height;
     mSurface = surfaceTexture;
     mSurfaceTextureReady = true;
     mHasSurface = true;
     GL_THREAD_MANAGER.notifyAll();
     while ((mWaitingForSurface) && (!mExited)) {
       try {
         GL_THREAD_MANAGER.wait();
       } catch (InterruptedException e) {
         Thread.currentThread().interrupt();
       }
     }
   }
 }
Esempio n. 9
0
 public void onResume() {
   synchronized (GL_THREAD_MANAGER) {
     if (LOG_PAUSE_RESUME) {
       Log.i("GLThread", "onResume tid=" + getId());
     }
     mRequestPaused = false;
     mRequestRender = true;
     mRenderComplete = false;
     GL_THREAD_MANAGER.notifyAll();
     // No need to wait really resume if there is no surface,
     while ((!mExited) && mPaused && (!mRenderComplete) && (mHasSurface)) {
       if (LOG_PAUSE_RESUME) {
         Log.i("Main thread", "onResume waiting for !mPaused.");
       }
       try {
         GL_THREAD_MANAGER.wait();
       } catch (InterruptedException ex) {
         Thread.currentThread().interrupt();
       }
     }
   }
 }
Esempio n. 10
0
    @Override
    public void run() {
      setName("GLThread " + getId());
      if (LOG_THREADS) {
        Log.i("GLThread", "starting tid=" + getId());
      }

      try {
        guardedRun();
      } catch (InterruptedException e) {
        // fall thru and exit normally
        e.printStackTrace();
      } finally {
        if (LOG_THREADS) {
          Log.i("GLThread", "threadExiting tid=" + getId());
        }
        GL_THREAD_MANAGER.threadExiting(this);
      }
    }
Esempio n. 11
0
    private void guardedRun() throws InterruptedException {
      mEglHelper = new EglHelper();
      mHaveEglContext = false;
      mHaveEglSurface = false;
      try {
        GL10 gl = null;
        boolean createEglContext = false;
        boolean lostEglContext = false;
        boolean sizeChanged = false;
        boolean wantRenderNotification = false;
        boolean doRenderNotification = false;
        boolean askedToReleaseEglContext = false;
        Runnable event = null;

        while (true) {
          synchronized (GL_THREAD_MANAGER) {
            while (true) {
              if (mShouldExit) {
                return;
              }

              if (!mEventQueue.isEmpty()) {
                event = mEventQueue.remove(0);
                break;
              }

              // Update the pause state.
              if (mPaused != mRequestPaused) {
                mPaused = mRequestPaused;
                GL_THREAD_MANAGER.notifyAll();
                if (LOG_PAUSE_RESUME) {
                  Log.i("GLThread", "mPaused is now " + mPaused + " tid=" + getId());
                }
              }

              // Do we need to give up the EGL context?
              if (mShouldReleaseEglContext) {
                if (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;
              }

              // Do we need to release the EGL surface?
              if (mHaveEglSurface && mPaused) {
                if (LOG_SURFACE) {
                  Log.i("GLThread", "releasing EGL surface because paused tid=" + getId());
                }
                stopEglSurfaceLocked();
                if (GL_THREAD_MANAGER.shouldReleaseEGLContextWhenPausing()) {
                  stopEglContextLocked();
                  if (LOG_SURFACE) {
                    Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
                  }
                }
                if (GL_THREAD_MANAGER.shouldTerminateEGLWhenPausing()) {
                  mEglHelper.finish();
                  if (LOG_SURFACE) {
                    Log.i("GLThread", "terminating EGL because paused tid=" + getId());
                  }
                }

                // Notify render that GLThread is going to pause
                mRenderer.onPaused();
              }

              // Have we lost the surface view surface?
              if ((!mHasSurface) && (!mWaitingForSurface)) {
                if (LOG_SURFACE) {
                  Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
                }
                if (mHaveEglSurface) {
                  stopEglSurfaceLocked();
                }
                mWaitingForSurface = true;

                // Notify the wait in surfaceDestroyed() to avoid ANR
                // with low memory case, Activity Manager destroys hardware resource of
                // SurfaceTexture directly.
                GL_THREAD_MANAGER.notifyAll();
              }

              // Have we acquired the surface view surface?
              if (mHasSurface && mWaitingForSurface) {
                if (LOG_SURFACE) {
                  Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId());
                }
                mWaitingForSurface = false;
                GL_THREAD_MANAGER.notifyAll();
              }

              if (doRenderNotification) {
                if (LOG_SURFACE) {
                  Log.i("GLThread", "sending render notification tid=" + getId());
                }
                wantRenderNotification = false;
                doRenderNotification = false;
                mRenderComplete = true;
                GL_THREAD_MANAGER.notifyAll();
              }
              // Ready to draw?
              if (readyToDraw()) {
                // If we don't have an EGL context, try to acquire one.
                if (!mHaveEglContext) {
                  if (askedToReleaseEglContext) {
                    askedToReleaseEglContext = false;
                  } else if (GL_THREAD_MANAGER.tryAcquireEglContextLocked(this)) {
                    try {
                      mEglHelper.start(mSurface);
                    } catch (RuntimeException t) {
                      GL_THREAD_MANAGER.releaseEglContextLocked(this);
                      throw t;
                    }
                    mHaveEglContext = true;
                    createEglContext = true;

                    GL_THREAD_MANAGER.notifyAll();
                  }
                }

                if (mHaveEglContext && !mHaveEglSurface) {
                  mHaveEglSurface = true;
                  sizeChanged = true;
                }

                if (mHaveEglSurface) {
                  if (mSizeChanged) {
                    sizeChanged = true;
                    wantRenderNotification = true;
                    if (LOG_SURFACE) {
                      Log.i("GLThread", "noticing that we want render notification tid=" + getId());
                    }

                    if (DRAW_TWICE_AFTER_SIZE_CHANGED) {
                      // We keep mRequestRender true so that we draw twice after the size changes.
                      // (Once because of mSizeChanged, the second time because of mRequestRender.)
                      // This forces the updated graphics onto the screen.
                    } else {
                      mRequestRender = false;
                      mSurfaceTextureReady = false;
                    }
                    mSizeChanged = false;
                  } else {
                    mRequestRender = false;
                    mSurfaceTextureReady = false;
                  }
                  GL_THREAD_MANAGER.notifyAll();
                  break;
                }
              }

              // By design, this is the only place in a GLThread thread where we wait().
              if (LOG_THREADS) {
                Log.i(
                    "GLThread",
                    "waiting tid="
                        + getId()
                        + " mHaveEglContext: "
                        + mHaveEglContext
                        + " mHaveEglSurface: "
                        + mHaveEglSurface
                        + " mPaused: "
                        + mPaused
                        + " mHasSurface: "
                        + mHasSurface
                        + " mSurfaceTextureReady: "
                        + mSurfaceTextureReady
                        + " mWaitingForSurface: "
                        + mWaitingForSurface
                        + " mWidth: "
                        + mWidth
                        + " mHeight: "
                        + mHeight
                        + " mRequestRender: "
                        + mRequestRender
                        + " mRenderMode: "
                        + mRenderMode);
              }
              GL_THREAD_MANAGER.wait();
            }
          } // end of synchronized(GL_THREAD_MANAGER)

          if (event != null) {
            event.run();
            event = null;
            continue;
          }

          if (!mHasSurface) {
            continue;
          }

          if (createEglContext) {
            if (LOG_RENDERER) {
              Log.w("GLThread", "onSurfaceCreated");
            }
            gl = (GL10) mEglHelper.mEglContext.getGL();
            mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
            createEglContext = false;
          }

          if (sizeChanged) {
            if (LOG_RENDERER) {
              Log.w("GLThread", "onSurfaceChanged(" + mWidth + ", " + mHeight + ")");
            }
            mEglHelper.purgeBuffers();
            mRenderer.onSurfaceChanged(gl, mWidth, mHeight);
            sizeChanged = false;
          }

          if (LOG_RENDERER_DRAW_FRAME) {
            Log.w("GLThread", "onDrawFrame tid=" + getId());
          }

          mRenderer.onDrawFrame(gl);

          if (!mEglHelper.swap()) {
            if (LOG_SURFACE) {
              Log.i("GLThread", "egl context lost tid=" + getId());
            }
            lostEglContext = true;
          }

          if (wantRenderNotification) {
            doRenderNotification = true;
          }
        }

      } finally {
        /*
         * clean-up everything...
         */
        synchronized (GL_THREAD_MANAGER) {
          stopEglSurfaceLocked();
          stopEglContextLocked();
        }
      }
    }
Esempio n. 12
0
 public void requestReleaseEglContextLocked() {
   mShouldReleaseEglContext = true;
   GL_THREAD_MANAGER.notifyAll();
 }
Esempio n. 13
0
 /*
  * We need to sync OpneGL render streaming with SurfaceTexture updated
  */
 public void setSurfaceTextureReady() {
   synchronized (GL_THREAD_MANAGER) {
     mSurfaceTextureReady = true;
     GL_THREAD_MANAGER.notifyAll();
   }
 }
Esempio n. 14
0
 public void requestRender() {
   synchronized (GL_THREAD_MANAGER) {
     mRequestRender = true;
     GL_THREAD_MANAGER.notifyAll();
   }
 }