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

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: And the rest of the feedback Created 5 years 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 void BufferQueue::Initialize() { 45 void BufferQueue::Initialize() {
46 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 46 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
47 gl->GenFramebuffers(1, &fbo_); 47 gl->GenFramebuffers(1, &fbo_);
48 } 48 }
49 49
50 void BufferQueue::BindFramebuffer() { 50 void BufferQueue::BindFramebuffer() {
51 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 51 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
52 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 52 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
53 53
54 if (!current_surface_.texture) { 54 if (!current_surface_)
55 current_surface_ = GetNextSurface(); 55 current_surface_ = GetNextSurface();
56
57 if (current_surface_) {
56 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 58 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
57 texture_target_, current_surface_.texture, 0); 59 texture_target_, current_surface_->texture, 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_)
73 for (size_t i = 0; i < available_surfaces_.size(); i++) 75 displayed_surface_->damage.Union(damage);
74 available_surfaces_[i].damage.Union(damage); 76 for (auto& surface : available_surfaces_)
75 77 surface->damage.Union(damage);
76 for (std::deque<AllocatedSurface>::iterator it = 78 for (auto& surface : in_flight_surfaces_) {
77 in_flight_surfaces_.begin(); 79 if (surface)
78 it != in_flight_surfaces_.end(); 80 surface->damage.Union(damage);
79 ++it) 81 }
80 it->damage.Union(damage);
81 } 82 }
82 83
83 void BufferQueue::SwapBuffers(const gfx::Rect& damage) { 84 void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
84 if (!damage.IsEmpty() && damage != gfx::Rect(size_)) { 85 if (current_surface_) {
85 // We must have a frame available to copy from. 86 if (!damage.IsEmpty() && damage != gfx::Rect(size_)) {
86 DCHECK(!in_flight_surfaces_.empty() || displayed_surface_.texture); 87 // Copy damage from the most recently swapped buffer. In the event that
87 unsigned int texture_id = !in_flight_surfaces_.empty() 88 // the buffer was destroyed and failed to recreate, pick from the most
88 ? in_flight_surfaces_.back().texture 89 // recently available buffer.
89 : displayed_surface_.texture; 90 unsigned int texture_id = 0;
91 for (auto it = in_flight_surfaces_.rbegin();
danakj 2015/12/10 19:46:42 you could use for (auto& surface : base::Reversed
ccameron 2015/12/11 21:14:23 done
92 it != in_flight_surfaces_.rend(); ++it) {
93 auto& surface = *it;
94 if (surface) {
95 texture_id = surface->texture;
96 break;
97 }
98 }
99 if (!texture_id && displayed_surface_)
100 texture_id = displayed_surface_->texture;
90 101
91 CopyBufferDamage(current_surface_.texture, texture_id, damage, 102 if (texture_id) {
92 current_surface_.damage); 103 CopyBufferDamage(current_surface_->texture, texture_id, damage,
104 current_surface_->damage);
105 }
106 }
107 current_surface_->damage = gfx::Rect();
93 } 108 }
94 UpdateBufferDamage(damage); 109 UpdateBufferDamage(damage);
95 current_surface_.damage = gfx::Rect(); 110 in_flight_surfaces_.push_back(std::move(current_surface_));
96 in_flight_surfaces_.push_back(current_surface_);
97 current_surface_.texture = 0;
98 current_surface_.image = 0;
99 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer 111 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
100 // paths), so ensure we restore it here. 112 // paths), so ensure we restore it here.
101 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 113 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
102 } 114 }
103 115
104 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { 116 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
105 if (size == size_) 117 if (size == size_)
106 return; 118 return;
107 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that 119 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
108 // is cause for concern or if it is benign. 120 // is cause for concern or if it is benign.
109 // http://crbug.com/524624 121 // http://crbug.com/524624
110 #if !defined(OS_MACOSX) 122 #if !defined(OS_MACOSX)
111 DCHECK(!current_surface_.texture); 123 DCHECK(!current_surface_);
112 #endif 124 #endif
113 size_ = size; 125 size_ = size;
114 126
115 // TODO: add stencil buffer when needed. 127 // TODO: add stencil buffer when needed.
116 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 128 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
117 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 129 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
118 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 130 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
119 texture_target_, 0, 0); 131 texture_target_, 0, 0);
120 132
121 FreeAllSurfaces(); 133 FreeAllSurfaces();
122 } 134 }
123 135
124 void BufferQueue::RecreateBuffers() { 136 void BufferQueue::RecreateBuffers() {
125 // We need to recreate the buffers, for whatever reason the old ones are not 137 // We need to recreate the buffers, for whatever reason the old ones are not
126 // presentable on the device anymore. 138 // presentable on the device anymore.
127 // Unused buffers can be freed directly, they will be re-allocated as needed. 139 // Unused buffers can be freed directly, they will be re-allocated as needed.
128 // Any in flight, current or displayed surface must be replaced. 140 // Any in flight, current or displayed surface must be replaced.
129 for (size_t i = 0; i < available_surfaces_.size(); i++)
130 FreeSurface(&available_surfaces_[i]);
131 available_surfaces_.clear(); 141 available_surfaces_.clear();
132 142
143 // Recreate all in-flight surfaces and put the recreated copies in the queue.
133 for (auto& surface : in_flight_surfaces_) 144 for (auto& surface : in_flight_surfaces_)
134 surface = RecreateBuffer(&surface); 145 surface = RecreateBuffer(std::move(surface));
135 146
136 current_surface_ = RecreateBuffer(&current_surface_); 147 current_surface_ = RecreateBuffer(std::move(current_surface_));
137 displayed_surface_ = RecreateBuffer(&displayed_surface_); 148 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
138 149
139 if (current_surface_.texture) { 150 if (current_surface_) {
140 // If we have a texture bound, we will need to re-bind it. 151 // If we have a texture bound, we will need to re-bind it.
141 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 152 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
142 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 153 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
143 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 154 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
144 texture_target_, current_surface_.texture, 0); 155 texture_target_, current_surface_->texture, 0);
145 } 156 }
146 } 157 }
147 158
148 BufferQueue::AllocatedSurface BufferQueue::RecreateBuffer( 159 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
149 AllocatedSurface* surface) { 160 scoped_ptr<AllocatedSurface> surface) {
150 if (!surface->texture) 161 if (!surface)
151 return *surface; 162 return nullptr;
152 AllocatedSurface new_surface = GetNextSurface(); 163
153 new_surface.damage = surface->damage; 164 scoped_ptr<AllocatedSurface> new_surface(GetNextSurface());
165 if (!new_surface)
166 return nullptr;
167
168 new_surface->damage = surface->damage;
154 169
155 // Copy the entire texture. 170 // Copy the entire texture.
156 CopyBufferDamage(new_surface.texture, surface->texture, gfx::Rect(), 171 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
157 gfx::Rect(size_)); 172 gfx::Rect(size_));
158
159 FreeSurface(surface);
160 return new_surface; 173 return new_surface;
161 } 174 }
162 175
163 void BufferQueue::PageFlipComplete() { 176 void BufferQueue::PageFlipComplete() {
164 DCHECK(!in_flight_surfaces_.empty()); 177 DCHECK(!in_flight_surfaces_.empty());
165 178 if (displayed_surface_)
166 if (displayed_surface_.texture) 179 available_surfaces_.push_back(std::move(displayed_surface_));
167 available_surfaces_.push_back(displayed_surface_); 180 displayed_surface_ = std::move(in_flight_surfaces_.front());
168
169 displayed_surface_ = in_flight_surfaces_.front();
170 in_flight_surfaces_.pop_front(); 181 in_flight_surfaces_.pop_front();
171 } 182 }
172 183
173 void BufferQueue::FreeAllSurfaces() { 184 void BufferQueue::FreeAllSurfaces() {
174 FreeSurface(&displayed_surface_); 185 displayed_surface_.reset();
175 FreeSurface(&current_surface_); 186 current_surface_.reset();
176 // This is intentionally not emptied since the swap buffers acks are still 187 // This is intentionally not emptied since the swap buffers acks are still
177 // expected to arrive. 188 // expected to arrive.
178 for (auto& surface : in_flight_surfaces_) 189 for (auto& surface : in_flight_surfaces_)
179 FreeSurface(&surface); 190 surface = nullptr;
180
181 for (size_t i = 0; i < available_surfaces_.size(); i++)
182 FreeSurface(&available_surfaces_[i]);
183
184 available_surfaces_.clear(); 191 available_surfaces_.clear();
185 } 192 }
186 193
187 void BufferQueue::FreeSurface(AllocatedSurface* surface) { 194 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
188 if (surface->texture) { 195 if (!surface->texture)
189 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 196 return;
190 gl->BindTexture(texture_target_, surface->texture); 197
191 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); 198 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
192 gl->DeleteTextures(1, &surface->texture); 199 gl->BindTexture(texture_target_, surface->texture);
193 gl->DestroyImageCHROMIUM(surface->image); 200 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
194 surface->image = 0; 201 gl->DeleteTextures(1, &surface->texture);
195 surface->texture = 0; 202 gl->DestroyImageCHROMIUM(surface->image);
196 allocated_count_--; 203 surface->buffer.reset();
197 } 204 allocated_count_--;
198 } 205 }
199 206
200 BufferQueue::AllocatedSurface BufferQueue::GetNextSurface() { 207 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
201 if (!available_surfaces_.empty()) { 208 if (!available_surfaces_.empty()) {
202 AllocatedSurface surface = available_surfaces_.back(); 209 scoped_ptr<AllocatedSurface> surface =
210 std::move(available_surfaces_.back());
203 available_surfaces_.pop_back(); 211 available_surfaces_.pop_back();
204 return surface; 212 return surface;
205 } 213 }
206 214
207 unsigned int texture = 0; 215 unsigned int texture = 0;
208 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 216 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
209 gl->GenTextures(1, &texture); 217 gl->GenTextures(1, &texture);
210 if (!texture) 218 if (!texture)
211 return AllocatedSurface(); 219 return nullptr;
212 220
213 // We don't want to allow anything more than triple buffering. 221 // We don't want to allow anything more than triple buffering.
214 DCHECK_LT(allocated_count_, 4U); 222 DCHECK_LT(allocated_count_, 4U);
215 223
216 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 224 scoped_ptr<gfx::GpuMemoryBuffer> buffer(
217 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout( 225 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout(
218 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat( 226 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat(
219 internal_format_), 227 internal_format_),
220 surface_id_)); 228 surface_id_));
221 if (!buffer.get()) { 229 if (!buffer.get()) {
222 gl->DeleteTextures(1, &texture); 230 gl->DeleteTextures(1, &texture);
223 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; 231 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
224 return AllocatedSurface(); 232 return nullptr;
225 } 233 }
226 234
227 unsigned int id = gl->CreateImageCHROMIUM( 235 unsigned int id = gl->CreateImageCHROMIUM(
228 buffer->AsClientBuffer(), size_.width(), size_.height(), 236 buffer->AsClientBuffer(), size_.width(), size_.height(),
229 internal_format_); 237 internal_format_);
230
231 if (!id) { 238 if (!id) {
232 LOG(ERROR) << "Failed to allocate backing image surface"; 239 LOG(ERROR) << "Failed to allocate backing image surface";
233 gl->DeleteTextures(1, &texture); 240 gl->DeleteTextures(1, &texture);
234 return AllocatedSurface(); 241 return nullptr;
235 } 242 }
243
236 allocated_count_++; 244 allocated_count_++;
237 gl->BindTexture(texture_target_, texture); 245 gl->BindTexture(texture_target_, texture);
238 gl->BindTexImage2DCHROMIUM(texture_target_, id); 246 gl->BindTexImage2DCHROMIUM(texture_target_, id);
239 return AllocatedSurface(buffer.Pass(), texture, id, gfx::Rect(size_)); 247 return make_scoped_ptr(new AllocatedSurface(this, std::move(buffer), texture,
248 id, gfx::Rect(size_)));
240 } 249 }
241 250
242 BufferQueue::AllocatedSurface::AllocatedSurface() : texture(0), image(0) {}
243
244 BufferQueue::AllocatedSurface::AllocatedSurface( 251 BufferQueue::AllocatedSurface::AllocatedSurface(
252 BufferQueue* buffer_queue,
245 scoped_ptr<gfx::GpuMemoryBuffer> buffer, 253 scoped_ptr<gfx::GpuMemoryBuffer> buffer,
246 unsigned int texture, 254 unsigned int texture,
247 unsigned int image, 255 unsigned int image,
248 const gfx::Rect& rect) 256 const gfx::Rect& rect)
249 : buffer(buffer.release()), texture(texture), image(image), damage(rect) {} 257 : buffer_queue(buffer_queue),
258 buffer(buffer.release()),
259 texture(texture),
260 image(image),
261 damage(rect) {}
250 262
251 BufferQueue::AllocatedSurface::~AllocatedSurface() {} 263 BufferQueue::AllocatedSurface::~AllocatedSurface() {
264 buffer_queue->FreeSurfaceResources(this);
265 }
252 266
253 } // namespace content 267 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698