diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5cbc293..a94e3c4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,9 +14,9 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: Install dependencies
-      run: >
-        sudo apt install meson libdrm-dev libgbm-dev libudev-dev
-        libwayland-dev wayland-protocols libx11-dev
+      run: |
+        sudo apt-get update
+        sudo apt-get install meson libdrm-dev libgbm-dev libudev-dev libwayland-dev wayland-protocols libx11-dev
     - name: Setup
       run: meson setup build -Dflavors=x11-gl,x11-glesv2,wayland-gl,wayland-glesv2,drm-gl,drm-glesv2
     - name: Build
@@ -29,7 +29,9 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: Install dependencies
-      run: sudo apt install meson libdrm-dev libgbm-dev libudev-dev
+      run: |
+        sudo apt-get update
+        sudo apt-get install meson libdrm-dev libgbm-dev libudev-dev
     - name: Setup
       run: meson setup build -Dflavors=drm-gl,drm-glesv2
     - name: Build
@@ -42,7 +44,9 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: Install dependencies
-      run: sudo apt install meson libwayland-dev wayland-protocols
+      run: |
+        sudo apt-get update
+        sudo apt-get install meson libwayland-dev wayland-protocols
     - name: Setup
       run: meson setup build -Dflavors=wayland-gl,wayland-glesv2
     - name: Build
@@ -55,7 +59,9 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: Install dependencies
-      run: sudo apt install meson libx11-dev
+      run: |
+        sudo apt-get update
+        sudo apt-get install meson libx11-dev
     - name: Setup
       run: meson setup build -Dflavors=x11-gl,x11-glesv2
     - name: Build
@@ -68,9 +74,9 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: Install dependencies
-      run: >
-        sudo apt install libdrm-dev libgbm-dev libudev-dev
-        libwayland-dev wayland-protocols libx11-dev
+      run: |
+        sudo apt-get update
+        sudo apt-get install libdrm-dev libgbm-dev libudev-dev libwayland-dev wayland-protocols libx11-dev
     - name: Setup
       run: ./waf configure --with-flavors=x11-gl,x11-glesv2,wayland-gl,wayland-glesv2,drm-gl,drm-glesv2
     - name: Build
diff --git a/NEWS b/NEWS
index 4c2635d..c7227e0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,13 @@
+glmark2 2021.12 (20211223)
+==========================
+
+* Fix crash with NVIDIA OpenGL driver.
+* Fix issues when running with the Wayland backend under Sway.
+* Gracefully handle missing GL features.
+* Fix model loading on big-endian systems.
+* Support EGL versions < 1.4.
+* Fix crash with the DRM backend when we can't become DRM master.
+
 glmark2 2021.02 (20210215)
 ==========================
 
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index fb3074f..5e4b75e 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       android:versionCode="1"
-      android:versionName="2021.02" package="org.linaro.glmark2">
+      android:versionName="2021.12" package="org.linaro.glmark2">
     <application android:icon="@mipmap/ic_launcher"
                  android:label="@string/app_name"
                  android:roundIcon="@mipmap/ic_launcher_round">
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 6003d2f..02f17fc 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -54,7 +54,7 @@ include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libglmark2-android
 LOCAL_STATIC_LIBRARIES := libglmark2-matrix libglmark2-png libglmark2-ideas libglmark2-jpeg
-LOCAL_CFLAGS := -DGLMARK_DATA_PATH="" -DGLMARK_VERSION="\"2021.02\"" \
+LOCAL_CFLAGS := -DGLMARK_DATA_PATH="" -DGLMARK_VERSION="\"2021.12\"" \
                 -DGLMARK2_USE_GLESv2 -Werror -Wall -Wextra -Wnon-virtual-dtor \
                 -Wno-error=unused-parameter
 LOCAL_SHARED_LIBRARIES := liblog libz libEGL libGLESv2 libandroid libdl libstlport
