diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium')
44 files changed, 1617 insertions, 694 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp index ad961aa..4cb119a 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp @@ -56,7 +56,7 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium() layerRendererContext()->deleteTexture(m_textureId); } -void Canvas2DLayerChromium::updateContentsIfDirty() +void Canvas2DLayerChromium::updateCompositorResources() { if (!m_contentsDirty || !m_drawingBuffer) return; diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h index a14cb98..81b118c 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h @@ -46,7 +46,7 @@ public: static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner); virtual ~Canvas2DLayerChromium(); virtual bool drawsContent() const { return true; } - virtual void updateContentsIfDirty(); + virtual void updateCompositorResources(); void setTextureChanged(); unsigned textureId() const; @@ -55,8 +55,6 @@ public: private: explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner); DrawingBuffer* m_drawingBuffer; - - static unsigned m_shaderProgramId; }; } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp index 0264868..f306207 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp @@ -40,8 +40,6 @@ namespace WebCore { -unsigned CanvasLayerChromium::m_shaderProgramId = 0; - CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) , m_textureChanged(true) @@ -54,22 +52,18 @@ CanvasLayerChromium::~CanvasLayerChromium() { } -void CanvasLayerChromium::draw() +PassRefPtr<CCLayerImpl> CanvasLayerChromium::createCCLayerImpl() { - ASSERT(layerRenderer()); - const CanvasLayerChromium::Program* program = layerRenderer()->canvasLayerProgram(); - ASSERT(program && program->initialized()); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); - GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; - GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); - layerRenderer()->useShader(program->program()); - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); + return CCCanvasLayerImpl::create(this); +} + +void CanvasLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer); + canvasLayer->setTextureId(m_textureId); + canvasLayer->setPremultipliedAlpha(m_premultipliedAlpha); } } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h index ed3a06f..cb2ccc9 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h @@ -43,9 +43,9 @@ class CanvasLayerChromium : public LayerChromium { public: virtual ~CanvasLayerChromium(); - virtual void draw(); + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + virtual void pushPropertiesTo(CCLayerImpl*); protected: explicit CanvasLayerChromium(GraphicsLayerChromium* owner); @@ -55,9 +55,6 @@ protected: bool m_textureChanged; unsigned m_textureId; bool m_premultipliedAlpha; - -private: - static unsigned m_shaderProgramId; }; } diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 78f93d5..4ea9c92 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -66,7 +66,7 @@ void ContentLayerChromium::cleanupResources() m_contentsTexture.clear(); } -bool ContentLayerChromium::requiresClippedUpdateRect() const +bool ContentLayerChromium::requiresClippedUpdateRect() { // To avoid allocating excessively large textures, switch into "large layer mode" if // one of the layer's dimensions is larger than 2000 pixels or the size of @@ -77,7 +77,7 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const || !layerRenderer()->checkTextureSize(bounds())); } -void ContentLayerChromium::updateContentsIfDirty() +void ContentLayerChromium::paintContentsIfDirty() { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); if (!backing || backing->paintingGoesToWindow()) @@ -93,34 +93,25 @@ void ContentLayerChromium::updateContentsIfDirty() // FIXME: Remove this test when tiled layers are implemented. if (requiresClippedUpdateRect()) { - // A layer with 3D transforms could require an arbitrarily large number - // of texels to be repainted, so ignore these layers until tiling is - // implemented. - if (!ccLayerImpl()->drawTransform().isIdentityOrTranslation()) { - m_skipsDraw = true; - return; - } - // Calculate the region of this layer that is currently visible. const IntRect clipRect = ccLayerImpl()->targetRenderSurface()->contentRect(); TransformationMatrix layerOriginTransform = ccLayerImpl()->drawTransform(); layerOriginTransform.translate3d(-0.5 * bounds().width(), -0.5 * bounds().height(), 0); - // For now we apply the large layer treatment only for layers that are either untransformed - // or are purely translated. Their matrix is expected to be invertible. - ASSERT(layerOriginTransform.isInvertible()); - + // We compute the visible portion of the layer by back-mapping the current RenderSurface + // content area to the layer. To do that, we invert the drawing matrix of the layer + // and project the content area rectangle to it. If the layer transform is not invertible + // then we skip rendering the layer. + if (!layerOriginTransform.isInvertible()) { + m_skipsDraw = true; + return; + } TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); - IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); + FloatQuad mappedClipToLayer = targetToLayerMatrix.projectQuad(FloatRect(clipRect)); + IntRect visibleRectInLayerCoords = mappedClipToLayer.enclosingBoundingBox(); visibleRectInLayerCoords.intersect(IntRect(0, 0, bounds().width(), bounds().height())); - // For normal layers, the center of the texture corresponds with the center of the layer. - // In large layers the center of the texture is the center of the visible region so we have - // to keep track of the offset in order to render correctly. - IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords); - m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center(); - // If this is still too large to render, then skip the layer completely. if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) { m_skipsDraw = true; @@ -256,9 +247,14 @@ void ContentLayerChromium::draw() GLC(context, context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); if (requiresClippedUpdateRect()) { - float m43 = ccLayerImpl()->drawTransform().m43(); - TransformationMatrix transform; - transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43); + // Compute the offset between the layer's center point and the center of the visible portion + // of the layer. + FloatPoint visibleRectCenterOffset = FloatRect(m_visibleRectInLayerCoords).center(); + visibleRectCenterOffset.move(-0.5 * bounds().width(), -0.5 * bounds().height()); + + TransformationMatrix transform = ccLayerImpl()->drawTransform(); + transform.translate(visibleRectCenterOffset.x(), visibleRectCenterOffset.y()); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), transform, m_visibleRectInLayerCoords.width(), m_visibleRectInLayerCoords.height(), ccLayerImpl()->drawOpacity(), @@ -273,6 +269,11 @@ void ContentLayerChromium::draw() unreserveContentsTexture(); } +void ContentLayerChromium::updateCompositorResources() +{ + updateTextureIfNeeded(); +} + void ContentLayerChromium::unreserveContentsTexture() { if (!m_skipsDraw && m_contentsTexture) @@ -281,8 +282,6 @@ void ContentLayerChromium::unreserveContentsTexture() void ContentLayerChromium::bindContentsTexture() { - updateTextureIfNeeded(); - if (!m_skipsDraw && m_contentsTexture) m_contentsTexture->bindTexture(); } diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 6f070c2..cf296ab 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -50,7 +50,8 @@ public: virtual ~ContentLayerChromium(); - virtual void updateContentsIfDirty(); + virtual void paintContentsIfDirty(); + virtual void updateCompositorResources(); virtual void unreserveContentsTexture(); virtual void bindContentsTexture(); @@ -63,7 +64,7 @@ protected: explicit ContentLayerChromium(GraphicsLayerChromium* owner); virtual void cleanupResources(); - bool requiresClippedUpdateRect() const; + bool requiresClippedUpdateRect(); void resizeUploadBuffer(const IntSize&); virtual const char* layerTypeAsString() const { return "ContentLayer"; } @@ -82,7 +83,6 @@ private: PlatformCanvas m_canvas; IntRect m_visibleRectInLayerCoords; - FloatPoint m_layerCenterInSurfaceCoords; }; } diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index 227fbe4..b442d53 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -29,7 +29,7 @@ #import "config.h" #import "CrossProcessFontLoading.h" -#import "../graphics/cocoa/FontPlatformData.h" +#import "../graphics/FontPlatformData.h" #import "PlatformBridge.h" #import <AppKit/NSFont.h> #import <wtf/HashMap.h> diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp index d956841..e559edb 100644 --- a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp @@ -46,10 +46,6 @@ namespace WebCore { -#if ENABLE(SKIA_GPU) -extern GrContext* GetGlobalGrContext(); -#endif - struct DrawingBufferInternal { unsigned offscreenColorTexture; #if USE(ACCELERATED_COMPOSITING) @@ -91,6 +87,9 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, , m_multisampleFBO(0) , m_multisampleColorBuffer(0) , m_internal(new DrawingBufferInternal) +#if ENABLE(SKIA_GPU) + , m_grContext(0) +#endif { if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) { m_context.clear(); @@ -137,7 +136,8 @@ void DrawingBuffer::publishToPlatformLayer() // would insert a fence into the child command stream that the compositor could wait for. m_context->makeContextCurrent(); #if ENABLE(SKIA_GPU) - GetGlobalGrContext()->flush(false); + if (m_grContext) + m_grContext->flush(0); #endif static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture); m_context->flush(); @@ -166,4 +166,13 @@ Platform3DObject DrawingBuffer::platformColorBuffer() const return m_colorBuffer; } +#if ENABLE(SKIA_GPU) +void DrawingBuffer::setGrContext(GrContext* context) +{ + // We just take a ptr without referencing it, as we require that we never outlive + // the SharedGraphicsContext3D object that is giving us the context. + m_grContext = context; +} +#endif + } diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index bbe6d62..598ae86 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -153,7 +153,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic(), - fontDescription.orientation()); + fontDescription.orientation(), + fontDescription.textOrientation()); tf->unref(); return result; } diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index e57a84c..3c254dc 100644 --- a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -196,7 +196,7 @@ class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter { // left of m_point. We express it this way so that if we're using the Skia // drawing path we can use floating-point positioning, even though we have // to use integer positioning in the GDI path. - bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, int startAdvance) const; + bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const; private: virtual IntRect estimateTextBounds(); @@ -256,11 +256,11 @@ IntRect TransparencyAwareGlyphPainter::estimateTextBounds() bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, - int startAdvance) const + float startAdvance) const { if (!m_useGDI) { SkPoint origin = m_point; - origin.fX += startAdvance; + origin.fX += SkFloatToScalar(startAdvance); return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(), numGlyphs, glyphs, advances, 0, &origin); } @@ -400,17 +400,25 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, Vector<WORD, kMaxBufferLength> glyphs; Vector<int, kMaxBufferLength> advances; int glyphIndex = 0; // The starting glyph of the current chunk. - int curAdvance = 0; // How far from the left the current chunk is. + + // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position + // of each glyph in floating point units and rounds to integer advances at the last possible moment. + + float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph. + int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered. while (glyphIndex < numGlyphs) { // How many chars will be in this chunk? int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex); glyphs.resize(curLen); advances.resize(curLen); - int curWidth = 0; + float currentWidth = 0; for (int i = 0; i < curLen; ++i, ++glyphIndex) { glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex); - advances[i] = static_cast<int>(glyphBuffer.advanceAt(from + glyphIndex)); + horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex); + advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded; + lastHorizontalOffsetRounded += advances[i]; + currentWidth += glyphBuffer.advanceAt(from + glyphIndex); // Bug 26088 - very large positive or negative runs can fail to // render so we clamp the size here. In the specs, negative @@ -420,15 +428,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, // -32830, so we give ourselves a little breathing room. const int maxNegativeRun = -32768; const int maxPositiveRun = 32768; - if ((curWidth + advances[i] < maxNegativeRun) || (curWidth + advances[i] > maxPositiveRun)) + if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) advances[i] = 0; - curWidth += advances[i]; } // Actually draw the glyphs (with retry on failure). bool success = false; for (int executions = 0; executions < 2; ++executions) { - success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], curAdvance); + success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth); if (!success && executions == 0) { // Ask the browser to load the font for us and retry. PlatformBridge::ensureFontLoaded(font->platformData().hfont()); @@ -439,8 +446,6 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, if (!success) LOG_ERROR("Unable to draw the glyphs after second attempt"); - - curAdvance += curWidth; } } @@ -509,8 +514,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, // Uniscribe counts the coordinates from the upper left, while WebKit uses // the baseline, so we have to subtract off the ascent. - state.draw(graphicsContext, hdc, static_cast<int>(point.x()), - static_cast<int>(point.y() - fontMetrics().ascent()), from, to); + state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to); context->canvas()->endPlatformPaint(); } diff --git a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp index 823dbc9..3c4a494 100644 --- a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -98,7 +98,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, SkPoint* vPosBegin = storage2.get(); SkPoint* vPosEnd = storage3.get(); - bool isVertical = font->orientation() == Vertical; + bool isVertical = font->platformData().orientation() == Vertical; for (int i = 0; i < numGlyphs; i++) { SkScalar myWidth = SkFloatToScalar(adv[i].width()); pos[i].set(x, y); diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index b6ebb2e..84edebc 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -71,6 +71,7 @@ public: float size() const { return m_size; } FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. unsigned hash() const { @@ -105,7 +106,7 @@ private: HFONT hfont() const { return m_hfont; } unsigned hash() const { - return WTF::StringHasher::createBlobHash<sizeof(HFONT)>(&m_hfont); + return StringHasher::hashMemory<sizeof(HFONT)>(&m_hfont); } bool operator==(const RefCountedHFONT& other) const diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 6f9009f..c3edfac 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -76,13 +76,14 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) , m_orientation(src.m_orientation) + , m_textOrientation(src.m_textOrientation) , m_style(src.m_style) , m_harfbuzzFace(src.m_harfbuzzFace) { SkSafeRef(m_typeface); } -FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation) +FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) : m_typeface(tf) , m_family(family) , m_textSize(textSize) @@ -90,6 +91,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float tex , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) , m_orientation(orientation) + , m_textOrientation(textOrientation) { SkSafeRef(m_typeface); querySystemForRenderStyle(); @@ -102,6 +104,8 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) , m_emSizeInFontUnits(src.m_emSizeInFontUnits) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) + , m_orientation(src.m_orientation) + , m_textOrientation(src.m_textOrientation) , m_harfbuzzFace(src.m_harfbuzzFace) { SkSafeRef(m_typeface); @@ -134,6 +138,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) m_fakeItalic = src.m_fakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; m_orientation = src.m_orientation; + m_textOrientation = src.m_textOrientation; m_style = src.m_style; m_emSizeInFontUnits = src.m_emSizeInFontUnits; @@ -199,13 +204,14 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const && m_fakeBold == a.m_fakeBold && m_fakeItalic == a.m_fakeItalic && m_orientation == a.m_orientation + && m_textOrientation == a.m_textOrientation && m_style == a.m_style; } unsigned FontPlatformData::hash() const { unsigned h = SkTypeface::UniqueID(m_typeface); - h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic)); + h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic)); // This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing // rules. Memcpy is generally optimized enough so that performance doesn't diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index d9ebb61..541aa86 100644 --- a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -33,6 +33,7 @@ #include "FontOrientation.h" #include "FontRenderStyle.h" +#include "TextOrientation.h" #include <wtf/Forward.h> #include <wtf/RefPtr.h> #include <wtf/text/CString.h> @@ -66,6 +67,8 @@ public: , m_emSizeInFontUnits(0) , m_fakeBold(false) , m_fakeItalic(false) + , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData() @@ -75,6 +78,7 @@ public: , m_fakeBold(false) , m_fakeItalic(false) , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData(float textSize, bool fakeBold, bool fakeItalic) @@ -84,10 +88,11 @@ public: , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) , m_orientation(Horizontal) + , m_textOrientation(TextOrientationVerticalRight) { } FontPlatformData(const FontPlatformData&); - FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal); + FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight); FontPlatformData(const FontPlatformData& src, float textSize); ~FontPlatformData(); @@ -113,7 +118,8 @@ public: int emSizeInFontUnits() const; FontOrientation orientation() const { return m_orientation; } - + void setOrientation(FontOrientation orientation) { m_orientation = orientation; } + bool operator==(const FontPlatformData&) const; FontPlatformData& operator=(const FontPlatformData&); bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); } @@ -161,6 +167,7 @@ private: bool m_fakeBold; bool m_fakeItalic; FontOrientation m_orientation; + TextOrientation m_textOrientation; FontRenderStyle m_style; mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace; diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 2ff6b8b..cc5a060 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -62,29 +62,51 @@ typedef void (GLAPIENTRY *TESSCB)(); typedef WTF::Vector<float> FloatVector; typedef WTF::Vector<double> DoubleVector; +struct PathAndTransform { + PathAndTransform(const Path& p, const AffineTransform& t) + : path(p) + , transform(t) + { + } + Path path; + AffineTransform transform; +}; + struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) + , m_shadowColor(0, 0, 0, 0) , m_alpha(1.0f) , m_compositeOp(CompositeSourceOver) - , m_clippingEnabled(false) + , m_numClippingPaths(0) + , m_shadowOffset(0, 0) + , m_shadowBlur(0) + , m_shadowsIgnoreTransforms(false) { } State(const State& other) : m_fillColor(other.m_fillColor) + , m_shadowColor(other.m_shadowColor) , m_alpha(other.m_alpha) , m_compositeOp(other.m_compositeOp) , m_ctm(other.m_ctm) , m_clippingPaths() // Don't copy; clipping paths are tracked per-state. - , m_clippingEnabled(other.m_clippingEnabled) + , m_numClippingPaths(other.m_numClippingPaths) + , m_shadowOffset(other.m_shadowOffset) + , m_shadowBlur(other.m_shadowBlur) + , m_shadowsIgnoreTransforms(other.m_shadowsIgnoreTransforms) { } Color m_fillColor; + Color m_shadowColor; float m_alpha; CompositeOperator m_compositeOp; AffineTransform m_ctm; - WTF::Vector<Path> m_clippingPaths; - bool m_clippingEnabled; + WTF::Vector<PathAndTransform> m_clippingPaths; + int m_numClippingPaths; + FloatSize m_shadowOffset; + float m_shadowBlur; + bool m_shadowsIgnoreTransforms; // Helper function for applying the state's alpha value to the given input // color to produce a new output color. The logic is the same as @@ -100,7 +122,11 @@ struct GLES2Canvas::State { int a = (c.alpha() * s) >> 8; return Color(c.red(), c.green(), c.blue(), a); } - + bool shadowActive() const + { + return m_shadowColor.alpha() > 0 && (m_shadowBlur || m_shadowOffset.width() || m_shadowOffset.height()); + } + bool clippingEnabled() { return m_numClippingPaths > 0; } }; static inline FloatPoint operator*(const FloatPoint& f, float scale) @@ -193,12 +219,8 @@ void GLES2Canvas::bindFramebuffer() void GLES2Canvas::clearRect(const FloatRect& rect) { bindFramebuffer(); - if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) { - m_context->scissor(rect.x(), m_size.height() - rect.height() - rect.y(), rect.width(), rect.height()); - m_context->enable(GraphicsContext3D::SCISSOR_TEST); - m_context->clearColor(Color(RGBA32(0))); - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); - m_context->disable(GraphicsContext3D::SCISSOR_TEST); + if (m_state->m_ctm.isIdentity() && !m_state->clippingEnabled()) { + scissorClear(rect.x(), rect.y(), rect.width(), rect.height()); } else { save(); setCompositeOperation(CompositeClear); @@ -207,35 +229,66 @@ void GLES2Canvas::clearRect(const FloatRect& rect) } } +void GLES2Canvas::scissorClear(float x, float y, float width, float height) +{ + int intX = static_cast<int>(x + 0.5f); + int intY = static_cast<int>(y + 0.5f); + int intWidth = static_cast<int>(x + width + 0.5f) - intX; + int intHeight = static_cast<int>(y + height + 0.5f) - intY; + m_context->scissor(intX, m_size.height() - intHeight - intY, intWidth, intHeight); + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + m_context->disable(GraphicsContext3D::SCISSOR_TEST); +} + void GLES2Canvas::fillPath(const Path& path) { + if (m_state->shadowActive()) { + beginShadowDraw(); + fillPathInternal(path, m_state->m_shadowColor); + endShadowDraw(path.boundingRect()); + } + + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); - applyClipping(m_state->m_clippingEnabled); - fillPath(path, m_state->applyAlpha(m_state->m_fillColor)); + applyClipping(m_state->clippingEnabled()); + + fillPathInternal(path, m_state->applyAlpha(m_state->m_fillColor)); } void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { + if (m_state->shadowActive()) { + beginShadowDraw(); + fillRectInternal(rect, m_state->m_shadowColor); + endShadowDraw(rect); + } + + bindFramebuffer(); m_context->applyCompositeOperator(m_state->m_compositeOp); - applyClipping(m_state->m_clippingEnabled); - m_context->useQuadVertices(); + applyClipping(m_state->clippingEnabled()); + + fillRectInternal(rect, color); +} + +void GLES2Canvas::fillRect(const FloatRect& rect) +{ + fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); +} +void GLES2Canvas::fillRectInternal(const FloatRect& rect, const Color& color) +{ AffineTransform matrix(m_flipMatrix); matrix *= m_state->m_ctm; matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); + m_context->useQuadVertices(); m_context->useFillSolidProgram(matrix, color); - - bindFramebuffer(); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); } -void GLES2Canvas::fillRect(const FloatRect& rect) -{ - fillRect(rect, m_state->applyAlpha(m_state->m_fillColor), ColorSpaceDeviceRGB); -} - void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace) { m_state->m_fillColor = color; @@ -246,6 +299,26 @@ void GLES2Canvas::setAlpha(float alpha) m_state->m_alpha = alpha; } +void GLES2Canvas::setShadowColor(const Color& color, ColorSpace) +{ + m_state->m_shadowColor = color; +} + +void GLES2Canvas::setShadowOffset(const FloatSize& offset) +{ + m_state->m_shadowOffset = offset; +} + +void GLES2Canvas::setShadowBlur(float shadowBlur) +{ + m_state->m_shadowBlur = shadowBlur; +} + +void GLES2Canvas::setShadowsIgnoreTransforms(bool shadowsIgnoreTransforms) +{ + m_state->m_shadowsIgnoreTransforms = shadowsIgnoreTransforms; +} + void GLES2Canvas::translate(float x, float y) { m_state->m_ctm.translate(x, y); @@ -275,12 +348,12 @@ void GLES2Canvas::clipPath(const Path& path) { bindFramebuffer(); checkGLError("bindFramebuffer"); - beginStencilDraw(); + beginStencilDraw(GraphicsContext3D::INCR); // Red is used so we can see it if it ends up in the color buffer. Color red(255, 0, 0, 255); - fillPath(path, red); - m_state->m_clippingPaths.append(path); - m_state->m_clippingEnabled = true; + fillPathInternal(path, red); + m_state->m_clippingPaths.append(PathAndTransform(path, m_state->m_ctm)); + m_state->m_numClippingPaths++; } void GLES2Canvas::clipOut(const Path& path) @@ -297,53 +370,48 @@ void GLES2Canvas::save() void GLES2Canvas::restore() { ASSERT(!m_stateStack.isEmpty()); - bool hadClippingPaths = !m_state->m_clippingPaths.isEmpty(); - m_stateStack.removeLast(); - m_state = &m_stateStack.last(); - if (hadClippingPaths) { - m_context->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); - beginStencilDraw(); - StateVector::const_iterator iter; - for (iter = m_stateStack.begin(); iter < m_stateStack.end(); ++iter) { - const State& state = *iter; - const Vector<Path>& clippingPaths = state.m_clippingPaths; - Vector<Path>::const_iterator pathIter; - for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { - // Red is used so we can see it if it ends up in the color buffer. - Color red(255, 0, 0, 255); - fillPath(*pathIter, red); - } + const Vector<PathAndTransform>& clippingPaths = m_state->m_clippingPaths; + if (!clippingPaths.isEmpty()) { + beginStencilDraw(GraphicsContext3D::DECR); + WTF::Vector<PathAndTransform>::const_iterator pathIter; + for (pathIter = clippingPaths.begin(); pathIter < clippingPaths.end(); ++pathIter) { + m_state->m_ctm = pathIter->transform; + // Red is used so we can see it if it ends up in the color buffer. + Color red(255, 0, 0, 255); + fillPathInternal(pathIter->path, red); } } + m_stateStack.removeLast(); + m_state = &m_stateStack.last(); } void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(false); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); - drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); + drawTexturedQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha); } void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) { - drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->m_clippingEnabled); + drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->clippingEnabled()); } void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip) { + bindFramebuffer(); m_context->applyCompositeOperator(compositeOp); applyClipping(clip); const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); - m_context->useQuadVertices(); m_context->setActiveTexture(GraphicsContext3D::TEXTURE0); for (int y = tileIdxRect.y(); y <= tileIdxRect.maxY(); y++) { @@ -367,13 +435,18 @@ void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRe IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile); - drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); + drawTexturedQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha); } -void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +void GLES2Canvas::convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth) { + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + AffineTransform matrix(m_flipMatrix); - matrix *= transform; matrix.translate(dstRect.x(), dstRect.y()); matrix.scale(dstRect.width(), dstRect.height()); @@ -382,13 +455,79 @@ void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, texMatrix.translate(srcRect.x(), srcRect.y()); texMatrix.scale(srcRect.width(), srcRect.height()); - bindFramebuffer(); + m_context->useQuadVertices(); + m_context->useConvolutionProgram(matrix, texMatrix, kernel, kernelWidth, imageIncrement); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} +static float gauss(float x, float sigma) +{ + return exp(- (x * x) / (2.0f * sigma * sigma)); +} + +static void buildKernel(float sigma, float* kernel, int kernelWidth) +{ + float halfWidth = (kernelWidth - 1.0f) / 2.0f; + float sum = 0.0f; + for (int i = 0; i < kernelWidth; ++i) { + kernel[i] = gauss(i - halfWidth, sigma); + sum += kernel[i]; + } + // Normalize the kernel + float scale = 1.0f / sum; + for (int i = 0; i < kernelWidth; ++i) + kernel[i] *= scale; +} + +void GLES2Canvas::drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + AffineTransform texMatrix; + texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height()); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->useQuadVertices(); m_context->useTextureProgram(matrix, texMatrix, alpha); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); checkGLError("glDrawArrays"); } +void GLES2Canvas::drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha) +{ + static const float mitchellCoefficients[16] = { + 0.0f / 18.0f, 1.0f / 18.0f, 16.0f / 18.0f, 1.0f / 18.0f, + 0.0f / 18.0f, 9.0f / 18.0f, 0.0f / 18.0f, -9.0f / 18.0f, + -6.0f / 18.0f, 27.0f / 18.0f, -36.0f / 18.0f, 15.0f / 18.0f, + 7.0f / 18.0f, -21.0f / 18.0f, 21.0f / 18.0f, -7.0f / 18.0f, + }; + + AffineTransform matrix(m_flipMatrix); + matrix *= transform; + matrix.translate(dstRect.x(), dstRect.y()); + matrix.scale(dstRect.width(), dstRect.height()); + + float imageIncrement[2] = { 1.0f / textureSize.width(), 1.0f / textureSize.height() }; + + AffineTransform texMatrix; + texMatrix.scale(imageIncrement[0], imageIncrement[1]); + texMatrix.translate(srcRect.x(), srcRect.y()); + texMatrix.scale(srcRect.width(), srcRect.height()); + + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST); + + m_context->useQuadVertices(); + m_context->useBicubicProgram(matrix, texMatrix, mitchellCoefficients, imageIncrement, alpha); + m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); + checkGLError("glDrawArrays"); +} + void GLES2Canvas::setCompositeOperation(CompositeOperator op) { m_state->m_compositeOp = op; @@ -554,12 +693,9 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig *count = indices.size(); } -void GLES2Canvas::fillPath(const Path& path, const Color& color) +void GLES2Canvas::fillPathInternal(const Path& path, const Color& color) { if (SharedGraphicsContext3D::useLoopBlinnForPathRendering()) { - bindFramebuffer(); - m_context->applyCompositeOperator(m_state->m_compositeOp); - m_pathCache.clear(); LoopBlinnPathProcessor processor; processor.process(path, m_pathCache); @@ -590,18 +726,18 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) int count; unsigned vertexBuffer, indexBuffer; createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); + + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); checkGLError("bindBuffer"); m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); checkGLError("bindBuffer"); - AffineTransform matrix(m_flipMatrix); - matrix *= m_state->m_ctm; - m_context->useFillSolidProgram(matrix, color); checkGLError("useFillSolidProgram"); - bindFramebuffer(); m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); checkGLError("drawArrays"); @@ -613,7 +749,141 @@ void GLES2Canvas::fillPath(const Path& path, const Color& color) } } -void GLES2Canvas::beginStencilDraw() +FloatRect GLES2Canvas::flipRect(const FloatRect& rect) +{ + FloatRect flippedRect(rect); + flippedRect.setY(m_size.height() - rect.y()); + flippedRect.setHeight(-rect.height()); + return flippedRect; +} + +void GLES2Canvas::clearBorders(const FloatRect& rect, int width) +{ + scissorClear(rect.x(), rect.y() - width, rect.width() + width, width); + scissorClear(rect.maxX(), rect.y(), width, rect.height() + width); + scissorClear(rect.x() - width, rect.maxY(), rect.width() + width, width); + scissorClear(rect.x() - width, rect.y() - width, width, rect.height() + width); +} + +void GLES2Canvas::beginShadowDraw() +{ + float offsetX = m_state->m_shadowOffset.width(); + float offsetY = m_state->m_shadowOffset.height(); + save(); + if (m_state->m_shadowsIgnoreTransforms) { + AffineTransform newCTM; + newCTM.translate(offsetX, -offsetY); + newCTM *= m_state->m_ctm; + m_state->m_ctm = newCTM; + } else + m_state->m_ctm.translate(offsetX, offsetY); + + if (m_state->m_shadowBlur > 0) { + // Draw hard shadow to offscreen buffer 0. + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(0, m_size); + dstBuffer->bind(); + m_context->applyCompositeOperator(CompositeCopy); + applyClipping(false); + m_context->clearColor(Color(RGBA32(0))); + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + } else { + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + } +} + +void GLES2Canvas::endShadowDraw(const FloatRect& boundingBox) +{ + if (m_state->m_shadowBlur > 0) { + // Buffer 0 contains the primitive drawn with a hard shadow. + DrawingBuffer* srcBuffer = m_context->getOffscreenBuffer(0, m_size); + DrawingBuffer* dstBuffer = m_context->getOffscreenBuffer(1, m_size); + + float sigma = m_state->m_shadowBlur * 0.333333f; + FloatRect shadowBoundingBox(m_state->m_ctm.mapRect(boundingBox)); + FloatRect rect(FloatPoint(0, 0), m_size); + FloatRect srcRect(shadowBoundingBox); + + int scaleFactor = 1; + while (sigma > cMaxSigma) { + srcRect.scale(0.5f); + scaleFactor *= 2; + sigma *= 0.5f; + } + srcRect = enclosingIntRect(srcRect); + srcRect.scale(scaleFactor); + for (int i = 1; i < scaleFactor; i *= 2) { + dstBuffer->bind(); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + FloatRect dstRect(srcRect); + dstRect.scale(0.5f); + // Clear out 1 pixel border for linear filtering. + clearBorders(dstRect, 1); + drawTexturedQuad(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + srcRect = dstRect; + std::swap(srcBuffer, dstBuffer); + } + + int halfWidth = static_cast<int>(sigma * 3.0f); + int kernelWidth = halfWidth * 2 + 1; + OwnArrayPtr<float> kernel = adoptArrayPtr(new float[kernelWidth]); + buildKernel(sigma, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.maxX(), srcRect.y(), kernelWidth, srcRect.height()); + scissorClear(srcRect.x() - kernelWidth, srcRect.y(), kernelWidth, srcRect.height()); + } + + // Blur in X offscreen. + dstBuffer->bind(); + srcRect.inflateX(halfWidth); + srcRect.intersect(rect); + float imageIncrementX[2] = {1.0f / srcBuffer->size().width(), 0.0f}; + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementX, kernel.get(), kernelWidth); + + if (scaleFactor > 1) { + scissorClear(srcRect.x(), srcRect.maxY(), srcRect.width(), kernelWidth); + scissorClear(srcRect.x(), srcRect.y() - kernelWidth, srcRect.width(), kernelWidth); + } + srcRect.inflateY(halfWidth); + srcRect.intersect(rect); + std::swap(srcBuffer, dstBuffer); + + float imageIncrementY[2] = {0.0f, 1.0f / srcBuffer->size().height()}; + if (scaleFactor > 1) { + // Blur in Y offscreen. + dstBuffer->bind(); + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + // Clear out 2 pixel border for bicubic filtering. + clearBorders(srcRect, 2); + std::swap(srcBuffer, dstBuffer); + + // Upsample srcBuffer -> main framebuffer using bicubic filtering. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, srcBuffer->colorBuffer()); + FloatRect dstRect = srcRect; + dstRect.scale(scaleFactor); + drawTexturedQuadMitchell(srcBuffer->size(), flipRect(srcRect), dstRect, AffineTransform(), 1.0); + } else { + // Blur in Y directly to framebuffer. + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + applyClipping(m_state->clippingEnabled()); + + convolveRect(srcBuffer->colorBuffer(), srcBuffer->size(), flipRect(srcRect), srcRect, imageIncrementY, kernel.get(), kernelWidth); + } + } + restore(); +} + +void GLES2Canvas::beginStencilDraw(unsigned op) { // Turn on stencil test. m_context->enableStencil(true); @@ -624,9 +894,7 @@ void GLES2Canvas::beginStencilDraw() checkGLError("stencilFunc"); // All writes incremement the stencil buffer. - m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::INCR, - GraphicsContext3D::INCR, - GraphicsContext3D::INCR); + m_context->graphicsContext3D()->stencilOp(op, op, op); checkGLError("stencilOp"); } @@ -635,7 +903,7 @@ void GLES2Canvas::applyClipping(bool enable) m_context->enableStencil(enable); if (enable) { // Enable drawing only where stencil is non-zero. - m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_clippingPaths.size() % 256, 1); + m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::EQUAL, m_state->m_numClippingPaths, -1); checkGLError("stencilFunc"); // Keep all stencil values the same. m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::KEEP, diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h index 8887a16..f6a8bcf 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -64,6 +64,10 @@ public: void clearRect(const FloatRect&); void setFillColor(const Color&, ColorSpace); void setAlpha(float alpha); + void setShadowColor(const Color&, ColorSpace); + void setShadowOffset(const FloatSize&); + void setShadowBlur(float); + void setShadowsIgnoreTransforms(bool); void setCompositeOperation(CompositeOperator); void translate(float x, float y); void rotate(float angleInRadians); @@ -96,12 +100,21 @@ public: DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; } private: + void scissorClear(float x, float y, float width, float height); void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); - void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void drawTexturedQuadMitchell(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); + void convolveRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, float imageIncrement[2], const float* kernel, int kernelWidth); + void applyCompositeOperator(CompositeOperator); void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer); - void fillPath(const Path&, const Color&); - void beginStencilDraw(); + void fillPathInternal(const Path&, const Color&); + void fillRectInternal(const FloatRect&, const Color&); + FloatRect flipRect(const FloatRect&); + void clearBorders(const FloatRect&, int width); + void beginShadowDraw(); + void endShadowDraw(const FloatRect& boundingBox); + void beginStencilDraw(unsigned op); void applyClipping(bool enable); void checkGLError(const char* header); diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp index ee2b5ab..cfc1754 100644 --- a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp @@ -36,8 +36,8 @@ #include "GlyphPageTreeNode.h" #include "PlatformBridge.h" #include "SimpleFontData.h" +#include "SystemInfo.h" #include "UniscribeHelperTextRun.h" -#include "WindowsVersion.h" namespace WebCore { @@ -134,7 +134,7 @@ static bool fillBMPGlyphs(unsigned offset, bool haveGlyphs = false; int invalidGlyph = 0xFFFF; const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF '). - if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) + if ((windowsVersion() < WindowsVista) && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) invalidGlyph = 0x1F; Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled. diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 7c42366..60c1332 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -60,7 +60,7 @@ void ImageLayerChromium::setContents(Image* contents) setNeedsDisplay(); } -void ImageLayerChromium::updateContentsIfDirty() +void ImageLayerChromium::paintContentsIfDirty() { ASSERT(layerRenderer()); @@ -68,7 +68,7 @@ void ImageLayerChromium::updateContentsIfDirty() if (requiresClippedUpdateRect()) { // Use the base version of updateContents which draws a subset of the // image to a bitmap, as the pixel contents can't be uploaded directly. - ContentLayerChromium::updateContentsIfDirty(); + ContentLayerChromium::paintContentsIfDirty(); return; } diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h index cc9064d..6addabc 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -50,7 +50,7 @@ class ImageLayerChromium : public ContentLayerChromium { public: static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0); - virtual void updateContentsIfDirty(); + virtual void paintContentsIfDirty(); virtual bool drawsContent() const { return m_contents; } void setContents(Image* image); diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp index 95b7386..bc28239 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -62,6 +62,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) : m_owner(owner) , m_contentsDirty(false) , m_maskLayer(0) + , m_ccLayerImpl(0) , m_superlayer(0) #ifndef NDEBUG , m_debugID(s_nextLayerDebugID++) @@ -77,7 +78,7 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) , m_opaque(true) , m_geometryFlipped(false) , m_needsDisplayOnBoundsChange(false) - , m_ccLayerImpl(CCLayerImpl::create(this)) + , m_doubleSided(true) , m_replicaLayer(0) { } @@ -94,7 +95,8 @@ LayerChromium::~LayerChromium() void LayerChromium::cleanupResources() { - m_ccLayerImpl->cleanupResources(); + if (m_ccLayerImpl) + m_ccLayerImpl->cleanupResources(); } void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) @@ -105,8 +107,7 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) cleanupResources(); setNeedsDisplay(); } - - m_ccLayerImpl->setLayerRenderer(renderer); + m_layerRenderer = renderer; } void LayerChromium::setNeedsCommit() @@ -188,7 +189,7 @@ void LayerChromium::setBounds(const IntSize& size) bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height(); - m_ccLayerImpl->setBounds(size); + m_bounds = size; if (firstResize) setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height())); @@ -240,7 +241,6 @@ LayerChromium* LayerChromium::superlayer() const void LayerChromium::setName(const String& name) { m_name = name; - m_ccLayerImpl->setName(name); } void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) @@ -288,6 +288,29 @@ void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m) flattened[15] = m.m44(); } +void LayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + layer->setAnchorPoint(m_anchorPoint); + layer->setAnchorPointZ(m_anchorPointZ); + layer->setBounds(m_bounds); + layer->setDebugBorderColor(m_debugBorderColor); + layer->setDebugBorderWidth(m_debugBorderWidth); + layer->setDoubleSided(m_doubleSided); + layer->setLayerRenderer(m_layerRenderer.get()); + layer->setMasksToBounds(m_masksToBounds); + layer->setName(m_name); + layer->setOpacity(m_opacity); + layer->setPosition(m_position); + layer->setPreserves3D(preserves3D()); + layer->setSublayerTransform(m_sublayerTransform); + layer->setTransform(m_transform); + + if (maskLayer()) + maskLayer()->pushPropertiesTo(layer->maskLayer()); + if (replicaLayer()) + replicaLayer()->pushPropertiesTo(layer->replicaLayer()); +} + GraphicsContext3D* LayerChromium::layerRendererContext() const { ASSERT(layerRenderer()); @@ -316,31 +339,6 @@ void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const Transform GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); } - - -// Returns true if any of the layer's descendants has drawable content. -bool LayerChromium::descendantsDrawContent() -{ - const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers(); - for (size_t i = 0; i < sublayers.size(); ++i) - if (sublayers[i]->descendantsDrawContentRecursive()) - return true; - return false; -} - -// Returns true if either this layer or one of its descendants has drawable content. -bool LayerChromium::descendantsDrawContentRecursive() -{ - if (drawsContent()) - return true; - - const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers(); - for (size_t i = 0; i < sublayers.size(); ++i) - if (sublayers[i]->descendantsDrawContentRecursive()) - return true; - return false; -} - String LayerChromium::layerTreeAsText() const { TextStream ts; @@ -359,7 +357,8 @@ void LayerChromium::dumpLayer(TextStream& ts, int indent) const writeIndent(ts, indent); ts << layerTypeAsString() << "(" << m_name << ")\n"; dumpLayerProperties(ts, indent+2); - m_ccLayerImpl->dumpLayerProperties(ts, indent+2); + if (m_ccLayerImpl) + m_ccLayerImpl->dumpLayerProperties(ts, indent+2); if (m_replicaLayer) { writeIndent(ts, indent+2); ts << "Replica:\n"; @@ -385,48 +384,38 @@ void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const } -// Begin calls that forward to the CCLayerImpl. -// ============================================== -// These exists just for debugging (via drawDebugBorder()). -void LayerChromium::setBorderColor(const Color& color) +PassRefPtr<CCLayerImpl> LayerChromium::createCCLayerImpl() { - m_ccLayerImpl->setDebugBorderColor(color); - setNeedsCommit(); + return CCLayerImpl::create(this); } -Color LayerChromium::borderColor() const +void LayerChromium::createCCLayerImplIfNeeded() { - return m_ccLayerImpl->debugBorderColor(); + if (!m_ccLayerImpl) + m_ccLayerImpl = createCCLayerImpl(); } -void LayerChromium::setBorderWidth(float width) +CCLayerImpl* LayerChromium::ccLayerImpl() { - m_ccLayerImpl->setDebugBorderWidth(width); - setNeedsCommit(); + return m_ccLayerImpl.get(); } -float LayerChromium::borderWidth() const -{ - return m_ccLayerImpl->debugBorderWidth(); -} - -LayerRendererChromium* LayerChromium::layerRenderer() const +void LayerChromium::setBorderColor(const Color& color) { - return m_ccLayerImpl->layerRenderer(); + m_debugBorderColor = color; + setNeedsCommit(); } -void LayerChromium::setDoubleSided(bool doubleSided) +void LayerChromium::setBorderWidth(float width) { - m_ccLayerImpl->setDoubleSided(doubleSided); + m_debugBorderWidth = width; setNeedsCommit(); } -const IntSize& LayerChromium::bounds() const +LayerRendererChromium* LayerChromium::layerRenderer() const { - return m_ccLayerImpl->bounds(); + return m_layerRenderer.get(); } -// ============================================== -// End calls that forward to the CCLayerImpl. } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h index 29a2165..428ce61 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h @@ -89,6 +89,9 @@ public: void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); } Color backgroundColor() const { return m_backgroundColor; } + void setBounds(const IntSize&); + const IntSize& bounds() const { return m_bounds; } + void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); } bool clearsContext() const { return m_clearsContext; } @@ -133,6 +136,9 @@ public: void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); } const TransformationMatrix& transform() const { return m_transform; } + bool doubleSided() const { return m_doubleSided; } + void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); } + // FIXME: This setting is currently ignored. void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } @@ -143,9 +149,6 @@ public: // in the LayerRendererChromium. virtual void setLayerRenderer(LayerRendererChromium*); - // Returns true if any of the layer's descendants has content to draw. - bool descendantsDrawContent(); - void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; } void setReplicaLayer(LayerChromium* layer) { m_replicaLayer = layer; } @@ -153,14 +156,14 @@ public: // These methods typically need to be overwritten by derived classes. virtual bool drawsContent() const { return false; } - virtual void updateContentsIfDirty() { } + virtual void paintContentsIfDirty() { } + virtual void updateCompositorResources() { } virtual void unreserveContentsTexture() { } virtual void bindContentsTexture() { } virtual void draw() { } // These exists just for debugging (via drawDebugBorder()). void setBorderColor(const Color&); - Color borderColor() const; #ifndef NDEBUG int debugID() const { return m_debugID; } @@ -170,21 +173,19 @@ public: String layerTreeAsText() const; void setBorderWidth(float); - float borderWidth() const; // Everything from here down in the public section will move to CCLayerImpl. - - CCLayerImpl* ccLayerImpl() const { return m_ccLayerImpl.get(); } + CCLayerImpl* ccLayerImpl(); + void createCCLayerImplIfNeeded(); static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation); + virtual void pushPropertiesTo(CCLayerImpl*); + // Begin calls that forward to the CCLayerImpl. LayerRendererChromium* layerRenderer() const; - void setDoubleSided(bool); - void setBounds(const IntSize&); - const IntSize& bounds() const; // End calls that forward to the CCLayerImpl. typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram; @@ -217,6 +218,11 @@ protected: static const unsigned s_positionAttribLocation; static const unsigned s_texCoordAttribLocation; + // Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type. + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + + // For now, the LayerChromium directly owns its CCLayerImpl. + RefPtr<CCLayerImpl> m_ccLayerImpl; private: void setNeedsCommit(); @@ -233,19 +239,22 @@ private: // This should only be called from removeFromSuperlayer. void removeSublayer(LayerChromium*); - bool descendantsDrawContentRecursive(); - Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; + RefPtr<LayerRendererChromium> m_layerRenderer; + #ifndef NDEBUG int m_debugID; #endif // Layer properties. + IntSize m_bounds; FloatPoint m_position; FloatPoint m_anchorPoint; Color m_backgroundColor; + Color m_debugBorderColor; + float m_debugBorderWidth; float m_opacity; float m_zPosition; float m_anchorPointZ; @@ -255,13 +264,12 @@ private: bool m_opaque; bool m_geometryFlipped; bool m_needsDisplayOnBoundsChange; + bool m_doubleSided; TransformationMatrix m_transform; TransformationMatrix m_sublayerTransform; FloatRect m_frame; - // For now, the LayerChromium directly owns its CCLayerImpl. - RefPtr<CCLayerImpl> m_ccLayerImpl; // Replica layer used for reflections. LayerChromium* m_replicaLayer; diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index e7b299f..fc15abd 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -36,6 +36,7 @@ #include "cc/CCLayerImpl.h" #include "Canvas2DLayerChromium.h" +#include "FloatQuad.h" #include "GeometryBinding.h" #include "GraphicsContext3D.h" #include "LayerChromium.h" @@ -43,6 +44,7 @@ #include "NotImplemented.h" #include "TextStream.h" #include "TextureManager.h" +#include "TraceEvent.h" #include "WebGLLayerChromium.h" #include "cc/CCLayerImpl.h" #if USE(SKIA) @@ -91,21 +93,23 @@ bool LayerRendererChromium::compareLayerZ(const CCLayerImpl* a, const CCLayerImp return a->drawDepth() < b->drawDepth(); } -PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context) +PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint) { if (!context) return 0; - RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context))); + RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint, scrollbarPaint))); if (!layerRenderer->hardwareCompositing()) return 0; return layerRenderer.release(); } -LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context) - : m_rootLayer(0) - , m_scrollPosition(IntPoint(-1, -1)) +LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint) + : m_viewportScrollPosition(IntPoint(-1, -1)) + , m_rootLayer(0) + , m_rootLayerContentPaint(contentPaint) + , m_rootLayerScrollbarPaint(scrollbarPaint) , m_currentShader(0) , m_currentRenderSurface(0) , m_offscreenFramebufferId(0) @@ -114,8 +118,8 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte , m_defaultRenderSurface(0) { m_hardwareCompositing = initializeSharedObjects(); - m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); - ASSERT(m_rootLayerTiler); + m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); + ASSERT(m_rootLayerContentTiler); m_headsUpDisplay = CCHeadsUpDisplay::create(this); } @@ -146,129 +150,149 @@ void LayerRendererChromium::useShader(unsigned programId) } } -IntRect LayerRendererChromium::verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect) +IntRect LayerRendererChromium::verticalScrollbarRect() const { - IntRect verticalScrollbar(IntPoint(contentRect.maxX(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height())); + IntRect verticalScrollbar(IntPoint(m_viewportContentRect.maxX(), m_viewportContentRect.y()), IntSize(m_viewportVisibleRect.width() - m_viewportContentRect.width(), m_viewportVisibleRect.height())); return verticalScrollbar; } -IntRect LayerRendererChromium::horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect) +IntRect LayerRendererChromium::horizontalScrollbarRect() const { - IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.maxY()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height())); + IntRect horizontalScrollbar(IntPoint(m_viewportContentRect.x(), m_viewportContentRect.maxY()), IntSize(m_viewportVisibleRect.width(), m_viewportVisibleRect.height() - m_viewportContentRect.height())); return horizontalScrollbar; } -void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect) +void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect) { - m_rootLayerTiler->invalidateRect(dirtyRect); + m_rootLayerContentTiler->invalidateRect(dirtyRect); + + // Scrollbars never need to render beyond the fold, so clip to the viewport. + IntRect visibleDirtyRect = dirtyRect; + visibleDirtyRect.intersect(m_viewportVisibleRect); + if (m_horizontalScrollbarTiler) { - IntRect scrollbar = horizontalScrollbarRect(visibleRect, contentRect); - if (dirtyRect.intersects(scrollbar)) { + IntRect scrollbar = horizontalScrollbarRect(); + if (visibleDirtyRect.intersects(scrollbar)) { m_horizontalScrollbarTiler->setLayerPosition(scrollbar.location()); - m_horizontalScrollbarTiler->invalidateRect(dirtyRect); + m_horizontalScrollbarTiler->invalidateRect(visibleDirtyRect); } } if (m_verticalScrollbarTiler) { - IntRect scrollbar = verticalScrollbarRect(visibleRect, contentRect); - if (dirtyRect.intersects(scrollbar)) { + IntRect scrollbar = verticalScrollbarRect(); + if (visibleDirtyRect.intersects(scrollbar)) { m_verticalScrollbarTiler->setLayerPosition(scrollbar.location()); - m_verticalScrollbarTiler->invalidateRect(dirtyRect); + m_verticalScrollbarTiler->invalidateRect(visibleDirtyRect); } } } -void LayerRendererChromium::updateRootLayerContents(TilePaintInterface& tilePaint, const IntRect& visibleRect) +void LayerRendererChromium::updateRootLayerContents() { - m_rootLayerTiler->update(tilePaint, visibleRect); + TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0); + m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect); } -void LayerRendererChromium::updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect) +void LayerRendererChromium::updateRootLayerScrollbars() { - if (visibleRect.width() > contentRect.width()) { - IntRect verticalScrollbar = verticalScrollbarRect(visibleRect, contentRect); + TRACE_EVENT("LayerRendererChromium::updateRootLayerScrollbars", this, 0); + if (m_viewportVisibleRect.width() > m_viewportContentRect.width()) { + IntRect verticalScrollbar = verticalScrollbarRect(); IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_verticalScrollbarTiler) m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_verticalScrollbarTiler->setTileSize(tileSize); m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location()); - m_verticalScrollbarTiler->update(scrollbarPaint, visibleRect); + m_verticalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect); } else m_verticalScrollbarTiler.clear(); - if (visibleRect.height() > contentRect.height()) { - IntRect horizontalScrollbar = horizontalScrollbarRect(visibleRect, contentRect); + if (m_viewportVisibleRect.height() > m_viewportContentRect.height()) { + IntRect horizontalScrollbar = horizontalScrollbarRect(); IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_horizontalScrollbarTiler) m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_horizontalScrollbarTiler->setTileSize(tileSize); m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location()); - m_horizontalScrollbarTiler->update(scrollbarPaint, visibleRect); + m_horizontalScrollbarTiler->update(*m_rootLayerScrollbarPaint, m_viewportVisibleRect); } else m_horizontalScrollbarTiler.clear(); } void LayerRendererChromium::drawRootLayer() { - m_rootLayerTiler->draw(m_visibleRect); + m_rootLayerContentTiler->draw(m_viewportVisibleRect); if (m_verticalScrollbarTiler) - m_verticalScrollbarTiler->draw(m_visibleRect); + m_verticalScrollbarTiler->draw(m_viewportVisibleRect); if (m_horizontalScrollbarTiler) - m_horizontalScrollbarTiler->draw(m_visibleRect); + m_horizontalScrollbarTiler->draw(m_viewportVisibleRect); +} + +void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition) +{ + bool visibleRectChanged = m_viewportVisibleRect.size() != visibleRect.size(); + + m_viewportVisibleRect = visibleRect; + m_viewportContentRect = contentRect; + m_viewportScrollPosition = scrollPosition; + + if (visibleRectChanged) { + // Reset the current render surface to force an update of the viewport and + // projection matrix next time useRenderSurface is called. + m_currentRenderSurface = 0; + + m_rootLayerContentTiler->invalidateEntireLayer(); + if (m_horizontalScrollbarTiler) + m_horizontalScrollbarTiler->invalidateEntireLayer(); + if (m_verticalScrollbarTiler) + m_verticalScrollbarTiler->invalidateEntireLayer(); + } } -void LayerRendererChromium::updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint) +void LayerRendererChromium::updateAndDrawLayers() { ASSERT(m_hardwareCompositing); if (!m_rootLayer) return; - updateRootLayerContents(tilePaint, visibleRect); + updateRootLayerContents(); + // Recheck that we still have a root layer. This may become null if // compositing gets turned off during a paint operation. if (!m_rootLayer) return; - updateRootLayerScrollbars(scrollbarPaint, visibleRect, contentRect); + updateRootLayerScrollbars(); Vector<CCLayerImpl*> renderSurfaceLayerList; - updateLayers(visibleRect, contentRect, scrollPosition, renderSurfaceLayerList); + updateLayers(renderSurfaceLayerList); drawLayers(renderSurfaceLayerList); + + if (isCompositingOffscreen()) + copyOffscreenTextureToDisplay(); } -void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - Vector<CCLayerImpl*>& renderSurfaceLayerList) +void LayerRendererChromium::updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList) { + TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0); + m_rootLayer->createCCLayerImplIfNeeded(); CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); if (!rootDrawLayer->renderSurface()) rootDrawLayer->createRenderSurface(); ASSERT(rootDrawLayer->renderSurface()); - // If the size of the visible area has changed then allocate a new texture - // to store the contents of the root layer and adjust the projection matrix - // and viewport. - - rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), visibleRect.size()); + rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size()); - if (visibleRect.size() != m_visibleRect.size()) { - // Reset the current render surface to force an update of the viewport and - // projection matrix next time useRenderSurface is called. - m_currentRenderSurface = 0; - } - m_visibleRect = visibleRect; - - m_scrollPosition = scrollPosition; // Scissor out the scrollbars to avoid rendering on top of them. - IntRect rootScissorRect(contentRect); + IntRect rootScissorRect(m_viewportContentRect); // The scissorRect should not include the scroll offset. - rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y()); rootDrawLayer->setScissorRect(rootScissorRect); m_defaultRenderSurface = rootDrawLayer->renderSurface(); @@ -283,16 +307,19 @@ void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRe // concept of a large content layer. updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); - updateContentsRecursive(m_rootLayer.get()); + paintContentsRecursive(m_rootLayer.get()); + + updateCompositorResourcesRecursive(m_rootLayer.get()); } void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList) { + TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0); CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); makeContextCurrent(); // The GL viewport covers the entire visible area, including the scrollbars. - GLC(m_context.get(), m_context->viewport(0, 0, m_visibleRect.width(), m_visibleRect.height())); + GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height())); // Bind the common vertex attributes used for drawing all the layers. m_sharedGeometry->prepareForDraw(); @@ -363,11 +390,13 @@ void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurface void LayerRendererChromium::finish() { + TRACE_EVENT("LayerRendererChromium::finish", this, 0); m_context->finish(); } void LayerRendererChromium::present() { + TRACE_EVENT("LayerRendererChromium::present", this, 0); // We're done! Time to swapbuffers! // Note that currently this has the same effect as swapBuffers; we should @@ -382,7 +411,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) m_rootLayer = layer; if (m_rootLayer) m_rootLayer->setLayerRenderer(this); - m_rootLayerTiler->invalidateEntireLayer(); + m_rootLayerContentTiler->invalidateEntireLayer(); if (m_horizontalScrollbarTiler) m_horizontalScrollbarTiler->invalidateEntireLayer(); if (m_verticalScrollbarTiler) @@ -391,7 +420,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) { - ASSERT(rect.maxX() <= visibleRectSize().width() && rect.maxY() <= visibleRectSize().height()); + ASSERT(rect.maxX() <= m_viewportVisibleRect.width() && rect.maxY() <= m_viewportVisibleRect.height()); if (!pixels) return; @@ -446,8 +475,29 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform // necessary transformations, scissor rectangles, render surfaces, etc. void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList) { + // Make sure we have CCLayerImpls for this subtree. + layer->createCCLayerImplIfNeeded(); layer->setLayerRenderer(this); + if (layer->maskLayer()) { + layer->maskLayer()->createCCLayerImplIfNeeded(); + layer->maskLayer()->setLayerRenderer(this); + } + if (layer->replicaLayer()) { + layer->replicaLayer()->createCCLayerImplIfNeeded(); + layer->replicaLayer()->setLayerRenderer(this); + } + if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { + layer->replicaLayer()->maskLayer()->createCCLayerImplIfNeeded(); + layer->replicaLayer()->maskLayer()->setLayerRenderer(this); + } + CCLayerImpl* drawLayer = layer->ccLayerImpl(); + // Currently we're calling pushPropertiesTo() twice - once here and once in updateCompositorResourcesRecursive(). + // We should only call pushPropertiesTo() in commit, but because we rely on the draw layer state to update + // RenderSurfaces and we rely on RenderSurfaces being up to date in order to paint contents we have + // to update the draw layers twice. + // FIXME: Remove this call once layer updates no longer depend on render surfaces. + layer->pushPropertiesTo(drawLayer); // Compute the new matrix transformation that will be applied to this layer and // all its sublayers. It's important to remember that the layer's position @@ -467,9 +517,9 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Where: P is the projection matrix // M is the layer's matrix computed above // S is the scale adjustment (to scale up to the layer size) - IntSize bounds = layer->bounds(); - FloatPoint anchorPoint = layer->anchorPoint(); - FloatPoint position = layer->position(); + IntSize bounds = drawLayer->bounds(); + FloatPoint anchorPoint = drawLayer->anchorPoint(); + FloatPoint position = drawLayer->position(); // Offset between anchor point and the center of the quad. float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width(); @@ -477,16 +527,16 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay TransformationMatrix layerLocalTransform; // LT = Tr[l] - layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ()); + layerLocalTransform.translate3d(position.x(), position.y(), drawLayer->anchorPointZ()); // LT = Tr[l] * M[l] - layerLocalTransform.multiply(layer->transform()); + layerLocalTransform.multiply(drawLayer->transform()); // LT = Tr[l] * M[l] * Tr[c] - layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ()); + layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -drawLayer->anchorPointZ()); TransformationMatrix combinedTransform = parentMatrix; combinedTransform = combinedTransform.multiply(layerLocalTransform); - FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height()); + FloatRect layerRect(-0.5 * drawLayer->bounds().width(), -0.5 * drawLayer->bounds().height(), drawLayer->bounds().width(), drawLayer->bounds().height()); IntRect transformedLayerRect; // The layer and its descendants render on a new RenderSurface if any of @@ -498,12 +548,11 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening // out its children. The opacity value of the children layers is multiplied by the opacity // of their parent. - bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform); - bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D(); - bool useSurfaceForMasking = layer->maskDrawLayer(); - bool useSurfaceForReflection = layer->replicaLayer(); - if (((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) - || useSurfaceForMasking || useSurfaceForReflection) { + bool useSurfaceForClipping = drawLayer->masksToBounds() && !isScaleOrTranslation(combinedTransform); + bool useSurfaceForOpacity = drawLayer->opacity() != 1 && !drawLayer->preserves3D(); + bool useSurfaceForMasking = drawLayer->maskLayer(); + bool useSurfaceForReflection = drawLayer->replicaLayer(); + if (useSurfaceForMasking || useSurfaceForReflection || ((useSurfaceForClipping || useSurfaceForOpacity) && drawLayer->descendantsDrawsContent())) { RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); if (!renderSurface) renderSurface = drawLayer->createRenderSurface(); @@ -516,15 +565,15 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height()); // Layer's opacity will be applied when drawing the render surface. - renderSurface->m_drawOpacity = layer->opacity(); - if (layer->superlayer() && layer->superlayer()->preserves3D()) + renderSurface->m_drawOpacity = drawLayer->opacity(); + if (drawLayer->superlayer() && drawLayer->superlayer()->preserves3D()) renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity(); drawLayer->setDrawOpacity(1); TransformationMatrix layerOriginTransform = combinedTransform; layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0); renderSurface->m_originTransform = layerOriginTransform; - if (layerOriginTransform.isInvertible() && layer->superlayer()) { + if (layerOriginTransform.isInvertible() && drawLayer->superlayer()) { TransformationMatrix parentToLayer = layerOriginTransform.inverse(); drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect())); @@ -538,17 +587,14 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay renderSurface->m_layerList.clear(); - if (layer->maskDrawLayer()) { - renderSurface->m_maskLayer = layer->maskDrawLayer(); - layer->maskDrawLayer()->setLayerRenderer(this); - layer->maskDrawLayer()->setTargetRenderSurface(renderSurface); + if (drawLayer->maskLayer()) { + renderSurface->m_maskLayer = drawLayer->maskLayer(); + drawLayer->maskLayer()->setTargetRenderSurface(renderSurface); } else renderSurface->m_maskLayer = 0; - if (layer->replicaLayer() && layer->replicaLayer()->maskDrawLayer()) { - layer->replicaLayer()->maskDrawLayer()->setLayerRenderer(this); - layer->replicaLayer()->maskDrawLayer()->setTargetRenderSurface(renderSurface); - } + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer()) + drawLayer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface); renderSurfaceLayerList.append(drawLayer); } else { @@ -556,10 +602,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay drawLayer->setDrawTransform(combinedTransform); transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect)); - drawLayer->setDrawOpacity(layer->opacity()); + drawLayer->setDrawOpacity(drawLayer->opacity()); - if (layer->superlayer()) { - if (layer->superlayer()->preserves3D()) + if (drawLayer->superlayer()) { + if (drawLayer->superlayer()->preserves3D()) drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity()); // Layers inherit the scissor rect from their superlayer. @@ -571,7 +617,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay if (layer != m_rootLayer) drawLayer->clearRenderSurface(); - if (layer->masksToBounds()) { + if (drawLayer->masksToBounds()) { IntRect scissor = drawLayer->scissorRect(); scissor.intersect(transformedLayerRect); drawLayer->setScissorRect(scissor); @@ -581,7 +627,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay if (drawLayer->renderSurface()) drawLayer->setTargetRenderSurface(drawLayer->renderSurface()); else { - ASSERT(layer->superlayer()); + ASSERT(drawLayer->superlayer()); drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); } @@ -595,7 +641,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay TransformationMatrix sublayerMatrix = drawLayer->drawTransform(); // Flatten to 2D if the layer doesn't preserve 3D. - if (!layer->preserves3D()) { + if (!drawLayer->preserves3D()) { sublayerMatrix.setM13(0); sublayerMatrix.setM23(0); sublayerMatrix.setM31(0); @@ -606,7 +652,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay } // Apply the sublayer transform at the center of the layer. - sublayerMatrix.multiply(layer->sublayerTransform()); + sublayerMatrix.multiply(drawLayer->sublayerTransform()); // The origin of the sublayers is the top left corner of the layer, not the // center. The matrix passed down to the sublayers is therefore: @@ -619,6 +665,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); ++i) { + sublayers[i]->createCCLayerImplIfNeeded(); CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl(); updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants); @@ -635,7 +682,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay } } - if (layer->masksToBounds() || useSurfaceForMasking) { + if (drawLayer->masksToBounds() || useSurfaceForMasking) { IntRect drawableContentRect = drawLayer->drawableContentRect(); drawableContentRect.intersect(transformedLayerRect); drawLayer->setDrawableContentRect(drawableContentRect); @@ -651,7 +698,7 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Don't clip if the layer is reflected as the reflection shouldn't be // clipped. - if (!layer->replicaLayer()) { + if (!drawLayer->replicaLayer()) { renderSurface->m_contentRect.intersect(drawLayer->scissorRect()); FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter(); centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter; @@ -675,10 +722,10 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Compute the transformation matrix used to draw the replica of the render // surface. - if (layer->replicaLayer()) { + if (drawLayer->replicaLayer()) { renderSurface->m_replicaDrawTransform = renderSurface->m_originTransform; - renderSurface->m_replicaDrawTransform.translate3d(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y(), 0); - renderSurface->m_replicaDrawTransform.multiply(layer->replicaLayer()->transform()); + renderSurface->m_replicaDrawTransform.translate3d(drawLayer->replicaLayer()->position().x(), drawLayer->replicaLayer()->position().y(), 0); + renderSurface->m_replicaDrawTransform.multiply(drawLayer->replicaLayer()->transform()); renderSurface->m_replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0); } } @@ -686,8 +733,8 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // Compute the depth value of the center of the layer which will be used when // sorting the layers for the preserves-3d property. const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform(); - if (layer->superlayer()) { - if (!layer->superlayer()->preserves3D()) + if (drawLayer->superlayer()) { + if (!drawLayer->superlayer()->preserves3D()) drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth()); else drawLayer->setDrawDepth(layerDrawMatrix.m43()); @@ -697,24 +744,50 @@ void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* lay // If preserves-3d then sort all the descendants by the Z coordinate of their // center. If the preserves-3d property is also set on the superlayer then // skip the sorting as the superlayer will sort all the descendants anyway. - if (layer->preserves3D() && (!layer->superlayer() || !layer->superlayer()->preserves3D())) + if (drawLayer->preserves3D() && (!drawLayer->superlayer() || !drawLayer->superlayer()->preserves3D())) std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ); } -void LayerRendererChromium::updateContentsRecursive(LayerChromium* layer) +void LayerRendererChromium::paintContentsRecursive(LayerChromium* layer) { const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); ++i) - updateContentsRecursive(sublayers[i].get()); + paintContentsRecursive(sublayers[i].get()); + + if (layer->bounds().isEmpty()) + return; if (layer->drawsContent()) - layer->updateContentsIfDirty(); + layer->paintContentsIfDirty(); if (layer->maskLayer() && layer->maskLayer()->drawsContent()) - layer->maskLayer()->updateContentsIfDirty(); + layer->maskLayer()->paintContentsIfDirty(); if (layer->replicaLayer() && layer->replicaLayer()->drawsContent()) - layer->replicaLayer()->updateContentsIfDirty(); + layer->replicaLayer()->paintContentsIfDirty(); if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent()) - layer->replicaLayer()->maskLayer()->updateContentsIfDirty(); + layer->replicaLayer()->maskLayer()->paintContentsIfDirty(); +} + +void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer) +{ + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) + updateCompositorResourcesRecursive(sublayers[i].get()); + + if (layer->bounds().isEmpty()) + return; + + CCLayerImpl* drawLayer = layer->ccLayerImpl(); + + if (drawLayer->drawsContent()) + drawLayer->updateCompositorResources(); + if (drawLayer->maskLayer() && drawLayer->maskLayer()->drawsContent()) + drawLayer->maskLayer()->updateCompositorResources(); + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->drawsContent()) + drawLayer->replicaLayer()->updateCompositorResources(); + if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer() && drawLayer->replicaLayer()->maskLayer()->drawsContent()) + drawLayer->replicaLayer()->maskLayer()->updateCompositorResources(); + + layer->pushPropertiesTo(drawLayer); } void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen) @@ -788,22 +861,38 @@ void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* return; } - if (layer->bounds().isEmpty()) + if (layer->bounds().isEmpty()) { + layer->unreserveContentsTexture(); return; + } setScissorToRect(layer->scissorRect()); // Check if the layer falls within the visible bounds of the page. IntRect layerRect = layer->getDrawRect(); bool isLayerVisible = layer->scissorRect().intersects(layerRect); - if (!isLayerVisible) + if (!isLayerVisible) { + layer->unreserveContentsTexture(); return; + } // FIXME: Need to take into account the commulative render surface transforms all the way from // the default render surface in order to determine visibility. - TransformationMatrix combinedDrawMatrix = (layer->renderSurface() ? layer->renderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); - if (!layer->doubleSided() && combinedDrawMatrix.m33() < 0) - return; + TransformationMatrix combinedDrawMatrix = (layer->targetRenderSurface() ? layer->targetRenderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); + + if (!layer->doubleSided()) { + FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds())); + FloatQuad mappedLayer = combinedDrawMatrix.mapQuad(FloatQuad(layerRect)); + FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1(); + FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1(); + FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0); + FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0); + FloatPoint3D zAxis = xAxis.cross(yAxis); + if (zAxis.z() < 0) { + layer->unreserveContentsTexture(); + return; + } + } if (layer->drawsContent()) layer->draw(); @@ -880,10 +969,10 @@ bool LayerRendererChromium::initializeSharedObjects() m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get())); m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get())); m_contentLayerProgram = adoptPtr(new ContentLayerChromium::Program(m_context.get())); - m_canvasLayerProgram = adoptPtr(new CanvasLayerChromium::Program(m_context.get())); - m_videoLayerRGBAProgram = adoptPtr(new VideoLayerChromium::RGBAProgram(m_context.get())); - m_videoLayerYUVProgram = adoptPtr(new VideoLayerChromium::YUVProgram(m_context.get())); - m_pluginLayerProgram = adoptPtr(new PluginLayerChromium::Program(m_context.get())); + m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get())); + m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get())); + m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get())); + m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get())); m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get())); m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get())); m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get())); @@ -920,7 +1009,7 @@ void LayerRendererChromium::cleanupSharedObjects() GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); // Clear tilers before the texture manager, as they have references to textures. - m_rootLayerTiler.clear(); + m_rootLayerContentTiler.clear(); m_horizontalScrollbarTiler.clear(); m_verticalScrollbarTiler.clear(); diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 7e8850a..667ede2 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -34,16 +34,17 @@ #if USE(ACCELERATED_COMPOSITING) -#include "CanvasLayerChromium.h" #include "ContentLayerChromium.h" #include "IntRect.h" #include "LayerChromium.h" #include "LayerTilerChromium.h" -#include "PluginLayerChromium.h" #include "RenderSurfaceChromium.h" #include "SkBitmap.h" #include "VideoLayerChromium.h" +#include "cc/CCCanvasLayerImpl.h" #include "cc/CCHeadsUpDisplay.h" +#include "cc/CCPluginLayerImpl.h" +#include "cc/CCVideoLayerImpl.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> @@ -66,17 +67,18 @@ class CCHeadsUpDisplay; // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public RefCounted<LayerRendererChromium> { public: - static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D> graphicsContext3D); + static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint); ~LayerRendererChromium(); GraphicsContext3D* context(); - void invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect); + void invalidateRootLayerRect(const IntRect& dirtyRect); + + void setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition); // updates and draws the current layers onto the backbuffer - void updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - TilePaintInterface&, TilePaintInterface& scrollbarPaint); + void updateAndDrawLayers(); // waits for rendering to finish void finish(); @@ -84,7 +86,7 @@ public: // puts backbuffer onscreen void present(); - IntSize visibleRectSize() const { return m_visibleRect.size(); } + IntSize viewportSize() const { return m_viewportVisibleRect.size(); } void setRootLayer(PassRefPtr<LayerChromium> layer); LayerChromium* rootLayer() { return m_rootLayer.get(); } @@ -94,8 +96,6 @@ public: void setCompositeOffscreen(bool); bool isCompositingOffscreen() const { return m_compositeOffscreen; } - LayerTexture* getOffscreenLayerTexture(); - void copyOffscreenTextureToDisplay(); unsigned createLayerTexture(); void deleteLayerTexture(unsigned); @@ -111,13 +111,13 @@ public: const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } const LayerChromium::BorderProgram* borderProgram() const { return m_borderProgram.get(); } const ContentLayerChromium::Program* contentLayerProgram() const { return m_contentLayerProgram.get(); } - const CanvasLayerChromium::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); } - const VideoLayerChromium::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); } - const VideoLayerChromium::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); } - const PluginLayerChromium::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); } const RenderSurfaceChromium::Program* renderSurfaceProgram() const { return m_renderSurfaceProgram.get(); } const RenderSurfaceChromium::MaskProgram* renderSurfaceMaskProgram() const { return m_renderSurfaceMaskProgram.get(); } const LayerTilerChromium::Program* tilerProgram() const { return m_tilerProgram.get(); } + const CCCanvasLayerImpl::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); } + const CCPluginLayerImpl::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); } + const CCVideoLayerImpl::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); } + const CCVideoLayerImpl::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); } void resizeOnscreenContent(const IntSize&); @@ -132,19 +132,21 @@ public: String layerTreeAsText() const; private: - explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D); + explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D>, PassOwnPtr<TilePaintInterface> contentPaint, PassOwnPtr<TilePaintInterface> scrollbarPaint); - void updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, - Vector<CCLayerImpl*>& renderSurfaceLayerList); - void updateRootLayerContents(TilePaintInterface&, const IntRect& visibleRect); - void updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect); + void updateLayers(Vector<CCLayerImpl*>& renderSurfaceLayerList); + void updateRootLayerContents(); + void updateRootLayerScrollbars(); void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList); - void updateContentsRecursive(LayerChromium*); + void paintContentsRecursive(LayerChromium*); + void updateCompositorResourcesRecursive(LayerChromium*); void drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList); void drawLayer(CCLayerImpl*, RenderSurfaceChromium*); void drawRootLayer(); + LayerTexture* getOffscreenLayerTexture(); + void copyOffscreenTextureToDisplay(); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); @@ -161,19 +163,22 @@ private: bool initializeSharedObjects(); void cleanupSharedObjects(); - static IntRect verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); - static IntRect horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); + IntRect verticalScrollbarRect() const; + IntRect horizontalScrollbarRect() const; - IntRect m_visibleRect; + IntRect m_viewportVisibleRect; + IntRect m_viewportContentRect; + IntPoint m_viewportScrollPosition; TransformationMatrix m_projectionMatrix; RefPtr<LayerChromium> m_rootLayer; - OwnPtr<LayerTilerChromium> m_rootLayerTiler; + OwnPtr<TilePaintInterface> m_rootLayerContentPaint; + OwnPtr<TilePaintInterface> m_rootLayerScrollbarPaint; + OwnPtr<LayerTilerChromium> m_rootLayerContentTiler; OwnPtr<LayerTilerChromium> m_horizontalScrollbarTiler; OwnPtr<LayerTilerChromium> m_verticalScrollbarTiler; - IntPoint m_scrollPosition; bool m_hardwareCompositing; unsigned m_currentShader; @@ -202,13 +207,13 @@ private: OwnPtr<GeometryBinding> m_sharedGeometry; OwnPtr<LayerChromium::BorderProgram> m_borderProgram; OwnPtr<ContentLayerChromium::Program> m_contentLayerProgram; - OwnPtr<CanvasLayerChromium::Program> m_canvasLayerProgram; - OwnPtr<VideoLayerChromium::RGBAProgram> m_videoLayerRGBAProgram; - OwnPtr<VideoLayerChromium::YUVProgram> m_videoLayerYUVProgram; - OwnPtr<PluginLayerChromium::Program> m_pluginLayerProgram; OwnPtr<RenderSurfaceChromium::Program> m_renderSurfaceProgram; OwnPtr<RenderSurfaceChromium::MaskProgram> m_renderSurfaceMaskProgram; OwnPtr<LayerTilerChromium::Program> m_tilerProgram; + OwnPtr<CCCanvasLayerImpl::Program> m_canvasLayerProgram; + OwnPtr<CCVideoLayerImpl::RGBAProgram> m_videoLayerRGBAProgram; + OwnPtr<CCVideoLayerImpl::YUVProgram> m_videoLayerYUVProgram; + OwnPtr<CCPluginLayerImpl::Program> m_pluginLayerProgram; OwnPtr<TextureManager> m_textureManager; diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp index 86592a6..bc37201 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp @@ -34,6 +34,7 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "LayerTexture.h" +#include "TraceEvent.h" #include <wtf/PassOwnArrayPtr.h> @@ -84,58 +85,50 @@ void LayerTilerChromium::reset() { m_tiles.clear(); m_unusedTiles.clear(); - m_tilingData.setTotalSize(0, 0); - m_lastUpdateLayerRect = IntRect(); } LayerTilerChromium::Tile* LayerTilerChromium::createTile(int i, int j) { - const int index = tileIndex(i, j); - ASSERT(!m_tiles[index]); + ASSERT(!tileAt(i, j)); + RefPtr<Tile> tile; if (m_unusedTiles.size() > 0) { - m_tiles[index] = m_unusedTiles.last().release(); + tile = m_unusedTiles.last().release(); m_unusedTiles.removeLast(); + ASSERT(tile->refCount() == 1); } else { GraphicsContext3D* context = layerRendererContext(); TextureManager* manager = layerRenderer()->textureManager(); - OwnPtr<Tile> tile = adoptPtr(new Tile(LayerTexture::create(context, manager))); - m_tiles[index] = tile.release(); + tile = adoptRef(new Tile(LayerTexture::create(context, manager))); } + m_tiles.add(make_pair(i, j), tile); + + tile->moveTo(i, j); + tile->m_dirtyLayerRect = tileLayerRect(tile.get()); - m_tiles[index]->m_dirtyLayerRect = tileLayerRect(i, j); - return m_tiles[index].get(); + return tile.get(); } -void LayerTilerChromium::invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect) +void LayerTilerChromium::invalidateTiles(const IntRect& contentRect) { if (!m_tiles.size()) return; - IntRect oldContentRect = layerRectToContentRect(oldLayerRect); - int oldLeft, oldTop, oldRight, oldBottom; - contentRectToTileIndices(oldContentRect, oldLeft, oldTop, oldRight, oldBottom); - - IntRect newContentRect = layerRectToContentRect(newLayerRect); - int newLeft, newTop, newRight, newBottom; - contentRectToTileIndices(newContentRect, newLeft, newTop, newRight, newBottom); - - // Iterating through just the old tile indices is an optimization to avoid - // iterating through the entire m_tiles array. - for (int j = oldTop; j <= oldBottom; ++j) { - for (int i = oldLeft; i <= oldRight; ++i) { - if (i >= newLeft && i <= newRight && j >= newTop && j <= newBottom) - continue; - - const int index = tileIndex(i, j); - if (m_tiles[index]) - m_unusedTiles.append(m_tiles[index].release()); - } + Vector<TileMapKey> removeKeys; + for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) { + Tile* tile = iter->second.get(); + IntRect tileRect = tileContentRect(tile); + if (tileRect.intersects(contentRect)) + continue; + removeKeys.append(iter->first); } + + for (size_t i = 0; i < removeKeys.size(); ++i) + m_unusedTiles.append(m_tiles.take(removeKeys[i])); } -void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const +void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int& left, int& top, int& right, int& bottom) const { const IntRect layerRect = contentRectToLayerRect(contentRect); @@ -163,36 +156,28 @@ IntRect LayerTilerChromium::layerRectToContentRect(const IntRect& layerRect) con return contentRect; } -int LayerTilerChromium::tileIndex(int i, int j) const +LayerTilerChromium::Tile* LayerTilerChromium::tileAt(int i, int j) const { - return m_tilingData.tileIndex(i, j); + Tile* tile = m_tiles.get(make_pair(i, j)).get(); + ASSERT(!tile || tile->refCount() == 1); + return tile; } -IntRect LayerTilerChromium::tileContentRect(int i, int j) const +IntRect LayerTilerChromium::tileContentRect(const Tile* tile) const { - IntRect contentRect = tileLayerRect(i, j); + IntRect contentRect = tileLayerRect(tile); contentRect.move(m_layerPosition.x(), m_layerPosition.y()); return contentRect; } -IntRect LayerTilerChromium::tileLayerRect(int i, int j) const +IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const { - const int index = m_tilingData.tileIndex(i, j); + const int index = m_tilingData.tileIndex(tile->i(), tile->j()); IntRect layerRect = m_tilingData.tileBoundsWithBorder(index); layerRect.setSize(m_tileSize); return layerRect; } -IntSize LayerTilerChromium::layerSize() const -{ - return IntSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); -} - -IntSize LayerTilerChromium::layerTileSize() const -{ - return IntSize(m_tilingData.numTilesX(), m_tilingData.numTilesY()); -} - void LayerTilerChromium::invalidateRect(const IntRect& contentRect) { if (contentRect.isEmpty()) @@ -202,16 +187,16 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect) // Dirty rects are always in layer space, as the layer could be repositioned // after invalidation. - IntRect layerRect = contentRectToLayerRect(contentRect); + const IntRect layerRect = contentRectToLayerRect(contentRect); int left, top, right, bottom; contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) continue; - IntRect bound = tileLayerRect(i, j); + IntRect bound = tileLayerRect(tile); bound.intersect(layerRect); tile->m_dirtyLayerRect.unite(bound); } @@ -220,14 +205,13 @@ void LayerTilerChromium::invalidateRect(const IntRect& contentRect) void LayerTilerChromium::invalidateEntireLayer() { - for (size_t i = 0; i < m_tiles.size(); ++i) { - if (m_tiles[i]) - m_unusedTiles.append(m_tiles[i].release()); + for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter) { + ASSERT(iter->second->refCount() == 1); + m_unusedTiles.append(iter->second.release()); } m_tiles.clear(); m_tilingData.setTotalSize(0, 0); - m_lastUpdateLayerRect = IntRect(); } void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& contentRect) @@ -237,10 +221,7 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont // Invalidate old tiles that were previously used but aren't in use this // frame so that they can get reused for new tiles. - IntRect layerRect = contentRectToLayerRect(contentRect); - invalidateTiles(m_lastUpdateLayerRect, layerRect); - m_lastUpdateLayerRect = layerRect; - + invalidateTiles(contentRect); growLayerToContain(contentRect); // Create tiles as needed, expanding a dirty rect to contain all @@ -250,11 +231,11 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); if (!tile->texture()->isValid(m_tileSize, GraphicsContext3D::RGBA)) - tile->m_dirtyLayerRect = tileLayerRect(i, j); + tile->m_dirtyLayerRect = tileLayerRect(tile); dirtyLayerRect.unite(tile->m_dirtyLayerRect); } } @@ -267,10 +248,16 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont m_canvas.resize(paintRect.size()); PlatformCanvas::Painter canvasPainter(&m_canvas); canvasPainter.context()->translate(-paintRect.x(), -paintRect.y()); - painter.paint(*canvasPainter.context(), paintRect); + { + TRACE_EVENT("LayerTilerChromium::update::paint", this, 0); + painter.paint(*canvasPainter.context(), paintRect); + } PlatformCanvas::AutoLocker locker(&m_canvas); - updateFromPixels(paintRect, locker.pixels()); + { + TRACE_EVENT("LayerTilerChromium::updateFromPixels", this, 0); + updateFromPixels(paintRect, locker.pixels()); + } } void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_t* paintPixels) @@ -285,14 +272,14 @@ void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_ contentRectToTileIndices(paintRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + Tile* tile = tileAt(i, j); if (!tile) CRASH(); if (!tile->dirty()) continue; // Calculate page-space rectangle to copy from. - IntRect sourceRect = tileContentRect(i, j); + IntRect sourceRect = tileContentRect(tile); const IntPoint anchor = sourceRect.location(); sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect)); if (sourceRect.isEmpty()) @@ -366,8 +353,7 @@ void LayerTilerChromium::draw(const IntRect& contentRect) contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - const int index = tileIndex(i, j); - Tile* tile = m_tiles[index].get(); + Tile* tile = tileAt(i, j); ASSERT(tile); tile->texture()->bindTexture(); @@ -376,11 +362,11 @@ void LayerTilerChromium::draw(const IntRect& contentRect) // Don't use tileContentRect here, as that contains the full // rect with border texels which shouldn't be drawn. - IntRect tileRect = m_tilingData.tileBounds(index); + IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(tile->i(), tile->j())); tileRect.move(m_layerPosition.x(), m_layerPosition.y()); tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0); - IntPoint texOffset = m_tilingData.textureOffset(i, j); + IntPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j()); float tileWidth = static_cast<float>(m_tileSize.width()); float tileHeight = static_cast<float>(m_tileSize.height()); float texTranslateX = texOffset.x() / tileWidth; @@ -395,37 +381,15 @@ void LayerTilerChromium::draw(const IntRect& contentRect) } } -void LayerTilerChromium::resizeLayer(const IntSize& size) -{ - if (layerSize() == size) - return; - - const IntSize oldTileSize = layerTileSize(); - m_tilingData.setTotalSize(size.width(), size.height()); - const IntSize newTileSize = layerTileSize(); - - if (oldTileSize == newTileSize) - return; - - if (newTileSize.height() && (newTileSize.width() > INT_MAX / newTileSize.height())) - CRASH(); - - Vector<OwnPtr<Tile> > newTiles; - newTiles.resize(newTileSize.width() * newTileSize.height()); - for (int j = 0; j < oldTileSize.height(); ++j) - for (int i = 0; i < oldTileSize.width(); ++i) - newTiles[i + j * newTileSize.width()].swap(m_tiles[i + j * oldTileSize.width()]); - m_tiles.swap(newTiles); -} - void LayerTilerChromium::growLayerToContain(const IntRect& contentRect) { // Grow the tile array to contain this content rect. IntRect layerRect = contentRectToLayerRect(contentRect); IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY()); - IntSize newSize = rectSize.expandedTo(layerSize()); - resizeLayer(newSize); + IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); + IntSize newSize = rectSize.expandedTo(oldLayerSize); + m_tilingData.setTotalSize(newSize.width(), newSize.height()); } void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h index bdb35a5..2f356e4 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h @@ -33,7 +33,9 @@ #include "LayerTexture.h" #include "PlatformCanvas.h" #include "TilingData.h" +#include <wtf/HashTraits.h> #include <wtf/OwnArrayPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { @@ -70,20 +72,26 @@ public: private: LayerTilerChromium(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption); - class Tile { + class Tile : public RefCounted<Tile> { WTF_MAKE_NONCOPYABLE(Tile); public: - explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex) {} + explicit Tile(PassOwnPtr<LayerTexture> tex) : m_tex(tex), m_i(-1), m_j(-1) {} LayerTexture* texture() { return m_tex.get(); } bool dirty() const { return !m_dirtyLayerRect.isEmpty(); } void clearDirty() { m_dirtyLayerRect = IntRect(); } + int i() const { return m_i; } + int j() const { return m_j; } + void moveTo(int i, int j) { m_i = i; m_j = j; } + // Layer-space dirty rectangle that needs to be repainted. IntRect m_dirtyLayerRect; private: OwnPtr<LayerTexture> m_tex; + int m_i; + int m_j; }; void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, @@ -92,40 +100,45 @@ private: float texScaleX, float texScaleY, const LayerTilerChromium::Program*); - void resizeLayer(const IntSize& size); // Grow layer size to contain this rectangle. void growLayerToContain(const IntRect& contentRect); LayerRendererChromium* layerRenderer() const { return m_layerRenderer; } GraphicsContext3D* layerRendererContext() const; Tile* createTile(int i, int j); - // Invalidate any tiles which do not intersect with the newLayerRect. - void invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect); + // Invalidate any tiles which do not intersect with the contentRect + void invalidateTiles(const IntRect& contentRect); void reset(); void contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const; IntRect contentRectToLayerRect(const IntRect& contentRect) const; IntRect layerRectToContentRect(const IntRect& layerRect) const; - // Returns the index into m_tiles for a given tile location. - int tileIndex(int i, int j) const; - // Returns the bounds in content space for a given tile location. - IntRect tileContentRect(int i, int j) const; - // Returns the bounds in layer space for a given tile location. - IntRect tileLayerRect(int i, int j) const; - - IntSize layerSize() const; - IntSize layerTileSize() const; + Tile* tileAt(int, int) const; + IntRect tileContentRect(const Tile*) const; + IntRect tileLayerRect(const Tile*) const; IntSize m_tileSize; - IntRect m_lastUpdateLayerRect; IntPoint m_layerPosition; bool m_skipsDraw; - // Logical 2D array of tiles (dimensions of m_layerTileSize) - Vector<OwnPtr<Tile> > m_tiles; - // Linear array of unused tiles. - Vector<OwnPtr<Tile> > m_unusedTiles; + // Default hash key traits for integers disallow 0 and -1 as a key, so + // use a custom hash trait which disallows -1 and -2 instead. + typedef std::pair<int, int> TileMapKey; + struct TileMapKeyTraits : HashTraits<TileMapKey> { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = false; + static TileMapKey emptyValue() { return std::make_pair(-1, -1); } + static void constructDeletedValue(TileMapKey& slot) { slot = std::make_pair(-2, -2); } + static bool isDeletedValue(TileMapKey value) { return value.first == -2 && value.second == -2; } + }; + // FIXME: The mapped value in TileMap should really be an OwnPtr, as the + // refcount of a Tile should never be more than 1. However, HashMap + // doesn't easily support OwnPtr as a value. + typedef HashMap<TileMapKey, RefPtr<Tile>, DefaultHash<TileMapKey>::Hash, TileMapKeyTraits> TileMap; + TileMap m_tiles; + // Tightly packed set of unused tiles. + Vector<RefPtr<Tile> > m_unusedTiles; PlatformCanvas m_canvas; diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp index 5d595ad..3667fbb 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp @@ -29,10 +29,10 @@ #include "PluginLayerChromium.h" -#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#include <GLES2/gl2.h> +#include "cc/CCLayerImpl.h" +#include "cc/CCPluginLayerImpl.h" namespace WebCore { @@ -43,40 +43,26 @@ PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromiu PluginLayerChromium::PluginLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) + , m_textureId(0) { } -void PluginLayerChromium::setTextureId(unsigned id) +PassRefPtr<CCLayerImpl> PluginLayerChromium::createCCLayerImpl() { - m_textureId = id; + return CCPluginLayerImpl::create(this); } -void PluginLayerChromium::updateContentsIfDirty() +void PluginLayerChromium::setTextureId(unsigned id) { + m_textureId = id; } -void PluginLayerChromium::draw() +void PluginLayerChromium::pushPropertiesTo(CCLayerImpl* layer) { - ASSERT(layerRenderer()); - const PluginLayerChromium::Program* program = layerRenderer()->pluginLayerProgram(); - ASSERT(program && program->initialized()); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GL_TEXTURE0)); - GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId)); - - // FIXME: setting the texture parameters every time is redundant. Move this code somewhere - // where it will only happen once per texture. - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - - layerRenderer()->useShader(program->program()); - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); + LayerChromium::pushPropertiesTo(layer); + + CCPluginLayerImpl* pluginLayer = static_cast<CCPluginLayerImpl*>(layer); + pluginLayer->setTextureId(m_textureId); } } diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h index 8d66f5f..852dc2e 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h @@ -38,18 +38,19 @@ class PluginLayerChromium : public LayerChromium { public: static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0); virtual bool drawsContent() const { return true; } - virtual void updateContentsIfDirty(); - virtual void draw(); - + + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + void setTextureId(unsigned textureId); - - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + unsigned textureId() const { return m_textureId; } + + virtual void pushPropertiesTo(CCLayerImpl*); protected: virtual const char* layerTypeAsString() const { return "PluginLayer"; } private: - PluginLayerChromium(GraphicsLayerChromium* owner); + explicit PluginLayerChromium(GraphicsLayerChromium* owner); unsigned m_textureId; }; diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp index 49b3462..b7f447b 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp @@ -248,7 +248,7 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo() , m_vTextureLocation(-1) , m_alphaLocation(-1) , m_ccMatrixLocation(-1) - , m_signAdjLocation(-1) + , m_yuvAdjLocation(-1) { } @@ -259,10 +259,10 @@ bool FragmentShaderYUVVideo::init(GraphicsContext3D* context, unsigned program) m_vTextureLocation = context->getUniformLocation(program, "v_texture"); m_alphaLocation = context->getUniformLocation(program, "alpha"); m_ccMatrixLocation = context->getUniformLocation(program, "cc_matrix"); - m_signAdjLocation = context->getUniformLocation(program, "adj"); + m_yuvAdjLocation = context->getUniformLocation(program, "yuv_adj"); return m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 - && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_signAdjLocation != -1; + && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_yuvAdjLocation != -1; } String FragmentShaderYUVVideo::getShaderString() const @@ -276,14 +276,15 @@ String FragmentShaderYUVVideo::getShaderString() const uniform sampler2D u_texture; uniform sampler2D v_texture; uniform float alpha; - uniform float adj; + uniform vec3 yuv_adj; uniform mat3 cc_matrix; void main() { - float y = texture2D(y_texture, y_texCoord).x; - float u = texture2D(u_texture, uv_texCoord).x - adj; - float v = texture2D(v_texture, uv_texCoord).x - adj; - vec3 rgb = cc_matrix * vec3(y, u, v); + float y_raw = texture2D(y_texture, y_texCoord).x; + float u_unsigned = texture2D(u_texture, uv_texCoord).x; + float v_unsigned = texture2D(v_texture, uv_texCoord).x; + vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj; + vec3 rgb = cc_matrix * yuv; gl_FragColor = vec4(rgb, float(1)) * alpha; } ); diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h index 758c62b..3a3e175 100644 --- a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h @@ -158,7 +158,7 @@ public: int vTextureLocation() const { return m_vTextureLocation; } int alphaLocation() const { return m_alphaLocation; } int ccMatrixLocation() const { return m_ccMatrixLocation; } - int signAdjLocation() const { return m_signAdjLocation; } + int yuvAdjLocation() const { return m_yuvAdjLocation; } private: int m_yTextureLocation; @@ -166,7 +166,7 @@ private: int m_vTextureLocation; int m_alphaLocation; int m_ccMatrixLocation; - int m_signAdjLocation; + int m_yuvAdjLocation; }; class FragmentShaderColor { diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index 9423d1e..7cd47fe 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -113,13 +113,13 @@ void SimpleFontData::platformInit() m_fontMetrics.setXHeight(xHeight); m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap)); - if (m_orientation == Vertical) { + if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G'); size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag); size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag); - if ((vheaSize <= 0) && (vorgSize <= 0)) - m_orientation = Horizontal; + if ((vheaSize > 0) || (vorgSize > 0)) + m_hasVerticalGlyphs = true; } // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 5d7a6e7..182e730 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,7 +33,6 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" -#include "cc/CCLayerImpl.h" #include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" @@ -41,17 +40,11 @@ #include "RenderLayerBacking.h" #include "VideoFrameChromium.h" #include "VideoFrameProvider.h" +#include "cc/CCLayerImpl.h" +#include "cc/CCVideoLayerImpl.h" namespace WebCore { -// These values are magic numbers that are used in the transformation -// from YUV to RGB color values. -const float VideoLayerChromium::yuv2RGB[9] = { - 1.f, 1.f, 1.f, - 0.f, -.344f, 1.772f, - 1.403f, -.714f, 0.f, -}; - PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner, VideoFrameProvider* provider) { @@ -71,23 +64,37 @@ VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameP VideoLayerChromium::~VideoLayerChromium() { cleanupResources(); + deleteTexturesInUse(); } -void VideoLayerChromium::cleanupResources() +PassRefPtr<CCLayerImpl> VideoLayerChromium::createCCLayerImpl() +{ + return CCVideoLayerImpl::create(this); +} + +void VideoLayerChromium::deleteTexturesInUse() { - LayerChromium::cleanupResources(); - releaseCurrentFrame(); if (!layerRenderer()) return; GraphicsContext3D* context = layerRendererContext(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - if (m_textures[plane]) - GLC(context, context->deleteTexture(m_textures[plane])); + Texture texture = m_textures[plane]; + if (!texture.isEmpty && texture.ownedByLayerRenderer) + GLC(context, context->deleteTexture(texture.id)); } } -void VideoLayerChromium::updateContentsIfDirty() +void VideoLayerChromium::cleanupResources() +{ + LayerChromium::cleanupResources(); + if (m_currentFrame) + releaseCurrentFrame(); + else + resetFrameParameters(); +} + +void VideoLayerChromium::updateCompositorResources() { if (!m_contentsDirty) return; @@ -116,6 +123,9 @@ void VideoLayerChromium::updateContentsIfDirty() return; } + // If the incoming frame is backed by a texture (i.e. decoded in hardware), + // then we do not need to allocate a texture via the layer renderer. Instead + // we save the texture data then exit. if (frame->surfaceType() == VideoFrameChromium::TypeTexture) { releaseCurrentFrame(); saveCurrentFrame(frame); @@ -136,8 +146,9 @@ void VideoLayerChromium::updateContentsIfDirty() // Update texture planes. for (unsigned plane = 0; plane < frame->planes(); plane++) { - ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]); - updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane)); + Texture texture = m_textures[plane]; + ASSERT(frame->requiredTextureSize(plane) == texture.size); + updateTexture(context, texture.id, texture.size, textureFormat, frame->data(plane)); } m_dirtyRect.setSize(FloatSize()); @@ -146,7 +157,19 @@ void VideoLayerChromium::updateContentsIfDirty() m_provider->putCurrentFrame(frame); } -unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) +void VideoLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCVideoLayerImpl* videoLayer = static_cast<CCVideoLayerImpl*>(layer); + videoLayer->setSkipsDraw(m_skipsDraw); + videoLayer->setFrameFormat(m_frameFormat); + for (size_t i = 0; i < 3; ++i) + videoLayer->setTexture(i, m_textures[i]); +} + + +unsigned VideoLayerChromium::determineTextureFormat(const VideoFrameChromium* frame) { switch (frame->format()) { case VideoFrameChromium::YV12: @@ -160,56 +183,68 @@ unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) return GraphicsContext3D::INVALID_VALUE; } -bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat) +bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, const VideoFrameChromium* frame, unsigned textureFormat) { ASSERT(context); ASSERT(frame); for (unsigned plane = 0; plane < frame->planes(); plane++) { - IntSize planeTextureSize = frame->requiredTextureSize(plane); + IntSize requiredTextureSize = frame->requiredTextureSize(plane); + Texture texture = m_textures[plane]; // If the renderer cannot handle this large of a texture, return false. // FIXME: Remove this test when tiled layers are implemented. - if (!layerRenderer()->checkTextureSize(planeTextureSize)) + if (!layerRenderer()->checkTextureSize(requiredTextureSize)) return false; - if (!m_textures[plane]) - m_textures[plane] = layerRenderer()->createLayerTexture(); - - if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) { - allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat); - m_textureSizes[plane] = planeTextureSize; - int frameWidth = frame->width(plane); - int frameHeight = frame->height(plane); - // When there are dead pixels at the edge of the texture, decrease - // the frame width by 1 to prevent the rightmost pixels from - // interpolating with the dead pixels. - if (frame->hasPaddingBytes(plane)) - --frameWidth; - m_frameSizes[plane] = IntSize(frameWidth, frameHeight); + if (texture.isEmpty) { + texture.id = layerRenderer()->createLayerTexture(); + texture.ownedByLayerRenderer = true; + texture.isEmpty = false; + } + + if (!requiredTextureSize.isZero() && requiredTextureSize != texture.size) { + allocateTexture(context, texture.id, requiredTextureSize, textureFormat); + texture.size = requiredTextureSize; + texture.visibleSize = computeVisibleSize(frame, plane); } + m_textures[plane] = texture; } + return true; +} + +IntSize VideoLayerChromium::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane) +{ + int visibleWidth = frame->width(plane); + int visibleHeight = frame->height(plane); + // When there are dead pixels at the edge of the texture, decrease + // the frame width by 1 to prevent the rightmost pixels from + // interpolating with the dead pixels. + if (frame->hasPaddingBytes(plane)) + --visibleWidth; + // In YV12, every 2x2 square of Y values corresponds to one U and // one V value. If we decrease the width of the UV plane, we must decrease the // width of the Y texture by 2 for proper alignment. This must happen // always, even if Y's texture does not have padding bytes. - if (frame->format() == VideoFrameChromium::YV12) { - int yPlaneOriginalWidth = frame->width(VideoFrameChromium::yPlane); - if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) - m_frameSizes[VideoFrameChromium::yPlane].setWidth(yPlaneOriginalWidth - 2); + if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) { + if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) { + int originalWidth = frame->width(plane); + visibleWidth = originalWidth - 2; + } } - return true; + return IntSize(visibleWidth, visibleHeight); } -void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) +void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const { GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE)); } -void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) +void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) const { ASSERT(context); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); @@ -225,33 +260,6 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text } } -void VideoLayerChromium::draw() -{ - if (m_skipsDraw) - return; - - ASSERT(layerRenderer()); - const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); - ASSERT(rgbaProgram && rgbaProgram->initialized()); - const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); - ASSERT(yuvProgram && yuvProgram->initialized()); - - switch (m_frameFormat) { - case VideoFrameChromium::YV12: - case VideoFrameChromium::YV16: - drawYUV(yuvProgram); - break; - case VideoFrameChromium::RGBA: - drawRGBA(rgbaProgram); - break; - default: - // FIXME: Implement other paths. - notImplemented(); - break; - } - releaseCurrentFrame(); -} - void VideoLayerChromium::releaseCurrentFrame() { if (!m_currentFrame) @@ -262,86 +270,29 @@ void VideoLayerChromium::releaseCurrentFrame() resetFrameParameters(); } -void VideoLayerChromium::drawYUV(const VideoLayerChromium::YUVProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); - - layerRenderer()->useShader(program->program()); - unsigned yFrameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); - unsigned yTextureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); - // Arbitrarily take the u sizes because u and v dimensions are identical. - unsigned uvFrameWidth = m_frameSizes[VideoFrameChromium::uPlane].width(); - unsigned uvTextureWidth = m_textureSizes[VideoFrameChromium::uPlane].width(); - - float yWidthScaleFactor = static_cast<float>(yFrameWidth) / yTextureWidth; - float uvWidthScaleFactor = static_cast<float>(uvFrameWidth) / uvTextureWidth; - GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); - GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); - - GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); - GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); - GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); - - // This value of 0.5 maps to 128. It is used in the YUV to RGB conversion - // formula to turn unsigned u and v values to signed u and v values. - // This is loaded as a uniform because certain drivers have problems - // reading literal float values. - GLC(context, context->uniform1f(program->fragmentShader().signAdjLocation(), 0.5)); - - GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); - - // Reset active texture back to texture 0. - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); -} - -void VideoLayerChromium::drawRGBA(const VideoLayerChromium::RGBAProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane])); - - layerRenderer()->useShader(program->program()); - unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width(); - unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width(); - float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; - GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); - - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); -} - void VideoLayerChromium::resetFrameParameters() { + deleteTexturesInUse(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - m_textures[plane] = 0; - m_textureSizes[plane] = IntSize(); - m_frameSizes[plane] = IntSize(); + m_textures[plane].id = 0; + m_textures[plane].size = IntSize(); + m_textures[plane].visibleSize = IntSize(); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = true; } } void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame) { ASSERT(!m_currentFrame); + deleteTexturesInUse(); m_currentFrame = frame; for (unsigned plane = 0; plane < frame->planes(); plane++) { - m_textures[plane] = frame->texture(plane); - m_textureSizes[plane] = frame->requiredTextureSize(plane); - m_frameSizes[plane] = m_textureSizes[plane]; + m_textures[plane].id = frame->texture(plane); + m_textures[plane].size = frame->requiredTextureSize(plane); + m_textures[plane].visibleSize = computeVisibleSize(frame, plane); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = false; } } diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h index 2170e13..ef08bd8 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h @@ -42,19 +42,28 @@ namespace WebCore { // A Layer that contains a Video element. class VideoLayerChromium : public LayerChromium { public: + struct Texture { + unsigned id; + IntSize size; + IntSize visibleSize; + bool ownedByLayerRenderer; + bool isEmpty; + }; + static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0, VideoFrameProvider* = 0); virtual ~VideoLayerChromium(); - virtual void updateContentsIfDirty(); + + virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); + + virtual void updateCompositorResources(); virtual bool drawsContent() const { return true; } - virtual void draw(); // This function is called by VideoFrameProvider. When this method is called // putCurrentFrame() must be called to return the frame currently held. void releaseCurrentFrame(); - typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram; - typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram; + virtual void pushPropertiesTo(CCLayerImpl*); protected: virtual void cleanupResources(); @@ -63,27 +72,27 @@ protected: private: VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*); - static unsigned determineTextureFormat(VideoFrameChromium*); - bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat); - void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*); - void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*); - void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat); - void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data); - void drawYUV(const YUVProgram*); - void drawRGBA(const RGBAProgram*); + static unsigned determineTextureFormat(const VideoFrameChromium*); + static IntSize computeVisibleSize(const VideoFrameChromium*, unsigned plane); + void deleteTexturesInUse(); + + bool allocateTexturesIfNeeded(GraphicsContext3D*, const VideoFrameChromium*, unsigned textureFormat); + void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const; + + void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data) const; + void resetFrameParameters(); void saveCurrentFrame(VideoFrameChromium*); - static const float yuv2RGB[9]; - bool m_skipsDraw; VideoFrameChromium::Format m_frameFormat; VideoFrameProvider* m_provider; - VideoFrameChromium* m_currentFrame; - unsigned m_textures[3]; - IntSize m_textureSizes[3]; - IntSize m_frameSizes[3]; + Texture m_textures[3]; + + // This will be null for the entire duration of video playback if hardware + // decoding is not being used. + VideoFrameChromium* m_currentFrame; }; } diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp index e83d045..652e752 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -47,10 +47,11 @@ PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium* WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner) : CanvasLayerChromium(owner) , m_context(0) + , m_textureUpdated(false) { } -void WebGLLayerChromium::updateContentsIfDirty() +void WebGLLayerChromium::updateCompositorResources() { if (!m_contentsDirty) return; @@ -68,19 +69,28 @@ void WebGLLayerChromium::updateContentsIfDirty() m_textureChanged = false; } // Update the contents of the texture used by the compositor. - if (m_contentsDirty) { + if (m_contentsDirty && m_textureUpdated) { m_context->prepareTexture(); + m_context->markLayerComposited(); m_contentsDirty = false; + m_textureUpdated = false; } } +void WebGLLayerChromium::setTextureUpdated() +{ + m_textureUpdated = true; +} + void WebGLLayerChromium::setContext(const GraphicsContext3D* context) { m_context = const_cast<GraphicsContext3D*>(context); unsigned int textureId = m_context->platformTexture(); - if (textureId != m_textureId) + if (textureId != m_textureId) { m_textureChanged = true; + m_textureUpdated = true; + } m_textureId = textureId; m_premultipliedAlpha = m_context->getContextAttributes().premultipliedAlpha; } diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h index 70be876..33db730 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h @@ -45,7 +45,8 @@ class WebGLLayerChromium : public CanvasLayerChromium { public: static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0); virtual bool drawsContent() const { return m_context; } - virtual void updateContentsIfDirty(); + virtual void updateCompositorResources(); + void setTextureUpdated(); void setContext(const GraphicsContext3D* context); @@ -55,6 +56,7 @@ protected: private: explicit WebGLLayerChromium(GraphicsLayerChromium* owner); GraphicsContext3D* m_context; + bool m_textureUpdated; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp new file mode 100644 index 0000000..649d049 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCCanvasLayerImpl.h" + +#include "CanvasLayerChromium.h" +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +CCCanvasLayerImpl::CCCanvasLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) + , m_textureId(0) + , m_premultipliedAlpha(true) +{ +} + +CCCanvasLayerImpl::~CCCanvasLayerImpl() +{ +} + +void CCCanvasLayerImpl::draw() +{ + ASSERT(layerRenderer()); + const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram(); + ASSERT(program && program->initialized()); + GraphicsContext3D* context = layerRenderer()->context(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); + GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; + GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); + +} + + +void CCCanvasLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "canvas layer texture id: " << m_textureId << " premultiplied: " << m_premultipliedAlpha << "\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h new file mode 100644 index 0000000..8cbf8d1 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCCanvasLayerImpl_h +#define CCCanvasLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class CCCanvasLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCCanvasLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCCanvasLayerImpl(owner)); + } + virtual ~CCCanvasLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setTextureId(unsigned id) { m_textureId = id; } + void setPremultipliedAlpha(bool premultipliedAlpha) { m_premultipliedAlpha = premultipliedAlpha; } +private: + explicit CCCanvasLayerImpl(LayerChromium*); + + unsigned m_textureId; + bool m_premultipliedAlpha; +}; + +} + +#endif // CCCanvasLayerImpl_h + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp index 604ef61..404944b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp @@ -66,8 +66,8 @@ void CCHeadsUpDisplay::draw() // Use a fullscreen texture only if we need to... IntSize hudSize; if (m_showPlatformLayerTree) { - hudSize.setWidth(min(2048, m_layerRenderer->visibleRectSize().width())); - hudSize.setHeight(min(2048, m_layerRenderer->visibleRectSize().height())); + hudSize.setWidth(min(2048, m_layerRenderer->viewportSize().width())); + hudSize.setHeight(min(2048, m_layerRenderer->viewportSize().height())); } else { hudSize.setWidth(512); hudSize.setHeight(128); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h index dbac22a..d56f8ab 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h @@ -53,7 +53,7 @@ public: void setShowPlatformLayerTree(bool enable) { m_showPlatformLayerTree = enable; } bool showPlatformLayerTree() const { return m_showPlatformLayerTree; } - bool enabled() const { return true || m_showPlatformLayerTree || m_showFPSCounter; } + bool enabled() const { return m_showPlatformLayerTree || m_showFPSCounter; } void draw(); private: diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp index a0ad0fb..9411e5a 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp @@ -62,13 +62,18 @@ namespace WebCore { CCLayerImpl::CCLayerImpl(LayerChromium* owner) : m_owner(owner) + , m_anchorPoint(0.5, 0.5) + , m_anchorPointZ(0) + , m_doubleSided(true) + , m_masksToBounds(false) + , m_opacity(1.0) + , m_preserves3D(false) #ifndef NDEBUG , m_debugID(owner->debugID()) #endif , m_targetRenderSurface(0) , m_drawDepth(0) , m_drawOpacity(0) - , m_doubleSided(true) , m_debugBorderColor(0, 0, 0, 0) , m_debugBorderWidth(0) , m_renderSurface(0) @@ -107,7 +112,18 @@ RenderSurfaceChromium* CCLayerImpl::createRenderSurface() return m_renderSurface.get(); } -// These belong on CCLayerImpl, but should be subclased by each type and not defer to the LayerChromium subtypes. +bool CCLayerImpl::descendantsDrawsContent() +{ + const Vector<RefPtr<LayerChromium> >& sublayers = m_owner->getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) { + sublayers[i]->createCCLayerImplIfNeeded(); + if (sublayers[i]->ccLayerImpl()->drawsContent() || sublayers[i]->ccLayerImpl()->descendantsDrawsContent()) + return true; + } + return false; +} + +// These belong on CCLayerImpl, but should be overridden by each type and not defer to the LayerChromium subtypes. bool CCLayerImpl::drawsContent() const { return m_owner->drawsContent(); @@ -118,6 +134,11 @@ void CCLayerImpl::draw() return m_owner->draw(); } +void CCLayerImpl::updateCompositorResources() +{ + return m_owner->updateCompositorResources(); +} + void CCLayerImpl::unreserveContentsTexture() { m_owner->unreserveContentsTexture(); @@ -167,7 +188,7 @@ void CCLayerImpl::drawDebugBorder() GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); } -static void writeIndent(TextStream& ts, int indent) +void CCLayerImpl::writeIndent(TextStream& ts, int indent) { for (int i = 0; i != indent; ++i) ts << " "; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h index 6892976..96c4f1b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -49,7 +49,7 @@ public: return adoptRef(new CCLayerImpl(owner)); } // When this class gets subclasses, remember to add 'virtual' here. - ~CCLayerImpl(); + virtual ~CCLayerImpl(); #ifndef NDEBUG int debugID() const { return m_debugID; } @@ -59,13 +59,43 @@ public: CCLayerImpl* maskLayer() const; CCLayerImpl* replicaLayer() const; - void draw(); - bool drawsContent() const; + virtual void draw(); + virtual void updateCompositorResources(); void unreserveContentsTexture(); void bindContentsTexture(); + // Returns true if this layer has content to draw. + virtual bool drawsContent() const; + + // Returns true if any of the layer's descendants has content to draw. + bool descendantsDrawsContent(); + void cleanupResources(); + void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; } + const FloatPoint& anchorPoint() const { return m_anchorPoint; } + + void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; } + float anchorPointZ() const { return m_anchorPointZ; } + + void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; } + bool masksToBounds() const { return m_masksToBounds; } + + void setOpacity(float opacity) { m_opacity = opacity; } + float opacity() const { return m_opacity; } + + void setPosition(const FloatPoint& position) { m_position = position; } + const FloatPoint& position() const { return m_position; } + + void setPreserves3D(bool preserves3D) { m_preserves3D = preserves3D; } + bool preserves3D() const { return m_preserves3D; } + + void setSublayerTransform(const TransformationMatrix& sublayerTransform) { m_sublayerTransform = sublayerTransform; } + const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } + + void setTransform(const TransformationMatrix& transform) { m_transform = transform; } + const TransformationMatrix& transform() const { return m_transform; } + void setName(const String& name) { m_name = name; } const String& name() const { return m_name; } @@ -108,11 +138,30 @@ public: virtual void dumpLayerProperties(TextStream&, int indent) const; -private: +protected: // For now, CCLayers are owned directly by a LayerChromium. LayerChromium* m_owner; explicit CCLayerImpl(LayerChromium*); + static void writeIndent(TextStream&, int indent); + +private: + // Properties synchronized from the associated LayerChromium. + FloatPoint m_anchorPoint; + float m_anchorPointZ; + IntSize m_bounds; + + // Whether the "back" of this layer should draw. + bool m_doubleSided; + + bool m_masksToBounds; + float m_opacity; + FloatPoint m_position; + bool m_preserves3D; + TransformationMatrix m_sublayerTransform; + TransformationMatrix m_transform; + + // Properties owned exclusively by this CCLayerImpl. // Debugging. #ifndef NDEBUG int m_debugID; @@ -131,17 +180,12 @@ private: float m_drawDepth; float m_drawOpacity; - // Whether the "back" of this layer should draw. - bool m_doubleSided; - // Debug borders. Color m_debugBorderColor; float m_debugBorderWidth; TransformationMatrix m_drawTransform; - IntSize m_bounds; - // The scissor rectangle that should be used when this layer is drawn. // Inherited by the parent layer and further restricted if this layer masks // to bounds. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp new file mode 100644 index 0000000..4aef639 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCPluginLayerImpl.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include "PluginLayerChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +CCPluginLayerImpl::CCPluginLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) + , m_textureId(0) +{ +} + +CCPluginLayerImpl::~CCPluginLayerImpl() +{ +} + +void CCPluginLayerImpl::draw() +{ + ASSERT(layerRenderer()); + const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram(); + ASSERT(program && program->initialized()); + GraphicsContext3D* context = layerRenderer()->context(); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); + + // FIXME: setting the texture parameters every time is redundant. Move this code somewhere + // where it will only happen once per texture. + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); +} + + +void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "plugin layer texture id: " << m_textureId << "\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h new file mode 100644 index 0000000..65eb5b7 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCPluginLayerImpl_h +#define CCPluginLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class CCPluginLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCPluginLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCPluginLayerImpl(owner)); + } + virtual ~CCPluginLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setTextureId(unsigned id) { m_textureId = id; } + +private: + explicit CCPluginLayerImpl(LayerChromium*); + + unsigned m_textureId; +}; + +} + +#endif // CCPluginLayerImpl_h + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp new file mode 100644 index 0000000..eb3612b --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCVideoLayerImpl.h" + +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" +#include "NotImplemented.h" +#include "VideoLayerChromium.h" +#include <wtf/text/WTFString.h> + +namespace WebCore { + +// These values are magic numbers that are used in the transformation +// from YUV to RGB color values. +// They are taken from the following webpage: +// http://www.fourcc.org/fccyvrgb.php +const float CCVideoLayerImpl::yuv2RGB[9] = { + 1.164f, 1.164f, 1.164f, + 0.f, -.391f, 2.018f, + 1.596f, -.813f, 0.f, +}; + +// These values map to 16, 128, and 128 respectively, and are computed +// as a fraction over 256 (e.g. 16 / 256 = 0.0625). +// They are used in the YUV to RGBA conversion formula: +// Y - 16 : Gives 16 values of head and footroom for overshooting +// U - 128 : Turns unsigned U into signed U [-128,127] +// V - 128 : Turns unsigned V into signed V [-128,127] +const float CCVideoLayerImpl::yuvAdjust[3] = { + -0.0625f, + -0.5f, + -0.5f, +}; + +CCVideoLayerImpl::CCVideoLayerImpl(LayerChromium* owner) + : CCLayerImpl(owner) +{ +} + +CCVideoLayerImpl::~CCVideoLayerImpl() +{ + cleanupResources(); +} + +void CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture) +{ + ASSERT(i < 3); + m_textures[i] = texture; +} + +void CCVideoLayerImpl::draw() +{ + if (m_skipsDraw) + return; + + ASSERT(layerRenderer()); + const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); + ASSERT(rgbaProgram && rgbaProgram->initialized()); + const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); + ASSERT(yuvProgram && yuvProgram->initialized()); + + switch (m_frameFormat) { + case VideoFrameChromium::YV12: + case VideoFrameChromium::YV16: + drawYUV(yuvProgram); + break; + case VideoFrameChromium::RGBA: + drawRGBA(rgbaProgram); + break; + default: + // FIXME: Implement other paths. + notImplemented(); + break; + } +} + +void CCVideoLayerImpl::drawYUV(const CCVideoLayerImpl::YUVProgram* program) const +{ + GraphicsContext3D* context = layerRenderer()->context(); + VideoLayerChromium::Texture yTexture = m_textures[VideoFrameChromium::yPlane]; + VideoLayerChromium::Texture uTexture = m_textures[VideoFrameChromium::uPlane]; + VideoLayerChromium::Texture vTexture = m_textures[VideoFrameChromium::vPlane]; + + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id)); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id)); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id)); + + layerRenderer()->useShader(program->program()); + + float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width(); + // Arbitrarily take the u sizes because u and v dimensions are identical. + float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width(); + GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); + GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); + + GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); + GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); + GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); + + GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); + GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1)); + + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); + + // Reset active texture back to texture 0. + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); +} + +void CCVideoLayerImpl::drawRGBA(const CCVideoLayerImpl::RGBAProgram* program) const +{ + GraphicsContext3D* context = layerRenderer()->context(); + VideoLayerChromium::Texture texture = m_textures[VideoFrameChromium::rgbPlane]; + + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture.id)); + + layerRenderer()->useShader(program->program()); + float widthScaleFactor = static_cast<float>(texture.visibleSize.width()) / texture.size.width(); + GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); + + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); +} + + +void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "video layer\n"; + CCLayerImpl::dumpLayerProperties(ts, indent); +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h new file mode 100644 index 0000000..62f8778 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCVideoLayerImpl_h +#define CCVideoLayerImpl_h + +#include "ProgramBinding.h" +#include "ShaderChromium.h" +#include "VideoFrameChromium.h" +#include "VideoLayerChromium.h" +#include "cc/CCLayerImpl.h" + +namespace WebCore { + +class VideoFrameProvider; + +class CCVideoLayerImpl : public CCLayerImpl { +public: + static PassRefPtr<CCVideoLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCVideoLayerImpl(owner)); + } + virtual ~CCVideoLayerImpl(); + + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram; + typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram; + + virtual void draw(); + + virtual void dumpLayerProperties(TextStream&, int indent) const; + + void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; } + void setFrameFormat(VideoFrameChromium::Format format) { m_frameFormat = format; } + void setTexture(size_t, VideoLayerChromium::Texture); + +private: + explicit CCVideoLayerImpl(LayerChromium*); + + void drawYUV(const YUVProgram*) const; + void drawRGBA(const RGBAProgram*) const; + + static const float yuv2RGB[9]; + static const float yuvAdjust[3]; + + bool m_skipsDraw; + VideoFrameChromium::Format m_frameFormat; + VideoLayerChromium::Texture m_textures[3]; +}; + +} + +#endif // CCVideoLayerImpl_h + |