| OLD | NEW |
| 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 "components/display_compositor/buffer_queue.h" | 5 #include "components/display_compositor/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 "base/memory/ptr_util.h" |
| 9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 10 #include "cc/output/context_provider.h" | |
| 11 #include "components/display_compositor/gl_helper.h" | 10 #include "components/display_compositor/gl_helper.h" |
| 12 #include "gpu/GLES2/gl2extchromium.h" | 11 #include "gpu/GLES2/gl2extchromium.h" |
| 13 #include "gpu/command_buffer/client/gles2_interface.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
| 14 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" | 13 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
| 15 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" | 14 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" |
| 16 #include "third_party/skia/include/core/SkRect.h" | 15 #include "third_party/skia/include/core/SkRect.h" |
| 17 #include "third_party/skia/include/core/SkRegion.h" | 16 #include "third_party/skia/include/core/SkRegion.h" |
| 18 #include "ui/gfx/gpu_memory_buffer.h" | 17 #include "ui/gfx/gpu_memory_buffer.h" |
| 19 #include "ui/gfx/skia_util.h" | 18 #include "ui/gfx/skia_util.h" |
| 20 | 19 |
| 21 namespace display_compositor { | 20 namespace display_compositor { |
| 22 | 21 |
| 23 BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider, | 22 BufferQueue::BufferQueue(gpu::gles2::GLES2Interface* gl, |
| 24 unsigned int texture_target, | 23 unsigned int texture_target, |
| 25 unsigned int internalformat, | 24 unsigned int internalformat, |
| 26 GLHelper* gl_helper, | 25 GLHelper* gl_helper, |
| 27 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, | 26 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, |
| 28 gpu::SurfaceHandle surface_handle) | 27 gpu::SurfaceHandle surface_handle) |
| 29 : context_provider_(context_provider), | 28 : gl_(gl), |
| 30 fbo_(0), | 29 fbo_(0), |
| 31 allocated_count_(0), | 30 allocated_count_(0), |
| 32 texture_target_(texture_target), | 31 texture_target_(texture_target), |
| 33 internal_format_(internalformat), | 32 internal_format_(internalformat), |
| 34 gl_helper_(gl_helper), | 33 gl_helper_(gl_helper), |
| 35 gpu_memory_buffer_manager_(gpu_memory_buffer_manager), | 34 gpu_memory_buffer_manager_(gpu_memory_buffer_manager), |
| 36 surface_handle_(surface_handle) {} | 35 surface_handle_(surface_handle) {} |
| 37 | 36 |
| 38 BufferQueue::~BufferQueue() { | 37 BufferQueue::~BufferQueue() { |
| 39 FreeAllSurfaces(); | 38 FreeAllSurfaces(); |
| 40 | 39 |
| 41 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
| 42 if (fbo_) | 40 if (fbo_) |
| 43 gl->DeleteFramebuffers(1, &fbo_); | 41 gl_->DeleteFramebuffers(1, &fbo_); |
| 44 } | 42 } |
| 45 | 43 |
| 46 void BufferQueue::Initialize() { | 44 void BufferQueue::Initialize() { |
| 47 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 45 gl_->GenFramebuffers(1, &fbo_); |
| 48 gl->GenFramebuffers(1, &fbo_); | |
| 49 } | 46 } |
| 50 | 47 |
| 51 void BufferQueue::BindFramebuffer() { | 48 void BufferQueue::BindFramebuffer() { |
| 52 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 49 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 53 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | |
| 54 | 50 |
| 55 if (!current_surface_) | 51 if (!current_surface_) |
| 56 current_surface_ = GetNextSurface(); | 52 current_surface_ = GetNextSurface(); |
| 57 | 53 |
| 58 if (current_surface_) { | 54 if (current_surface_) { |
| 59 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 55 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 60 texture_target_, current_surface_->texture, 0); | 56 texture_target_, current_surface_->texture, 0); |
| 61 } | 57 } |
| 62 } | 58 } |
| 63 | 59 |
| 64 void BufferQueue::CopyBufferDamage(int texture, | 60 void BufferQueue::CopyBufferDamage(int texture, |
| 65 int source_texture, | 61 int source_texture, |
| 66 const gfx::Rect& new_damage, | 62 const gfx::Rect& new_damage, |
| 67 const gfx::Rect& old_damage) { | 63 const gfx::Rect& old_damage) { |
| 68 gl_helper_->CopySubBufferDamage(texture_target_, texture, source_texture, | 64 gl_helper_->CopySubBufferDamage(texture_target_, texture, source_texture, |
| 69 SkRegion(gfx::RectToSkIRect(new_damage)), | 65 SkRegion(gfx::RectToSkIRect(new_damage)), |
| 70 SkRegion(gfx::RectToSkIRect(old_damage))); | 66 SkRegion(gfx::RectToSkIRect(old_damage))); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 101 CopyBufferDamage(current_surface_->texture, texture_id, damage, | 97 CopyBufferDamage(current_surface_->texture, texture_id, damage, |
| 102 current_surface_->damage); | 98 current_surface_->damage); |
| 103 } | 99 } |
| 104 } | 100 } |
| 105 current_surface_->damage = gfx::Rect(); | 101 current_surface_->damage = gfx::Rect(); |
| 106 } | 102 } |
| 107 UpdateBufferDamage(damage); | 103 UpdateBufferDamage(damage); |
| 108 in_flight_surfaces_.push_back(std::move(current_surface_)); | 104 in_flight_surfaces_.push_back(std::move(current_surface_)); |
| 109 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer | 105 // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer |
| 110 // paths), so ensure we restore it here. | 106 // paths), so ensure we restore it here. |
| 111 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 107 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 112 } | 108 } |
| 113 | 109 |
| 114 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { | 110 void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { |
| 115 if (size == size_) | 111 if (size == size_) |
| 116 return; | 112 return; |
| 117 #if !defined(OS_MACOSX) | 113 #if !defined(OS_MACOSX) |
| 118 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that | 114 // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that |
| 119 // is cause for concern or if it is benign. | 115 // is cause for concern or if it is benign. |
| 120 // http://crbug.com/524624 | 116 // http://crbug.com/524624 |
| 121 DCHECK(!current_surface_); | 117 DCHECK(!current_surface_); |
| 122 #endif | 118 #endif |
| 123 size_ = size; | 119 size_ = size; |
| 124 | 120 |
| 125 // TODO: add stencil buffer when needed. | 121 // TODO: add stencil buffer when needed. |
| 126 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 122 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 127 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 123 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 128 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 124 texture_target_, 0, 0); |
| 129 texture_target_, 0, 0); | |
| 130 | 125 |
| 131 FreeAllSurfaces(); | 126 FreeAllSurfaces(); |
| 132 } | 127 } |
| 133 | 128 |
| 134 void BufferQueue::RecreateBuffers() { | 129 void BufferQueue::RecreateBuffers() { |
| 135 // We need to recreate the buffers, for whatever reason the old ones are not | 130 // We need to recreate the buffers, for whatever reason the old ones are not |
| 136 // presentable on the device anymore. | 131 // presentable on the device anymore. |
| 137 // Unused buffers can be freed directly, they will be re-allocated as needed. | 132 // Unused buffers can be freed directly, they will be re-allocated as needed. |
| 138 // Any in flight, current or displayed surface must be replaced. | 133 // Any in flight, current or displayed surface must be replaced. |
| 139 available_surfaces_.clear(); | 134 available_surfaces_.clear(); |
| 140 | 135 |
| 141 // Recreate all in-flight surfaces and put the recreated copies in the queue. | 136 // Recreate all in-flight surfaces and put the recreated copies in the queue. |
| 142 for (auto& surface : in_flight_surfaces_) | 137 for (auto& surface : in_flight_surfaces_) |
| 143 surface = RecreateBuffer(std::move(surface)); | 138 surface = RecreateBuffer(std::move(surface)); |
| 144 | 139 |
| 145 current_surface_ = RecreateBuffer(std::move(current_surface_)); | 140 current_surface_ = RecreateBuffer(std::move(current_surface_)); |
| 146 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_)); | 141 displayed_surface_ = RecreateBuffer(std::move(displayed_surface_)); |
| 147 | 142 |
| 148 if (current_surface_) { | 143 if (current_surface_) { |
| 149 // If we have a texture bound, we will need to re-bind it. | 144 // If we have a texture bound, we will need to re-bind it. |
| 150 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 145 gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 151 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | 146 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| 152 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | 147 texture_target_, current_surface_->texture, 0); |
| 153 texture_target_, current_surface_->texture, 0); | |
| 154 } | 148 } |
| 155 } | 149 } |
| 156 | 150 |
| 157 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer( | 151 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer( |
| 158 std::unique_ptr<AllocatedSurface> surface) { | 152 std::unique_ptr<AllocatedSurface> surface) { |
| 159 if (!surface) | 153 if (!surface) |
| 160 return nullptr; | 154 return nullptr; |
| 161 | 155 |
| 162 std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface()); | 156 std::unique_ptr<AllocatedSurface> new_surface(GetNextSurface()); |
| 163 if (!new_surface) | 157 if (!new_surface) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 186 // expected to arrive. | 180 // expected to arrive. |
| 187 for (auto& surface : in_flight_surfaces_) | 181 for (auto& surface : in_flight_surfaces_) |
| 188 surface = nullptr; | 182 surface = nullptr; |
| 189 available_surfaces_.clear(); | 183 available_surfaces_.clear(); |
| 190 } | 184 } |
| 191 | 185 |
| 192 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) { | 186 void BufferQueue::FreeSurfaceResources(AllocatedSurface* surface) { |
| 193 if (!surface->texture) | 187 if (!surface->texture) |
| 194 return; | 188 return; |
| 195 | 189 |
| 196 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 190 gl_->BindTexture(texture_target_, surface->texture); |
| 197 gl->BindTexture(texture_target_, surface->texture); | 191 gl_->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); |
| 198 gl->ReleaseTexImage2DCHROMIUM(texture_target_, surface->image); | 192 gl_->DeleteTextures(1, &surface->texture); |
| 199 gl->DeleteTextures(1, &surface->texture); | 193 gl_->DestroyImageCHROMIUM(surface->image); |
| 200 gl->DestroyImageCHROMIUM(surface->image); | |
| 201 surface->buffer.reset(); | 194 surface->buffer.reset(); |
| 202 allocated_count_--; | 195 allocated_count_--; |
| 203 } | 196 } |
| 204 | 197 |
| 205 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() { | 198 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() { |
| 206 if (!available_surfaces_.empty()) { | 199 if (!available_surfaces_.empty()) { |
| 207 std::unique_ptr<AllocatedSurface> surface = | 200 std::unique_ptr<AllocatedSurface> surface = |
| 208 std::move(available_surfaces_.back()); | 201 std::move(available_surfaces_.back()); |
| 209 available_surfaces_.pop_back(); | 202 available_surfaces_.pop_back(); |
| 210 return surface; | 203 return surface; |
| 211 } | 204 } |
| 212 | 205 |
| 213 unsigned int texture = 0; | 206 GLuint texture; |
| 214 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 207 gl_->GenTextures(1, &texture); |
| 215 gl->GenTextures(1, &texture); | |
| 216 if (!texture) | |
| 217 return nullptr; | |
| 218 | 208 |
| 219 // We don't want to allow anything more than triple buffering. | 209 // We don't want to allow anything more than triple buffering. |
| 220 DCHECK_LT(allocated_count_, 4U); | 210 DCHECK_LT(allocated_count_, 4U); |
| 221 | 211 |
| 222 std::unique_ptr<gfx::GpuMemoryBuffer> buffer( | 212 std::unique_ptr<gfx::GpuMemoryBuffer> buffer( |
| 223 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( | 213 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( |
| 224 size_, gpu::DefaultBufferFormatForImageFormat(internal_format_), | 214 size_, gpu::DefaultBufferFormatForImageFormat(internal_format_), |
| 225 gfx::BufferUsage::SCANOUT, surface_handle_)); | 215 gfx::BufferUsage::SCANOUT, surface_handle_)); |
| 226 if (!buffer.get()) { | 216 if (!buffer.get()) { |
| 227 gl->DeleteTextures(1, &texture); | 217 gl_->DeleteTextures(1, &texture); |
| 228 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; | 218 DLOG(ERROR) << "Failed to allocate GPU memory buffer"; |
| 229 return nullptr; | 219 return nullptr; |
| 230 } | 220 } |
| 231 | 221 |
| 232 unsigned int id = | 222 unsigned int id = |
| 233 gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(), | 223 gl_->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(), |
| 234 size_.height(), internal_format_); | 224 size_.height(), internal_format_); |
| 235 if (!id) { | 225 if (!id) { |
| 236 LOG(ERROR) << "Failed to allocate backing image surface"; | 226 LOG(ERROR) << "Failed to allocate backing image surface"; |
| 237 gl->DeleteTextures(1, &texture); | 227 gl_->DeleteTextures(1, &texture); |
| 238 return nullptr; | 228 return nullptr; |
| 239 } | 229 } |
| 240 | 230 |
| 241 allocated_count_++; | 231 allocated_count_++; |
| 242 gl->BindTexture(texture_target_, texture); | 232 gl_->BindTexture(texture_target_, texture); |
| 243 gl->BindTexImage2DCHROMIUM(texture_target_, id); | 233 gl_->BindTexImage2DCHROMIUM(texture_target_, id); |
| 244 return base::WrapUnique(new AllocatedSurface(this, std::move(buffer), texture, | 234 return base::WrapUnique(new AllocatedSurface(this, std::move(buffer), texture, |
| 245 id, gfx::Rect(size_))); | 235 id, gfx::Rect(size_))); |
| 246 } | 236 } |
| 247 | 237 |
| 248 BufferQueue::AllocatedSurface::AllocatedSurface( | 238 BufferQueue::AllocatedSurface::AllocatedSurface( |
| 249 BufferQueue* buffer_queue, | 239 BufferQueue* buffer_queue, |
| 250 std::unique_ptr<gfx::GpuMemoryBuffer> buffer, | 240 std::unique_ptr<gfx::GpuMemoryBuffer> buffer, |
| 251 unsigned int texture, | 241 unsigned int texture, |
| 252 unsigned int image, | 242 unsigned int image, |
| 253 const gfx::Rect& rect) | 243 const gfx::Rect& rect) |
| 254 : buffer_queue(buffer_queue), | 244 : buffer_queue(buffer_queue), |
| 255 buffer(buffer.release()), | 245 buffer(buffer.release()), |
| 256 texture(texture), | 246 texture(texture), |
| 257 image(image), | 247 image(image), |
| 258 damage(rect) {} | 248 damage(rect) {} |
| 259 | 249 |
| 260 BufferQueue::AllocatedSurface::~AllocatedSurface() { | 250 BufferQueue::AllocatedSurface::~AllocatedSurface() { |
| 261 buffer_queue->FreeSurfaceResources(this); | 251 buffer_queue->FreeSurfaceResources(this); |
| 262 } | 252 } |
| 263 | 253 |
| 264 } // namespace display_compositor | 254 } // namespace display_compositor |
| OLD | NEW |