diff --git a/android/jni/Android.ndk.mk b/android/jni/Android.ndk.mk
index 2e2b97d..97a9f86 100644
--- a/android/jni/Android.ndk.mk
+++ b/android/jni/Android.ndk.mk
@@ -102,7 +102,7 @@ include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libglmark2-android
 LOCAL_STATIC_LIBRARIES := libglmark2-matrix libglmark2-png libglmark2-ideas libglmark2-jpeg libglad-egl libglad-glesv2
-LOCAL_CFLAGS := -DGLMARK_DATA_PATH="" -DGLMARK_VERSION="\"2021.02\"" \
+LOCAL_CFLAGS := -DGLMARK_DATA_PATH="" -DGLMARK_VERSION="\"2021.12\"" \
                 -DGLMARK2_USE_GLESv2 -Werror -Wall -Wextra -Wnon-virtual-dtor \
                 -Wno-error=unused-parameter
 LOCAL_LDLIBS := -landroid -llog -lz
diff --git a/debian/changelog b/debian/changelog
index 101e036..23a6945 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+glmark2 (2021.12+git20220214.1.af498f4-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 15 Apr 2022 03:01:54 -0000
+
 glmark2 (2021.10~git.e359bb0-2) unstable; urgency=medium
 
   * Add Provides/Replaces to ease transition from Ubuntu packages.
diff --git a/debian/patches/man.patch b/debian/patches/man.patch
index 387cd23..3144f00 100644
--- a/debian/patches/man.patch
+++ b/debian/patches/man.patch
@@ -3,10 +3,11 @@ Author: Dmitry Smirnov <onlyjob@member.fsf.org>
 Forwarded: no
 Description: lintianisation of man pages
 
---- a/doc/glmark2.1.in
-+++ b/doc/glmark2.1.in
-@@ -39,9 +39,9 @@
- \fB\-s\fR, \fB\-\-size\fR WxH
+Index: glmark2/doc/glmark2.1.in
+===================================================================
+--- glmark2.orig/doc/glmark2.1.in
++++ glmark2/doc/glmark2.1.in
+@@ -43,7 +43,7 @@ Use a single context for all scenes
  Size of the output window (default: 800x600)
  .TP
  \fB\-\-fullscreen\fR
@@ -15,9 +16,7 @@ Description: lintianisation of man pages
  .TP
  \fB\-l\fR, \fB\-\-list\-scenes\fR
  Display information about the available scenes
- and their options
-@@ -55,9 +55,9 @@
- back to the first
+@@ -59,7 +59,7 @@ back to the first
  .TP
  \fB\-\-annotate\fR
  Annotate the benchmarks with on-screen information
@@ -26,9 +25,7 @@ Description: lintianisation of man pages
  .TP
  \fB\-d\fR, \fB\-\-debug\fR
  Display debug messages
- .TP
-@@ -92,22 +92,22 @@
- To run a benchmark using scene 'shading' with a 'duration' of '5.0' seconds and
+@@ -99,20 +99,20 @@ To run a benchmark using scene 'shading'
   'shading' of type 'phong':
  .PP
  .RS
@@ -52,4 +49,3 @@ Description: lintianisation of man pages
  .RE
  .PP
  
- .SH AUTHOR
diff --git a/doc/glmark2.1.in b/doc/glmark2.1.in
index f0d7f65..0c5febf 100644
--- a/doc/glmark2.1.in
+++ b/doc/glmark2.1.in
@@ -1,4 +1,4 @@
-.TH @APPNAME@ "1" "February 2021" "@appname@ @appversion@"
+.TH @APPNAME@ "1" "December 2021" "@appname@ @appversion@"
 .SH NAME
 @appname@ \- OpenGL (ES) 2.0 benchmark suite
 .SH SYNOPSIS
@@ -64,6 +64,9 @@ Annotate the benchmarks with on-screen information
 \fB\-d\fR, \fB\-\-debug\fR
 Display debug messages
 .TP
+\fB\-\-version\fR
+Display program version
+.TP
 \fB\-h\fR, \fB\-\-help\fR
 Display help
 .SH BENCHMARKS
diff --git a/fastlane/metadata/android/en-US/changelogs/20211223 b/fastlane/metadata/android/en-US/changelogs/20211223
new file mode 100644
index 0000000..172f2d2
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/20211223
@@ -0,0 +1,9 @@
+glmark2 2021.12 (20211223)
+==========================
+
+* Fix crash with NVIDIA OpenGL driver.
+* Fix issues when running with the Wayland backend under Sway.
+* Gracefully handle missing GL features.
+* Fix model loading on big-endian systems.
+* Support EGL versions < 1.4.
+* Fix crash with the DRM backend when we can't become DRM master.
diff --git a/meson.build b/meson.build
index 0da984e..8faa842 100644
--- a/meson.build
+++ b/meson.build
@@ -2,7 +2,7 @@ project(
     'glmark2',
     ['cpp', 'c'],
     default_options : ['cpp_std=c++14'],
-    version : '2021.02',
+    version : '2021.12',
     meson_version: '>=0.47'
     )
 
diff --git a/src/canvas-android.cpp b/src/canvas-android.cpp
index 33162a1..382dcf7 100644
--- a/src/canvas-android.cpp
+++ b/src/canvas-android.cpp
@@ -93,25 +93,30 @@ CanvasAndroid::init()
 
     clear();
 
+    eglGetConfigAttrib(egl_display, egl_config, EGL_BUFFER_SIZE, &chosen_config_.buffer);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_RED_SIZE, &chosen_config_.red);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_GREEN_SIZE, &chosen_config_.green);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_BLUE_SIZE, &chosen_config_.blue);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_ALPHA_SIZE, &chosen_config_.alpha);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_DEPTH_SIZE, &chosen_config_.depth);
+    eglGetConfigAttrib(egl_display, egl_config, EGL_STENCIL_SIZE, &chosen_config_.stencil);
+
     if (Options::show_debug) {
-        int buf, red, green, blue, alpha, depth, id, native_id;
+        int id, native_id;
         eglGetConfigAttrib(egl_display, egl_config, EGL_CONFIG_ID, &id);
         eglGetConfigAttrib(egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &native_id);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_BUFFER_SIZE, &buf);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_RED_SIZE, &red);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_GREEN_SIZE, &green);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_BLUE_SIZE, &blue);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_ALPHA_SIZE, &alpha);
