diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a76b8cbe10c958f32c55cc04425748d7c02300e..8cc19dd4bb976ee1a2153fd193dc1134c63e7f8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,8 +83,9 @@ cmake_dependent_option(XRT_HAVE_WAYLAND "Enable Wayland support" ON "WAYLAND_FOU
 cmake_dependent_option(XRT_HAVE_XLIB "Enable xlib support" ON "X11_FOUND" OFF)
 cmake_dependent_option(XRT_HAVE_XCB "Enable xcb support" ON "XCB_FOUND" OFF)
 cmake_dependent_option(XRT_HAVE_OPENGL "Enable OpenGL Graphics API support" ON "OPENGL_FOUND" OFF)
+cmake_dependent_option(XRT_HAVE_OPENGLES "Enable OpenGL-ES Graphics API support" ON "XRT_HAVE_OPENGL OR ANDROID" OFF)
 cmake_dependent_option(XRT_HAVE_VULKAN "Enable Vulkan Graphics API support (also needed for compositor)" ON "VULKAN_FOUND" OFF)
-cmake_dependent_option(XRT_HAVE_EGL "Enable OpenGL on EGL Graphics API support" ON "XRT_HAVE_OPENGL AND EGL_FOUND" OFF)
+cmake_dependent_option(XRT_HAVE_EGL "Enable OpenGL on EGL Graphics API support" ON "EGL_FOUND; XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES" OFF)
 cmake_dependent_option(XRT_HAVE_DBUS "Enable dbus support (for BLE support)" ON "DBUS_FOUND" OFF)
 cmake_dependent_option(XRT_FEATURE_COMPOSITOR_MAIN "Build main compositor host functionality" ON "XRT_HAVE_VULKAN; XRT_HAVE_WAYLAND OR XRT_HAVE_XCB" OFF)
 cmake_dependent_option(XRT_FEATURE_OPENXR "Build OpenXR runtime target" ON "XRT_FEATURE_COMPOSITOR_MAIN" OFF)
@@ -194,6 +195,7 @@ message(STATUS "#    WAYLAND:      ${XRT_HAVE_WAYLAND}")
 message(STATUS "#    XLIB:         ${XRT_HAVE_XLIB}")
 message(STATUS "#    XCB:          ${XRT_HAVE_XCB}")
 message(STATUS "#    OPENGL:       ${XRT_HAVE_OPENGL}")
+message(STATUS "#    OPENGLES:     ${XRT_HAVE_OPENGLES}")
 message(STATUS "#    VULKAN:       ${XRT_HAVE_VULKAN}")
 message(STATUS "#    EGL:          ${XRT_HAVE_EGL}")
 message(STATUS "#    DBUS:         ${XRT_HAVE_DBUS}")
diff --git a/meson.build b/meson.build
index 81805bd5c5e935ff336266d9541ad15a30dfbcf0..09b3775ddeb5f14961f9cc2fd3668727efd7d7bb 100644
--- a/meson.build
+++ b/meson.build
@@ -54,20 +54,21 @@ glslangValidator = find_program('glslangValidator')
 pthreads = cc.find_library('pthread', required: true)
 rt = cc.find_library('rt', required: true)
 
-avcodec = dependency('libavcodec', required: false)
-egl     = dependency('egl', required: get_option('egl'))
-egl     = egl.partial_dependency(includes: true)
-eigen3  = dependency('eigen3')
-libjpeg = dependency('libjpeg', required: false)
-libusb  = dependency('libusb-1.0', required: false)
-opengl  = dependency('gl', required: get_option('opengl'))
-rs      = dependency('realsense2', required: false)
-sdl2    = dependency('sdl2', required: get_option('gui'))
-udev    = dependency('libudev', required: false)
-libuvc  = dependency('libuvc', required: false)
-vulkan  = dependency('vulkan', required: true)
-zlib    = dependency('zlib', required: false)
-survive = dependency('survive', required: false)
+avcodec  = dependency('libavcodec', required: false)
+egl      = dependency('egl', required: get_option('egl'))
+egl      = egl.partial_dependency(includes: true)
+eigen3   = dependency('eigen3')
+libjpeg  = dependency('libjpeg', required: false)
+libusb   = dependency('libusb-1.0', required: false)
+opengl   = dependency('gl', required: get_option('opengl'))
+opengles = dependency('glesv2', required: get_option('opengles'))
+rs       = dependency('realsense2', required: false)
+sdl2     = dependency('sdl2', required: get_option('gui'))
+udev     = dependency('libudev', required: false)
+libuvc   = dependency('libuvc', required: false)
+vulkan   = dependency('vulkan', required: true)
+zlib     = dependency('zlib', required: false)
+survive  = dependency('survive', required: false)
 
 opencv = dependency('opencv4', required: false)
 if not opencv.found()
@@ -100,6 +101,11 @@ if get_option('opengl').enabled() or get_option('opengl').auto()
         build_opengl = opengl.found()
 endif
 
+build_opengles = false
+if get_option('opengles').enabled() or get_option('opengles').auto()
+        build_opengles = opengles.found() and egl.found()
+endif
+
 
 build_egl = false
 if get_option('egl').enabled() or get_option('egl').auto()
diff --git a/meson_options.txt b/meson_options.txt
index 08bcc1fc8f41d1781222216ea7e88fd6eea8e450..74fc924917f5d68f47315acbd440031751a0605d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -40,7 +40,12 @@ option('install-active-runtime',
 option('opengl',
 	type: 'feature',
 	value: 'auto',
-	description: 'Enable OpenGL/GLES application support.')
+	description: 'Enable OpenGL application support.')
+
+option('opengles',
+	type: 'feature',
+	value: 'auto',
+	description: 'Enable OpenGL|ES application support.')
 
 option('egl',
 	type: 'feature',
diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt
index 42998050b577281879dfddcbfe2505ffd34d83cf..372b6d95d0e9e262854d453a8567277fc32d14e1 100644
--- a/src/xrt/auxiliary/CMakeLists.txt
+++ b/src/xrt/auxiliary/CMakeLists.txt
@@ -19,10 +19,20 @@ set(MATH_SOURCE_FILES
 	)
 
 set(OGL_SOURCE_FILES
-	ogl/ogl_api.c
-	ogl/ogl_api.h
 	ogl/ogl_documentation.h
 	)
+if(XRT_HAVE_OPENGL)
+	list(APPEND OGL_SOURCE_FILES
+		ogl/ogl_api.c
+		ogl/ogl_api.h
+		)
+elseif(XRT_HAVE_OPENGLES)
+	# Only want one of these two sets of files, to avoid duplicate definitions.
+	list(APPEND OGL_SOURCE_FILES
+		ogl/ogles_api.c
+		ogl/ogles_api.h
+		)
+endif()
 
 set(OS_SOURCE_FILES
 	os/os_ble.h
@@ -116,7 +126,7 @@ add_library(aux-includes INTERFACE)
 target_include_directories(aux-includes INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
 target_link_libraries(aux-includes INTERFACE xrt-interfaces)
 
-if(XRT_HAVE_OPENGL)
+if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
 	# OpenGL library.
 	add_library(aux_ogl STATIC ${OGL_SOURCE_FILES})
 	target_link_libraries(aux_ogl PUBLIC aux-includes)
diff --git a/src/xrt/auxiliary/meson.build b/src/xrt/auxiliary/meson.build
index a214ac4df417082db52491542971193cadeb2b09..d86828df74cd7c5c5b147ca78c45f5b2331b171a 100644
--- a/src/xrt/auxiliary/meson.build
+++ b/src/xrt/auxiliary/meson.build
@@ -58,23 +58,37 @@ aux_util = declare_dependency(
 	link_with: lib_aux_util,
 )
 
-lib_aux_ogl = static_library(
-	'aux_ogl',
-	files(
-		'ogl/ogl_api.h',
-		'ogl/ogl_api.c',
+if build_opengl or build_opengles
+	ogl_files = [
 		'ogl/ogl_documentation.h',
-	),
-	include_directories: [
-		xrt_include,
-		glad_include,
-	],
-)
+	]
 
-aux_ogl = declare_dependency(
-	include_directories: aux_include,
-	link_with: lib_aux_ogl,
-)
+	if build_opengl
+		ogl_files += [
+			'ogl/ogl_api.h',
+			'ogl/ogl_api.c',
+		]
+	elif build_opengles
+		ogl_files += [
+			'ogl/ogles_api.h',
+			'ogl/ogles_api.c',
+		]
+	endif
+
+	lib_aux_ogl = static_library(
+		'aux_ogl',
+		files(ogl_files),
+		include_directories: [
+			xrt_include,
+			glad_include,
+		],
+	)
+
+	aux_ogl = declare_dependency(
+		include_directories: aux_include,
+		link_with: lib_aux_ogl,
+	)
+endif
 
 lib_aux_os = static_library(
 	'aux_os',
diff --git a/src/xrt/auxiliary/ogl/ogles_api.c b/src/xrt/auxiliary/ogl/ogles_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..81904b8c22645e1313f9a7b720e939a655c16a8a
--- /dev/null
+++ b/src/xrt/auxiliary/ogl/ogles_api.c
@@ -0,0 +1,10 @@
+// Copyright 2020, Collabora, Ltd.
+// SPDX-License-Identifier: BSL-1.0
+/*!
+ * @file
+ * @brief  OpenGL-ES API wrapper.
+ * @author Ryan Pavlik <ryan.pavlik@collabora.com>
+ * @ingroup aux_ogl
+ */
+
+#include "../../external/glad/src/gles2.c"
diff --git a/src/xrt/auxiliary/ogl/ogles_api.h b/src/xrt/auxiliary/ogl/ogles_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6028075e5e81f498af5aec1fb06c41597d8ba4b
--- /dev/null
+++ b/src/xrt/auxiliary/ogl/ogles_api.h
@@ -0,0 +1,12 @@
+// Copyright 2020, Collabora, Ltd.
+// SPDX-License-Identifier: BSL-1.0
+/*!
+ * @file
+ * @brief  OpenGL API wrapper header.
+ * @author Ryan Pavlik <ryan.pavlik@collabora.com>
+ * @ingroup aux_ogl
+ */
+
+#pragma once
+
+#include "glad/gles2.h"
diff --git a/src/xrt/compositor/CMakeLists.txt b/src/xrt/compositor/CMakeLists.txt
index be041dd712557c73e62a25f602fedc116021c850..96bbf79e34b603cfc95c82d5d97a8348b4fceb41 100644
--- a/src/xrt/compositor/CMakeLists.txt
+++ b/src/xrt/compositor/CMakeLists.txt
@@ -45,12 +45,20 @@ if(XRT_HAVE_VULKAN)
 		client/comp_vk_glue.c
 		)
 endif()
-if(XRT_HAVE_OPENGL)
+if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
 	list(APPEND CLIENT_SOURCE_FILES
 		client/comp_gl_client.c
 		client/comp_gl_client.h
+		)
+endif()
+if(XRT_HAVE_OPENGL)
+	list(APPEND CLIENT_SOURCE_FILES
 		client/comp_gl_glue.c
-		client/comp_gles_glue.c # TODO separate config for GLES
+		)
+endif()
+if(XRT_HAVE_OPENGLES)
+	list(APPEND CLIENT_SOURCE_FILES
+		client/comp_gles_glue.c
 		)
 endif()
 if(XRT_HAVE_OPENGL AND XRT_HAVE_XLIB)
@@ -60,7 +68,7 @@ if(XRT_HAVE_OPENGL AND XRT_HAVE_XLIB)
 		client/comp_gl_xlib_glue.c
 		)
 endif()
-if(XRT_HAVE_OPENGL AND XRT_HAVE_EGL)
+if(XRT_HAVE_EGL)
 	list(APPEND CLIENT_SOURCE_FILES
 		client/comp_egl_glue.c
 		)
@@ -73,7 +81,7 @@ target_include_directories(comp_client PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
 if(XRT_HAVE_VULKAN)
 	target_link_libraries(comp_client PRIVATE aux_vk)
 endif()
-if(XRT_HAVE_OPENGL)
+if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
 	target_link_libraries(comp_client PRIVATE aux_ogl)
 endif()
 
diff --git a/src/xrt/compositor/client/comp_gl_client.c b/src/xrt/compositor/client/comp_gl_client.c
index 4a414c518e5a12d76790af47a54ebb522fadbfa7..1eaf9f1f6a2a54257f520d28abd198186f76a857 100644
--- a/src/xrt/compositor/client/comp_gl_client.c
+++ b/src/xrt/compositor/client/comp_gl_client.c
@@ -12,9 +12,16 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include <xrt/xrt_config_have.h>
 #include "util/u_misc.h"
 
+#if defined(XRT_HAVE_OPENGL)
+// or both OpenGL and GL-ES
 #include "ogl/ogl_api.h"
+#elif defined(XRT_HAVE_OPENGLES)
+#include "ogl/ogles_api.h"
+#endif
+
 #include "client/comp_gl_client.h"
 
 #include <inttypes.h>
@@ -379,7 +386,11 @@ client_gl_compositor_init(struct client_gl_compositor *c,
 	}
 	c->base.base.num_formats = count;
 
+#if defined(XRT_HAVE_OPENGL)
 	gladLoadGL(get_gl_procaddr);
+#elif defined(XRT_HAVE_OPENGLES)
+	gladLoadGLES2(get_gl_procaddr);
+#endif
 	// @todo log this to a proper logger.
 #define CHECK_REQUIRED_EXTENSION(EXT)                                          \
 	do {                                                                   \
diff --git a/src/xrt/compositor/meson.build b/src/xrt/compositor/meson.build
index 22ed10ac66503cb1a86d1b84c31c236af856bf94..5fb47ce47230d46c11f4292b749d7364fb757932 100644
--- a/src/xrt/compositor/meson.build
+++ b/src/xrt/compositor/meson.build
@@ -44,16 +44,27 @@ if build_xcb_xrandr_direct
 	compositor_deps += [xcb_randr, x11_xcb]
 endif
 
-if build_opengl
+if build_opengl or build_opengles
 	compositor_srcs += [
 		'client/comp_gl_client.c',
 		'client/comp_gl_client.h',
+	]
+endif
+
+if build_opengl
+	compositor_srcs += [
 		'client/comp_gl_glue.c',
-		'client/comp_gles_glue.c',
 	]
 	compositor_deps += [opengl]
 	compositor_includes += [glad_include]
 endif
+if build_opengles
+	compositor_srcs += [
+		'client/comp_gles_glue.c',
+	]
+	compositor_deps += [opengles]
+	compositor_includes += [glad_include]
+endif
 
 if build_opengl and build_xlib
 	compositor_srcs += [
diff --git a/src/xrt/include/xrt/meson.build b/src/xrt/include/xrt/meson.build
index 925910e2ab1a746446806a9bdf1e0069532e127b..65e7bec51d95e1257a8937d368d98a1b85e20e5f 100644
--- a/src/xrt/include/xrt/meson.build
+++ b/src/xrt/include/xrt/meson.build
@@ -53,6 +53,14 @@ if opencv.found()
 	have_conf.set('XRT_HAVE_OPENCV', true)
 endif
 
+if build_opengl
+	have_conf.set('XRT_HAVE_OPENGL', true)
+endif
+
+if build_opengles
+	have_conf.set('XRT_HAVE_OPENGLES', true)
+endif
+
 if sdl2.found()
 	have_conf.set('XRT_HAVE_SDL2', true)
 endif
diff --git a/src/xrt/include/xrt/xrt_config_have.h.cmake_in b/src/xrt/include/xrt/xrt_config_have.h.cmake_in
index 323699ae72396238f673c95f4e5c855802029ab9..211a2b93f9421bbba7a109305d3dd9546fb65179 100644
--- a/src/xrt/include/xrt/xrt_config_have.h.cmake_in
+++ b/src/xrt/include/xrt/xrt_config_have.h.cmake_in
@@ -9,12 +9,15 @@
 
 #pragma once
 
+#cmakedefine XRT_HAVE_EGL
 #cmakedefine XRT_HAVE_FFMPEG
 #cmakedefine XRT_HAVE_JPEG
 #cmakedefine XRT_HAVE_LIBUDEV
 #cmakedefine XRT_HAVE_LIBUSB
 #cmakedefine XRT_HAVE_LIBUVC
 #cmakedefine XRT_HAVE_OPENCV
+#cmakedefine XRT_HAVE_OPENGL
+#cmakedefine XRT_HAVE_OPENGLES
 #cmakedefine XRT_HAVE_SDL2
 #cmakedefine XRT_HAVE_SYSTEMD
 #cmakedefine XRT_HAVE_V4L2
diff --git a/src/xrt/include/xrt/xrt_openxr_includes.h b/src/xrt/include/xrt/xrt_openxr_includes.h
index 00b5893bb56aab06b53f04053de99a0b83c682ac..5d87246e833a0f270d52ec5cb587a8a2bfa7c32a 100644
--- a/src/xrt/include/xrt/xrt_openxr_includes.h
+++ b/src/xrt/include/xrt/xrt_openxr_includes.h
@@ -29,7 +29,7 @@ typedef void *GLXDrawable;
 typedef void *GLXContext;
 #endif
 
-#ifdef XR_USE_PLATFORM_EGL
+#if defined(XR_USE_PLATFORM_EGL) || defined(XR_USE_GRAPHICS_API_OPENGL_ES)
 typedef void *EGLDisplay;
 typedef void *EGLContext;
 typedef void *EGLConfig;
diff --git a/src/xrt/state_trackers/oxr/CMakeLists.txt b/src/xrt/state_trackers/oxr/CMakeLists.txt
index 9dada77136306b50c10b59765456e1289d392cfe..62597f4d1cca20c5a1a0c8daa92f5ff632648798 100644
--- a/src/xrt/state_trackers/oxr/CMakeLists.txt
+++ b/src/xrt/state_trackers/oxr/CMakeLists.txt
@@ -67,7 +67,13 @@ if(XRT_HAVE_VULKAN)
 endif()
 
 if(XRT_HAVE_OPENGL)
-	add_definitions(-DXR_USE_GRAPHICS_API_OPENGL -DXR_USE_GRAPHICS_API_OPENGL_ES)
+	add_definitions(-DXR_USE_GRAPHICS_API_OPENGL)
+endif()
+if(XRT_HAVE_OPENGLES)
+	add_definitions(-DXR_USE_GRAPHICS_API_OPENGL_ES)
+endif()
+
+if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
 	list(APPEND OXR_SOURCE_FILES
 		oxr_session_gl.c
 		oxr_swapchain_gl.c
diff --git a/src/xrt/state_trackers/oxr/meson.build b/src/xrt/state_trackers/oxr/meson.build
index 3152093fdc04c5f04fbd729655627753c5d42867..0556eb84b2e28c8f0b7bb8b2cdef63b54aedeafa 100644
--- a/src/xrt/state_trackers/oxr/meson.build
+++ b/src/xrt/state_trackers/oxr/meson.build
@@ -24,7 +24,11 @@ generated = custom_target('bindings code',
 
 compile_args = []
 if build_opengl
-	compile_args += ['-DXR_USE_GRAPHICS_API_OPENGL', '-DXR_USE_GRAPHICS_API_OPENGL_ES']
+	compile_args += ['-DXR_USE_GRAPHICS_API_OPENGL']
+endif
+
+if build_opengles
+	compile_args += ['-DXR_USE_GRAPHICS_API_OPENGL_ES']
 endif
 
 if build_egl
diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h
index 40650acf2a326ec8539fa06e41d2f97f5266450f..57b686b2c6dfcc5136a6f2107cdded8b20ec3f17 100644
--- a/src/xrt/state_trackers/oxr/oxr_objects.h
+++ b/src/xrt/state_trackers/oxr/oxr_objects.h
@@ -911,13 +911,18 @@ oxr_session_populate_gl_xlib(struct oxr_logger *log,
                              struct oxr_session *sess);
 #endif // XR_USE_PLATFORM_XLIB
 
+#endif // XR_USE_GRAPHICS_API_OPENGL
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) ||                                     \
+    defined(XR_USE_GRAPHICS_API_OPENGL_ES)
 XrResult
 oxr_swapchain_gl_create(struct oxr_logger *,
                         struct oxr_session *sess,
                         const XrSwapchainCreateInfo *,
                         struct oxr_swapchain **out_swapchain);
 
-#endif // XR_USE_GRAPHICS_API_OPENGL
+#endif // XR_USE_GRAPHICS_API_OPENGL || XR_USE_GRAPHICS_API_OPENGL_ES
+
 
 
 /*