Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Use a host interface for CustomLayer instead of function pointers (#1…
Browse files Browse the repository at this point in the history
…1553)

Use a host interface for CustomLayer instead of function pointers

Co-authored-by: Julian Rex <julian.rex@mapbox.com>
  • Loading branch information
Asheem Mamoowala and Julian Rex authored Apr 2, 2018
1 parent c3079c6 commit 099fcc3
Show file tree
Hide file tree
Showing 21 changed files with 404 additions and 306 deletions.
6 changes: 3 additions & 3 deletions include/mbgl/renderer/renderer_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class RendererBackend {
// as a matched pair, exclusively through BackendScope, in two situations:
//
// 1. When releasing GL resources during Renderer destruction
// (Including calling CustomLayerDeinitializeFunction during RenderCustomLayer destruction)
// (Including calling CustomLayerHost::deinitialize during RenderCustomLayer destruction)
// 2. When renderering through Renderer::render()
// (Including calling CustomLayerDeinitializeFunction for newly added custom layers and
// CustomLayerDeinitializeFunction on layer removal)
// (Including calling CustomLayerHost::initialize for newly added custom layers and
// CustomLayerHost::deinitialize on layer removal)
virtual void activate() = 0;
virtual void deactivate() = 0;

Expand Down
86 changes: 40 additions & 46 deletions include/mbgl/style/layers/custom_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@ namespace mbgl {
namespace style {

/**
* Initialize any GL state needed by the custom layer. This method is called once, from the
* main thread, at a point when the GL context is active but before rendering for the first
* time.
*
* Resources that are acquired in this method must be released in the UninitializeFunction.
*/
using CustomLayerInitializeFunction = void (*)(void* context);

/**
* Parameters that define the current camera position for a CustomLayerRenderFunction.
* Parameters that define the current camera position for a `CustomLayerHost::render()` function.
*/
struct CustomLayerRenderParameters {
double width;
Expand All @@ -28,46 +19,49 @@ struct CustomLayerRenderParameters {
double fieldOfView;
};

/**
* Render the layer. This method is called once per frame. The implementation should not make
* any assumptions about the GL state (other than that the correct context is active). It may
* make changes to the state, and is not required to reset values such as the depth mask, stencil
* mask, and corresponding test flags to their original values.
* Make sure that you are drawing your fragments with a z value of 1 to take advantage of the
* opaque fragment culling in case there are opaque layers above your custom layer.
*/
using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&);

/**
* Called when the system has destroyed the underlying GL context. The
* `CustomLayerDeinitializeFunction` will not be called in this case, however
* `CustomLayerInitializeFunction` will be called instead to prepare for a new render.
*
*/
using CustomLayerContextLostFunction = void (*)(void* context);

/**
* Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
* method is called once, from the main thread, at a point when the GL context is active.
*
* Note that it may be called even when the InitializeFunction has not been called.
*/
using CustomLayerDeinitializeFunction = void (*)(void* context);
class CustomLayerHost {
public:
virtual ~CustomLayerHost() = default;
/**
* Initialize any GL state needed by the custom layer. This method is called once, from the
* main thread, at a point when the GL context is active but before rendering for the first
* time.
*
* Resources that are acquired in this method must be released in the `deinitialize` function.
*/
virtual void initialize() = 0;

/**
* Render the layer. This method is called once per frame. The implementation should not make
* any assumptions about the GL state (other than that the correct context is active). It may
* make changes to the state, and is not required to reset values such as the depth mask, stencil
* mask, and corresponding test flags to their original values.
* Make sure that you are drawing your fragments with a z value of 1 to take advantage of the
* opaque fragment culling in case there are opaque layers above your custom layer.
*/
virtual void render(const CustomLayerRenderParameters&) = 0;

/**
* Called when the system has destroyed the underlying GL context. The
* `deinitialize` function will not be called in this case, however
* `initialize` will be called instead to prepare for a new render.
*
*/
virtual void contextLost() = 0;

/**
* Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
* method is called once, from the main thread, at a point when the GL context is active.
*
* Note that it may be called even when the `initialize` function has not been called.
*/
virtual void deinitialize() = 0;
};

class CustomLayer : public Layer {
public:
CustomLayer(const std::string& id,
CustomLayerInitializeFunction,
CustomLayerRenderFunction,
CustomLayerContextLostFunction,
CustomLayerDeinitializeFunction,
void* context);

CustomLayer(const std::string& id,
CustomLayerInitializeFunction,
CustomLayerRenderFunction,
CustomLayerDeinitializeFunction,
void* context);
std::unique_ptr<CustomLayerHost> host);

~CustomLayer() final;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,8 @@
public class CustomLayer extends Layer {

public CustomLayer(String id,
long context,
long initializeFunction,
long renderFunction,
long deinitializeFunction) {
this(id, context, initializeFunction, renderFunction, 0L, deinitializeFunction);
}

public CustomLayer(String id,
long context,
long initializeFunction,
long renderFunction,
long contextLostFunction,
long deinitializeFunction) {
initialize(id, initializeFunction, renderFunction, contextLostFunction, deinitializeFunction, context);
long host) {
initialize(id, host);
}

public CustomLayer(long nativePtr) {
Expand All @@ -33,9 +21,7 @@ public void update() {
nativeUpdate();
}

protected native void initialize(String id, long initializeFunction, long renderFunction,
long contextLostFunction, long deinitializeFunction,
long context);
protected native void initialize(String id, long host);

protected native void nativeUpdate();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@ private void swapCustomLayer() {
fab.setImageResource(R.drawable.ic_layers);
} else {
customLayer = new CustomLayer("custom",
ExampleCustomLayer.createContext(),
ExampleCustomLayer.InitializeFunction,
ExampleCustomLayer.RenderFunction,
ExampleCustomLayer.ContextLostFunction, // Optional
ExampleCustomLayer.DeinitializeFunction);
ExampleCustomLayer.createContext());
mapboxMap.addLayerBelow(customLayer, "building");
fab.setImageResource(R.drawable.ic_layers_clear);
}
Expand Down
75 changes: 28 additions & 47 deletions platform/android/src/example_custom_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,9 @@ void checkCompileStatus(GLuint shader) {
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
static const GLchar * fragmentShaderSource = "uniform highp vec4 fill_color; void main() { gl_FragColor = fill_color; }";

class ExampleCustomLayer {
class ExampleCustomLayer: mbgl::style::CustomLayerHost {
public:
~ExampleCustomLayer() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "~ExampleCustomLayer");
if (program) {
glDeleteBuffers(1, &buffer);
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(program);
}
}

void initialize() {
Expand Down Expand Up @@ -158,8 +149,15 @@ class ExampleCustomLayer {
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
}

void render() {
void render(const mbgl::style::CustomLayerRenderParameters&) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Render");
glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glUniform4fv(fill_color, 1, color);

GL_CHECK_ERROR(glUseProgram(program));
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
Expand All @@ -172,6 +170,23 @@ class ExampleCustomLayer {

}

void contextLost() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "ContextLost");
program = 0;
}

void deinitialize() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "DeInitialize");
if (program) {
glDeleteBuffers(1, &buffer);
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(program);
}
}

GLuint program = 0;
GLuint vertexShader = 0;
GLuint fragmentShader = 0;
Expand All @@ -186,7 +201,8 @@ GLfloat ExampleCustomLayer::color[] = { 0.0f, 1.0f, 0.0f, 1.0f };

jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeCreateContext");
return reinterpret_cast<jlong>(new ExampleCustomLayer());
auto exampleCustomLayer = std::make_unique<ExampleCustomLayer>();
return reinterpret_cast<jlong>(exampleCustomLayer.release());
}

void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
Expand All @@ -197,25 +213,6 @@ void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat b
ExampleCustomLayer::color[3] = alpha;
}

void nativeInitialize(void *context) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeInitialize");
reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
}