-        eglGetConfigAttrib(egl_display, egl_config, EGL_DEPTH_SIZE, &depth);
         Log::debug("EGL chosen config ID: 0x%x Native Visual ID: 0x%x\n"
                    "  Buffer: %d bits\n"
                    "     Red: %d bits\n"
                    "   Green: %d bits\n"
                    "    Blue: %d bits\n"
                    "   Alpha: %d bits\n"
-                   "   Depth: %d bits\n",
+                   "   Depth: %d bits\n"
+                   " Stencil: %d bits\n",
                    id, native_id,
-                   buf, red, green, blue, alpha, depth);
+                   chosen_config_.buffer,
+                   chosen_config_.red, chosen_config_.green, chosen_config_.blue,
+                   chosen_config_.alpha, chosen_config_.depth, chosen_config_.stencil);
     }
 
     return true;
@@ -142,9 +147,15 @@ CanvasAndroid::print_info()
     std::stringstream ss;
 
     ss << "    OpenGL Information" << std::endl;
-    ss << "    GL_VENDOR:     " << glGetString(GL_VENDOR) << std::endl;
-    ss << "    GL_RENDERER:   " << glGetString(GL_RENDERER) << std::endl;
-    ss << "    GL_VERSION:    " << glGetString(GL_VERSION) << std::endl;
+    ss << "    GL_VENDOR:      " << glGetString(GL_VENDOR) << std::endl;
+    ss << "    GL_RENDERER:    " << glGetString(GL_RENDERER) << std::endl;
+    ss << "    GL_VERSION:     " << glGetString(GL_VERSION) << std::endl;
+    ss << "    Surface Config: " << "buf=" << chosen_config_.buffer
+       << " r=" << chosen_config_.red << " g=" << chosen_config_.green
+       << " b=" << chosen_config_.blue << " a=" << chosen_config_.alpha
+       << " depth=" << chosen_config_.depth
+       << " stencil=" << chosen_config_.stencil << std::endl;
+    ss << "    Surface Size:   " << width_ << "x" << height_ << std::endl;
 
     Log::info("%s", ss.str().c_str());
 }
