CCTiledLayerImpl.cpp [plain text]
#include "config.h"
#if USE(ACCELERATED_COMPOSITING)
#include "cc/CCTiledLayerImpl.h"
#include "LayerRendererChromium.h"
#include "cc/CCCheckerboardDrawQuad.h"
#include "cc/CCDebugBorderDrawQuad.h"
#include "cc/CCQuadCuller.h"
#include "cc/CCSolidColorDrawQuad.h"
#include "cc/CCTileDrawQuad.h"
#include <wtf/text/WTFString.h>
using namespace std;
namespace WebCore {
static const int debugTileBorderWidth = 1;
static const int debugTileBorderAlpha = 100;
static const int debugTileBorderColorRed = 80;
static const int debugTileBorderColorGreen = 200;
static const int debugTileBorderColorBlue = 200;
static const int debugTileBorderMissingTileColorRed = 255;
static const int debugTileBorderMissingTileColorGreen = 0;
static const int debugTileBorderMissingTileColorBlue = 0;
class ManagedTexture;
class DrawableTile : public CCLayerTilingData::Tile {
WTF_MAKE_NONCOPYABLE(DrawableTile);
public:
static PassOwnPtr<DrawableTile> create() { return adoptPtr(new DrawableTile()); }
Platform3DObject textureId() const { return m_textureId; }
void setTextureId(Platform3DObject textureId) { m_textureId = textureId; }
private:
DrawableTile() : m_textureId(0) { }
Platform3DObject m_textureId;
};
CCTiledLayerImpl::CCTiledLayerImpl(int id)
: CCLayerImpl(id)
, m_skipsDraw(true)
, m_contentsSwizzled(false)
{
}
CCTiledLayerImpl::~CCTiledLayerImpl()
{
}
void CCTiledLayerImpl::bindContentsTexture(LayerRendererChromium* layerRenderer)
{
ASSERT(m_tiler);
ASSERT(m_tiler->numTilesX() == 1);
ASSERT(m_tiler->numTilesY() == 1);
DrawableTile* tile = tileAt(0, 0);
Platform3DObject textureId = tile ? tile->textureId() : 0;
ASSERT(textureId);
layerRenderer->context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
}
void CCTiledLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
{
CCLayerImpl::dumpLayerProperties(ts, indent);
writeIndent(ts, indent);
ts << "skipsDraw: " << (!m_tiler || m_skipsDraw) << "\n";
}
bool CCTiledLayerImpl::hasTileAt(int i, int j) const
{
return m_tiler->tileAt(i, j);
}
bool CCTiledLayerImpl::hasTextureIdForTileAt(int i, int j) const
{
return hasTileAt(i, j) && tileAt(i, j)->textureId();
}
DrawableTile* CCTiledLayerImpl::tileAt(int i, int j) const
{
return static_cast<DrawableTile*>(m_tiler->tileAt(i, j));
}
DrawableTile* CCTiledLayerImpl::createTile(int i, int j)
{
OwnPtr<DrawableTile> tile(DrawableTile::create());
DrawableTile* addedTile = tile.get();
m_tiler->addTile(tile.release(), i, j);
return addedTile;
}
TransformationMatrix CCTiledLayerImpl::quadTransform() const
{
TransformationMatrix transform = drawTransform();
if (contentBounds().isEmpty())
return transform;
transform.scaleNonUniform(bounds().width() / static_cast<double>(contentBounds().width()),
bounds().height() / static_cast<double>(contentBounds().height()));
transform.translate(-contentBounds().width() / 2.0, -contentBounds().height() / 2.0);
return transform;
}
void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool& hadMissingTiles)
{
const IntRect& layerRect = visibleLayerRect();
if (!m_tiler || m_tiler->hasEmptyBounds() || layerRect.isEmpty())
return;
int left, top, right, bottom;
m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
if (hasDebugBorders()) {
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
DrawableTile* tile = tileAt(i, j);
IntRect tileRect = m_tiler->tileBounds(i, j);
Color borderColor;
if (m_skipsDraw || !tile || !tile->textureId())
borderColor = Color(debugTileBorderMissingTileColorRed, debugTileBorderMissingTileColorGreen, debugTileBorderMissingTileColorBlue, debugTileBorderAlpha);
else
borderColor = Color(debugTileBorderColorRed, debugTileBorderColorGreen, debugTileBorderColorBlue, debugTileBorderAlpha);
quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState, tileRect, borderColor, debugTileBorderWidth));
}
}
}
if (m_skipsDraw)
return;
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
DrawableTile* tile = tileAt(i, j);
IntRect tileRect = m_tiler->tileBounds(i, j);
IntRect displayRect = tileRect;
tileRect.intersect(layerRect);
if (tileRect.isEmpty())
continue;
if (!tile || !tile->textureId()) {
if (drawCheckerboardForMissingTiles())
hadMissingTiles |= quadList.append(CCCheckerboardDrawQuad::create(sharedQuadState, tileRect));
else
hadMissingTiles |= quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
continue;
}
IntRect tileOpaqueRect = tile->opaqueRect();
tileOpaqueRect.intersect(layerRect);
IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minXMinYCorner();
IntPoint textureOffset = m_tiler->textureOffset(i, j) + displayOffset;
float tileWidth = static_cast<float>(m_tiler->tileSize().width());
float tileHeight = static_cast<float>(m_tiler->tileSize().height());
IntSize textureSize(tileWidth, tileHeight);
bool useAA = m_tiler->hasBorderTexels() && !sharedQuadState->isLayerAxisAlignedIntRect();
bool leftEdgeAA = !i && useAA;
bool topEdgeAA = !j && useAA;
bool rightEdgeAA = i == m_tiler->numTilesX() - 1 && useAA;
bool bottomEdgeAA = j == m_tiler->numTilesY() - 1 && useAA;
const GC3Dint textureFilter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
quadList.append(CCTileDrawQuad::create(sharedQuadState, tileRect, tileOpaqueRect, tile->textureId(), textureOffset, textureSize, textureFilter, contentsSwizzled(), leftEdgeAA, topEdgeAA, rightEdgeAA, bottomEdgeAA));
}
}
}
void CCTiledLayerImpl::setTilingData(const CCLayerTilingData& tiler)
{
if (m_tiler)
m_tiler->reset();
else
m_tiler = CCLayerTilingData::create(tiler.tileSize(), tiler.hasBorderTexels() ? CCLayerTilingData::HasBorderTexels : CCLayerTilingData::NoBorderTexels);
*m_tiler = tiler;
}
void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject textureId, const IntRect& opaqueRect)
{
DrawableTile* tile = tileAt(i, j);
if (!tile)
tile = createTile(i, j);
tile->setTextureId(textureId);
tile->setOpaqueRect(opaqueRect);
}
Region CCTiledLayerImpl::visibleContentOpaqueRegion() const
{
if (m_skipsDraw)
return Region();
if (opaque())
return visibleLayerRect();
return m_tiler->opaqueRegionInLayerRect(visibleLayerRect());
}
void CCTiledLayerImpl::didLoseContext()
{
m_tiler->reset();
}
}
#endif // USE(ACCELERATED_COMPOSITING)