// Copyright 2011 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. #include "cc/texture_layer_impl.h" #include "base/stringprintf.h" #include "cc/layer_tree_impl.h" #include "cc/quad_sink.h" #include "cc/renderer.h" #include "cc/texture_draw_quad.h" namespace cc { TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* treeImpl, int id, bool usesMailbox) : LayerImpl(treeImpl, id) , m_textureId(0) , m_externalTextureResource(0) , m_premultipliedAlpha(true) , m_flipped(true) , m_uvTopLeft(0.f, 0.f) , m_uvBottomRight(1.f, 1.f) , m_usesMailbox(usesMailbox) , m_ownMailbox(false) { m_vertexOpacity[0] = 1.0f; m_vertexOpacity[1] = 1.0f; m_vertexOpacity[2] = 1.0f; m_vertexOpacity[3] = 1.0f; } TextureLayerImpl::~TextureLayerImpl() { freeTextureMailbox(); } void TextureLayerImpl::setTextureMailbox(const TextureMailbox& mailbox) { DCHECK(m_usesMailbox); DCHECK(mailbox.IsEmpty() || !mailbox.Equals(m_textureMailbox)); freeTextureMailbox(); m_textureMailbox = mailbox; m_ownMailbox = true; } scoped_ptr TextureLayerImpl::CreateLayerImpl(LayerTreeImpl* treeImpl) { return TextureLayerImpl::Create(treeImpl, id(), m_usesMailbox).PassAs(); } void TextureLayerImpl::PushPropertiesTo(LayerImpl* layer) { LayerImpl::PushPropertiesTo(layer); TextureLayerImpl* textureLayer = static_cast(layer); textureLayer->setFlipped(m_flipped); textureLayer->setUVTopLeft(m_uvTopLeft); textureLayer->setUVBottomRight(m_uvBottomRight); textureLayer->setVertexOpacity(m_vertexOpacity); textureLayer->setPremultipliedAlpha(m_premultipliedAlpha); if (m_usesMailbox && m_ownMailbox) { textureLayer->setTextureMailbox(m_textureMailbox); m_ownMailbox = false; } else { textureLayer->setTextureId(m_textureId); } } void TextureLayerImpl::WillDraw(ResourceProvider* resourceProvider) { if (m_usesMailbox || !m_textureId) return; DCHECK(!m_externalTextureResource); m_externalTextureResource = resourceProvider->CreateResourceFromExternalTexture(m_textureId); } void TextureLayerImpl::AppendQuads(QuadSink* quadSink, AppendQuadsData* appendQuadsData) { if (!m_externalTextureResource) return; SharedQuadState* sharedQuadState = quadSink->useSharedQuadState(CreateSharedQuadState()); AppendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); gfx::Rect quadRect(content_bounds()); gfx::Rect opaqueRect(contents_opaque() ? quadRect : gfx::Rect()); scoped_ptr quad = TextureDrawQuad::Create(); quad->SetNew(sharedQuadState, quadRect, opaqueRect, m_externalTextureResource, m_premultipliedAlpha, m_uvTopLeft, m_uvBottomRight, m_vertexOpacity, m_flipped); // Perform explicit clipping on a quad to avoid setting a scissor later. if (sharedQuadState->is_clipped && quad->PerformClipping()) sharedQuadState->is_clipped = false; if (!quad->rect.IsEmpty()) quadSink->append(quad.PassAs(), appendQuadsData); } void TextureLayerImpl::DidDraw(ResourceProvider* resourceProvider) { if (m_usesMailbox || !m_externalTextureResource) return; // FIXME: the following assert will not be true when sending resources to a // parent compositor. A synchronization scheme (double-buffering or // pipelining of updates) for the client will need to exist to solve this. DCHECK(!resourceProvider->InUseByConsumer(m_externalTextureResource)); resourceProvider->DeleteResource(m_externalTextureResource); m_externalTextureResource = 0; } void TextureLayerImpl::DumpLayerProperties(std::string* str, int indent) const { str->append(IndentString(indent)); base::StringAppendF(str, "texture layer texture id: %u premultiplied: %d\n", m_textureId, m_premultipliedAlpha); LayerImpl::DumpLayerProperties(str, indent); } void TextureLayerImpl::setVertexOpacity(const float vertexOpacity[4]) { m_vertexOpacity[0] = vertexOpacity[0]; m_vertexOpacity[1] = vertexOpacity[1]; m_vertexOpacity[2] = vertexOpacity[2]; m_vertexOpacity[3] = vertexOpacity[3]; } void TextureLayerImpl::DidLoseOutputSurface() { m_textureId = 0; m_externalTextureResource = 0; } const char* TextureLayerImpl::LayerTypeAsString() const { return "TextureLayer"; } bool TextureLayerImpl::CanClipSelf() const { return true; } void TextureLayerImpl::DidBecomeActive() { if (!m_ownMailbox) return; DCHECK(!m_externalTextureResource); ResourceProvider* resourceProvider = layer_tree_impl()->resource_provider(); if (!m_textureMailbox.IsEmpty()) m_externalTextureResource = resourceProvider->CreateResourceFromTextureMailbox(m_textureMailbox); m_ownMailbox = false; } void TextureLayerImpl::freeTextureMailbox() { if (!m_usesMailbox) return; if (m_ownMailbox) { DCHECK(!m_externalTextureResource); m_textureMailbox.RunReleaseCallback(m_textureMailbox.sync_point()); } else if (m_externalTextureResource) { DCHECK(!m_ownMailbox); ResourceProvider* resourceProvider = layer_tree_impl()->resource_provider(); resourceProvider->DeleteResource(m_externalTextureResource); m_externalTextureResource = 0; } } } // namespace cc