1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/common/gl_surface_egl_readback.h"
#include <utility>
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"
#include "ui/ozone/common/egl_util.h"
namespace ui {
namespace {
constexpr size_t kBytesPerPixelBGRA = 4;
} // namespace
GLSurfaceEglReadback::GLSurfaceEglReadback(gl::GLDisplayEGL* display)
: PbufferGLSurfaceEGL(display, gfx::Size(1, 1)),
task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
bool GLSurfaceEglReadback::Resize(const gfx::Size& size,
float scale_factor,
const gfx::ColorSpace& color_space,
bool has_alpha) {
pixels_.reset();
if (!PbufferGLSurfaceEGL::Resize(size, scale_factor, color_space, has_alpha))
return false;
// For NullDrawGLBindings, all draws will be skipped,
// so reading back pixels will causes use-of-uninitialized-value problem
// on MemorySanitizer enabled trybots, so don't allocate the pixel_ and skip
// pixels reading back.
// See crbug.com/1259170 for detail.
if (gl::HasInitializedNullDrawGLBindings())
return true;
// Allocate a new buffer for readback.
const size_t buffer_size = size.width() * size.height() * kBytesPerPixelBGRA;
pixels_ = std::make_unique<uint8_t[]>(buffer_size);
return true;
}
bool GLSurfaceEglReadback::IsOffscreen() {
return false;
}
gfx::SwapResult GLSurfaceEglReadback::SwapBuffers(
PresentationCallback callback) {
gfx::SwapResult swap_result = gfx::SwapResult::SWAP_FAILED;
gfx::PresentationFeedback feedback;
if (pixels_) {
ReadPixels(pixels_.get());
if (HandlePixels(pixels_.get())) {
// Swap is successful, so return SWAP_ACK and provide the current time
// with presentation feedback.
swap_result = gfx::SwapResult::SWAP_ACK;
feedback.timestamp = base::TimeTicks::Now();
}
} else {
swap_result = gfx::SwapResult::SWAP_ACK;
feedback.timestamp = base::TimeTicks::Now();
}
task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), feedback));
return swap_result;
}
gfx::SurfaceOrigin GLSurfaceEglReadback::GetOrigin() const {
return gfx::SurfaceOrigin::kTopLeft;
}
GLSurfaceEglReadback::~GLSurfaceEglReadback() {
Destroy();
}
bool GLSurfaceEglReadback::HandlePixels(uint8_t* pixels) {
return true;
}
void GLSurfaceEglReadback::ReadPixels(void* buffer) {
const gfx::Size size = GetSize();
GLint read_fbo = 0;
GLint pixel_pack_buffer = 0;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_fbo);
glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &pixel_pack_buffer);
// Make sure pixels are read from fbo 0.
if (read_fbo)
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
// Make sure pixels are stored into |pixels_| instead of buffer binding to
// GL_PIXEL_PACK_BUFFER.
if (pixel_pack_buffer)
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glReadPixels(0, 0, size.width(), size.height(), GL_BGRA, GL_UNSIGNED_BYTE,
buffer);
if (read_fbo)
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_fbo);
if (pixel_pack_buffer)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixel_pack_buffer);
}
} // namespace ui
|