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

Side by Side Diff: content/browser/compositor/buffer_queue.cc

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

Powered by Google App Engine
This is Rietveld 408576698