blob: f15aa2007119afd796a20117a4d67765fae8d818 [file] [log] [blame]
// 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 <GLES2/gl2extchromium.h>
#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<mojo::GLTexture> texture,
uint32_t resource_id)
: texture_(texture.Pass()), resource_id_(resource_id) {
}
TextureCache::TextureInfo::~TextureInfo() {
}
TextureCache::TextureCache(base::WeakPtr<mojo::GLContext> 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::TextureInfo> 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<TextureInfo> 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<TextureInfo>();
}
// We couldn't find an existing texture to reuse, create a new one!
scoped_ptr<mojo::GLTexture> new_texture(
new mojo::GLTexture(gl_context_, requested_size));
next_resource_id_++;
scoped_ptr<TextureInfo> texture_info(
new TextureInfo(new_texture.Pass(), next_resource_id_));
return texture_info.Pass();
}
void TextureCache::NotifyPendingResourceReturn(
uint32_t resource_id,
scoped_ptr<mojo::GLTexture> texture) {
resource_to_texture_map_[resource_id] = texture.Pass();
}
// mojo::ResourceReturner
void TextureCache::ReturnResources(
mojo::Array<mojo::ReturnedResourcePtr> 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