Scene: Add ::supported() method and implement it for scenes that need it.
diff --git a/src/scene-buffer.cpp b/src/scene-buffer.cpp
index 5cf11a6..2214e53 100644
--- a/src/scene-buffer.cpp
+++ b/src/scene-buffer.cpp
@@ -327,6 +327,22 @@
 }
 
 bool
+SceneBuffer::supported(bool show_errors)
+{
+    if (options_["update-method"].value != "subdata" &&
+        (GLExtensions::MapBuffer == 0 || GLExtensions::UnmapBuffer == 0))
+    {
+        if (show_errors) {
+            Log::error("Requested MapBuffer VBO update method but GL_OES_mapbuffer"
+                       " is not supported!\n");
+        }
+        return false;
+    }
+
+    return true;
+}
+
+bool
 SceneBuffer::load()
 {
     running_ = false;
@@ -347,6 +363,10 @@
     Scene::setup();
 
     bool should_run = true;
+
+    if (!supported(true))
+        should_run = false;
+
     bool interleave = (options_["interleave"].value == "true");
     Mesh::VBOUpdateMethod update_method;
     Mesh::VBOUsage usage;
@@ -374,13 +394,6 @@
     nlength = Util::fromString<size_t>(options_["columns"].value);
     nwidth = Util::fromString<size_t>(options_["rows"].value);
 
-    if (update_method == Mesh::VBOUpdateMethodMap &&
-        (GLExtensions::MapBuffer == 0 || GLExtensions::UnmapBuffer == 0))
-    {
-        Log::error("Requested MapBuffer VBO update method but GL_OES_mapbuffer"
-                   " is not supported!\n");
-        should_run = false;
-    }
 
     priv_->wave = new WaveMesh(5.0, 2.0, nlength, nwidth,
                                update_fraction * (1.0 - update_dispersion + 0.0001),
diff --git a/src/scene-terrain.cpp b/src/scene-terrain.cpp
index 9b5bd22..8cea0fb 100644
--- a/src/scene-terrain.cpp
+++ b/src/scene-terrain.cpp
@@ -231,6 +231,21 @@
 }
 
 bool
+SceneTerrain::supported(bool show_errors)
+{
+    GLint vertex_textures;
+    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vertex_textures);
+
+    if (show_errors && vertex_textures <= 0) {
+        Log::error("SceneTerrain requires Vertex Texture Fetch support, "
+                   "but GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS is %d\n",
+                   vertex_textures);
+    }
+    
+    return vertex_textures > 0;
+}
+
+bool
 SceneTerrain::load()
 {
     Scene::load();
@@ -251,13 +266,7 @@
 {
     Scene::setup();
 
-    /* Ensure implementation supports vertex texture fetch */
-    GLint vertex_textures;
-    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vertex_textures);
-    if (vertex_textures <= 0) {
-        Log::error("SceneTerrain requires Vertex Texture Fetch support, "
-                   "but GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS is %d\n",
-                   vertex_textures);
+    if (!supported(true)) {
         currentFrame_ = 0;
         startTime_ = Util::get_timestamp_us() / 1000000.0;
         running_ = false;
diff --git a/src/scene.cpp b/src/scene.cpp
index be6dd9a..a842efd 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -76,6 +76,13 @@
 }
 
 bool
+Scene::supported(bool show_errors)
+{
+    static_cast<void>(show_errors);
+    return true;
+}
+
+bool
 Scene::load()
 {
     return true;
diff --git a/src/scene.h b/src/scene.h
index c52239a..ebd8e82 100644
--- a/src/scene.h
+++ b/src/scene.h
@@ -74,6 +74,15 @@
     };
 
     /**
+     * Checks whether this scene (in its current configuration) is supported.
+     *
+     * @param show_errors whether to log errors about unsupported features
+     *
+     * @return whether the scene is supported
+     */
+    virtual bool supported(bool show_errors);
+
+    /**
      * Performs option-independent resource loading and configuration.
      *
      * It should be safe to call ::load() (and the corresponding ::unload())
@@ -473,6 +482,7 @@
 {
 public:
     SceneBuffer(Canvas &canvas);
+    bool supported(bool show_errors);
     bool load();
     void unload();
     void setup();
@@ -513,6 +523,7 @@
 {
 public:
     SceneTerrain(Canvas &pCanvas);
+    bool supported(bool show_errors);
     bool load();
     void unload();
     void setup();