diff options
Diffstat (limited to 'WebCore/platform/graphics/chromium/LayerChromium.cpp')
-rw-r--r-- | WebCore/platform/graphics/chromium/LayerChromium.cpp | 156 |
1 files changed, 89 insertions, 67 deletions
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 8fb28ef..b08df82 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -34,10 +34,17 @@ #include "LayerChromium.h" +#include "LayerRendererChromium.h" +#if PLATFORM(SKIA) +#include "NativeImageSkia.h" #include "PlatformContextSkia.h" +#endif #include "RenderLayerBacking.h" #include "skia/ext/platform_canvas.h" +#include <GLES2/gl2.h> + + namespace WebCore { using namespace std; @@ -52,7 +59,9 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) , m_owner(owner) , m_layerType(type) , m_superlayer(0) + , m_layerRenderer(0) , m_borderWidth(0) + , m_allocatedTextureId(0) , m_borderColor(0, 0, 0, 0) , m_backgroundColor(0, 0, 0, 0) , m_anchorPoint(0.5, 0.5) @@ -66,13 +75,9 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) , m_opacity(1.0) , m_opaque(true) , m_zPosition(0.0) - , m_canvas(0) - , m_skiaContext(0) - , m_graphicsContext(0) , m_geometryFlipped(false) , m_contentsDirty(false) , m_contents(0) - , m_hasContext(false) { } @@ -84,61 +89,92 @@ LayerChromium::~LayerChromium() // Remove the superlayer reference from all sublayers. removeAllSublayers(); -} - -void LayerChromium::updateGraphicsContext() -{ - // If the layer doesn't draw anything (e.g. it's a container layer) then we - // don't create a canvas / context for it. The root layer is a special - // case as even if it's marked as a container layer it does actually have - // content that it draws. - RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); - if (!drawsContent() && !(this == rootLayer())) { - m_graphicsContext.clear(); - m_skiaContext.clear(); - m_canvas.clear(); - m_hasContext = false; - return; - } - -#if PLATFORM(SKIA) - // Create new canvas and context. OwnPtr takes care of freeing up - // the old ones. - m_canvas = new skia::PlatformCanvas(m_backingStoreSize.width(), m_backingStoreSize.height(), false); - m_skiaContext = new PlatformContextSkia(m_canvas.get()); - - // This is needed to get text to show up correctly. Without it, - // GDI renders with zero alpha and the text becomes invisible. - // Unfortunately, setting this to true disables cleartype. - m_skiaContext->setDrawingToImageBuffer(true); - - m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get())); - m_hasContext = true; - m_contentsDirty = true; -#else -#error "Need to implement for your platform." -#endif - - return; + // Notify the renderer to clean up the texture associated with the layer. + if (m_layerRenderer) + m_layerRenderer->freeLayerTexture(this); } -void LayerChromium::drawsContentUpdated() +void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) { - // Create a drawing context if the layer now draws content - // or delete the existing context if the layer doesn't draw - // content anymore. - updateGraphicsContext(); + // It's not expected that layers will ever switch renderers. + ASSERT(!renderer || !m_layerRenderer || renderer == m_layerRenderer); + + m_layerRenderer = renderer; } -void LayerChromium::updateContents() +void LayerChromium::updateTextureContents(unsigned int textureId) { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); - if (backing && !backing->paintingGoesToWindow() && drawsContent()) - m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height())); + if (backing && !backing->paintingGoesToWindow()) { + void* pixels = 0; + IntRect dirtyRect(m_dirtyRect); + IntSize requiredTextureSize; + IntSize bitmapSize; +#if PLATFORM(SKIA) + const SkBitmap* skiaBitmap = 0; + OwnPtr<skia::PlatformCanvas> canvas; + OwnPtr<PlatformContextSkia> skiaContext; + OwnPtr<GraphicsContext> graphicsContext; + if (drawsContent()) { // Layer contents must be drawn into a canvas. + canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); + skiaContext.set(new PlatformContextSkia(canvas.get())); + + // This is needed to get text to show up correctly. Without it, + // GDI renders with zero alpha and the text becomes invisible. + // Unfortunately, setting this to true disables cleartype. + // FIXME: Does this take us down a very slow text rendering path? + skiaContext->setDrawingToImageBuffer(true); + + graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); + + // Bring the canvas into the coordinate system of the paint rect. + canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); + + m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); + const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); + skiaBitmap = &bitmap; + requiredTextureSize = IntSize(max(m_bounds.width(), dirtyRect.width()), + max(m_bounds.height(), dirtyRect.height())); + } else { // Layer is a container. + // The layer contains an Image. + NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(contents()); + skiaBitmap = skiaImage; + requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + } + + ASSERT(skiaBitmap); + SkAutoLockPixels lock(*skiaBitmap); + SkBitmap::Config skiaConfig = skiaBitmap->config(); + // FIXME: do we need to support more image configurations? + if (skiaConfig == SkBitmap::kARGB_8888_Config) { + pixels = skiaBitmap->getPixels(); + bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + } +#else +#error "Need to implement for your platform." +#endif + if (pixels) { + glBindTexture(GL_TEXTURE_2D, textureId); + // If the texture id or size changed since last time then we need to tell GL + // to re-allocate a texture. + if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) { + ASSERT(bitmapSize == requiredTextureSize); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + m_allocatedTextureId = textureId; + m_allocatedTextureSize = requiredTextureSize; + } else { + ASSERT(dirtyRect.width() <= m_allocatedTextureSize.width() && dirtyRect.height() <= m_allocatedTextureSize.height()); + ASSERT(dirtyRect.width() == bitmapSize.width() && dirtyRect.height() == bitmapSize.height()); + glTexSubImage2D(GL_TEXTURE_2D, 0, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + } + } m_contentsDirty = false; + m_dirtyRect.setSize(FloatSize()); } void LayerChromium::setContents(NativeImagePtr contents) @@ -147,7 +183,7 @@ void LayerChromium::setContents(NativeImagePtr contents) if (m_contents == contents) return; m_contents = contents; - m_contentsDirty = true; + setNeedsDisplay(); } void LayerChromium::setNeedsCommit() @@ -221,19 +257,6 @@ int LayerChromium::indexOfSublayer(const LayerChromium* reference) return -1; } -// This method can be called to overide the size of the backing store -// used for the layer. It's typically called on the root layer to limit -// its size to the actual visible size. -void LayerChromium::setBackingStoreSize(const IntSize& size) -{ - if (m_backingStoreSize == size) - return; - - m_backingStoreSize = size; - updateGraphicsContext(); - setNeedsCommit(); -} - void LayerChromium::setBounds(const IntSize& size) { if (m_bounds == size) @@ -242,8 +265,6 @@ void LayerChromium::setBounds(const IntSize& size) m_bounds = size; m_backingStoreSize = size; - // Re-create the canvas and associated contexts. - updateGraphicsContext(); setNeedsCommit(); } @@ -293,16 +314,17 @@ void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) { // Simply mark the contents as dirty. The actual redraw will // happen when it's time to do the compositing. - // FIXME: Should only update the dirty rect instead of marking - // the entire layer dirty. m_contentsDirty = true; + m_dirtyRect.unite(dirtyRect); + setNeedsCommit(); } void LayerChromium::setNeedsDisplay() { - // FIXME: implement + m_dirtyRect.setSize(m_bounds); + m_contentsDirty = true; } } |