Revert "screen-capture-utils: Reorganize egl_capture interface."

This reverts commit 812d15d97c17eccff6f6d10ecdb2c385dcd5e2d1.

Reason for revert: b:176004895
tast.graphics.Smoke.* broken on various boards (cave, lars, sentry)

Original change's description:
> screen-capture-utils: Reorganize egl_capture interface.
>
> In preparation for extending the use with kmsvnc so that set up and teardown is
> separate.
>
> BUG=b:168259048
> BUG=b:174629145
> TEST=screenshot /tmp/hoge.png  # on rammus.
>
> Change-Id: I4eafdd269f138fbd4b065857d008042975dbd435
> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2569163
> Tested-by: Junichi Uekawa <uekawa@chromium.org>
> Commit-Queue: Junichi Uekawa <uekawa@chromium.org>
> Reviewed-by: Daniele Castagna <dcastagna@chromium.org>
> Reviewed-by: Shuhei Takahashi <nya@chromium.org>

Bug: b:168259048
Bug: b:174629145
Bug: b:176004895
Test: flash caroline-cq build, verify `tast graphics.Smoke.platform` passes
Change-Id: I8a4350a488e8d493ca34798350e27312ed22709b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2599794
Reviewed-by: Shuhei Takahashi <nya@chromium.org>
Tested-by: Shao-Chuan Lee <shaochuan@chromium.org>
diff --git a/screen-capture-utils/bo_import_capture.cc b/screen-capture-utils/bo_import_capture.cc
index f1201ea..e8c6d46 100644
--- a/screen-capture-utils/bo_import_capture.cc
+++ b/screen-capture-utils/bo_import_capture.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,48 +17,57 @@
 
 namespace screenshot {
 
-GbmBoDisplayBuffer::GbmBoDisplayBuffer(
-    const Crtc* crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
-    : crtc_(*crtc),
-      device_(gbm_create_device(crtc_.file().GetPlatformFile())),
-      x_(x),
-      y_(y),
+GbmBoMap::GbmBoMap(ScopedGbmDevicePtr device,
+                   ScopedGbmBoPtr bo,
+                   uint32_t x,
+                   uint32_t y,
+                   uint32_t width,
+                   uint32_t height)
+    : device_(std::move(device)),
+      bo_(std::move(bo)),
       width_(width),
       height_(height) {
-  CHECK(device_) << "gbm_create_device failed";
-
-  {
-    int fd;
-    int rv = drmPrimeHandleToFD(crtc_.file().GetPlatformFile(),
-                                crtc_.fb()->handle, 0, &fd);
-    CHECK_EQ(rv, 0) << "drmPrimeHandleToFD failed";
-    buffer_fd_.reset(fd);
-  }
-
-  buffer_ = gbm_bo_map2(bo_.get(), x_, y_, width_, height_,
-                        GBM_BO_TRANSFER_READ, &stride_, &map_data_, 0);
+  buffer_ = gbm_bo_map2(bo_.get(), x, y, width, height, GBM_BO_TRANSFER_READ,
+                        &stride_, &map_data_, 0);
   PCHECK(buffer_ != MAP_FAILED) << "gbm_bo_map failed";
 }
 
-GbmBoDisplayBuffer::~GbmBoDisplayBuffer() {
+GbmBoMap::~GbmBoMap() {
   gbm_bo_unmap(bo_.get(), map_data_);
 }
 
-DisplayBuffer::Result GbmBoDisplayBuffer::Capture() {
-  gbm_import_fd_data fd_data = {
-      buffer_fd_.get(),
-      crtc_.fb()->width,
-      crtc_.fb()->height,
-      crtc_.fb()->pitch,
-      // TODO(djmk): The buffer format is hardcoded to ARGB8888, we should fix
-      // this to query for the frambuffer's format instead.
-      GBM_FORMAT_ARGB8888,
-  };
-  bo_.reset(gbm_bo_import(device_.get(), GBM_BO_IMPORT_FD, &fd_data,
-                          GBM_BO_USE_SCANOUT));
-  CHECK(bo_.get()) << "gbm_bo_import failed";
+std::unique_ptr<GbmBoMap> Capture(
+    const Crtc& crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
+  ScopedGbmDevicePtr device(gbm_create_device(crtc.file().GetPlatformFile()));
+  CHECK(device) << "gbm_create_device failed";
 
-  return {width_, height_, stride_, buffer_};
+  base::ScopedFD buffer_fd;
+  {
+    int fd;
+    int rv = drmPrimeHandleToFD(crtc.file().GetPlatformFile(),
+                                crtc.fb()->handle, 0, &fd);
+    CHECK_EQ(rv, 0) << "drmPrimeHandleToFD failed";
+    buffer_fd.reset(fd);
+  }
+
+  ScopedGbmBoPtr bo;
+  {
+    gbm_import_fd_data fd_data = {
+        buffer_fd.get(),
+        crtc.fb()->width,
+        crtc.fb()->height,
+        crtc.fb()->pitch,
+        // TODO(djmk): The buffer format is hardcoded to ARGB8888, we should fix
+        // this to query for the frambuffer's format instead.
+        GBM_FORMAT_ARGB8888,
+    };
+    bo.reset(gbm_bo_import(device.get(), GBM_BO_IMPORT_FD, &fd_data,
+                           GBM_BO_USE_SCANOUT));
+  }
+  CHECK(bo) << "gbm_bo_import failed";
+
+  return std::make_unique<GbmBoMap>(std::move(device), std::move(bo), x, y,
+                                    width, height);
 }
 
 }  // namespace screenshot
diff --git a/screen-capture-utils/bo_import_capture.h b/screen-capture-utils/bo_import_capture.h
index 5cd5100..a76b60b 100644
--- a/screen-capture-utils/bo_import_capture.h
+++ b/screen-capture-utils/bo_import_capture.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,11 +9,9 @@
 
 #include <memory>
 
-#include <base/files/scoped_file.h>
 #include <base/macros.h>
 #include <gbm.h>
 
-#include "screen-capture-utils/capture.h"
 #include "screen-capture-utils/ptr_util.h"
 
 namespace screenshot {
@@ -21,35 +19,38 @@
 class Crtc;
 
 // Utility class to map/unmap GBM buffer with RAII.
-class GbmBoDisplayBuffer : public DisplayBuffer {
+class GbmBoMap {
  public:
-  GbmBoDisplayBuffer(const Crtc* crtc,
-                     uint32_t x,
-                     uint32_t y,
-                     uint32_t width,
-                     uint32_t height);
-  GbmBoDisplayBuffer(const GbmBoDisplayBuffer&) = delete;
-  GbmBoDisplayBuffer& operator=(const GbmBoDisplayBuffer&) = delete;
+  GbmBoMap(ScopedGbmDevicePtr device,
+           ScopedGbmBoPtr bo,
+           uint32_t x,
+           uint32_t y,
+           uint32_t width,
+           uint32_t height);
+  GbmBoMap(const GbmBoMap&) = delete;
+  GbmBoMap& operator=(const GbmBoMap&) = delete;
 
-  ~GbmBoDisplayBuffer() override;
+  ~GbmBoMap();
 
-  DisplayBuffer::Result Capture() override;
+  uint32_t width() const { return width_; }
+  uint32_t height() const { return height_; }
+  uint32_t stride() const { return stride_; }
+  void* buffer() const { return buffer_; }
 
  private:
-  const Crtc& crtc_;
   const ScopedGbmDevicePtr device_;
-  const uint32_t x_;
-  const uint32_t y_;
+  const ScopedGbmBoPtr bo_;
   const uint32_t width_;
   const uint32_t height_;
-
-  ScopedGbmBoPtr bo_{nullptr};
-  uint32_t stride_{0};
-  void* map_data_{nullptr};
-  void* buffer_{nullptr};
-  base::ScopedFD buffer_fd_{0};
+  uint32_t stride_ = 0;
+  void* map_data_ = nullptr;
+  void* buffer_ = nullptr;
 };
 
+// Captures a screenshot from the specified CRTC.
+std::unique_ptr<GbmBoMap> Capture(
+    const Crtc& crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
+
 }  // namespace screenshot
 
 #endif  // SCREEN_CAPTURE_UTILS_BO_IMPORT_CAPTURE_H_
diff --git a/screen-capture-utils/capture.h b/screen-capture-utils/capture.h
deleted file mode 100644
index 8a6e2dd..0000000
--- a/screen-capture-utils/capture.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SCREEN_CAPTURE_UTILS_CAPTURE_H_
-#define SCREEN_CAPTURE_UTILS_CAPTURE_H_
-
-namespace screenshot {
-
-class DisplayBuffer {
- public:
-  struct Result {
-    const uint32_t width;
-    const uint32_t height;
-    const uint32_t stride;
-    void* buffer;
-  };
-  DisplayBuffer(const DisplayBuffer&) = delete;
-  DisplayBuffer& operator=(const DisplayBuffer&) = delete;
-
-  DisplayBuffer() = default;
-  virtual ~DisplayBuffer() = default;
-  virtual Result Capture() = 0;
-};
-
-}  // namespace screenshot
-
-#endif  // SCREEN_CAPTURE_UTILS_CAPTURE_H_
diff --git a/screen-capture-utils/egl_capture.cc b/screen-capture-utils/egl_capture.cc
index 6797eed..6b4b495 100644
--- a/screen-capture-utils/egl_capture.cc
+++ b/screen-capture-utils/egl_capture.cc
@@ -27,8 +27,6 @@
 namespace screenshot {
 namespace {
 
-constexpr int kBytesPerPixel = 4;
-
 GLuint LoadShader(const GLenum type, const char* const src) {
   GLuint shader = 0;
   shader = glCreateShader(type);
@@ -44,8 +42,7 @@
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
     std::vector<char> shader_log(log_length);
     glGetShaderInfoLog(shader, log_length, nullptr, shader_log.data());
-    CHECK(false) << "Shader failed to compile: " << shader_log.data()
-                 << ": program: " << src;
+    CHECK(false) << "Shader failed to compile: " << shader_log.data();
   }
 
   return shader;
@@ -145,21 +142,28 @@
 
 }  // namespace
 
-EglDisplayBuffer::EglDisplayBuffer(
-    const Crtc* crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
-    : crtc_(*crtc),
-      x_(x),
-      y_(y),
+EglPixelBuf::EglPixelBuf(ScopedGbmDevicePtr device,
+                         std::vector<char> buffer,
+                         uint32_t x,
+                         uint32_t y,
+                         uint32_t width,
+                         uint32_t height,
+                         uint32_t stride)
+    : device_(std::move(device)),
       width_(width),
       height_(height),
-      device_(gbm_create_device(crtc_.file().GetPlatformFile())),
-      display_(eglGetDisplay(EGL_DEFAULT_DISPLAY)),
-      buffer_(width_ * height_ * kBytesPerPixel) {
-  CHECK(device_) << "gbm_create_device failed";
+      stride_(stride),
+      buffer_(buffer) {}
 
-  CHECK(display_ != EGL_NO_DISPLAY) << "Could not get EGLDisplay";
+std::unique_ptr<EglPixelBuf> EglCapture(
+    const Crtc& crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
+  ScopedGbmDevicePtr device(gbm_create_device(crtc.file().GetPlatformFile()));
+  CHECK(device) << "gbm_create_device failed";
 
-  EGLBoolean egl_ret = eglInitialize(display_, NULL, NULL);
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  CHECK(display != EGL_NO_DISPLAY) << "Could not get EGLDisplay";
+
+  EGLBoolean egl_ret = eglInitialize(display, NULL, NULL);
   CHECK(egl_ret) << "Could not initialize EGLDisplay";
 
   const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_DONT_CARE,
@@ -171,17 +175,17 @@
   EGLint num_configs;
   EGLConfig config;
 
-  egl_ret = eglChooseConfig(display_, config_attribs, &config, 1, &num_configs);
+  egl_ret = eglChooseConfig(display, config_attribs, &config, 1, &num_configs);
   CHECK(egl_ret) << "Could not choose EGLConfig";
   CHECK(num_configs != 0) << "Could not choose an EGL configuration";
 
-  ctx_ = eglCreateContext(display_, config, EGL_NO_CONTEXT, GLES2);
-  CHECK(ctx_ != EGL_NO_CONTEXT) << "Could not create EGLContext";
+  EGLContext ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, GLES2);
+  CHECK(ctx != EGL_NO_CONTEXT) << "Could not create EGLContext";
 
-  egl_ret = eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx_);
+  egl_ret = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx);
   CHECK(egl_ret) << "Could not bind context";
 
-  std::string egl_extensions = eglQueryString(display_, EGL_EXTENSIONS);
+  std::string egl_extensions = eglQueryString(display, EGL_EXTENSIONS);
   CHECK(egl_extensions.find("EGL_KHR_image_base") != std::string::npos)
       << "Missing EGL extension: EGL_KHR_image_base";
   CHECK(egl_extensions.find("EGL_EXT_image_dma_buf_import") !=
@@ -193,111 +197,103 @@
       << "Missing GL extension: GL_OES_EGL_image";
   CHECK(gl_extensions.find("GL_OES_EGL_image_external") != std::string::npos)
       << "Missing GL extension: GL_OES_EGL_image_external";
-  createImageKHR_ =
-      (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
-  CHECK(createImageKHR_) << "CreateImageKHR not supported";
-  destroyImageKHR_ =
-      (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
-  CHECK(destroyImageKHR_) << "DestroyImageKHR not supported";
 
-  const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
+  PFNEGLCREATEIMAGEKHRPROC CreateImageKHR =
+      (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+  CHECK(CreateImageKHR) << "CreateImageKHR not supported";
+  PFNEGLDESTROYIMAGEKHRPROC DestroyImageKHR =
+      (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+  CHECK(DestroyImageKHR) << "DestroyImageKHR not supported";
+
+  const char* extensions = eglQueryString(display, EGL_EXTENSIONS);
   CHECK(extensions) << "eglQueryString() failed to get egl extensions";
-  import_modifiers_exist_ =
+  const bool import_modifiers_exist =
       DoesExtensionExist(extensions, "EGL_EXT_image_dma_buf_import_modifiers");
 
-  glGenTextures(1, &output_texture_);
-  glBindTexture(GL_TEXTURE_2D, output_texture_);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
+  GLuint output_texture;
+  glGenTextures(1, &output_texture);
+  glBindTexture(GL_TEXTURE_2D, output_texture);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
                GL_UNSIGNED_BYTE, NULL);
 
-  glGenTextures(1, &input_texture_);
-  glBindTexture(GL_TEXTURE_EXTERNAL_OES, input_texture_);
+  GLuint input_texture;
+  glGenTextures(1, &input_texture);
+  glBindTexture(GL_TEXTURE_EXTERNAL_OES, input_texture);
 
-  glEGLImageTargetTexture2DOES_ =
+  PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES =
       (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress(
           "glEGLImageTargetTexture2DOES");
-  CHECK(glEGLImageTargetTexture2DOES_)
+  CHECK(glEGLImageTargetTexture2DOES)
       << "glEGLImageTargetTexture2DOES not supported";
 
-  glGenFramebuffers(1, &fbo_);
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
+  unsigned int fbo;
+  glGenFramebuffers(1, &fbo);
+  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 
-  const GLchar* vert = R"(#version 300 es
-out vec2 tex_pos;
-void main() {
-  vec2 pos[4];
-  pos[0] = vec2(-1.0, -1.0);
-  pos[1] = vec2(1.0, -1.0);
-  pos[2] = vec2(-1.0, 1.0);
-  pos[3] = vec2(1.0, 1.0);
-  gl_Position.xy = pos[gl_VertexID];
-  gl_Position.zw = vec2(0.0, 1.0);
-  vec2 uvs[4];
-  uvs[0] = vec2(0.0, 0.0);
-  uvs[1] = vec2(1.0, 0.0);
-  uvs[2] = vec2(0.0, 1.0);
-  uvs[3] = vec2(1.0, 1.0);
-  tex_pos = uvs[gl_VertexID];
-}
-)";
+  const GLchar* vert =
+      "#version 300 es\n"
+      "out vec2 tex_pos;\n"
+      "void main() {\n"
+      " vec2 pos[4];\n"
+      " pos[0] = vec2(-1.0, -1.0);\n"
+      " pos[1] = vec2(1.0, -1.0);\n"
+      " pos[2] = vec2(-1.0, 1.0);\n"
+      " pos[3] = vec2(1.0, 1.0);\n"
+      " gl_Position.xy = pos[gl_VertexID];\n"
+      " gl_Position.zw = vec2(0.0, 1.0);\n"
+      " vec2 uvs[4];\n"
+      " uvs[0] = vec2(0.0, 0.0);\n"
+      " uvs[1] = vec2(1.0, 0.0);\n"
+      " uvs[2] = vec2(0.0, 1.0);\n"
+      " uvs[3] = vec2(1.0, 1.0);\n"
+      " tex_pos = uvs[gl_VertexID];\n"
+      "}\n";
 
-  const GLchar* frag = R"(#version 300 es
-#extension GL_OES_EGL_image_external_essl3 : require
-precision highp float;
-uniform samplerExternalOES tex;
-in vec2 tex_pos;
-out vec4 fragColor;
-void main() {
-  fragColor = texture(tex, tex_pos);
-}
-)";
+  const GLchar* frag =
+      "#version 300 es\n"
+      "#extension GL_OES_EGL_image_external_essl3 : require\n"
+      "precision highp float;\n"
+      "uniform samplerExternalOES tex;\n"
+      "in vec2 tex_pos;\n"
+      "out vec4 fragColor;\n"
+      "void main() {\n"
+      "  fragColor = texture(tex, tex_pos);\n"
+      "}\n";
 
   LoadProgram(vert, frag);
 
   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         output_texture_, 0);
+                         output_texture, 0);
 
   GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
   CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << "fb did not complete";
 
+  GLuint indices[4] = {0, 1, 2, 3};
 
   glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-}
 
-EglDisplayBuffer::~EglDisplayBuffer() {
-  eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-  glDeleteTextures(1, &input_texture_);
-  glDeleteTextures(1, &output_texture_);
-  glDeleteFramebuffers(1, &fbo_);
-  eglDestroyContext(display_, ctx_);
-  eglTerminate(display_);
-}
-
-DisplayBuffer::Result EglDisplayBuffer::Capture() {
-  const GLuint indices[4] = {0, 1, 2, 3};
-
-  if (crtc_.planes().empty()) {
+  if (crtc.planes().empty()) {
     EGLImageKHR image =
-        CreateImage(createImageKHR_, import_modifiers_exist_,
-                    crtc_.file().GetPlatformFile(), display_, crtc_.fb2());
+        CreateImage(CreateImageKHR, import_modifiers_exist,
+                    crtc.file().GetPlatformFile(), display, crtc.fb2());
     CHECK(image != EGL_NO_IMAGE_KHR) << "Failed to create image";
 
-    glViewport(0, 0, width_, height_);
-    glEGLImageTargetTexture2DOES_(GL_TEXTURE_EXTERNAL_OES, image);
+    glViewport(0, 0, width, height);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
 
     glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, indices);
 
-    destroyImageKHR_(display_, image);
+    DestroyImageKHR(display, image);
   } else {
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-    for (auto& plane : crtc_.planes()) {
-      EGLImageKHR image = CreateImage(createImageKHR_, import_modifiers_exist_,
-                                      crtc_.file().GetPlatformFile(), display_,
+    for (auto& plane : crtc.planes()) {
+      EGLImageKHR image = CreateImage(CreateImageKHR, import_modifiers_exist,
+                                      crtc.file().GetPlatformFile(), display,
                                       plane.first.get());
       CHECK(image != EGL_NO_IMAGE_KHR) << "Failed to create image";
 
@@ -305,25 +301,29 @@
       glViewport(plane.second.x, plane.second.y, plane.second.w,
                  plane.second.h);
 
-      glEGLImageTargetTexture2DOES_(GL_TEXTURE_EXTERNAL_OES, image);
+      glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
 
       glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, indices);
 
-      destroyImageKHR_(display_, image);
+      DestroyImageKHR(display, image);
     }
   }
 
+  std::vector<char> buffer(width * height * 4);
   glPixelStorei(GL_PACK_ALIGNMENT, 1);
-  // TODO(uekawa): potentially improve speed by creating a bo and writing to it
-  // instead of reading out.
-  glReadPixels(x_, y_, width_, height_, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
-               buffer_.data());
+  glReadPixels(x, y, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
+               buffer.data());
 
-  return {
-      width_, height_,
-      width_ * kBytesPerPixel,            // stride
-      static_cast<void*>(buffer_.data())  // buffer
-  };
+  eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+  glDeleteTextures(1, &input_texture);
+  glDeleteTextures(1, &output_texture);
+  glDeleteFramebuffers(1, &fbo);
+  eglDestroyContext(display, ctx);
+  eglTerminate(display);
+
+  return std::make_unique<EglPixelBuf>(std::move(device), buffer, x, y, width,
+                                       height, width * 4);
 }
 
 }  // namespace screenshot
diff --git a/screen-capture-utils/egl_capture.h b/screen-capture-utils/egl_capture.h
index e55d50a..0d1d444 100644
--- a/screen-capture-utils/egl_capture.h
+++ b/screen-capture-utils/egl_capture.h
@@ -13,52 +13,42 @@
 #include <base/macros.h>
 #include <gbm.h>
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <EGL/eglplatform.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include "screen-capture-utils/capture.h"
 #include "screen-capture-utils/ptr_util.h"
 
 namespace screenshot {
 
 class Crtc;
 
-class EglDisplayBuffer : public DisplayBuffer {
+// Utility class to fill pixel buffer with RAII.
+class EglPixelBuf {
  public:
-  EglDisplayBuffer(const Crtc* crtc,
-                   uint32_t x,
-                   uint32_t y,
-                   uint32_t width,
-                   uint32_t height);
-  EglDisplayBuffer(const EglDisplayBuffer&) = delete;
-  EglDisplayBuffer& operator=(const EglDisplayBuffer&) = delete;
-  ~EglDisplayBuffer() override;
-  // Captures a screenshot from the specified CRTC.
-  DisplayBuffer::Result Capture() override;
+  EglPixelBuf(ScopedGbmDevicePtr device,
+              std::vector<char> buffer,
+              uint32_t x,
+              uint32_t y,
+              uint32_t width,
+              uint32_t height,
+              uint32_t stride);
+  EglPixelBuf(const EglPixelBuf&) = delete;
+  EglPixelBuf& operator=(const EglPixelBuf&) = delete;
+
+  uint32_t width() const { return width_; }
+  uint32_t height() const { return height_; }
+  uint32_t stride() const { return stride_; }
+  std::vector<char>& buffer() { return buffer_; }
 
  private:
-  const Crtc& crtc_;
-  const uint32_t x_;
-  const uint32_t y_;
+  const ScopedGbmDevicePtr device_;
   const uint32_t width_;
   const uint32_t height_;
-  const ScopedGbmDevicePtr device_;
-  const EGLDisplay display_;
-
-  GLuint input_texture_;
-  GLuint output_texture_;
-  unsigned int fbo_;
-  EGLContext ctx_;
-  PFNEGLCREATEIMAGEKHRPROC createImageKHR_;
-  PFNEGLDESTROYIMAGEKHRPROC destroyImageKHR_;
-  PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_;
-  bool import_modifiers_exist_;
+  uint32_t stride_ = 0;
   std::vector<char> buffer_;
 };
 
+// Captures a screenshot from the specified CRTC.
+std::unique_ptr<EglPixelBuf> EglCapture(
+    const Crtc& crtc, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
+
 }  // namespace screenshot
 
 #endif  // SCREEN_CAPTURE_UTILS_EGL_CAPTURE_H_
diff --git a/screen-capture-utils/main.cc b/screen-capture-utils/main.cc
index 3953d1c..726a0c0 100644
--- a/screen-capture-utils/main.cc
+++ b/screen-capture-utils/main.cc
@@ -12,7 +12,6 @@
 #include <base/strings/string_number_conversions.h>
 
 #include "screen-capture-utils/bo_import_capture.h"
-#include "screen-capture-utils/capture.h"
 #include "screen-capture-utils/crtc.h"
 #include "screen-capture-utils/egl_capture.h"
 #include "screen-capture-utils/png.h"
@@ -123,19 +122,15 @@
     LOG(INFO) << "Capturing primary plane only\n";
   }
 
-  std::unique_ptr<screenshot::DisplayBuffer> display_buffer;
-
   if (crtc->fb2() || !crtc->planes().empty()) {
-    display_buffer.reset(
-        new screenshot::EglDisplayBuffer(crtc.get(), x, y, width, height));
+    auto map = screenshot::EglCapture(*crtc, x, y, width, height);
+    screenshot::SaveAsPng(cmdline->GetArgs()[0].c_str(), map->buffer().data(),
+                          map->width(), map->height(), map->stride());
   } else {
-    display_buffer.reset(
-        new screenshot::GbmBoDisplayBuffer(crtc.get(), x, y, width, height));
+    auto map = screenshot::Capture(*crtc, x, y, width, height);
+    screenshot::SaveAsPng(cmdline->GetArgs()[0].c_str(), map->buffer(),
+                          map->width(), map->height(), map->stride());
   }
-
-  screenshot::DisplayBuffer::Result result = display_buffer->Capture();
-  screenshot::SaveAsPng(cmdline->GetArgs()[0].c_str(), result.buffer,
-                        result.width, result.height, result.stride);
   return 0;
 }