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

Side by Side Diff: components/mus/surfaces/buffer_queue.cc

Issue 1958813002: mus: Use BufferQueue and GLHelper from display_compositor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: , Created 4 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 2016 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/mus/surfaces/buffer_queue.h"
6
7 #include "base/containers/adapters.h"
8 #include "base/memory/ptr_util.h"
9 #include "cc/output/context_provider.h"
10 #include "components/mus/gles2/gl_helper.h"
11 #include "components/mus/gles2/ozone_gpu_memory_buffer.h"
12 #include "gpu/GLES2/gl2extchromium.h"
13 #include "gpu/command_buffer/client/gles2_interface.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/gfx/gpu_memory_buffer.h"
18 #include "ui/gfx/skia_util.h"
19
20 namespace mus {
21
22 BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
23 unsigned int texture_target,
24 unsigned int internalformat,
25 gfx::AcceleratedWidget widget)
26 : context_provider_(context_provider),
27 fbo_(0),
28 allocated_count_(0),
29 texture_target_(texture_target),
30 internal_format_(internalformat),
31 widget_(widget) {}
32
33 BufferQueue::~BufferQueue() {
34 FreeAllSurfaces();
35
36 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
37 if (fbo_)
38 gl->DeleteFramebuffers(1, &fbo_);
39 }
40
41 void BufferQueue::Initialize() {
42 DCHECK(context_provider_);
43 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
44 DCHECK(gl);
45 gl->GenFramebuffers(1, &fbo_);
46 }
47
48 void BufferQueue::BindFramebuffer() {
49 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
50 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
51
52 if (!current_surface_)
53 current_surface_ = GetNextSurface();
54
55 if (current_surface_) {
56 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
57 texture_target_, current_surface_->texture, 0);
58 }
59 }
60
61 void BufferQueue::CopyBufferDamage(int texture,
62 int source_texture,
63 const gfx::Rect& new_damage,
64 const gfx::Rect& old_damage) {
65 GLCopySubBufferDamage(context_provider_->ContextGL(), texture_target_,
66 texture, source_texture,
67 SkRegion(gfx::RectToSkIRect(new_damage)),
68 SkRegion(gfx::RectToSkIRect(old_damage)));
69 }
70
71 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
72 if (displayed_surface_)
73 displayed_surface_->damage.Union(damage);
74 for (auto& surface : available_surfaces_)
75 surface->damage.Union(damage);
76 for (auto& surface : in_flight_surfaces_) {
77 if (surface)
78 surface->damage.Union(damage);
79 }
80 }
81
82 void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
83 if (current_surface_) {
84 if (damage != gfx::Rect(size_)) {
85 // Copy damage from the most recently swapped buffer. In the event that
86 // the buffer was destroyed and failed to recreate, pick from the most
87 // recently available buffer.
88 unsigned int texture_id = 0;
89 for (auto& surface : base::Reversed(in_flight_surfaces_)) {
90 if (surface) {
91 texture_id = surface->texture;
92 break;
93 }
94 }
95 if (!texture_id && displayed_surface_)
96 texture_id = displayed_surface_->texture;
97
98 if (texture_id) {
99 CopyBufferDamage(current_surface_->texture, texture_id, damage,
100 current_surface_->damage);
101 }
102 }
103 current_surface_->damage = gfx::Rect();
104 }
105 UpdateBufferDamage(damage);
106 in_flight_surfaces_.push_back(std::move(current_surface_));
107 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
108 // paths), so ensure we restore it here.
109 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
110 }
111
112 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
113 if (size == size_)
114 return;
115
116 size_ = size;
117
118 // TODO: add stencil buffer when needed.
119 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
120 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
121 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
122 texture_target_, 0, 0);
123
124 FreeAllSurfaces();
125 }
126
127 void BufferQueue::RecreateBuffers() {
128 // We need to recreate the buffers, for whatever reason the old ones are not
129 // presentable on the device anymore.
130 // Unused buffers can be freed directly, they will be re-allocated as needed.
131 // Any in flight, current or displayed surface must be replaced.
132 available_surfaces_.clear();
133
134 // Recreate all in-flight surfaces and put the recreated copies in the queue.
135 for (auto& surface : in_flight_surfaces_)
136 surface = RecreateBuffer(std::move(surface));
137
138 current_surface_ = RecreateBuffer(std::move(current_surface_));
139 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
140
141 if (current_surface_) {
142 // If we have a texture bound, we will need to re-bind it.
143 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
144 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
145 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
146 texture_target_, current_surface_->texture, 0);
147 }
148 }
149
150 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
151 std::unique_ptr<AllocatedSurface> surface) {
152 if (!surface)
153 return nullptr;
154
155 std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface());
156 if (!new_surface)
157 return nullptr;
158
159 new_surface->damage = surface->damage;
160
161 // Copy the entire texture.
162 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
163 gfx::Rect(size_));
164 return new_surface;
165 }
166
167 void BufferQueue::PageFlipComplete() {
168 DCHECK(!in_flight_surfaces_.empty());
169 if (displayed_surface_)
170 available_surfaces_.push_back(std::move(displayed_surface_));
171 displayed_surface_ = std::move(in_flight_surfaces_.front());
172 in_flight_surfaces_.pop_front();
173 }
174
175 void BufferQueue::FreeAllSurfaces() {
176 displayed_surface_.reset();
177 current_surface_.reset();
178 // This is intentionally not emptied since the swap buffers acks are still
179 // expected to arrive.
180 for (auto& surface : in_flight_surfaces_)
181 surface = nullptr;
182 available_surfaces_.clear();
183 }
184
185 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
186 if (!surface->texture)
187 return;
188
189 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
190 gl->BindTexture(texture_target_, surface->texture);
191 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
192 gl->DeleteTextures(1, &surface->texture);
193 // TODO(rjk): Implement image deletion.
194 gl->DestroyImageCHROMIUM(surface->image);
195 surface->buffer.reset();
196 allocated_count_--;
197 }
198
199 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
200 if (!available_surfaces_.empty()) {
201 std::unique_ptr<AllocatedSurface> surface =
202 std::move(available_surfaces_.back());
203 available_surfaces_.pop_back();
204 return surface;
205 }
206
207 unsigned int texture = 0;
208 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
209 gl->GenTextures(1, &texture);
210 if (!texture)
211 return nullptr;
212
213 // We don't want to allow anything more than triple buffering.
214 DCHECK_LT(allocated_count_, 4U);
215
216 std::unique_ptr<gfx::GpuMemoryBuffer> buffer(
217 OzoneGpuMemoryBuffer::CreateOzoneGpuMemoryBuffer(
218 size_, gpu::DefaultBufferFormatForImageFormat(internal_format_),
219 gfx::BufferUsage::SCANOUT, widget_));
220
221 if (!buffer.get()) {
222 gl->DeleteTextures(1, &texture);
223 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
224 return nullptr;
225 }
226
227 // This ends up calling back into the CommandBufferLocal via its
228 // implementation of the GpuControl interface. In that case, we need to handle
229 // the given buffer pointer there.
230 unsigned int id =
231 gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(),
232 size_.height(), internal_format_);
233 if (!id) {
234 LOG(ERROR) << "Failed to allocate backing image surface";
235 gl->DeleteTextures(1, &texture);
236 return nullptr;
237 }
238
239 allocated_count_++;
240 gl->BindTexture(texture_target_, texture);
241 gl->BindTexImage2DCHROMIUM(texture_target_, id);
242 // It doesn't end up in the queue to re-use until we handle the page flip.
243 return base::WrapUnique(new AllocatedSurface(this, std::move(buffer), texture,
244 id, gfx::Rect(size_)));
245 }
246
247 BufferQueue::AllocatedSurface::AllocatedSurface(
248 BufferQueue* buffer_queue,
249 std::unique_ptr<gfx::GpuMemoryBuffer> buffer,
250 unsigned int texture,
251 unsigned int image,
252 const gfx::Rect& rect)
253 : buffer_queue(buffer_queue),
254 buffer(buffer.release()),
255 texture(texture),
256 image(image),
257 damage(rect) {}
258
259 BufferQueue::AllocatedSurface::~AllocatedSurface() {
260 buffer_queue->FreeSurfaceResources(this);
261 }
262
263 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/surfaces/buffer_queue.h ('k') | components/mus/surfaces/direct_output_surface_ozone.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698