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

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

Issue 1423843003: Make content::BufferQueue use scoped ptrs for AllocatedSurfaces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@surfaceless_only
Patch Set: Created 5 years, 1 month 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/compositor/buffer_queue.h" 5 #include "content/browser/compositor/buffer_queue.h"
6 6
7 #include "content/browser/compositor/image_transport_factory.h" 7 #include "content/browser/compositor/image_transport_factory.h"
8 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" 8 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
9 #include "content/common/gpu/client/context_provider_command_buffer.h" 9 #include "content/common/gpu/client/context_provider_command_buffer.h"
10 #include "content/common/gpu/client/gl_helper.h" 10 #include "content/common/gpu/client/gl_helper.h"
(...skipping 12 matching lines...) Expand all
23 unsigned int texture_target, 23 unsigned int texture_target,
24 unsigned int internalformat, 24 unsigned int internalformat,
25 GLHelper* gl_helper, 25 GLHelper* gl_helper,
26 BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager, 26 BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager,
27 int surface_id) 27 int surface_id)
28 : context_provider_(context_provider), 28 : context_provider_(context_provider),
29 fbo_(0), 29 fbo_(0),
30 allocated_count_(0), 30 allocated_count_(0),
31 texture_target_(texture_target), 31 texture_target_(texture_target),
32 internal_format_(internalformat), 32 internal_format_(internalformat),
33 deleted_in_flight_surface_count_(0),
33 gl_helper_(gl_helper), 34 gl_helper_(gl_helper),
34 gpu_memory_buffer_manager_(gpu_memory_buffer_manager), 35 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
35 surface_id_(surface_id) {} 36 surface_id_(surface_id) {}
36 37
37 BufferQueue::~BufferQueue() { 38 BufferQueue::~BufferQueue() {
38 FreeAllSurfaces(); 39 FreeAllSurfaces();
39 40
40 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 41 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
41 if (fbo_) 42 if (fbo_)
42 gl->DeleteFramebuffers(1, &fbo_); 43 gl->DeleteFramebuffers(1, &fbo_);
43 } 44 }
44 45
45 void BufferQueue::Initialize() { 46 void BufferQueue::Initialize() {
46 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 47 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
47 gl->GenFramebuffers(1, &fbo_); 48 gl->GenFramebuffers(1, &fbo_);
48 } 49 }
49 50
50 void BufferQueue::BindFramebuffer() { 51 void BufferQueue::BindFramebuffer() {
51 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 52 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
52 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 53 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
53 54
54 if (!current_surface_.texture) { 55 if (!current_surface_) {
55 current_surface_ = GetNextSurface(); 56 current_surface_ = GetNextSurface();
56 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 57 gl->FramebufferTexture2D(
57 texture_target_, current_surface_.texture, 0); 58 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target_,
59 current_surface_ ? current_surface_->texture : 0, 0);
58 } 60 }
59 } 61 }
60 62
61 void BufferQueue::CopyBufferDamage(int texture, 63 void BufferQueue::CopyBufferDamage(int texture,
62 int source_texture, 64 int source_texture,
63 const gfx::Rect& new_damage, 65 const gfx::Rect& new_damage,
64 const gfx::Rect& old_damage) { 66 const gfx::Rect& old_damage) {
65 gl_helper_->CopySubBufferDamage( 67 gl_helper_->CopySubBufferDamage(
66 texture_target_, texture, source_texture, 68 texture_target_, texture, source_texture,
67 SkRegion(gfx::RectToSkIRect(new_damage)), 69 SkRegion(gfx::RectToSkIRect(new_damage)),
68 SkRegion(gfx::RectToSkIRect(old_damage))); 70 SkRegion(gfx::RectToSkIRect(old_damage)));
69 } 71 }
70 72
71 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) { 73 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
72 displayed_surface_.damage.Union(damage); 74 if (displayed_surface_)
75 displayed_surface_->damage.Union(damage);
76
73 for (size_t i = 0; i < available_surfaces_.size(); i++) 77 for (size_t i = 0; i < available_surfaces_.size(); i++)
74 available_surfaces_[i].damage.Union(damage); 78 available_surfaces_[i]->damage.Union(damage);
75 79 for (size_t i = 0; i < in_flight_surfaces_.size(); i++)
76 for (std::deque<AllocatedSurface>::iterator it = 80 in_flight_surfaces_[i]->damage.Union(damage);
77 in_flight_surfaces_.begin();
78 it != in_flight_surfaces_.end();
79 ++it)
80 it->damage.Union(damage);
81 } 81 }
82 82
83 void BufferQueue::SwapBuffers(const gfx::Rect& damage) { 83 void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
84 if (!current_surface_)
85 return;
86
84 if (damage != gfx::Rect(size_)) { 87 if (damage != gfx::Rect(size_)) {
85 // We must have a frame available to copy from. 88 // If there is damage, then there must have been a previous frame to copy
86 DCHECK(!in_flight_surfaces_.empty() || displayed_surface_.texture); 89 // from (though it may have been deleted).
87 unsigned int texture_id = !in_flight_surfaces_.empty() 90 DCHECK(deleted_in_flight_surface_count_ || !in_flight_surfaces_.empty() ||
88 ? in_flight_surfaces_.back().texture 91 displayed_surface_);
89 : displayed_surface_.texture; 92 unsigned int texture_id = 0;
90 93 if (!in_flight_surfaces_.empty())
91 CopyBufferDamage(current_surface_.texture, texture_id, damage, 94 texture_id = in_flight_surfaces_.back()->texture;
92 current_surface_.damage); 95 else if (displayed_surface_)
96 texture_id = displayed_surface_->texture;
97 if (texture_id) {
98 CopyBufferDamage(current_surface_->texture, texture_id, damage,
99 current_surface_->damage);
100 }
93 } 101 }
94 UpdateBufferDamage(damage); 102 UpdateBufferDamage(damage);
95 current_surface_.damage = gfx::Rect(); 103 current_surface_->damage = gfx::Rect();
96 in_flight_surfaces_.push_back(current_surface_); 104 in_flight_surfaces_.push_back(current_surface_.Pass());
97 current_surface_.texture = 0;
98 current_surface_.image = 0;
99 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer 105 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
100 // paths), so ensure we restore it here. 106 // paths), so ensure we restore it here.
101 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 107 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
102 } 108 }
103 109
104 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { 110 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
105 if (size == size_) 111 if (size == size_)
106 return; 112 return;
107 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that 113 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
108 // is cause for concern or if it is benign. 114 // is cause for concern or if it is benign.
109 // http://crbug.com/524624 115 // http://crbug.com/524624
110 #if !defined(OS_MACOSX) 116 #if !defined(OS_MACOSX)
111 DCHECK(!current_surface_.texture); 117 DCHECK(!current_surface_);
112 #endif 118 #endif
113 size_ = size; 119 size_ = size;
114 120
115 // TODO: add stencil buffer when needed. 121 // TODO: add stencil buffer when needed.
116 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 122 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
117 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 123 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
118 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 124 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
119 texture_target_, 0, 0); 125 texture_target_, 0, 0);
120 126
121 FreeAllSurfaces(); 127 FreeAllSurfaces();
122 } 128 }
123 129
124 void BufferQueue::RecreateBuffers() { 130 void BufferQueue::RecreateBuffers() {
125 // We need to recreate the buffers, for whatever reason the old ones are not 131 // Available surfaces do not need to be recreated, so they may be destoryed.
126 // presentable on the device anymore. 132 while (!available_surfaces_.empty()) {
127 // Unused buffers can be freed directly, they will be re-allocated as needed. 133 FreeSurface(available_surfaces_.take_back().Pass());
128 // Any in flight, current or displayed surface must be replaced. 134 available_surfaces_.pop_back();
129 for (size_t i = 0; i < available_surfaces_.size(); i++) 135 }
130 FreeSurface(&available_surfaces_[i]);
131 available_surfaces_.clear();
132 136
133 for (auto& surface : in_flight_surfaces_) 137 // Recreate all in-flight surfaces and put the recreated copies in the queue.
134 surface = RecreateBuffer(&surface); 138 size_t old_in_flight_surface_size = in_flight_surfaces_.size();
139 for (size_t i = 0; i < old_in_flight_surface_size; ++i)
140 // Ensure that all entries in |in_flight_surfaces_| be non-null. If a
141 // recreation fails, then mark that it wasdeleted, to ensure it is accounted
142 // for in PageFlipComplete.
143 scoped_ptr<AllocatedSurface> recreated_buffer =
144 RecreateBuffer(in_flight_surfaces_.take_front().Pass());
145 if (recreated_buffer)
146 in_flight_surfaces_.push_back(recreated_buffer);
147 else
148 deleted_in_flight_surface_count_ += 1;
149 }
135 150
136 current_surface_ = RecreateBuffer(&current_surface_); 151 current_surface_ = RecreateBuffer(current_surface_.Pass());
137 displayed_surface_ = RecreateBuffer(&displayed_surface_); 152 displayed_surface_ = RecreateBuffer(displayed_surface_.Pass());
138 153
139 if (current_surface_.texture) { 154 if (current_surface_) {
140 // If we have a texture bound, we will need to re-bind it. 155 // If we have a texture bound, we will need to re-bind it.
141 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 156 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
142 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 157 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
143 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 158 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
144 texture_target_, current_surface_.texture, 0); 159 texture_target_, current_surface_->texture, 0);
145 } 160 }
146 } 161 }
147 162
148 BufferQueue::AllocatedSurface BufferQueue::RecreateBuffer( 163 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
149 AllocatedSurface* surface) { 164 scoped_ptr<AllocatedSurface> surface) {
150 if (!surface->texture) 165 if (!surface)
151 return *surface; 166 return scoped_ptr<AllocatedSurface>();
152 AllocatedSurface new_surface = GetNextSurface(); 167
153 new_surface.damage = surface->damage; 168 scoped_ptr<AllocatedSurface> new_surface(GetNextSurface());
169 new_surface->damage = surface->damage;
154 170
155 // Copy the entire texture. 171 // Copy the entire texture.
156 CopyBufferDamage(new_surface.texture, surface->texture, gfx::Rect(), 172 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
157 gfx::Rect(size_)); 173 gfx::Rect(size_));
158 174
159 FreeSurface(surface); 175 FreeSurface(surface.Pass());
160 return new_surface; 176 return new_surface.Pass();
161 } 177 }
162 178
163 void BufferQueue::PageFlipComplete() { 179 void BufferQueue::PageFlipComplete() {
180 // If the next in-flight surface was destroyed, simply leave the currently
181 // displaying surface unchanged.
182 if (deleted_in_flight_surface_count_ > 0) {
183 deleted_in_flight_surface_count_ -= 1;
184 return;
185 }
186
164 DCHECK(!in_flight_surfaces_.empty()); 187 DCHECK(!in_flight_surfaces_.empty());
165 188 if (displayed_surface_)
166 if (displayed_surface_.texture) 189 available_surfaces_.push_back(displayed_surface_.Pass());
167 available_surfaces_.push_back(displayed_surface_); 190 displayed_surface_ = in_flight_surfaces_.take_front();
168
169 displayed_surface_ = in_flight_surfaces_.front();
170 in_flight_surfaces_.pop_front();
171 } 191 }
172 192
173 void BufferQueue::FreeAllSurfaces() { 193 void BufferQueue::FreeAllSurfaces() {
174 FreeSurface(&displayed_surface_); 194 FreeSurface(displayed_surface_.Pass());
175 FreeSurface(&current_surface_); 195 FreeSurface(current_surface_.Pass());
176 // This is intentionally not emptied since the swap buffers acks are still
177 // expected to arrive.
178 for (auto& surface : in_flight_surfaces_)
179 FreeSurface(&surface);
180 196
181 for (size_t i = 0; i < available_surfaces_.size(); i++) 197 // Track the number of in-flight surfaces that have been destroyed, so that
182 FreeSurface(&available_surfaces_[i]); 198 // we account for them in PageFlipComplete.
199 deleted_in_flight_surface_count_ += in_flight_surfaces_.size();
200 while (!in_flight_surfaces_.empty())
201 FreeSurface(in_flight_surfaces_.take_front().Pass());
183 202
184 available_surfaces_.clear(); 203 while (!available_surfaces_.empty()) {
185 } 204 FreeSurface(available_surfaces_.take_back().Pass());
186 205 available_surfaces_.pop_back();
187 void BufferQueue::FreeSurface(AllocatedSurface* surface) {
188 if (surface->texture) {
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 gl->DestroyImageCHROMIUM(surface->image);
194 surface->image = 0;
195 surface->texture = 0;
196 allocated_count_--;
197 } 206 }
198 } 207 }
199 208
200 BufferQueue::AllocatedSurface BufferQueue::GetNextSurface() { 209 void BufferQueue::FreeSurface(scoped_ptr<AllocatedSurface> surface) {
reveman 2015/10/27 17:03:43 can we move all this into the AllocatedSurface dto
210 if (!surface)
211 return;
212
213 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
214 gl->BindTexture(texture_target_, surface->texture);
215 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
216 gl->DeleteTextures(1, &surface->texture);
217 gl->DestroyImageCHROMIUM(surface->image);
218 surface->image = 0;
219 surface->texture = 0;
220 allocated_count_--;
221 }
222
223 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
201 if (!available_surfaces_.empty()) { 224 if (!available_surfaces_.empty()) {
202 AllocatedSurface surface = available_surfaces_.back(); 225 scoped_ptr<AllocatedSurface> result =
226 available_surfaces_.take_back().Pass();
reveman 2015/10/27 17:03:43 hm, is .Pass() really needed here?
203 available_surfaces_.pop_back(); 227 available_surfaces_.pop_back();
204 return surface; 228 return result.Pass();
205 } 229 }
206 230
207 unsigned int texture = 0; 231 unsigned int texture = 0;
208 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 232 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
209 gl->GenTextures(1, &texture); 233 gl->GenTextures(1, &texture);
210 if (!texture) 234 if (!texture)
211 return AllocatedSurface(); 235 return scoped_ptr<AllocatedSurface>();
reveman 2015/10/27 17:03:44 nullptr
212 236
213 // We don't want to allow anything more than triple buffering. 237 // We don't want to allow anything more than triple buffering.
214 DCHECK_LT(allocated_count_, 4U); 238 DCHECK_LT(allocated_count_, 4U);
215 239
216 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 240 scoped_ptr<gfx::GpuMemoryBuffer> buffer(
217 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout( 241 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout(
218 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat( 242 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat(
219 internal_format_), 243 internal_format_),
220 surface_id_)); 244 surface_id_));
221 if (!buffer.get()) { 245 if (!buffer.get()) {
222 gl->DeleteTextures(1, &texture); 246 gl->DeleteTextures(1, &texture);
223 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; 247 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
224 return AllocatedSurface(); 248 return scoped_ptr<AllocatedSurface>();
reveman 2015/10/27 17:03:43 nullptr
225 } 249 }
226 250
227 unsigned int id = gl->CreateImageCHROMIUM( 251 unsigned int id = gl->CreateImageCHROMIUM(
228 buffer->AsClientBuffer(), size_.width(), size_.height(), 252 buffer->AsClientBuffer(), size_.width(), size_.height(),
229 internal_format_); 253 internal_format_);
230 254
231 if (!id) { 255 if (!id) {
232 LOG(ERROR) << "Failed to allocate backing image surface"; 256 LOG(ERROR) << "Failed to allocate backing image surface";
233 gl->DeleteTextures(1, &texture); 257 gl->DeleteTextures(1, &texture);
234 return AllocatedSurface(); 258 return scoped_ptr<AllocatedSurface>();
reveman 2015/10/27 17:03:44 nullptr
235 } 259 }
236 allocated_count_++; 260 allocated_count_++;
reveman 2015/10/27 17:03:43 is this member needed? is this just not the sum of
237 gl->BindTexture(texture_target_, texture); 261 gl->BindTexture(texture_target_, texture);
238 gl->BindTexImage2DCHROMIUM(texture_target_, id); 262 gl->BindTexImage2DCHROMIUM(texture_target_, id);
239 return AllocatedSurface(buffer.Pass(), texture, id, gfx::Rect(size_)); 263 return scoped_ptr<AllocatedSurface>(
reveman 2015/10/27 17:03:44 make_scoped_ptr(new All...)?
264 new AllocatedSurface(buffer.Pass(), texture, id, gfx::Rect(size_)))
265 .Pass();
240 } 266 }
241 267
242 BufferQueue::AllocatedSurface::AllocatedSurface() : texture(0), image(0) {} 268 BufferQueue::AllocatedSurface::AllocatedSurface() : texture(0), image(0) {}
243 269
244 BufferQueue::AllocatedSurface::AllocatedSurface( 270 BufferQueue::AllocatedSurface::AllocatedSurface(
245 scoped_ptr<gfx::GpuMemoryBuffer> buffer, 271 scoped_ptr<gfx::GpuMemoryBuffer> buffer,
246 unsigned int texture, 272 unsigned int texture,
247 unsigned int image, 273 unsigned int image,
248 const gfx::Rect& rect) 274 const gfx::Rect& rect)
249 : buffer(buffer.release()), texture(texture), image(image), damage(rect) {} 275 : buffer(buffer.release()), texture(texture), image(image), damage(rect) {}
250 276
251 BufferQueue::AllocatedSurface::~AllocatedSurface() {} 277 BufferQueue::AllocatedSurface::~AllocatedSurface() {}
252 278
253 } // namespace content 279 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698