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

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