diff --git a/src/canvas-android.h b/src/canvas-android.h
index bdf970c..ef7e0d2 100644
--- a/src/canvas-android.h
+++ b/src/canvas-android.h
@@ -53,6 +53,7 @@ public:
 private:
     SharedLibrary egl_lib_;
     SharedLibrary gles_lib_;
+    GLVisualConfig chosen_config_;
 
     static GLADapiproc load_proc(void *userdata, const char *name);
     void init_gl_extensions();
diff --git a/src/canvas-generic.cpp b/src/canvas-generic.cpp
index 4c3332d..a9f5bd6 100644
--- a/src/canvas-generic.cpp
+++ b/src/canvas-generic.cpp
@@ -133,11 +133,22 @@ CanvasGeneric::print_info()
     do_make_current();
 
     std::stringstream ss;
+    GLVisualConfig config;
+    NativeState::WindowProperties win_props;
+
+    gl_state_.getVisualConfig(config);
+    native_state_.window(win_props);
 
     ss << "    OpenGL Information" << std::endl;
-    ss << "    GL_VENDOR:     " << glGetString(GL_VENDOR) << std::endl;
-    ss << "    GL_RENDERER:   " << glGetString(GL_RENDERER) << std::endl;
-    ss << "    GL_VERSION:    " << glGetString(GL_VERSION) << std::endl;
+    ss << "    GL_VENDOR:      " << glGetString(GL_VENDOR) << std::endl;
+    ss << "    GL_RENDERER:    " << glGetString(GL_RENDERER) << std::endl;
+    ss << "    GL_VERSION:     " << glGetString(GL_VERSION) << std::endl;
+    ss << "    Surface Config: " << "buf=" << config.buffer
+       << " r=" << config.red << " g=" << config.green << " b=" << config.blue
+       << " a=" << config.alpha << " depth=" << config.depth
+       << " stencil=" << config.stencil << std::endl;
+    ss << "    Surface Size:   " << win_props.width << "x" << win_props.height
+       << (win_props.fullscreen ? " fullscreen" : " windowed") << std::endl;
 
     Log::info("%s", ss.str().c_str());
 }
diff --git a/src/libmatrix/program.h b/src/libmatrix/program.h
index f95b470..1c9de08 100644
--- a/src/libmatrix/program.h
+++ b/src/libmatrix/program.h
@@ -15,6 +15,7 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <utility>
 #include "mat.h"
 
 // Simple shader container.  Abstracts all of the OpenGL bits, but leaves
diff --git a/src/libmatrix/util.cc b/src/libmatrix/util.cc
index 80909bc..28ea724 100644
--- a/src/libmatrix/util.cc
+++ b/src/libmatrix/util.cc
@@ -101,6 +101,7 @@ fill_escape_vector(const string &str, vector<bool> &esc_vec)
                     state = StateNormal;
                 else
                     esc = true;
+                break;
             default:
                 break;
         }
diff --git a/src/main.cpp b/src/main.cpp
index 677962e..ce8b094 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -155,6 +155,11 @@ main(int argc, char *argv[])
         return 0;
     }
 
