11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/compositor/buffer_queue.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/compositor/image_transport_factory.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/common/gpu/client/context_provider_command_buffer.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/common/gpu/client/gl_helper.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gpu/GLES2/gl2extchromium.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gpu/command_buffer/client/gles2_interface.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/core/SkRect.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/core/SkRegion.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace content { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider, 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int internalformat) 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : context_provider_(context_provider), 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fbo_(0), 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci allocated_count_(0), 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internalformat_(internalformat) { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBufferQueue::~BufferQueue() { 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FreeAllSurfaces(); 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (fbo_) 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->DeleteFramebuffers(1, &fbo_); 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool BufferQueue::Initialize() { 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->GenFramebuffers(1, &fbo_); 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return fbo_ != 0; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::BindFramebuffer() { 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!current_surface_.texture) { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_ = GetNextSurface(); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->FramebufferTexture2D(GL_FRAMEBUFFER, 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GL_COLOR_ATTACHMENT0, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GL_TEXTURE_2D, 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_.texture, 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0); 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::CopyBufferDamage(int texture, 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int source_texture, 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& new_damage, 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& old_damage) { 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ImageTransportFactory::GetInstance()->GetGLHelper()->CopySubBufferDamage( 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci texture, 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci source_texture, 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SkRegion(SkIRect::MakeXYWH(new_damage.x(), 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_damage.y(), 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_damage.width(), 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_damage.height())), 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SkRegion(SkIRect::MakeXYWH(old_damage.x(), 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci old_damage.y(), 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci old_damage.width(), 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci old_damage.height()))); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < available_surfaces_.size(); i++) 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci available_surfaces_[i].damage.Union(damage); 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::deque<AllocatedSurface>::iterator it = 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_flight_surfaces_.begin(); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it != in_flight_surfaces_.end(); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it) 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->damage.Union(damage); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::SwapBuffers(const gfx::Rect& damage) { 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (damage != gfx::Rect(size_)) { 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We must have a frame available to copy from. 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!in_flight_surfaces_.empty()); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CopyBufferDamage(current_surface_.texture, 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_flight_surfaces_.back().texture, 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci damage, 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_.damage); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateBufferDamage(damage); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_.damage = gfx::Rect(); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_flight_surfaces_.push_back(current_surface_); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_.texture = 0; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_surface_.image = 0; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::Reshape(const gfx::Size& size, float scale_factor) { 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!current_surface_.texture); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (size == size_) 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_ = size; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO: add stencil buffer when needed. 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->FramebufferTexture2D( 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FreeAllSurfaces(); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::PageFlipComplete() { 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (in_flight_surfaces_.size() > 1) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci available_surfaces_.push_back(in_flight_surfaces_.front()); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_flight_surfaces_.pop_front(); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::FreeAllSurfaces() { 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FreeSurface(¤t_surface_); 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while (!in_flight_surfaces_.empty()) { 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FreeSurface(&in_flight_surfaces_.front()); 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in_flight_surfaces_.pop_front(); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < available_surfaces_.size(); i++) 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FreeSurface(&available_surfaces_[i]); 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci available_surfaces_.clear(); 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BufferQueue::FreeSurface(AllocatedSurface* surface) { 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (surface->texture) { 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->BindTexture(GL_TEXTURE_2D, surface->texture); 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, surface->image); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->DeleteTextures(1, &surface->texture); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->DestroyImageCHROMIUM(surface->image); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci surface->image = 0; 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci surface->texture = 0; 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci allocated_count_--; 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBufferQueue::AllocatedSurface BufferQueue::GetNextSurface() { 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!available_surfaces_.empty()) { 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AllocatedSurface surface = available_surfaces_.back(); 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci available_surfaces_.pop_back(); 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return surface; 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int texture = 0; 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->GenTextures(1, &texture); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!texture) 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AllocatedSurface(); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We don't want to allow anything more than triple buffering. 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_LT(allocated_count_, 4U); 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int id = gl->CreateImageCHROMIUM( 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_.width(), 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_.height(), 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internalformat_, 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GL_IMAGE_SCANOUT_CHROMIUM); 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!id) { 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOG(ERROR) << "Failed to allocate backing CreateImageCHROMIUM surface"; 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->DeleteTextures(1, &texture); 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AllocatedSurface(); 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci allocated_count_++; 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->BindTexture(GL_TEXTURE_2D, texture); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, id); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AllocatedSurface(texture, id, gfx::Rect(size_)); 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace content 175