From 8eceb082bab11fb1fd7d2dcfe85152daa6c54da4 Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Mon, 5 Jan 2015 12:28:32 +1300 Subject: [PATCH] Add failsafe to program binary loading --- android/cpp/native_map_view.cpp | 4 ++ .../java/com/mapbox/mapboxgl/lib/MapView.java | 2 +- src/mbgl/map/map.cpp | 5 +- src/mbgl/shader/shader.cpp | 53 +++++++++++++++---- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/android/cpp/native_map_view.cpp b/android/cpp/native_map_view.cpp index 986d33902..64bca2d59 100644 --- a/android/cpp/native_map_view.cpp +++ b/android/cpp/native_map_view.cpp @@ -624,6 +624,7 @@ void NativeMapView::loadExtensions() { } if (extensions.find("GL_OES_get_program_binary") != std::string::npos) { + mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_OES_get_program_binary."); GLint numBinaryFormats; MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats)); if (numBinaryFormats > 0) { @@ -638,6 +639,7 @@ void NativeMapView::loadExtensions() { } if (extensions.find("GL_KHR_debug") != std::string::npos) { + mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_KHR_debug."); gl::DebugMessageControl = reinterpret_cast( eglGetProcAddress("glDebugMessageControl")); gl::DebugMessageInsert = reinterpret_cast( @@ -673,6 +675,7 @@ void NativeMapView::loadExtensions() { assert(gl::GetObjectPtrLabel != nullptr); } else { if (extensions.find("GL_EXT_debug_marker") != std::string::npos) { + mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_EXT_debug_marker."); gl::InsertEventMarkerEXT = reinterpret_cast( eglGetProcAddress("glInsertEventMarkerEXT")); gl::PushGroupMarkerEXT = reinterpret_cast( @@ -685,6 +688,7 @@ void NativeMapView::loadExtensions() { } if (extensions.find("GL_EXT_debug_label") != std::string::npos) { + mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_EXT_debug_label."); gl::LabelObjectEXT = reinterpret_cast( eglGetProcAddress("glLabelObjectEXT")); gl::GetObjectLabelEXT = reinterpret_cast( diff --git a/android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java b/android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java index 8985c318b..bd37d3806 100644 --- a/android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java +++ b/android/java/lib/src/main/java/com/mapbox/mapboxgl/lib/MapView.java @@ -405,7 +405,7 @@ public class MapView extends SurfaceView { outState.putBoolean(STATE_DEBUG_ACTIVE, isDebugActive()); outState.putString(STATE_STYLE_URL, getStyleUrl()); outState.putString(STATE_ACCESS_TOKEN, getAccessToken()); - outState.putStringArrayList(STATE_APPLIED_CLASSES, new ArrayList(getAppliedStyleClasses())); + //outState.putStringArrayList(STATE_APPLIED_CLASSES, new ArrayList(getAppliedStyleClasses())); outState.putLong(STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration()); } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 36afadbc3..94ee72da6 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -602,8 +602,7 @@ void Map::setAppliedClasses(const std::vector &classes) { if (style->hasTransitions()) { update(); } - } - else { + } else { std::lock_guard lock(appliedClassesMutex); appliedClasses = mbgl::util::make_unique>(classes); } @@ -618,7 +617,7 @@ void Map::toggleClass(const std::string &name) { } const std::vector &Map::getAppliedClasses() const { - return style->getAppliedClasses(); + return style->getAppliedClasses(); } void Map::setDefaultTransitionDuration(uint64_t milliseconds) { diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index 87e841f42..d39e1f62e 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace mbgl; @@ -33,17 +34,47 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo binaryFile.read(reinterpret_cast(&binaryLength), sizeof(binaryLength)); binaryFile.read(reinterpret_cast(&binaryFormat), sizeof(binaryFormat)); - std::unique_ptr binary = mbgl::util::make_unique(binaryLength); - binaryFile.read(binary.get(), binaryLength); - binaryFile.close(); - MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength)); + GLint numBinaryFormats; + MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats)); - // Check if the binary was valid - GLint status; - MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status)); - if (status == GL_TRUE) { - skipCompile = true; + std::unique_ptr validBinaryFormats = mbgl::util::make_unique(numBinaryFormats); + MBGL_CHECK_ERROR(glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, reinterpret_cast(validBinaryFormats.get()))); + + bool validBinaryFormat = false; + for (GLint i = 0; i < numBinaryFormats; i++) { + if (validBinaryFormats[i] == binaryFormat) { + validBinaryFormat = true; + } + } + if (!validBinaryFormat) { + Log::Error(Event::OpenGL, "Trying load program binary with an invalid binaryFormat!"); + } + + if (binaryLength == 0) { + Log::Error(Event::OpenGL, "Trying load program binary with a zero length binary!"); + } + + if (validBinaryFormat && (binaryLength != 0)) { + + std::unique_ptr binary = mbgl::util::make_unique(binaryLength); + binaryFile.read(binary.get(), binaryLength); + binaryFile.close(); + + Log::Error(Event::OpenGL, "glProgramBinary(%u, %u, %u, %u)", program, binaryFormat, binary.get(), binaryLength); + MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength)); + + // Check if the binary was valid + GLint status; + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status)); + if (status == GL_TRUE) { + skipCompile = true; + } + } else { + binaryFile.close(); + + // Delete the bad file + std::remove(binaryFileName.c_str()); } } @@ -180,7 +211,9 @@ Shader::~Shader() { MBGL_CHECK_ERROR(glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); if (binaryLength > 0) { std::unique_ptr binary = mbgl::util::make_unique(binaryLength); - MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get())); + MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, nullptr, &binaryFormat, binary.get())); + + Log::Error(Event::OpenGL, "glGetProgramBinary(%u, %u, nullptr, %u, %u)", program, binaryLength, binaryFormat, binary.get()); // Write the binary to a file std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary);