From 774dd532684e644c3c046d52f8ddf6dda65f62c0 Mon Sep 17 00:00:00 2001 From: Tomaž Vajngerl Date: Sat, 4 Oct 2014 18:06:39 +0200 Subject: android: Rewrite GLThread to trash objects as little as possible Change-Id: I6a0042e2a1b5d98fbf5aa8c64b67a9422f8956a3 --- .../src/java/org/mozilla/gecko/gfx/GLThread.java | 178 --------------------- .../src/java/org/mozilla/gecko/gfx/LayerView.java | 45 +++--- .../mozilla/gecko/gfx/RenderControllerThread.java | 143 +++++++++++++++++ 3 files changed, 165 insertions(+), 201 deletions(-) delete mode 100644 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java create mode 100644 android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java (limited to 'android') diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java deleted file mode 100644 index a80ea82c2436..000000000000 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GLThread.java +++ /dev/null @@ -1,178 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Android code. - * - * The Initial Developer of the Original Code is Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011-2012 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Patrick Walton - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.gecko.gfx; - -import android.opengl.GLSurfaceView; - -import java.util.concurrent.LinkedBlockingQueue; - -import javax.microedition.khronos.opengles.GL10; - -// A GL thread managed by Java. It is not necessary to use this class to use the -// FlexibleGLSurfaceView, but it can be helpful, especially if the GL rendering is to be done -// entirely in Java. -class GLThread extends Thread { - private LinkedBlockingQueue mQueue; - private GLController mController; - private boolean mRenderQueued; - - public GLThread(GLController controller) { - mQueue = new LinkedBlockingQueue(); - mController = controller; - } - - @Override - public void run() { - while (true) { - Runnable runnable; - try { - runnable = mQueue.take(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - runnable.run(); - if (runnable instanceof ShutdownMessage) { - break; - } - } - } - - public void recreateSurface() { - mQueue.add(new RecreateSurfaceMessage()); - } - - public void renderFrame() { - // Make sure there's only one render event in the queue at a time. - synchronized (this) { - if (!mRenderQueued) { - mQueue.add(new RenderFrameMessage()); - mRenderQueued = true; - } - } - } - - public void shutdown() { - mQueue.add(new ShutdownMessage()); - } - - public void surfaceChanged(int width, int height) { - mQueue.add(new SizeChangedMessage(width, height)); - } - - public void surfaceCreated() { - mQueue.add(new SurfaceCreatedMessage()); - } - - public void surfaceDestroyed() { - mQueue.add(new SurfaceDestroyedMessage()); - } - - private void doRecreateSurface() { - mController.disposeGLContext(); - mController.initGLContext(); - } - - private GLSurfaceView.Renderer getRenderer() { - return mController.getView().getRenderer(); - } - - private class RecreateSurfaceMessage implements Runnable { - public void run() { - doRecreateSurface(); - } - } - - private class RenderFrameMessage implements Runnable { - public void run() { - synchronized (GLThread.this) { - mRenderQueued = false; - } - - // Bail out if the surface was lost. - if (mController.getEGLSurface() == null) { - return; - } - - GLSurfaceView.Renderer renderer = getRenderer(); - if (renderer != null) { - renderer.onDrawFrame((GL10)mController.getGL()); - } - - mController.swapBuffers(); - } - } - - private class ShutdownMessage implements Runnable { - public void run() { - mController.disposeGLContext(); - mController = null; - } - } - - private class SizeChangedMessage implements Runnable { - private int mWidth, mHeight; - - public SizeChangedMessage(int width, int height) { - mWidth = width; - mHeight = height; - } - - public void run() { - GLSurfaceView.Renderer renderer = getRenderer(); - if (renderer != null) { - renderer.onSurfaceChanged((GL10)mController.getGL(), mWidth, mHeight); - } - } - } - - private class SurfaceCreatedMessage implements Runnable { - public void run() { - if (!mController.hasSurface()) { - mController.initGLContext(); - } - } - } - - private class SurfaceDestroyedMessage implements Runnable { - public void run() { - mController.disposeGLContext(); - } - } -} - diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java index ad5ad666f8b7..2a52d91afe27 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java @@ -175,8 +175,8 @@ public class LayerView extends FrameLayout { } public void requestRender() { - if (mGLThread != null) { - mGLThread.renderFrame(); + if (mRenderControllerThread != null) { + mRenderControllerThread.renderFrame(); } if (mListener != null) { mListener.renderRequested(); @@ -276,8 +276,8 @@ public class LayerView extends FrameLayout { private void onSizeChanged(int width, int height) { mGLController.surfaceChanged(width, height); - if (mGLThread != null) { - mGLThread.surfaceChanged(width, height); + if (mRenderControllerThread != null) { + mRenderControllerThread.surfaceChanged(width, height); } if (mListener != null) { @@ -288,8 +288,8 @@ public class LayerView extends FrameLayout { private void onDestroyed() { mGLController.surfaceDestroyed(); - if (mGLThread != null) { - mGLThread.surfaceDestroyed(); + if (mRenderControllerThread != null) { + mRenderControllerThread.surfaceDestroyed(); } if (mListener != null) { @@ -331,8 +331,8 @@ public class LayerView extends FrameLayout { } public void surfaceCreated(SurfaceHolder holder) { - if (mGLThread != null) { - mGLThread.surfaceCreated(); + if (mRenderControllerThread != null) { + mRenderControllerThread.surfaceCreated(); } } @@ -345,8 +345,8 @@ public class LayerView extends FrameLayout { public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { // We don't do this for surfaceCreated above because it is always followed by a surfaceChanged, // but that is not the case here. - if (mGLThread != null) { - mGLThread.surfaceCreated(); + if (mRenderControllerThread != null) { + mRenderControllerThread.surfaceCreated(); } onSizeChanged(width, height); } @@ -364,23 +364,23 @@ public class LayerView extends FrameLayout { } } - private GLThread mGLThread; // Protected by this class's monitor. + private RenderControllerThread mRenderControllerThread; public synchronized void createGLThread() { - if (mGLThread != null) { + if (mRenderControllerThread != null) { throw new LayerViewException ("createGLThread() called with a GL thread already in place!"); } Log.e(LOGTAG, "### Creating GL thread!"); - mGLThread = new GLThread(mGLController); - mGLThread.start(); + mRenderControllerThread = new RenderControllerThread(mGLController); + mRenderControllerThread.start(); notifyAll(); } public synchronized Thread destroyGLThread() { // Wait for the GL thread to be started. Log.e(LOGTAG, "### Waiting for GL thread to be created..."); - while (mGLThread == null) { + while (mRenderControllerThread == null) { try { wait(); } catch (InterruptedException e) { @@ -389,19 +389,18 @@ public class LayerView extends FrameLayout { } Log.e(LOGTAG, "### Destroying GL thread!"); - Thread glThread = mGLThread; - mGLThread.shutdown(); - mGLThread = null; - return glThread; + Thread thread = mRenderControllerThread; + mRenderControllerThread.shutdown(); + mRenderControllerThread = null; + return thread; } public synchronized void recreateSurface() { - if (mGLThread == null) { - throw new LayerViewException("recreateSurface() called with no GL " + - "thread active!"); + if (mRenderControllerThread == null) { + throw new LayerViewException("recreateSurface() called with no GL thread active!"); } - mGLThread.recreateSurface(); + mRenderControllerThread.recreateSurface(); } public static class LayerViewException extends RuntimeException { diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java new file mode 100644 index 000000000000..df710bf26142 --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java @@ -0,0 +1,143 @@ +package org.mozilla.gecko.gfx; + +import android.opengl.GLSurfaceView; + +import java.util.concurrent.LinkedBlockingQueue; + +import javax.microedition.khronos.opengles.GL10; + +public class RenderControllerThread extends Thread { + private LinkedBlockingQueue queue = new LinkedBlockingQueue(); + private GLController controller; + private boolean renderQueued = false; + private int width; + private int height; + + public RenderControllerThread(GLController controller) { + this.controller = controller; + } + + @Override + public void run() { + while (true) { + RenderCommand command; + try { + command = queue.take(); + execute(command); + if (command == RenderCommand.SHUTDOWN) { + return; + } + } catch (InterruptedException exception) { + throw new RuntimeException(exception); + } + } + } + + void execute(RenderCommand command) { + switch (command) { + case SHUTDOWN: + doShutdown(); + break; + case RECREATE_SURFACE: + doRecreateSurface(); + break; + case RENDER_FRAME: + doRenderFrame(); + break; + case SIZE_CHANGED: + doSizeChanged(); + break; + case SURFACE_CREATED: + doSurfaceCreated(); + break; + case SURFACE_DESTROYED: + doSurfaceDestroyed(); + break; + } + } + + public void recreateSurface() { + queue.add(RenderCommand.RECREATE_SURFACE); + } + + public void renderFrame() { + synchronized (this) { + if (!renderQueued) { + queue.add(RenderCommand.RENDER_FRAME); + renderQueued = true; + } + } + } + + public void shutdown() { + queue.add(RenderCommand.SHUTDOWN); + } + + public void surfaceChanged(int width, int height) { + this.width = width; + this.height = height; + queue.add(RenderCommand.SIZE_CHANGED); + } + + public void surfaceCreated() { + queue.add(RenderCommand.SURFACE_CREATED); + } + + public void surfaceDestroyed() { + queue.add(RenderCommand.SURFACE_DESTROYED); + } + + private void doRecreateSurface() { + controller.disposeGLContext(); + controller.initGLContext(); + } + + private GLSurfaceView.Renderer getRenderer() { + return controller.getView().getRenderer(); + } + + private void doShutdown() { + controller.disposeGLContext(); + controller = null; + } + + private void doRenderFrame() { + synchronized (this) { + renderQueued = false; + } + if (controller.getEGLSurface() == null) { + return; + } + GLSurfaceView.Renderer renderer = getRenderer(); + if (renderer != null) { + renderer.onDrawFrame((GL10) controller.getGL()); + } + controller.swapBuffers(); + } + + private void doSizeChanged() { + GLSurfaceView.Renderer renderer = getRenderer(); + if (renderer != null) { + renderer.onSurfaceChanged((GL10) controller.getGL(), width, height); + } + } + + private void doSurfaceCreated() { + if (!controller.hasSurface()) { + controller.initGLContext(); + } + } + + private void doSurfaceDestroyed() { + controller.disposeGLContext(); + } + + public enum RenderCommand { + SHUTDOWN, + RECREATE_SURFACE, + RENDER_FRAME, + SIZE_CHANGED, + SURFACE_CREATED, + SURFACE_DESTROYED, + } +} -- cgit