// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #endif #include #include "mojo/gpu/gl_context.h" #include "mojo/gpu/gl_texture.h" #include "mojo/gpu/texture_cache.h" #include "mojo/services/geometry/public/interfaces/geometry.mojom.h" namespace mojo { TextureCache::TextureInfo::TextureInfo() : texture_(), resource_id_(0u) { } TextureCache::TextureInfo::TextureInfo(scoped_ptr texture, uint32_t resource_id) : texture_(texture.Pass()), resource_id_(resource_id) { } TextureCache::TextureInfo::~TextureInfo() { } TextureCache::TextureCache(base::WeakPtr gl_context, mojo::ResourceReturnerPtr* out_resource_returner) : gl_context_(gl_context), returner_binding_(this), next_resource_id_(0u) { if (out_resource_returner) { returner_binding_.Bind(GetProxy(out_resource_returner)); } } TextureCache::~TextureCache() { } scoped_ptr TextureCache::GetTexture( const mojo::Size& requested_size) { // Sift through our available textures to find one the correct size. If one // exists use it. As we find textures of the wrong size, clean them up. while (!available_textures_.empty()) { // Get the next available texture's resource id. uint32_t available_resource_id = available_textures_.front(); available_textures_.pop_front(); // Get the texture information from the texture map. auto texture_iterator = resource_to_texture_map_.find(available_resource_id); mojo::Size texture_size = texture_iterator->second->size(); scoped_ptr texture_info(new TextureInfo( texture_iterator->second.Pass(), texture_iterator->first)); resource_to_texture_map_.erase(texture_iterator); // Get the sync point from the sync point map. auto sync_point_iterator = resource_to_sync_point_map_.find(available_resource_id); int sync_point = sync_point_iterator->second; resource_to_sync_point_map_.erase(sync_point_iterator); // If the texture is the right size, use it. if (texture_size.width == requested_size.width && texture_size.height == requested_size.height) { glWaitSyncPointCHROMIUM(sync_point); return texture_info.Pass(); } } // If our context is invalid return an empty scoped ptr. if (!gl_context_) { return scoped_ptr(); } // We couldn't find an existing texture to reuse, create a new one! scoped_ptr new_texture( new mojo::GLTexture(gl_context_, requested_size)); next_resource_id_++; scoped_ptr texture_info( new TextureInfo(new_texture.Pass(), next_resource_id_)); return texture_info.Pass(); } void TextureCache::NotifyPendingResourceReturn( uint32_t resource_id, scoped_ptr texture) { resource_to_texture_map_[resource_id] = texture.Pass(); } // mojo::ResourceReturner void TextureCache::ReturnResources( mojo::Array resources) { if (!gl_context_) { return; } gl_context_->MakeCurrent(); for (size_t i = 0u; i < resources.size(); ++i) { mojo::ReturnedResourcePtr resource = resources[i].Pass(); DCHECK_EQ(1, resource->count); auto it = resource_to_texture_map_.find(resource->id); // Ignore the returned resource if we haven't been notified of its pending // return. if (it != resource_to_texture_map_.end()) { available_textures_.push_back(resource->id); resource_to_sync_point_map_[resource->id] = resource->sync_point; } } } } // namespace mojo