void nativeRender(void *context, const mbgl::style::CustomLayerRenderParameters& /*parameters*/) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeRender");
reinterpret_cast<ExampleCustomLayer*>(context)->render();
}

void nativeContextLost(void */*context*/) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeContextLost");
}

void nativeDeinitialize(void *context) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeDeinitialize");
delete reinterpret_cast<ExampleCustomLayer*>(context);
}

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "OnLoad");

Expand All @@ -234,22 +231,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return JNI_ERR;
}

env->SetStaticLongField(customLayerClass,
env->GetStaticFieldID(customLayerClass, "InitializeFunction", "J"),
reinterpret_cast<jlong>(nativeInitialize));

env->SetStaticLongField(customLayerClass,
env->GetStaticFieldID(customLayerClass, "RenderFunction", "J"),
reinterpret_cast<jlong>(nativeRender));

env->SetStaticLongField(customLayerClass,
env->GetStaticFieldID(customLayerClass, "ContextLostFunction", "J"),
reinterpret_cast<jlong>(nativeContextLost));

env->SetStaticLongField(customLayerClass,
env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"),
reinterpret_cast<jlong>(nativeDeinitialize));

return JNI_VERSION_1_6;
}

Expand Down
10 changes: 3 additions & 7 deletions platform/android/src/style/layers/custom_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@
namespace mbgl {
namespace android {

CustomLayer::CustomLayer(jni::JNIEnv& env, jni::String layerId, jni::jlong initializeFunction, jni::jlong renderFunction, jni::jlong contextLostFunction, jni::jlong deinitializeFunction, jni::jlong context)
CustomLayer::CustomLayer(jni::JNIEnv& env, jni::String layerId, jni::jlong host)
: Layer(env, std::make_unique<mbgl::style::CustomLayer>(
jni::Make<std::string>(env, layerId),
reinterpret_cast<mbgl::style::CustomLayerInitializeFunction>(initializeFunction),
reinterpret_cast<mbgl::style::CustomLayerRenderFunction>(renderFunction),
reinterpret_cast<mbgl::style::CustomLayerContextLostFunction>(contextLostFunction),
reinterpret_cast<mbgl::style::CustomLayerDeinitializeFunction>(deinitializeFunction),
reinterpret_cast<void*>(context))
std::unique_ptr<mbgl::style::CustomLayerHost>(reinterpret_cast<mbgl::style::CustomLayerHost*>(host)))
) {
}

Expand Down Expand Up @@ -53,7 +49,7 @@ namespace android {
// Register the peer
jni::RegisterNativePeer<CustomLayer>(
env, CustomLayer::javaClass, "nativePtr",
std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong, jni::jlong, jni::jlong, jni::jlong, jni::jlong>,
std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong>,
"initialize",
"finalize",
METHOD(&CustomLayer::update, "nativeUpdate"));
Expand Down
2 changes: 1 addition & 1 deletion platform/android/src/style/layers/custom_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CustomLayer : public Layer {

static void registerNative(jni::JNIEnv&);

CustomLayer(jni::JNIEnv&, jni::String, jni::jlong, jni::jlong, jni::jlong, jni::jlong, jni::jlong);
CustomLayer(jni::JNIEnv&, jni::String, jni::jlong);

CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&);

Expand Down
Loading

0 comments on commit 099fcc3

Please sign in to comment.