summaryrefslogtreecommitdiffstats
path: root/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java')
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java148
1 files changed, 148 insertions, 0 deletions
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java b/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
new file mode 100644
index 000000000..06f82f158
--- /dev/null
+++ b/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
@@ -0,0 +1,148 @@
+package org.mozilla.gecko.gfx;
+
+import android.opengl.GLSurfaceView;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Thread which controls the rendering to OpenGL context. Render commands are queued and
+ * processed and delegated by this thread.
+ */
+public class RenderControllerThread extends Thread implements LayerView.Listener {
+ private LinkedBlockingQueue<RenderCommand> queue = new LinkedBlockingQueue<RenderCommand>();
+ 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 RENDER_FRAME:
+ doRenderFrame();
+ break;
+ case SIZE_CHANGED:
+ doSizeChanged();
+ break;
+ case SURFACE_CREATED:
+ doSurfaceCreated();
+ break;
+ case SURFACE_DESTROYED:
+ doSurfaceDestroyed();
+ break;
+ }
+ }
+
+ public void shutdown() {
+ queue.add(RenderCommand.SHUTDOWN);
+ }
+
+ @Override
+ public void compositorCreated() {
+
+ }
+
+ @Override
+ public void renderRequested() {
+ synchronized (this) {
+ if (!renderQueued) {
+ queue.add(RenderCommand.RENDER_FRAME);
+ renderQueued = true;
+ }
+ }
+ }
+
+ @Override
+ public void compositionPauseRequested() {
+ queue.add(RenderCommand.SURFACE_DESTROYED);
+ }
+
+ @Override
+ public void compositionResumeRequested(int width, int height) {
+
+ }
+
+ @Override
+ 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);
+ }
+
+ 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,
+ }
+}