Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(709)

Side by Side Diff: components/display_compositor/buffer_queue.cc

Issue 2873243002: Move components/display_compositor to components/viz/display_compositor (Closed)
Patch Set: Rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/display_compositor/buffer_queue.h"
6
7 #include "base/containers/adapters.h"
8 #include "base/memory/ptr_util.h"
9 #include "build/build_config.h"
10 #include "components/display_compositor/gl_helper.h"
11 #include "gpu/GLES2/gl2extchromium.h"
12 #include "gpu/command_buffer/client/gles2_interface.h"
13 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
14 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
15 #include "third_party/skia/include/core/SkRect.h"
16 #include "third_party/skia/include/core/SkRegion.h"
17 #include "ui/display/types/display_snapshot.h"
18 #include "ui/gfx/gpu_memory_buffer.h"
19 #include "ui/gfx/skia_util.h"
20
21 namespace display_compositor {
22
23 BufferQueue::BufferQueue(gpu::gles2::GLES2Interface* gl,
24 uint32_t texture_target,
25 uint32_t internal_format,
26 gfx::BufferFormat format,
27 GLHelper* gl_helper,
28 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
29 gpu::SurfaceHandle surface_handle)
30 : gl_(gl),
31 fbo_(0),
32 allocated_count_(0),
33 texture_target_(texture_target),
34 internal_format_(internal_format),
35 format_(format),
36 gl_helper_(gl_helper),
37 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
38 surface_handle_(surface_handle) {
39 DCHECK(gpu::IsImageFormatCompatibleWithGpuMemoryBufferFormat(internal_format,
40 format_));
41 }
42
43 BufferQueue::~BufferQueue() {
44 FreeAllSurfaces();
45
46 if (fbo_)
47 gl_->DeleteFramebuffers(1, &fbo_);
48 }
49
50 void BufferQueue::Initialize() {
51 gl_->GenFramebuffers(1, &fbo_);
52 }
53
54 void BufferQueue::BindFramebuffer() {
55 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
56
57 if (!current_surface_)
58 current_surface_ = GetNextSurface();
59
60 if (current_surface_) {
61 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
62 texture_target_, current_surface_->texture, 0);
63 if (current_surface_->stencil) {
64 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
65 GL_RENDERBUFFER, current_surface_->stencil);
66 }
67 }
68 }
69
70 void BufferQueue::CopyBufferDamage(int texture,
71 int source_texture,
72 const gfx::Rect& new_damage,
73 const gfx::Rect& old_damage) {
74 gl_helper_->CopySubBufferDamage(texture_target_, texture, source_texture,
75 SkRegion(gfx::RectToSkIRect(new_damage)),
76 SkRegion(gfx::RectToSkIRect(old_damage)));
77 }
78
79 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
80 if (displayed_surface_)
81 displayed_surface_->damage.Union(damage);
82 for (auto& surface : available_surfaces_)
83 surface->damage.Union(damage);
84 for (auto& surface : in_flight_surfaces_) {
85 if (surface)
86 surface->damage.Union(damage);
87 }
88 }
89
90 void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
91 if (current_surface_) {
92 if (damage != gfx::Rect(size_)) {
93 // Copy damage from the most recently swapped buffer. In the event that
94 // the buffer was destroyed and failed to recreate, pick from the most
95 // recently available buffer.
96 uint32_t texture_id = 0;
97 for (auto& surface : base::Reversed(in_flight_surfaces_)) {
98 if (surface) {
99 texture_id = surface->texture;
100 break;
101 }
102 }
103 if (!texture_id && displayed_surface_)
104 texture_id = displayed_surface_->texture;
105
106 if (texture_id) {
107 CopyBufferDamage(current_surface_->texture, texture_id, damage,
108 current_surface_->damage);
109 }
110 }
111 current_surface_->damage = gfx::Rect();
112 }
113 UpdateBufferDamage(damage);
114 in_flight_surfaces_.push_back(std::move(current_surface_));
115 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
116 // paths), so ensure we restore it here.
117 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
118 }
119
120 void BufferQueue::Reshape(const gfx::Size& size,
121 float scale_factor,
122 const gfx::ColorSpace& color_space,
123 bool use_stencil) {
124 if (size == size_ && color_space == color_space_ &&
125 use_stencil == use_stencil_)
126 return;
127 #if !defined(OS_MACOSX)
128 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
129 // is cause for concern or if it is benign.
130 // http://crbug.com/524624
131 DCHECK(!current_surface_);
132 #endif
133 size_ = size;
134 color_space_ = color_space;
135 use_stencil_ = use_stencil;
136
137 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
138 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
139 texture_target_, 0, 0);
140 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
141 GL_RENDERBUFFER, 0);
142
143 FreeAllSurfaces();
144 }
145
146 void BufferQueue::RecreateBuffers() {
147 // We need to recreate the buffers, for whatever reason the old ones are not
148 // presentable on the device anymore.
149 // Unused buffers can be freed directly, they will be re-allocated as needed.
150 // Any in flight, current or displayed surface must be replaced.
151 available_surfaces_.clear();
152
153 // Recreate all in-flight surfaces and put the recreated copies in the queue.
154 for (auto& surface : in_flight_surfaces_)
155 surface = RecreateBuffer(std::move(surface));
156
157 current_surface_ = RecreateBuffer(std::move(current_surface_));
158 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
159
160 if (current_surface_) {
161 // If we have a texture bound, we will need to re-bind it.
162 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
163 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
164 texture_target_, current_surface_->texture, 0);
165 }
166 }
167
168 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
169 std::unique_ptr<AllocatedSurface> surface) {
170 if (!surface)
171 return nullptr;
172
173 std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface());
174 if (!new_surface)
175 return nullptr;
176
177 new_surface->damage = surface->damage;
178
179 // Copy the entire texture.
180 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
181 gfx::Rect(size_));
182 return new_surface;
183 }
184
185 void BufferQueue::PageFlipComplete() {
186 // Early out when no surface is in-flight. This can happen when using
187 // overlays and page flipping without changing the primary plane.
188 if (in_flight_surfaces_.empty())
189 return;
190 if (displayed_surface_)
191 available_surfaces_.push_back(std::move(displayed_surface_));
192 displayed_surface_ = std::move(in_flight_surfaces_.front());
193 in_flight_surfaces_.pop_front();
194 }
195
196 uint32_t BufferQueue::GetCurrentTextureId() const {
197 // Return current surface texture if bound.
198 if (current_surface_)
199 return current_surface_->texture;
200
201 // Return in-flight or displayed surface texture if no surface is
202 // currently bound. This can happen when using overlays and surface
203 // damage is empty. Note: |in_flight_surfaces_| entries can be null
204 // as a result of calling FreeAllSurfaces().
205 if (!in_flight_surfaces_.empty() && in_flight_surfaces_.back())
206 return in_flight_surfaces_.back()->texture;
207 if (displayed_surface_)
208 return displayed_surface_->texture;
209
210 return 0;
211 }
212
213 void BufferQueue::FreeAllSurfaces() {
214 displayed_surface_.reset();
215 current_surface_.reset();
216 // This is intentionally not emptied since the swap buffers acks are still
217 // expected to arrive.
218 for (auto& surface : in_flight_surfaces_)
219 surface = nullptr;
220 available_surfaces_.clear();
221 }
222
223 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
224 if (!surface->texture)
225 return;
226
227 gl_->BindTexture(texture_target_, surface->texture);
228 gl_->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
229 gl_->DeleteTextures(1, &surface->texture);
230 gl_->DestroyImageCHROMIUM(surface->image);
231 if (surface->stencil)
232 gl_->DeleteRenderbuffers(1, &surface->stencil);
233 surface->buffer.reset();
234 allocated_count_--;
235 }
236
237 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
238 if (!available_surfaces_.empty()) {
239 std::unique_ptr<AllocatedSurface> surface =
240 std::move(available_surfaces_.back());
241 available_surfaces_.pop_back();
242 return surface;
243 }
244
245 GLuint texture;
246 gl_->GenTextures(1, &texture);
247
248 GLuint stencil = 0;
249 if (use_stencil_) {
250 gl_->GenRenderbuffers(1, &stencil);
251 gl_->BindRenderbuffer(GL_RENDERBUFFER, stencil);
252 gl_->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, size_.width(),
253 size_.height());
254 gl_->BindRenderbuffer(GL_RENDERBUFFER, 0);
255 }
256
257 // We don't want to allow anything more than triple buffering.
258 DCHECK_LT(allocated_count_, 4U);
259 std::unique_ptr<gfx::GpuMemoryBuffer> buffer(
260 gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
261 size_, format_, gfx::BufferUsage::SCANOUT, surface_handle_));
262 if (!buffer.get()) {
263 gl_->DeleteTextures(1, &texture);
264 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
265 return nullptr;
266 }
267 buffer->SetColorSpaceForScanout(color_space_);
268
269 uint32_t id =
270 gl_->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(),
271 size_.height(), internal_format_);
272 if (!id) {
273 LOG(ERROR) << "Failed to allocate backing image surface";
274 gl_->DeleteTextures(1, &texture);
275 return nullptr;
276 }
277
278 allocated_count_++;
279 gl_->BindTexture(texture_target_, texture);
280 gl_->BindTexImage2DCHROMIUM(texture_target_, id);
281 return base::MakeUnique<AllocatedSurface>(this, std::move(buffer), texture,
282 id, stencil, gfx::Rect(size_));
283 }
284
285 BufferQueue::AllocatedSurface::AllocatedSurface(
286 BufferQueue* buffer_queue,
287 std::unique_ptr<gfx::GpuMemoryBuffer> buffer,
288 uint32_t texture,
289 uint32_t image,
290 uint32_t stencil,
291 const gfx::Rect& rect)
292 : buffer_queue(buffer_queue),
293 buffer(buffer.release()),
294 texture(texture),
295 image(image),
296 stencil(stencil),
297 damage(rect) {}
298
299 BufferQueue::AllocatedSurface::~AllocatedSurface() {
300 buffer_queue->FreeSurfaceResources(this);
301 }
302
303 } // namespace display_compositor
OLDNEW
« no previous file with comments | « components/display_compositor/buffer_queue.h ('k') | components/display_compositor/buffer_queue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698