Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/mus/surfaces/buffer_queue.h" |
| 6 | 6 |
| 7 #include "base/containers/adapters.h" | 7 #include "base/containers/adapters.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "cc/output/context_provider.h" |
| 9 #include "build/build_config.h" | 9 #include "components/mus/gles2/gl_helper.h" |
| 10 #include "content/browser/compositor/gl_helper.h" | 10 #include "components/mus/gles2/ozone_gpu_memory_buffer.h" |
| 11 #include "content/browser/compositor/image_transport_factory.h" | |
| 12 #include "content/common/gpu/client/context_provider_command_buffer.h" | |
| 13 #include "gpu/GLES2/gl2extchromium.h" | 11 #include "gpu/GLES2/gl2extchromium.h" |
| 14 #include "gpu/command_buffer/client/gles2_interface.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
| 15 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" | |
| 16 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" | 13 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" |
| 17 #include "gpu/command_buffer/service/image_factory.h" | |
| 18 #include "third_party/skia/include/core/SkRect.h" | 14 #include "third_party/skia/include/core/SkRect.h" |
| 19 #include "third_party/skia/include/core/SkRegion.h" | 15 #include "third_party/skia/include/core/SkRegion.h" |
| 20 #include "ui/gfx/gpu_memory_buffer.h" | 16 #include "ui/gfx/gpu_memory_buffer.h" |
| 21 #include "ui/gfx/skia_util.h" | 17 #include "ui/gfx/skia_util.h" |
| 22 | 18 |
| 23 namespace content { | 19 namespace mus { |
| 24 | 20 |
| 25 BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider, | 21 BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider, |
| 26 unsigned int texture_target, | 22 unsigned int texture_target, |
| 27 unsigned int internalformat, | 23 unsigned int internalformat, |
| 28 GLHelper* gl_helper, | 24 gfx::AcceleratedWidget widget) |
| 29 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, | |
| 30 int surface_id) | |
| 31 : context_provider_(context_provider), | 25 : context_provider_(context_provider), |
| 32 fbo_(0), | 26 fbo_(0), |
| 33 allocated_count_(0), | 27 allocated_count_(0), |
| 34 texture_target_(texture_target), | 28 texture_target_(texture_target), |
| 35 internal_format_(internalformat), | 29 internal_format_(internalformat), |
| 36 gl_helper_(gl_helper), | 30 widget_(widget) {} |
| 37 gpu_memory_buffer_manager_(gpu_memory_buffer_manager), | |
| 38 surface_id_(surface_id) {} | |
| 39 | 31 |
| 40 BufferQueue::~BufferQueue() { | 32 BufferQueue::~BufferQueue() { |
| 41 FreeAllSurfaces(); | 33 FreeAllSurfaces(); |
| 42 | 34 |
| 43 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 35 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 44 if (fbo_) | 36 if (fbo_) |
| 45 gl->DeleteFramebuffers(1, &fbo_); | 37 gl->DeleteFramebuffers(1, &fbo_); |
| 46 } | 38 } |
| 47 | 39 |
| 48 void BufferQueue::Initialize() { | 40 void BufferQueue::Initialize() { |
| 41 DCHECK(context_provider_); | |
| 49 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 42 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 43 DCHECK(gl); | |
| 50 gl->GenFramebuffers(1, &fbo_); | 44 gl->GenFramebuffers(1, &fbo_); |
| 51 } | 45 } |
| 52 | 46 |
| 53 void BufferQueue::BindFramebuffer() { | 47 void BufferQueue::BindFramebuffer() { |
| 54 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 48 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 55 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 49 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 56 | 50 |
| 57 if (!current_surface_) | 51 if (!current_surface_) |
| 58 current_surface_ = GetNextSurface(); | 52 current_surface_ = GetNextSurface(); |
| 59 | 53 |
| 60 if (current_surface_) { | 54 if (current_surface_) { |
| 61 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 55 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 62 texture_target_, current_surface_->texture, 0); | 56 texture_target_, current_surface_->texture, 0); |
| 63 } | 57 } |
| 64 } | 58 } |
| 65 | 59 |
| 66 void BufferQueue::CopyBufferDamage(int texture, | 60 void BufferQueue::CopyBufferDamage(int texture, |
| 67 int source_texture, | 61 int source_texture, |
| 68 const gfx::Rect& new_damage, | 62 const gfx::Rect& new_damage, |
| 69 const gfx::Rect& old_damage) { | 63 const gfx::Rect& old_damage) { |
| 70 gl_helper_->CopySubBufferDamage( | 64 GLCopySubBufferDamage(context_provider_->ContextGL(), texture_target_, |
| 71 texture_target_, texture, source_texture, | 65 texture, source_texture, |
| 72 SkRegion(gfx::RectToSkIRect(new_damage)), | 66 SkRegion(gfx::RectToSkIRect(new_damage)), |
| 73 SkRegion(gfx::RectToSkIRect(old_damage))); | 67 SkRegion(gfx::RectToSkIRect(old_damage))); |
| 74 } | 68 } |
| 75 | 69 |
| 76 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) { | 70 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) { |
| 77 if (displayed_surface_) | 71 if (displayed_surface_) |
| 78 displayed_surface_->damage.Union(damage); | 72 displayed_surface_->damage.Union(damage); |
| 79 for (auto& surface : available_surfaces_) | 73 for (auto& surface : available_surfaces_) |
| 80 surface->damage.Union(damage); | 74 surface->damage.Union(damage); |
| 81 for (auto& surface : in_flight_surfaces_) { | 75 for (auto& surface : in_flight_surfaces_) { |
| 82 if (surface) | 76 if (surface) |
| 83 surface->damage.Union(damage); | 77 surface->damage.Union(damage); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 110 UpdateBufferDamage(damage); | 104 UpdateBufferDamage(damage); |
| 111 in_flight_surfaces_.push_back(std::move(current_surface_)); | 105 in_flight_surfaces_.push_back(std::move(current_surface_)); |
| 112 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer | 106 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer |
| 113 // paths), so ensure we restore it here. | 107 // paths), so ensure we restore it here. |
| 114 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 108 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 115 } | 109 } |
| 116 | 110 |
| 117 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { | 111 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { |
| 118 if (size == size_) | 112 if (size == size_) |
| 119 return; | 113 return; |
| 120 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that | 114 |
| 121 // is cause for concern or if it is benign. | |
| 122 // http://crbug.com/524624 | |
| 123 #if !defined(OS_MACOSX) | |
| 124 DCHECK(!current_surface_); | |
| 125 #endif | |
| 126 size_ = size; | 115 size_ = size; |
| 127 | 116 |
| 128 // TODO: add stencil buffer when needed. | 117 // TODO: add stencil buffer when needed. |
| 129 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 118 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 130 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 119 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 131 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 120 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 132 texture_target_, 0, 0); | 121 texture_target_, 0, 0); |
| 133 | 122 |
| 134 FreeAllSurfaces(); | 123 FreeAllSurfaces(); |
| 135 } | 124 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 150 | 139 |
| 151 if (current_surface_) { | 140 if (current_surface_) { |
| 152 // If we have a texture bound, we will need to re-bind it. | 141 // If we have a texture bound, we will need to re-bind it. |
| 153 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 142 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 154 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 143 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 155 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 144 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 156 texture_target_, current_surface_->texture, 0); | 145 texture_target_, current_surface_->texture, 0); |
| 157 } | 146 } |
| 158 } | 147 } |
| 159 | 148 |
| 160 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer( | 149 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer( |
|
Fady Samuel
2016/04/12 02:54:40
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 161 std::unique_ptr<AllocatedSurface> surface) { | 150 scoped_ptr<AllocatedSurface> surface) { |
|
Fady Samuel
2016/04/12 02:54:40
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 162 if (!surface) | 151 if (!surface) |
| 163 return nullptr; | 152 return nullptr; |
| 164 | 153 |
| 165 std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface()); | 154 scoped_ptr<AllocatedSurface> new_surface(GetNextSurface()); |
|
Fady Samuel
2016/04/12 02:54:41
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 166 if (!new_surface) | 155 if (!new_surface) |
| 167 return nullptr; | 156 return nullptr; |
| 168 | 157 |
| 169 new_surface->damage = surface->damage; | 158 new_surface->damage = surface->damage; |
| 170 | 159 |
| 171 // Copy the entire texture. | 160 // Copy the entire texture. |
| 172 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(), | 161 CopyBufferDamage(new_surface->texture, surface->texture, gfx::Rect(), |
| 173 gfx::Rect(size_)); | 162 gfx::Rect(size_)); |
| 174 return new_surface; | 163 return new_surface; |
| 175 } | 164 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 193 } | 182 } |
| 194 | 183 |
| 195 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) { | 184 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) { |
| 196 if (!surface->texture) | 185 if (!surface->texture) |
| 197 return; | 186 return; |
| 198 | 187 |
| 199 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 188 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 200 gl->BindTexture(texture_target_, surface->texture); | 189 gl->BindTexture(texture_target_, surface->texture); |
| 201 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); | 190 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); |
| 202 gl->DeleteTextures(1, &surface->texture); | 191 gl->DeleteTextures(1, &surface->texture); |
| 192 // TODO(rjk): Implement image deletion. | |
| 203 gl->DestroyImageCHROMIUM(surface->image); | 193 gl->DestroyImageCHROMIUM(surface->image); |
| 204 surface->buffer.reset(); | 194 surface->buffer.reset(); |
| 205 allocated_count_--; | 195 allocated_count_--; |
| 206 } | 196 } |
| 207 | 197 |
| 208 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() { | 198 scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() { |
|
Fady Samuel
2016/04/12 02:54:40
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 209 if (!available_surfaces_.empty()) { | 199 if (!available_surfaces_.empty()) { |
| 210 std::unique_ptr<AllocatedSurface> surface = | 200 scoped_ptr<AllocatedSurface> surface = |
|
Fady Samuel
2016/04/12 02:54:40
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 211 std::move(available_surfaces_.back()); | 201 std::move(available_surfaces_.back()); |
| 212 available_surfaces_.pop_back(); | 202 available_surfaces_.pop_back(); |
| 213 return surface; | 203 return surface; |
| 214 } | 204 } |
| 215 | 205 |
| 216 unsigned int texture = 0; | 206 unsigned int texture = 0; |
| 217 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 207 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 218 gl->GenTextures(1, &texture); | 208 gl->GenTextures(1, &texture); |
| 219 if (!texture) | 209 if (!texture) |
| 220 return nullptr; | 210 return nullptr; |
| 221 | 211 |
| 222 // We don't want to allow anything more than triple buffering. | 212 // We don't want to allow anything more than triple buffering. |
| 223 DCHECK_LT(allocated_count_, 4U); | 213 DCHECK_LT(allocated_count_, 4U); |
| 224 | 214 |
| 225 std::unique_ptr<gfx::GpuMemoryBuffer> buffer( | 215 scoped_ptr<gfx::GpuMemoryBuffer> buffer( |
|
Fady Samuel
2016/04/12 02:54:41
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 226 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( | 216 OzoneGpuMemoryBuffer::CreateOzoneGpuMemoryBuffer( |
| 227 size_, gpu::DefaultBufferFormatForImageFormat(internal_format_), | 217 size_, gpu::DefaultBufferFormatForImageFormat(internal_format_), |
| 228 gfx::BufferUsage::SCANOUT, surface_id_)); | 218 gfx::BufferUsage::SCANOUT, widget_)); |
| 219 | |
| 229 if (!buffer.get()) { | 220 if (!buffer.get()) { |
| 230 gl->DeleteTextures(1, &texture); | 221 gl->DeleteTextures(1, &texture); |
| 231 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; | 222 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; |
| 232 return nullptr; | 223 return nullptr; |
| 233 } | 224 } |
| 234 | 225 |
| 235 unsigned int id = gl->CreateImageCHROMIUM( | 226 // Thanks to the convolutions of Chrome source code, this ends up calling back |
| 236 buffer->AsClientBuffer(), size_.width(), size_.height(), | 227 // into the CommandBufferLocal via |
| 237 internal_format_); | 228 // its implementation of the GpuControl interface. In that case, we need to |
|
Fady Samuel
2016/04/12 02:54:40
nit: weird wrapping.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 229 // handle the given buffer pointer there. | |
| 230 unsigned int id = | |
| 231 gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(), | |
| 232 size_.height(), internal_format_); | |
| 238 if (!id) { | 233 if (!id) { |
| 239 LOG(ERROR) << "Failed to allocate backing image surface"; | 234 LOG(ERROR) << "Failed to allocate backing image surface"; |
| 240 gl->DeleteTextures(1, &texture); | 235 gl->DeleteTextures(1, &texture); |
| 241 return nullptr; | 236 return nullptr; |
| 242 } | 237 } |
| 243 | 238 |
| 244 allocated_count_++; | 239 allocated_count_++; |
| 245 gl->BindTexture(texture_target_, texture); | 240 gl->BindTexture(texture_target_, texture); |
| 246 gl->BindTexImage2DCHROMIUM(texture_target_, id); | 241 gl->BindTexImage2DCHROMIUM(texture_target_, id); |
| 247 return base::WrapUnique(new AllocatedSurface(this, std::move(buffer), texture, | 242 // It doesn't end up in the queue to re-use until we handle the page flip. |
| 248 id, gfx::Rect(size_))); | 243 return make_scoped_ptr(new AllocatedSurface(this, std::move(buffer), texture, |
|
Fady Samuel
2016/04/12 02:54:41
WrapUnique
rjkroege
2016/04/12 19:27:54
Done.
| |
| 244 id, gfx::Rect(size_))); | |
| 249 } | 245 } |
| 250 | 246 |
| 251 BufferQueue::AllocatedSurface::AllocatedSurface( | 247 BufferQueue::AllocatedSurface::AllocatedSurface( |
| 252 BufferQueue* buffer_queue, | 248 BufferQueue* buffer_queue, |
| 253 std::unique_ptr<gfx::GpuMemoryBuffer> buffer, | 249 scoped_ptr<gfx::GpuMemoryBuffer> buffer, |
|
Fady Samuel
2016/04/12 02:54:40
nit: std::unique_ptr.
rjkroege
2016/04/12 19:27:54
Done.
| |
| 254 unsigned int texture, | 250 unsigned int texture, |
| 255 unsigned int image, | 251 unsigned int image, |
| 256 const gfx::Rect& rect) | 252 const gfx::Rect& rect) |
| 257 : buffer_queue(buffer_queue), | 253 : buffer_queue(buffer_queue), |
| 258 buffer(buffer.release()), | 254 buffer(buffer.release()), |
| 259 texture(texture), | 255 texture(texture), |
| 260 image(image), | 256 image(image), |
| 261 damage(rect) {} | 257 damage(rect) {} |
| 262 | 258 |
| 263 BufferQueue::AllocatedSurface::~AllocatedSurface() { | 259 BufferQueue::AllocatedSurface::~AllocatedSurface() { |
| 264 buffer_queue->FreeSurfaceResources(this); | 260 buffer_queue->FreeSurfaceResources(this); |
| 265 } | 261 } |
| 266 | 262 |
| 267 } // namespace content | 263 } // namespace mus |
| OLD | NEW |