+    if (Options::show_version) {
+        printf("%s\n", GLMARK_VERSION);
+        return 0;
+    }
+
     /* Force 800x600 output for validation */
     if (Options::validate &&
         Options::size != std::pair<int,int>(800, 600))
diff --git a/src/native-state-drm.cpp b/src/native-state-drm.cpp
index 2979917..d6bb743 100644
--- a/src/native-state-drm.cpp
+++ b/src/native-state-drm.cpp
@@ -83,10 +83,22 @@ NativeStateDRM::should_quit()
 void
 NativeStateDRM::flip()
 {
+    if (!crtc_set_ && drmSetMaster(fd_) < 0) {
+        Log::error("Failed to become DRM master "
+                   "(hint: glmark2-drm needs to be run in a VT)\n");
+        should_quit_ = true;
+        return;
+    }
+
     gbm_bo* next = gbm_surface_lock_front_buffer(surface_);
     fb_ = fb_get_from_bo(next);
     unsigned int waiting(1);
 
+    if (!next || !fb_) {
+        Log::error("Failed to get gbm front buffer\n");
+        return;
+    }
+
     if (!crtc_set_) {
         int status = drmModeSetCrtc(fd_, encoder_->crtc_id, fb_->fb_id, 0, 0,
                                     &connector_->connector_id, 1, mode_);
@@ -418,6 +430,10 @@ NativeStateDRM::fb_destroy_callback(gbm_bo* bo, void* data)
 NativeStateDRM::DRMFBState*
 NativeStateDRM::fb_get_from_bo(gbm_bo* bo)
 {
+    if (!bo) {
+        return NULL;
+    }
+
     DRMFBState* fb = reinterpret_cast<DRMFBState*>(gbm_bo_get_user_data(bo));
     if (fb) {
         return fb;
diff --git a/src/options.cpp b/src/options.cpp
index 0630669..aa2abfb 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -37,6 +37,7 @@ std::pair<int,int> Options::size(800, 600);
 bool Options::list_scenes = false;
 bool Options::show_all_options = false;
 bool Options::show_debug = false;
+bool Options::show_version = false;
 bool Options::show_help = false;
 bool Options::reuse_context = false;
 bool Options::run_forever = false;
@@ -60,6 +61,7 @@ static struct option long_options[] = {
     {"list-scenes", 0, 0, 0},
     {"show-all-options", 0, 0, 0},
     {"debug", 0, 0, 0},
+    {"version", 0, 0, 0},
     {"help", 0, 0, 0},
     {0, 0, 0, 0}
 };
@@ -146,6 +148,7 @@ Options::print_help()
            "      --annotate         Annotate the benchmarks with on-screen information\n"
            "                         (same as -b :show-fps=true:title=#info#)\n"
            "  -d, --debug            Display debug messages\n"
+           "      --version          Display program version\n"
            "  -h, --help             Display help\n");
 }
 
@@ -197,6 +200,8 @@ Options::parse_args(int argc, char **argv)
             Options::run_forever = true;
         else if (c == 'd' || !strcmp(optname, "debug"))
             Options::show_debug = true;
+        else if (!strcmp(optname, "version"))
+            Options::show_version = true;
         else if (c == 'h' || !strcmp(optname, "help"))
             Options::show_help = true;
     }
diff --git a/src/options.h b/src/options.h
index 7182534..c3bc500 100644
--- a/src/options.h
+++ b/src/options.h
@@ -49,6 +49,7 @@ struct Options {
     static bool list_scenes;
     static bool show_all_options;
     static bool show_debug;
+    static bool show_version;
     static bool show_help;
     static bool reuse_context;
     static bool run_forever;
diff --git a/wscript b/wscript
index 2d33a5a..fe56f5c 100644
--- a/wscript
+++ b/wscript
@@ -4,7 +4,7 @@ from waflib import Context
 out = 'build'
 top = '.'
 
-VERSION = '2021.02'
+VERSION = '2021.12'
 APPNAME = 'glmark2'
 
 FLAVORS = {