summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java
blob: f1c70325a09e4efdc7fac2909c338ad2d5137641 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.mapbox.mapboxsdk.maps.renderer;

import android.content.Context;
import android.support.annotation.CallSuper;

import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.storage.FileSource;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * The {@link MapRenderer} encapsulates the GL thread.
 * <p>
 * Performs actions on the GL thread to manage the GL resources and
 * render on the one end and acts as a scheduler to request work to
 * be performed on the GL thread on the other.
 */
public abstract class MapRenderer implements MapRendererScheduler {

  // Holds the pointer to the native peer after initialisation
  private long nativePtr = 0;

  private MapboxMap.OnFpsChangedListener onFpsChangedListener;

  public MapRenderer(Context context, String localIdeographFontFamily) {

    FileSource fileSource = FileSource.getInstance(context);
    float pixelRatio = context.getResources().getDisplayMetrics().density;
    String programCacheDir = context.getCacheDir().getAbsolutePath();
    // Initialise native peer
    nativeInitialize(this, fileSource, pixelRatio, programCacheDir, localIdeographFontFamily);
  }

  public void onStart() {
    // Implement if needed
  }

  public void onPause() {
    nativeOnPause();
  }

  public void onResume() {
    nativeOnResume();
  }

  public void onStop() {
    // Implement if needed
  }

  public void onDestroy() {
    // Implement if needed
  }

  public void setOnFpsChangedListener(MapboxMap.OnFpsChangedListener listener) {
    onFpsChangedListener = listener;
  }

  @CallSuper
  protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
    nativeOnSurfaceCreated();
  }

  @CallSuper
  protected void onSurfaceChanged(GL10 gl, int width, int height) {
    if (width < 0) {
      throw new IllegalArgumentException("fbWidth cannot be negative.");
    }

    if (height < 0) {
      throw new IllegalArgumentException("fbHeight cannot be negative.");
    }

    if (width > 65535) {
      throw new IllegalArgumentException(
        "fbWidth cannot be greater than 65535.");
    }

    if (height > 65535) {
      throw new IllegalArgumentException(
        "fbHeight cannot be greater than 65535.");
    }

    gl.glViewport(0, 0, width, height);
    nativeOnSurfaceChanged(width, height);
  }

  @CallSuper
  protected void onDrawFrame(GL10 gl) {
    nativeRender();

    if (onFpsChangedListener != null) {
      updateFps();
    }
  }

  /**
   * May be called from any thread.
   * <p>
   * Called from the native peer to schedule work on the GL
   * thread. Explicit override for easier to read jni code.
   *
   * @param runnable the runnable to execute
   * @see MapRendererRunnable
   */
  @CallSuper
  void queueEvent(MapRendererRunnable runnable) {
    this.queueEvent((Runnable) runnable);
  }

  private native void nativeInitialize(MapRenderer self,
                                       FileSource fileSource,
                                       float pixelRatio,
                                       String programCacheDir,
                                       String localIdeographFontFamily);

  @CallSuper
  @Override
  protected native void finalize() throws Throwable;

  private native void nativeOnSurfaceCreated();

  private native void nativeOnSurfaceChanged(int width, int height);

  private native void nativeRender();

  private native void nativeOnResume();

  private native void nativeOnPause();

  private long frames;
  private long timeElapsed;

  private void updateFps() {
    frames++;
    long currentTime = System.nanoTime();
    double fps = 0;
    if (currentTime - timeElapsed >= 1) {
      fps = frames / ((currentTime - timeElapsed) / 1E9);
      onFpsChangedListener.onFpsChanged(fps);
      timeElapsed = currentTime;
      frames = 0;
    }
  }

}