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

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: Use vector<scoped_ptr<T>> 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);
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 surface->damage.Union(damage);
78 it != in_flight_surfaces_.end();
79 ++it)
80 it->damage.Union(damage);
81 } 79 }
82 80
83 void BufferQueue::SwapBuffers(const gfx::Rect& damage) { 81 void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
82 DCHECK(current_surface_);
83
84 if (!damage.IsEmpty() && damage != gfx::Rect(size_)) { 84 if (!damage.IsEmpty() && damage != gfx::Rect(size_)) {
85 // We must have a frame available to copy from. 85 // We must have a frame available to copy from.
86 DCHECK(!in_flight_surfaces_.empty() || displayed_surface_.texture); 86 DCHECK(!in_flight_surfaces_.empty() || displayed_surface_);
87 unsigned int texture_id = !in_flight_surfaces_.empty() 87 unsigned int texture_id = !in_flight_surfaces_.empty()
88 ? in_flight_surfaces_.back().texture 88 ? in_flight_surfaces_.back()->texture
89 : displayed_surface_.texture; 89 : displayed_surface_->texture;
90 90 CopyBufferDamage(current_surface_->texture, texture_id, damage,
91 CopyBufferDamage(current_surface_.texture, texture_id, damage, 91 current_surface_->damage);
92 current_surface_.damage);
93 } 92 }
94 UpdateBufferDamage(damage); 93 UpdateBufferDamage(damage);
95 current_surface_.damage = gfx::Rect(); 94 current_surface_->damage = gfx::Rect();
96 in_flight_surfaces_.push_back(current_surface_); 95 in_flight_surfaces_.push_back(current_surface_.Pass());
danakj 2015/12/09 23:25:16 std::move()
ccameron 2015/12/10 00:19:28 Done.
97 current_surface_.texture = 0;
98 current_surface_.image = 0;
99 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer 96 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer
100 // paths), so ensure we restore it here. 97 // paths), so ensure we restore it here.
101 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 98 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
102 } 99 }
103 100
104 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { 101 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
105 if (size == size_) 102 if (size == size_)
106 return; 103 return;
107 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that 104 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
108 // is cause for concern or if it is benign. 105 // is cause for concern or if it is benign.
109 // http://crbug.com/524624 106 // http://crbug.com/524624
110 #if !defined(OS_MACOSX) 107 #if !defined(OS_MACOSX)
111 DCHECK(!current_surface_.texture); 108 DCHECK(!current_surface_);
112 #endif 109 #endif
113 size_ = size; 110 size_ = size;
114 111
115 // TODO: add stencil buffer when needed. 112 // TODO: add stencil buffer when needed.
116 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 113 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
117 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 114 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
118 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 115 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
119 texture_target_, 0, 0); 116 texture_target_, 0, 0);
120 117
121 FreeAllSurfaces(); 118 FreeAllSurfaces();
122 } 119 }
123 120
124 void BufferQueue::RecreateBuffers() { 121 void BufferQueue::RecreateBuffers() {
125 // We need to recreate the buffers, for whatever reason the old ones are not 122 // We need to recreate the buffers, for whatever reason the old ones are not
126 // presentable on the device anymore. 123 // presentable on the device anymore.
127 // Unused buffers can be freed directly, they will be re-allocated as needed. 124 // Unused buffers can be freed directly, they will be re-allocated as needed.
128 // Any in flight, current or displayed surface must be replaced. 125 // 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(); 126 available_surfaces_.clear();
132 127
128 // Recreate all in-flight surfaces and put the recreated copies in the queue.
133 for (auto& surface : in_flight_surfaces_) 129 for (auto& surface : in_flight_surfaces_)
134 surface = RecreateBuffer(&surface); 130 surface = RecreateBuffer(surface.Pass());
danakj 2015/12/09 23:25:15 std::move() for all passing
ccameron 2015/12/10 00:19:28 Done.
135 131
136 current_surface_ = RecreateBuffer(&current_surface_); 132 current_surface_ = RecreateBuffer(current_surface_.Pass());
137 displayed_surface_ = RecreateBuffer(&displayed_surface_); 133 displayed_surface_ = RecreateBuffer(displayed_surface_.Pass());
138 134
139 if (current_surface_.texture) { 135 if (current_surface_ && current_surface_->texture) {
danakj 2015/12/09 23:25:15 you could just make RecreateBuffer return null if
ccameron 2015/12/10 00:19:28 This is the "remnant" mentioned below.
140 // If we have a texture bound, we will need to re-bind it. 136 // If we have a texture bound, we will need to re-bind it.
141 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 137 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
142 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 138 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
143 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 139 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
144 texture_target_, current_surface_.texture, 0); 140 texture_target_, current_surface_->texture, 0);
145 } 141 }
146 } 142 }
147 143
148 BufferQueue::AllocatedSurface BufferQueue::RecreateBuffer( 144 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
149 AllocatedSurface* surface) { 145 scoped_ptr<AllocatedSurface> surface) {
150 if (!surface->texture) 146 if (!surface)
151 return *surface; 147 return scoped_ptr<AllocatedSurface>();
danakj 2015/12/09 23:25:15 return nullptr
ccameron 2015/12/10 00:19:28 Done.
152 AllocatedSurface new_surface = GetNextSurface(); 148
153 new_surface.damage = surface->damage; 149 scoped_ptr<AllocatedSurface> new_surface(GetNextSurface());
150 new_surface->damage = surface->damage;
154 151
155 // Copy the entire texture. 152 // Copy the entire texture.
156 CopyBufferDamage(new_surface.texture, surface->texture, gfx::Rect(), 153 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(),
157 gfx::Rect(size_)); 154 gfx::Rect(size_));
158 155 return new_surface.Pass();
danakj 2015/12/09 23:25:15 don't std::move() on return unless you're upcastin
ccameron 2015/12/10 00:19:28 It does :)
159 FreeSurface(surface);
160 return new_surface;
161 } 156 }
162 157
163 void BufferQueue::PageFlipComplete() { 158 void BufferQueue::PageFlipComplete() {
164 DCHECK(!in_flight_surfaces_.empty()); 159 DCHECK(!in_flight_surfaces_.empty());
165 160 if (displayed_surface_ && displayed_surface_->texture)
danakj 2015/12/09 23:25:15 can you be non-null but 0 texture?
ccameron 2015/12/10 00:19:28 Yes (... see discussion later).
166 if (displayed_surface_.texture) 161 available_surfaces_.push_back(displayed_surface_.Pass());
167 available_surfaces_.push_back(displayed_surface_); 162 displayed_surface_ = in_flight_surfaces_.front().Pass();
168
169 displayed_surface_ = in_flight_surfaces_.front();
170 in_flight_surfaces_.pop_front(); 163 in_flight_surfaces_.pop_front();
171 } 164 }
172 165
173 void BufferQueue::FreeAllSurfaces() { 166 void BufferQueue::FreeAllSurfaces() {
174 FreeSurface(&displayed_surface_); 167 displayed_surface_.reset();
175 FreeSurface(&current_surface_); 168 current_surface_.reset();
176 // This is intentionally not emptied since the swap buffers acks are still 169 // This is intentionally not emptied since the swap buffers acks are still
177 // expected to arrive. 170 // expected to arrive.
178 for (auto& surface : in_flight_surfaces_) 171 for (auto& surface : in_flight_surfaces_)
179 FreeSurface(&surface); 172 FreeSurfaceResources(surface.get());
180
181 for (size_t i = 0; i < available_surfaces_.size(); i++)
182 FreeSurface(&available_surfaces_[i]);
183
184 available_surfaces_.clear(); 173 available_surfaces_.clear();
185 } 174 }
186 175
187 void BufferQueue::FreeSurface(AllocatedSurface* surface) { 176 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) {
188 if (surface->texture) { 177 if (!surface->texture)
189 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 178 return;
190 gl->BindTexture(texture_target_, surface->texture); 179
191 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); 180 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
192 gl->DeleteTextures(1, &surface->texture); 181 gl->BindTexture(texture_target_, surface->texture);
193 gl->DestroyImageCHROMIUM(surface->image); 182 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image);
194 surface->image = 0; 183 gl->DeleteTextures(1, &surface->texture);
195 surface->texture = 0; 184 gl->DestroyImageCHROMIUM(surface->image);
196 allocated_count_--; 185 surface->image = 0;
197 } 186 surface->texture = 0;
187 surface->buffer.reset();
188 surface->buffer_queue = nullptr;
189 allocated_count_--;
198 } 190 }
199 191
200 BufferQueue::AllocatedSurface BufferQueue::GetNextSurface() { 192 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
201 if (!available_surfaces_.empty()) { 193 if (!available_surfaces_.empty()) {
202 AllocatedSurface surface = available_surfaces_.back(); 194 scoped_ptr<AllocatedSurface> surface = available_surfaces_.back().Pass();
203 available_surfaces_.pop_back(); 195 available_surfaces_.pop_back();
204 return surface; 196 return surface.Pass();
danakj 2015/12/09 23:25:15 should be move() but on return shouldn't be anythi
ccameron 2015/12/10 00:19:28 Done.
205 } 197 }
206 198
207 unsigned int texture = 0; 199 unsigned int texture = 0;
208 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 200 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
209 gl->GenTextures(1, &texture); 201 gl->GenTextures(1, &texture);
210 if (!texture) 202 if (!texture)
211 return AllocatedSurface(); 203 return scoped_ptr<AllocatedSurface>(new AllocatedSurface);
danakj 2015/12/09 23:25:15 make_scoped_ptr(new All...) but why not return nu
ccameron 2015/12/10 00:19:28 Myself as of a few hours agreed with you (actually
212 204
213 // We don't want to allow anything more than triple buffering. 205 // We don't want to allow anything more than triple buffering.
214 DCHECK_LT(allocated_count_, 4U); 206 DCHECK_LT(allocated_count_, 4U);
215 207
216 scoped_ptr<gfx::GpuMemoryBuffer> buffer( 208 scoped_ptr<gfx::GpuMemoryBuffer> buffer(
217 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout( 209 gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout(
218 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat( 210 size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat(
219 internal_format_), 211 internal_format_),
220 surface_id_)); 212 surface_id_));
221 if (!buffer.get()) { 213 if (!buffer.get()) {
222 gl->DeleteTextures(1, &texture); 214 gl->DeleteTextures(1, &texture);
223 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; 215 DLOG(ERROR) << "Failed to allocate GPU memory buffer";
224 return AllocatedSurface(); 216 return scoped_ptr<AllocatedSurface>(new AllocatedSurface);
danakj 2015/12/09 23:25:15 make_scoped_ptr
ccameron 2015/12/10 00:19:27 Done.
225 } 217 }
226 218
227 unsigned int id = gl->CreateImageCHROMIUM( 219 unsigned int id = gl->CreateImageCHROMIUM(
228 buffer->AsClientBuffer(), size_.width(), size_.height(), 220 buffer->AsClientBuffer(), size_.width(), size_.height(),
229 internal_format_); 221 internal_format_);
230 222
231 if (!id) { 223 if (!id) {
232 LOG(ERROR) << "Failed to allocate backing image surface"; 224 LOG(ERROR) << "Failed to allocate backing image surface";
233 gl->DeleteTextures(1, &texture); 225 gl->DeleteTextures(1, &texture);
234 return AllocatedSurface(); 226 return scoped_ptr<AllocatedSurface>(new AllocatedSurface);
danakj 2015/12/09 23:25:15 make_scoped_ptr
ccameron 2015/12/10 00:19:28 Done.
235 } 227 }
236 allocated_count_++; 228 allocated_count_++;
237 gl->BindTexture(texture_target_, texture); 229 gl->BindTexture(texture_target_, texture);
238 gl->BindTexImage2DCHROMIUM(texture_target_, id); 230 gl->BindTexImage2DCHROMIUM(texture_target_, id);
239 return AllocatedSurface(buffer.Pass(), texture, id, gfx::Rect(size_)); 231 return scoped_ptr<AllocatedSurface>(new AllocatedSurface(this, buffer.Pass(),
232 texture, id,
233 gfx::Rect(size_)))
234 .Pass();
240 } 235 }
241 236
242 BufferQueue::AllocatedSurface::AllocatedSurface() : texture(0), image(0) {} 237 BufferQueue::AllocatedSurface::AllocatedSurface()
238 : buffer_queue(nullptr), texture(0), image(0) {}
243 239
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/09 23:25:15 it can be null?
ccameron 2015/12/10 00:19:28 Yeah, if the default ctor was used.
254 buffer_queue->FreeSurfaceResources(this);
255 }
252 256
253 } // namespace content 257 } // 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