summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2016-11-04 17:39:14 +0100
committerKonstantin Käfer <mail@kkaefer.com>2016-11-04 21:24:05 +0100
commitc90a55959980f9ef9678a45b9c9ded906d637b34 (patch)
tree7bf7a9041c269934b3bb25f2b84934f29d330d8b
parenteed16cb1bb14c5de68e71ba7960cbe264cc08760 (diff)
downloadqtlocation-mapboxgl-c90a55959980f9ef9678a45b9c9ded906d637b34.tar.gz
[core] move framebuffer reading to gl::Context
-rwxr-xr-xplatform/android/src/native_map_view.cpp15
-rw-r--r--platform/default/offscreen_view.cpp15
-rw-r--r--platform/macos/src/MGLMapView.mm16
-rw-r--r--src/mbgl/gl/context.cpp26
-rw-r--r--src/mbgl/gl/context.hpp10
-rw-r--r--src/mbgl/gl/types.hpp4
-rw-r--r--src/mbgl/renderer/painter_debug.cpp41
-rw-r--r--src/mbgl/util/offscreen_texture.cpp16
8 files changed, 51 insertions, 92 deletions
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 65e39b198e..0026aaa708 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -10,8 +10,6 @@
#include <sys/system_properties.h>
-#include <GLES2/gl2.h>
-
#include <mbgl/platform/platform.hpp>
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
@@ -204,18 +202,7 @@ void NativeMapView::render() {
snapshot = false;
// take snapshot
- const unsigned int w = fbWidth;
- const unsigned int h = fbHeight;
- mbgl::PremultipliedImage image({ w, h });
- MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
- const size_t stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t *rgba = image.data.get();
- for (int i = 0, j = h - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
+ auto image = getContext().readFramebuffer<mbgl::PremultipliedImage>(getFramebufferSize());
// encode and convert to jbytes
std::string string = encodePNG(image);
diff --git a/platform/default/offscreen_view.cpp b/platform/default/offscreen_view.cpp
index 613e00fc2b..574686ebc9 100644
--- a/platform/default/offscreen_view.cpp
+++ b/platform/default/offscreen_view.cpp
@@ -1,6 +1,5 @@
#include <mbgl/platform/default/offscreen_view.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
#include <cstring>
#include <cassert>
@@ -25,19 +24,7 @@ void OffscreenView::bind() {
}
PremultipliedImage OffscreenView::readStillImage() {
- PremultipliedImage image { size };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size.width, size.height, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size.height - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
+ return context.readFramebuffer<PremultipliedImage>(size);
}
} // namespace mbgl
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 02f96ac3ff..513687f94e 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -24,7 +24,6 @@
#import <mbgl/platform/darwin/reachability.h>
#import <mbgl/platform/default/thread_pool.hpp>
#import <mbgl/gl/extension.hpp>
-#import <mbgl/gl/gl.hpp>
#import <mbgl/gl/context.hpp>
#import <mbgl/map/backend.hpp>
#import <mbgl/sprite/sprite_image.hpp>
@@ -2608,20 +2607,7 @@ public:
}
mbgl::PremultipliedImage readStillImage() {
- mbgl::PremultipliedImage image(nativeView.framebufferSize);
- MBGL_CHECK_ERROR(glReadPixels(0, 0, image.size.width, image.size.height, GL_RGBA,
- GL_UNSIGNED_BYTE, image.data.get()));
-
- const size_t stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t *rgba = image.data.get();
- for (int i = 0, j = image.size.height - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
+ return getContext().readFramebuffer<mbgl::PremultipliedImage>(nativeView.framebufferSize);
}
private:
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 1cd546f407..811a038caf 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -92,6 +92,32 @@ UniqueRenderbuffer Context::createRenderbuffer(const RenderbufferType type, cons
return renderbuffer;
}
+std::unique_ptr<uint8_t[]> Context::readFramebuffer(const Size size, const TextureFormat format, const bool flip) {
+ const size_t stride = size.width * (format == TextureFormat::RGBA ? 4 : 1);
+ auto data = std::make_unique<uint8_t[]>(stride * size.height);
+
+#if not MBGL_USE_GLES2
+ // When reading data from the framebuffer, make sure that we are storing the values
+ // tightly packed into the buffer to avoid buffer overruns.
+ pixelStorePack = { 1 };
+#endif // MBGL_USE_GLES2
+
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, size.width, size.height, static_cast<GLenum>(format),
+ GL_UNSIGNED_BYTE, data.get()));
+
+ if (flip) {
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t* rgba = data.get();
+ for (int i = 0, j = size.height - 1; i < j; i++, j--) {
+ std::memcpy(tmp.get(), rgba + i * stride, stride);
+ std::memcpy(rgba + i * stride, rgba + j * stride, stride);
+ std::memcpy(rgba + j * stride, tmp.get(), stride);
+ }
+ }
+
+ return data;
+}
+
namespace {
void checkFramebuffer() {
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 9bfa54fa55..169aa5566e 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -62,6 +62,15 @@ public:
const Renderbuffer<RenderbufferType::DepthStencil>&);
Framebuffer createFramebuffer(const Texture&);
+ template <typename Image,
+ TextureFormat format = Image::channels == 4 ? TextureFormat::RGBA
+ : TextureFormat::Alpha>
+ Image readFramebuffer(const Size size, bool flip = true) {
+ static_assert(Image::channels == (format == TextureFormat::RGBA ? 4 : 1),
+ "image format mismatch");
+ return { size, readFramebuffer(size, format, flip) };
+ }
+
// Create a texture from an image with data.
template <typename Image>
Texture createTexture(const Image& image, TextureUnit unit = 0) {
@@ -167,6 +176,7 @@ private:
void updateTexture(TextureID, Size size, const void* data, TextureFormat, TextureUnit);
UniqueFramebuffer createFramebuffer();
UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
+ std::unique_ptr<uint8_t[]> readFramebuffer(Size, TextureFormat, bool flip);
PrimitiveType operator()(const Points&);
PrimitiveType operator()(const Lines&);
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index 6e1bc5f8e1..1697656469 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -50,6 +50,10 @@ enum class TextureWrap : bool { Clamp, Repeat };
enum class TextureFormat : uint32_t {
RGBA = 0x1908,
Alpha = 0x1906,
+#if not MBGL_USE_GLES2
+ Stencil = 0x1901,
+ Depth = 0x1902,
+#endif // MBGL_USE_GLES2
};
enum class PrimitiveType {
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index bdc0b90bd4..dfb1581bab 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -68,29 +68,16 @@ void Painter::renderClipMasks(PaintParameters&) {
context.program = 0;
#if not MBGL_USE_GLES2
-
- // When reading data from the framebuffer, make sure that we are storing the depth values
- // tightly packed into the buffer to avoid buffer overruns. Also see unpacking adjustment below.
- context.pixelStorePack = { 1 };
-
// Reset the value in case someone else changed it, or it's dirty.
context.pixelTransferStencil = gl::value::PixelTransferStencil::Default;
// Read the stencil buffer
const auto viewport = context.viewport.getCurrentValue();
- auto pixels = std::make_unique<uint8_t[]>(viewport.size.width * viewport.size.height);
- MBGL_CHECK_ERROR(glReadPixels(
- viewport.x, // GLint x
- viewport.y, // GLint y
- viewport.size.width, // GLsizei width
- viewport.size.height, // GLsizei height
- GL_STENCIL_INDEX, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- pixels.get() // GLvoid * data
- ));
+ auto image =
+ context.readFramebuffer<AlphaImage, gl::TextureFormat::Stencil>(viewport.size, false);
// Scale the Stencil buffer to cover the entire color space.
- auto it = pixels.get();
+ auto it = image.data.get();
auto end = it + viewport.size.width * viewport.size.height;
const auto factor = 255.0f / *std::max_element(it, end);
for (; it != end; ++it) {
@@ -101,7 +88,7 @@ void Painter::renderClipMasks(PaintParameters&) {
context.rasterPos = { -1, -1, 0, 1 };
context.pixelStoreUnpack = { 1 };
MBGL_CHECK_ERROR(glDrawPixels(viewport.size.width, viewport.size.height, GL_LUMINANCE,
- GL_UNSIGNED_BYTE, pixels.get()));
+ GL_UNSIGNED_BYTE, image.data.get()));
#endif // MBGL_USE_GLES2
}
@@ -112,11 +99,6 @@ void Painter::renderDepthBuffer(PaintParameters&) {
context.program = 0;
#if not MBGL_USE_GLES2
-
- // When reading data from the framebuffer, make sure that we are storing the depth values
- // tightly packed into the buffer to avoid buffer overruns. Also see unpacking adjustment below.
- context.pixelStorePack = { 1 };
-
// Scales the values in the depth buffer so that they cover the entire grayscale range. This
// makes it easier to spot tiny differences.
const float base = 1.0f / (1.0f - depthRangeSize);
@@ -124,23 +106,14 @@ void Painter::renderDepthBuffer(PaintParameters&) {
// Read the stencil buffer
auto viewport = context.viewport.getCurrentValue();
- auto pixels = std::make_unique<uint8_t[]>(viewport.size.width * viewport.size.height);
-
- MBGL_CHECK_ERROR(glReadPixels(
- viewport.x, // GLint x
- viewport.y, // GLint y
- viewport.size.width, // GLsizei width
- viewport.size.height, // GLsizei height
- GL_DEPTH_COMPONENT, // GLenum format
- GL_UNSIGNED_BYTE, // GLenum type
- pixels.get() // GLvoid * data
- ));
+ auto image =
+ context.readFramebuffer<AlphaImage, gl::TextureFormat::Depth>(viewport.size, false);
context.pixelZoom = { 1, 1 };
context.rasterPos = { -1, -1, 0, 1 };
context.pixelStoreUnpack = { 1 };
MBGL_CHECK_ERROR(glDrawPixels(viewport.size.width, viewport.size.height, GL_LUMINANCE,
- GL_UNSIGNED_BYTE, pixels.get()));
+ GL_UNSIGNED_BYTE, image.data.get()));
#endif // MBGL_USE_GLES2
}
#endif // NDEBUG
diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp
index 6352e38ab7..aad20e59d3 100644
--- a/src/mbgl/util/offscreen_texture.cpp
+++ b/src/mbgl/util/offscreen_texture.cpp
@@ -1,6 +1,5 @@
#include <mbgl/util/offscreen_texture.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
#include <cstring>
#include <cassert>
@@ -29,20 +28,7 @@ gl::Texture& OffscreenTexture::getTexture() {
}
PremultipliedImage OffscreenTexture::readStillImage() {
- PremultipliedImage image { size };
- MBGL_CHECK_ERROR(
- glReadPixels(0, 0, size.width, size.height, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size.height - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
+ return context.readFramebuffer<PremultipliedImage>(size);
}