summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/chromium/LayerChromium.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/chromium/LayerChromium.cpp')
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp156
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;
}
}