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

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: Incorporate review foodback 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 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 56 gl->FramebufferTexture2D(
57 texture_target_, current_surface_.texture, 0); 57 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target_,
58 current_surface_ ? current_surface_->texture : 0, 0);
danakj 2015/12/10 01:36:02 is there a point to doing FramebufferTexture2D(...
ccameron 2015/12/10 07:39:27 The spec says that the texture is automatically un
58 } 59 }
59 } 60 }
60 61
61 void BufferQueue::CopyBufferDamage(int texture, 62 void BufferQueue::CopyBufferDamage(int texture,
62 int source_texture, 63 int source_texture,
63 const gfx::Rect& new_damage, 64 const gfx::Rect& new_damage,
64 const gfx::Rect& old_damage) { 65 const gfx::Rect& old_damage) {
65 gl_helper_->CopySubBufferDamage( 66 gl_helper_->CopySubBufferDamage(
66 texture_target_, texture, source_texture, 67 texture_target_, texture, source_texture,
67 SkRegion(gfx::RectToSkIRect(new_damage)), 68 SkRegion(gfx::RectToSkIRect(new_damage)),
68 SkRegion(gfx::RectToSkIRect(old_damage))); 69 SkRegion(gfx::RectToSkIRect(old_damage)));
69 } 70 }
70 71
71 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) { 72 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
72 displayed_surface_.damage.Union(damage); 73 if (displayed_surface_)
73 for (size_t i = 0; i < available_surfaces_.size(); i++) 74 displayed_surface_->damage.Union(damage);
74 available_surfaces_[i].damage.Union(damage); 75 for (auto& surface : available_surfaces_)
75 76 surface->damage.Union(damage);
76 for (std::deque<AllocatedSurface>::iterator it = 77 for (auto& surface : in_flight_surfaces_) {
77 in_flight_surfaces_.begin(); 78 if (surface)
78 it != in_flight_surfaces_.end(); 79 surface->damage.Union(damage);
79 ++it) 80 }
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 (!damage.IsEmpty() && damage != gfx::Rect(size_)) { 84 if (current_surface_) {
85 // We must have a frame available to copy from. 85 if (!damage.IsEmpty() && damage != gfx::Rect(size_)) {
86 DCHECK(!in_flight_surfaces_.empty() || displayed_surface_.texture); 86 unsigned int texture_id = 0;
danakj 2015/12/10 01:36:02 no more dcheck?
ccameron 2015/12/10 07:39:27 That was wrong-by-inspection. It was entirely poss
87 unsigned int texture_id = !in_flight_surfaces_.empty() 87 if (!in_flight_surfaces_.empty() && in_flight_surfaces_.back())
danakj 2015/12/10 01:36:02 This logic is a bit different. Before if there wa
ccameron 2015/12/10 07:39:27 Yeah. Actually, to be more thorough, we should do
88 ? in_flight_surfaces_.back().texture 88 texture_id = in_flight_surfaces_.back()->texture;
89 : displayed_surface_.texture; 89 else if (displayed_surface_)
90 90 texture_id = displayed_surface_->texture;
91 CopyBufferDamage(current_surface_.texture, texture_id, damage, 91 if (texture_id) {
danakj 2015/12/10 01:36:02 nit: can you put a whitespace line above this to s
ccameron 2015/12/10 07:39:27 Done.
92 current_surface_.damage); 92 CopyBufferDamage(current_surface_->texture, texture_id, damage,
93 current_surface_->damage);
94 }
95 }
96 current_surface_->damage = gfx::Rect();
93 } 97 }
94 UpdateBufferDamage(damage); 98 UpdateBufferDamage(damage);
95 current_surface_.damage = gfx::Rect(); 99 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 100 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
100 // paths), so ensure we restore it here. 101 // paths), so ensure we restore it here.
101 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 102 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
102 } 103 }
103 104
104 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { 105 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
105 if (size == size_) 106 if (size == size_)
106 return; 107 return;
107 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that 108 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
108 // is cause for concern or if it is benign. 109 // is cause for concern or if it is benign.
109 // http://crbug.com/524624 110 // http://crbug.com/524624
110 #if !defined(OS_MACOSX) 111 #if !defined(OS_MACOSX)
111 DCHECK(!current_surface_.texture); 112 DCHECK(!current_surface_);
112 #endif 113 #endif
113 size_ = size; 114 size_ = size;
114 115
115 // TODO: add stencil buffer when needed. 116 // TODO: add stencil buffer when needed.
116 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 117 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
117 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 118 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
118 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 119 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
119 texture_target_, 0, 0); 120 texture_target_, 0, 0);
120 121
121 FreeAllSurfaces(); 122 FreeAllSurfaces();
122 } 123 }
123 124
124 void BufferQueue::RecreateBuffers() { 125 void BufferQueue::RecreateBuffers() {
125 // We need to recreate the buffers, for whatever reason the old ones are not 126 // We need to recreate the buffers, for whatever reason the old ones are not
126 // presentable on the device anymore. 127 // presentable on the device anymore.
127 // Unused buffers can be freed directly, they will be re-allocated as needed. 128 // Unused buffers can be freed directly, they will be re-allocated as needed.
128 // Any in flight, current or displayed surface must be replaced. 129 // 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(); 130 available_surfaces_.clear();
132 131
132 // Recreate all in-flight surfaces and put the recreated copies in the queue.
133 for (auto& surface : in_flight_surfaces_) 133 for (auto& surface : in_flight_surfaces_)
134 surface = RecreateBuffer(&surface); 134 surface = RecreateBuffer(std::move(surface));
135 135
136 current_surface_ = RecreateBuffer(&current_surface_); 136 current_surface_ = RecreateBuffer(std::move(current_surface_));
137 displayed_surface_ = RecreateBuffer(&displayed_surface_); 137 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
138 138
139 if (current_surface_.texture) { 139 if (current_surface_) {
140 // If we have a texture bound, we will need to re-bind it. 140 // If we have a texture bound, we will need to re-bind it.
141 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 141 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
142 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 142 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
143 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 143 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
144 texture_target_, current_surface_.texture, 0); 144 texture_target_, current_surface_->texture, 0);
145 } 145 }
146 } 146 }
147 147
148 BufferQueue::AllocatedSurface BufferQueue::RecreateBuffer( 148 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
149 AllocatedSurface* surface) { 149 scoped_ptr<AllocatedSurface> surface) {
150 if (!surface->texture) 150 if (!surface)
151 return *surface; 151 return nullptr;
152 AllocatedSurface new_surface = GetNextSurface(); 152
153 new_surface.damage = surface->damage; 153 scoped_ptr<AllocatedSurface> new_surface(GetNextSurface());
154 if (!new_surface)
155 return nullptr;
156
157 new_surface->damage = surface->damage;
154 158
155 // Copy the entire texture. 159 // Copy the entire texture.
156 CopyBufferDamage(new_surface.texture, surface->texture, gfx::Rect(), 160 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
157 gfx::Rect(size_)); 161 gfx::Rect(size_));
158
159 FreeSurface(surface);
160 return new_surface; 162 return new_surface;
161 } 163 }
162 164
163 void BufferQueue::PageFlipComplete() { 165 void BufferQueue::PageFlipComplete() {
164 DCHECK(!in_flight_surfaces_.empty()); 166 DCHECK(!in_flight_surfaces_.empty());
165 167 if (displayed_surface_)
166 if (displayed_surface_.texture) 168 available_surfaces_.push_back(std::move(displayed_surface_));
167 available_surfaces_.push_back(displayed_surface_); 169 displayed_surface_ = std::move(in_flight_surfaces_.front());
168
169 displayed_surface_ = in_flight_surfaces_.front();
170 in_flight_surfaces_.pop_front(); 170 in_flight_surfaces_.pop_front();
171 } 171 }
172 172
173 void BufferQueue::FreeAllSurfaces() { 173 void BufferQueue::FreeAllSurfaces() {
174 FreeSurface(&displayed_surface_); 174 displayed_surface_.reset();
175 FreeSurface(&current_surface_); 175 current_surface_.reset();
176 // This is intentionally not emptied since the swap buffers acks are still 176 // This is intentionally not emptied since the swap buffers acks are still
177 // expected to arrive. 177 // expected to arrive.
178 for (auto& surface : in_flight_surfaces_) 178 for (auto& surface : in_flight_surfaces_)
179 FreeSurface(&surface); 179 surface = nullptr;
180
181 for (size_t i = 0; i < available_surfaces_.size(); i++)
182 FreeSurface(&available_surfaces_[i]);
183
184 available_surfaces_.clear(); 180 available_surfaces_.clear();
185 } 181 }
186 182
187 void BufferQueue::FreeSurface(AllocatedSurface* surface) { 183 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
188 if (surface->texture) { 184 if (!surface->texture)
189 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 185 return;
190 gl->BindTexture(texture_target_, surface->texture); 186
191 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); 187 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
192 gl->DeleteTextures(1, &surface->texture); 188 gl->BindTexture(texture_target_, surface->texture);
193 gl->DestroyImageCHROMIUM(surface->image); 189 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
194 surface->image = 0; 190 gl->DeleteTextures(1, &surface->texture);
195 surface->texture = 0; 191 gl->DestroyImageCHROMIUM(surface->image);
196 allocated_count_--; 192 surface->buffer.reset();
197 } 193 allocated_count_--;
198 } 194 }
199 195
200 BufferQueue::AllocatedSurface BufferQueue::GetNextSurface() { 196 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
201 if (!available_surfaces_.empty()) { 197 if (!available_surfaces_.empty()) {
202 AllocatedSurface surface = available_surfaces_.back(); 198 scoped_ptr<AllocatedSurface> surface =
199 std::move(available_surfaces_.back());
203 available_surfaces_.pop_back(); 200 available_surfaces_.pop_back();
204 return surface; 201 return surface;
205 } 202 }
206 203
207 unsigned int texture = 0; 204 unsigned int texture = 0;
208 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 205 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
209 gl->GenTextures(1, &texture); 206 gl->GenTextures(1, &texture);
210 if (!texture) 207 if (!texture)
211 return AllocatedSurface(); 208 return nullptr;
212 209
213 // We don't want to allow anything more than triple buffering. 210 // We don't want to allow anything more than triple buffering.
214 DCHECK_LT(allocated_count_, 4U); 211 DCHECK_LT(allocated_count_, 4U);
215 212
216 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 213 scoped_ptr<gfx::GpuMemoryBuffer> buffer(
217 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout( 214 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout(
218 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat( 215 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat(
219 internal_format_), 216 internal_format_),
220 surface_id_)); 217 surface_id_));
221 if (!buffer.get()) { 218 if (!buffer.get()) {
222 gl->DeleteTextures(1, &texture); 219 gl->DeleteTextures(1, &texture);
223 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; 220 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
224 return AllocatedSurface(); 221 return nullptr;
225 } 222 }
226 223
227 unsigned int id = gl->CreateImageCHROMIUM( 224 unsigned int id = gl->CreateImageCHROMIUM(
228 buffer->AsClientBuffer(), size_.width(), size_.height(), 225 buffer->AsClientBuffer(), size_.width(), size_.height(),
229 internal_format_); 226 internal_format_);
230
231 if (!id) { 227 if (!id) {
232 LOG(ERROR) << "Failed to allocate backing image surface"; 228 LOG(ERROR) << "Failed to allocate backing image surface";
233 gl->DeleteTextures(1, &texture); 229 gl->DeleteTextures(1, &texture);
234 return AllocatedSurface(); 230 return nullptr;
235 } 231 }
232
236 allocated_count_++; 233 allocated_count_++;
237 gl->BindTexture(texture_target_, texture); 234 gl->BindTexture(texture_target_, texture);
238 gl->BindTexImage2DCHROMIUM(texture_target_, id); 235 gl->BindTexImage2DCHROMIUM(texture_target_, id);
239 return AllocatedSurface(buffer.Pass(), texture, id, gfx::Rect(size_)); 236 return make_scoped_ptr(new AllocatedSurface(this, std::move(buffer), texture,
237 id, gfx::Rect(size_)));
240 } 238 }
241 239
242 BufferQueue::AllocatedSurface::AllocatedSurface() : texture(0), image(0) {}
243
244 BufferQueue::AllocatedSurface::AllocatedSurface( 240 BufferQueue::AllocatedSurface::AllocatedSurface(
241 BufferQueue* buffer_queue,
245 scoped_ptr<gfx::GpuMemoryBuffer> buffer, 242 scoped_ptr<gfx::GpuMemoryBuffer> buffer,
246 unsigned int texture, 243 unsigned int texture,
247 unsigned int image, 244 unsigned int image,
248 const gfx::Rect& rect) 245 const gfx::Rect& rect)
249 : buffer(buffer.release()), texture(texture), image(image), damage(rect) {} 246 : buffer_queue(buffer_queue),
247 buffer(buffer.release()),
248 texture(texture),
249 image(image),
250 damage(rect) {}
250 251
251 BufferQueue::AllocatedSurface::~AllocatedSurface() {} 252 BufferQueue::AllocatedSurface::~AllocatedSurface() {
253 if (buffer_queue)
danakj 2015/12/10 01:36:02 i don't see calls to default constructor anymore.
ccameron 2015/12/10 07:39:27 Good call -- I removed the default ctor, so this c
254 buffer_queue->FreeSurfaceResources(this);
255 }
252 256
253 } // namespace content 257 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698