summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--platform/default/headless_view.cpp36
2 files changed, 28 insertions, 10 deletions
diff --git a/package.json b/package.json
index ad8bbb8fde..e21e7f7691 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "mapbox-gl-native",
- "version": "2.2.0",
+ "version": "2.2.0-pbo",
"description": "Renders map tiles with Mapbox GL",
"keywords": [
"mapbox",
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
index 7fd3c37f3a..dda2f6ca3d 100644
--- a/platform/default/headless_view.cpp
+++ b/platform/default/headless_view.cpp
@@ -176,17 +176,35 @@ PremultipliedImage HeadlessView::readStillImage() {
const unsigned int h = dimensions[1] * pixelRatio;
PremultipliedImage image { w, h };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const int 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);
+ GLuint bufferId;
+
+ MBGL_CHECK_ERROR(glGenBuffers(1, &bufferId));
+ MBGL_CHECK_ERROR(glBindBuffer(GL_PIXEL_PACK_BUFFER, bufferId));
+ MBGL_CHECK_ERROR(glBufferData(GL_PIXEL_PACK_BUFFER, h * image.stride(), 0, GL_STREAM_READ));
+ MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0));
+
+ // map the PBO to process its data by CPU
+ GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
+
+ if (ptr) {
+ const int stride = image.stride();
+ auto tmp = std::make_unique<uint8_t[]>(stride);
+ uint8_t* rgba = image.data.get();
+
+ for (unsigned int i = 0, j = h - 1; i < h; i++, j--) {
+ std::memcpy(rgba + i * stride, ptr + j * stride, stride);
+ }
+
+ MBGL_CHECK_ERROR(glUnmapBuffer(GL_PIXEL_PACK_BUFFER));
+ } else {
+ throw std::runtime_error(std::string("Could not map buffer on return from read pixels."));
}
+ MBGL_CHECK_ERROR(glDeleteBuffers(1, &bufferId));
+
+ // back to conventional pixel operation
+ MBGL_CHECK_ERROR(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
+
return image;
}