Commit 2f0e7423 authored by eric@webkit.org's avatar eric@webkit.org
Browse files

2010-05-19 Vangelis Kokkevis <vangelis@chromium.org>

        Reviewed by Darin Fisher.

        Implementing hardware accelerated compositing of layers for Chromium.
        Completely removed the existing software compositing path to replace
        it with code implemented using OpenGL.
        https://bugs.webkit.org/show_bug.cgi?id=38783

        Tests: Covered by existing compositing tests.

        * WebCore.gyp/WebCore.gyp:
        * platform/graphics/chromium/GraphicsLayerChromium.cpp:
        (WebCore::GraphicsLayerChromium::~GraphicsLayerChromium):
        (WebCore::GraphicsLayerChromium::updateLayerDrawsContent):
        (WebCore::GraphicsLayerChromium::updateContentsRect):
        * platform/graphics/chromium/LayerChromium.cpp:
        (WebCore::LayerChromium::LayerChromium):
        (WebCore::LayerChromium::~LayerChromium):
        (WebCore::LayerChromium::updateGraphicsContext):
        (WebCore::LayerChromium::drawsContentUpdated):
        (WebCore::LayerChromium::updateContents):
        (WebCore::LayerChromium::setContents):
        (WebCore::LayerChromium::setBackingStoreSize):
        (WebCore::LayerChromium::setBounds):
        (WebCore::LayerChromium::setNeedsDisplay):
        * platform/graphics/chromium/LayerChromium.h:
        (WebCore::LayerChromium::contentsDirty):
        (WebCore::LayerChromium::drawsContent):
        * platform/graphics/chromium/LayerRendererChromium.cpp:
        (WebCore::):
        (WebCore::checkGLError):
        (WebCore::loadShader):
        (WebCore::loadShaderProgram):
        (WebCore::toGLMatrix):
        (WebCore::orthoMatrix):
        (WebCore::createLayerTexture):
        (WebCore::LayerRendererChromium::create):
        (WebCore::LayerRendererChromium::LayerRendererChromium):
        (WebCore::LayerRendererChromium::~LayerRendererChromium):
        (WebCore::LayerRendererChromium::drawTexturedQuad):
        (WebCore::LayerRendererChromium::drawLayers):
        (WebCore::LayerRendererChromium::getTextureId):
        (WebCore::LayerRendererChromium::assignTextureForLayer):
        (WebCore::LayerRendererChromium::freeLayerTexture):
        (WebCore::LayerRendererChromium::drawDebugBorder):
        (WebCore::LayerRendererChromium::isLayerVisible):
        (WebCore::LayerRendererChromium::compositeLayersRecursive):
        (WebCore::LayerRendererChromium::makeContextCurrent):
        (WebCore::LayerRendererChromium::initGL):
        (WebCore::LayerRendererChromium::bindCommonAttribLocation):
        (WebCore::LayerRendererChromium::initializeSharedGLObjects):
        * platform/graphics/chromium/LayerRendererChromium.h:
        (WebCore::LayerRendererChromium::):
2010-05-19  Vangelis Kokkevis  <vangelis@chromium.org>

        Reviewed by Darin Fisher.

        Modifying WebViewImpl to support new hardware compositing for
        LayerChromium layers.
        https://bugs.webkit.org/show_bug.cgi?id=38783

        * src/WebViewImpl.cpp:
        (WebKit::WebViewImpl::paint):
        (WebKit::WebViewImpl::setIsAcceleratedCompositingActive):
        (WebKit::WebViewImpl::updateRootLayerContents):
        (WebKit::WebViewImpl::setRootLayerNeedsDisplay):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@59822 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 383936c4
2010-05-19 Vangelis Kokkevis <vangelis@chromium.org>
Reviewed by Darin Fisher.
Implementing hardware accelerated compositing of layers for Chromium.
Completely removed the existing software compositing path to replace
it with code implemented using OpenGL.
https://bugs.webkit.org/show_bug.cgi?id=38783
Tests: Covered by existing compositing tests.
* WebCore.gyp/WebCore.gyp:
* platform/graphics/chromium/GraphicsLayerChromium.cpp:
(WebCore::GraphicsLayerChromium::~GraphicsLayerChromium):
(WebCore::GraphicsLayerChromium::updateLayerDrawsContent):
(WebCore::GraphicsLayerChromium::updateContentsRect):
* platform/graphics/chromium/LayerChromium.cpp:
(WebCore::LayerChromium::LayerChromium):
(WebCore::LayerChromium::~LayerChromium):
(WebCore::LayerChromium::updateGraphicsContext):
(WebCore::LayerChromium::drawsContentUpdated):
(WebCore::LayerChromium::updateContents):
(WebCore::LayerChromium::setContents):
(WebCore::LayerChromium::setBackingStoreSize):
(WebCore::LayerChromium::setBounds):
(WebCore::LayerChromium::setNeedsDisplay):
* platform/graphics/chromium/LayerChromium.h:
(WebCore::LayerChromium::contentsDirty):
(WebCore::LayerChromium::drawsContent):
* platform/graphics/chromium/LayerRendererChromium.cpp:
(WebCore::):
(WebCore::checkGLError):
(WebCore::loadShader):
(WebCore::loadShaderProgram):
(WebCore::toGLMatrix):
(WebCore::orthoMatrix):
(WebCore::createLayerTexture):
(WebCore::LayerRendererChromium::create):
(WebCore::LayerRendererChromium::LayerRendererChromium):
(WebCore::LayerRendererChromium::~LayerRendererChromium):
(WebCore::LayerRendererChromium::drawTexturedQuad):
(WebCore::LayerRendererChromium::drawLayers):
(WebCore::LayerRendererChromium::getTextureId):
(WebCore::LayerRendererChromium::assignTextureForLayer):
(WebCore::LayerRendererChromium::freeLayerTexture):
(WebCore::LayerRendererChromium::drawDebugBorder):
(WebCore::LayerRendererChromium::isLayerVisible):
(WebCore::LayerRendererChromium::compositeLayersRecursive):
(WebCore::LayerRendererChromium::makeContextCurrent):
(WebCore::LayerRendererChromium::initGL):
(WebCore::LayerRendererChromium::bindCommonAttribLocation):
(WebCore::LayerRendererChromium::initializeSharedGLObjects):
* platform/graphics/chromium/LayerRendererChromium.h:
(WebCore::LayerRendererChromium::):
2010-05-19 Andrey Kosyakov <caseq@chromium.org>
 
Reviewed by Timothy Hatcher.
......@@ -723,6 +723,7 @@
'include_dirs': [
'<(INTERMEDIATE_DIR)',
'<@(webcore_include_dirs)',
'<(chromium_src_dir)/gpu'
],
'sources': [
'<@(webcore_files)',
......
......@@ -101,12 +101,6 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
GraphicsLayerChromium::~GraphicsLayerChromium()
{
// Clean up the Skia layer.
if (m_layer)
m_layer->removeFromSuperlayer();
if (m_transformLayer)
m_transformLayer->removeFromSuperlayer();
}
void GraphicsLayerChromium::setName(const String& inName)
......@@ -485,6 +479,11 @@ void GraphicsLayerChromium::updateLayerPreserves3D()
void GraphicsLayerChromium::updateLayerDrawsContent()
{
// Since only layers that draw content have a valid context
// we need to call updateGraphicsContext() here to make sure one
// gets created.
m_layer->drawsContentUpdated();
if (m_drawsContent)
m_layer->setNeedsDisplay();
......@@ -533,7 +532,8 @@ void GraphicsLayerChromium::updateContentsRect()
if (!m_contentsLayer)
return;
m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
// The position of the layer is the center of quad.
m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x() + m_contentsRect.width() / 2, m_contentsRect.y() + m_contentsRect.height() / 2));
m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
}
......
......@@ -55,9 +55,10 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner)
, m_borderWidth(0)
, m_borderColor(0, 0, 0, 0)
, m_backgroundColor(0, 0, 0, 0)
, m_anchorPoint(0.5, 0.5)
, m_anchorPointZ(0)
, m_clearsContext(false)
, m_doubleSided(false)
, m_doubleSided(true)
, m_edgeAntialiasingMask(0)
, m_hidden(false)
, m_masksToBounds(false)
......@@ -69,9 +70,10 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner)
, m_skiaContext(0)
, m_graphicsContext(0)
, m_geometryFlipped(false)
, m_contentsDirty(false)
, m_contents(0)
, m_hasContext(false)
{
updateGraphicsContext(m_backingStoreRect);
}
LayerChromium::~LayerChromium()
......@@ -79,14 +81,30 @@ LayerChromium::~LayerChromium()
// Our superlayer should be holding a reference to us so there should be no
// way for us to be destroyed while we still have a superlayer.
ASSERT(!superlayer());
// Remove the superlayer reference from all sublayers.
removeAllSublayers();
}
void LayerChromium::updateGraphicsContext(const IntSize& size)
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(size.width(), size.height(), false);
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,
......@@ -95,31 +113,32 @@ void LayerChromium::updateGraphicsContext(const IntSize& size)
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
// The backing store allocated for a layer can be smaller than the layer's bounds.
// This is mostly true for the root layer whose backing store is sized based on the visible
// portion of the layer rather than the actual page size.
m_backingStoreRect = size;
return;
}
void LayerChromium::drawsContentUpdated()
{
// Create a drawing context if the layer now draws content
// or delete the existing context if the layer doesn't draw
// content anymore.
updateGraphicsContext();
}
void LayerChromium::updateContents()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (backing && !backing->paintingGoesToWindow())
if (backing && !backing->paintingGoesToWindow() && drawsContent())
m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height()));
}
void LayerChromium::drawDebugBorder()
{
m_graphicsContext->setStrokeColor(m_borderColor, DeviceColorSpace);
m_graphicsContext->setStrokeThickness(m_borderWidth);
m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(m_bounds.width(), 0));
m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(0, m_bounds.height()));
m_graphicsContext->drawLine(IntPoint(m_bounds.width(), 0), IntPoint(m_bounds.width(), m_bounds.height()));
m_graphicsContext->drawLine(IntPoint(0, m_bounds.height()), IntPoint(m_bounds.width(), m_bounds.height()));
m_contentsDirty = false;
}
void LayerChromium::setContents(NativeImagePtr contents)
......@@ -128,6 +147,7 @@ void LayerChromium::setContents(NativeImagePtr contents)
if (m_contents == contents)
return;
m_contents = contents;
m_contentsDirty = true;
}
void LayerChromium::setNeedsCommit()
......@@ -201,28 +221,29 @@ int LayerChromium::indexOfSublayer(const LayerChromium* reference)
return -1;
}
void LayerChromium::setBackingStoreRect(const IntSize& rect)
// 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_backingStoreRect == rect)
if (m_backingStoreSize == size)
return;
updateGraphicsContext(rect);
m_backingStoreSize = size;
updateGraphicsContext();
setNeedsCommit();
}
void LayerChromium::setBounds(const IntSize& rect)
void LayerChromium::setBounds(const IntSize& size)
{
if (rect == m_bounds)
if (m_bounds == size)
return;
m_bounds = rect;
m_bounds = size;
m_backingStoreSize = size;
// Re-create the canvas and associated contexts.
updateGraphicsContext(m_bounds);
// Layer contents need to be redrawn as the backing surface
// was recreated above.
updateContents();
updateGraphicsContext();
setNeedsCommit();
}
......@@ -270,8 +291,11 @@ LayerChromium* LayerChromium::superlayer() const
void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
{
// Redraw the contents of the layer.
updateContents();
// 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;
setNeedsCommit();
}
......
......@@ -151,6 +151,7 @@ public:
bool geometryFlipped() const { return m_geometryFlipped; }
void updateContents();
bool contentsDirty() { return m_contentsDirty; }
void setContents(NativeImagePtr contents);
NativeImagePtr contents() const { return m_contents; }
......@@ -158,9 +159,13 @@ public:
skia::PlatformCanvas* platformCanvas() { return m_canvas.get(); }
GraphicsContext* graphicsContext() { return m_graphicsContext.get(); }
void setBackingStoreRect(const IntSize&);
void setBackingStoreSize(const IntSize&);
void drawDebugBorder();
bool drawsContent() { return m_owner && m_owner->drawsContent(); }
// This method should be called every time the status drawsContent()
// status changes to ensure that the internal graphics context is in sync.
void drawsContentUpdated();
private:
LayerChromium(LayerType, GraphicsLayerChromium* owner);
......@@ -184,7 +189,8 @@ private:
// Re-creates the canvas and graphics context. This method
// must be called every time the layer is resized. Only layers
void updateGraphicsContext(const IntSize&);
// that do drawing and the root layer get a context.
void updateGraphicsContext();
Vector<RefPtr<LayerChromium> > m_sublayers;
LayerChromium* m_superlayer;
......@@ -195,11 +201,12 @@ private:
OwnPtr<PlatformContextSkia> m_skiaContext;
OwnPtr<GraphicsContext> m_graphicsContext;
#endif
bool m_hasContext;
LayerType m_layerType;
IntSize m_bounds;
IntSize m_backingStoreRect;
IntSize m_backingStoreSize;
FloatPoint m_position;
FloatPoint m_anchorPoint;
Color m_backgroundColor;
......@@ -223,6 +230,8 @@ private:
bool m_geometryFlipped;
bool m_needsDisplayOnBoundsChange;
bool m_contentsDirty;
ContentsGravityType m_contentsGravity;
NativeImagePtr m_contents;
String m_name;
......
......@@ -36,45 +36,98 @@
#include "IntRect.h"
#include "LayerChromium.h"
#include "SkBitmap.h"
#include <wtf/HashMap.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
namespace skia {
class PlatformCanvas;
}
namespace WebCore {
class GLES2Context;
class Page;
// Class that handles drawing of composited render layers using GL.
class LayerRendererChromium : public Noncopyable {
public:
static PassOwnPtr<LayerRendererChromium> create();
static PassOwnPtr<LayerRendererChromium> create(Page* page);
LayerRendererChromium();
LayerRendererChromium(Page* page);
~LayerRendererChromium();
#if PLATFORM(SKIA)
void drawLayersInCanvas(skia::PlatformCanvas*, const IntRect& clipRect);
#endif
void updateLayerContents();
// Updates the contents of the root layer that fall inside the updateRect and recomposites
// all the layers.
void drawLayers(const IntRect& updateRect, const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition);
void setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; }
LayerChromium* rootLayer() { return m_rootLayer.get(); }
void setNeedsDisplay() { m_needsDisplay = true; }
void setScrollFrame(SkIRect& scrollFrame) { m_scrollFrame = scrollFrame; }
// Frees the texture associated with the given layer.
bool freeLayerTexture(LayerChromium*);
bool hardwareCompositing() const { return m_hardwareCompositing; }
private:
#if PLATFORM(SKIA)
void drawLayerInCanvasRecursive(skia::PlatformCanvas*, LayerChromium*, float opacity);
#endif
void updateLayerContentsRecursive(LayerChromium*);
void compositeLayersRecursive(LayerChromium*, const TransformationMatrix&, float opacity, const IntRect& visibleRect);
void drawDebugBorder(LayerChromium*, const TransformationMatrix&);
void drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity, bool scrolling);
bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
void bindCommonAttribLocation(int location, char* attribName);
enum VboIds { Vertices, LayerElements };
// These are here only temporarily and should be removed once we switch over to GGL
bool initGL();
bool makeContextCurrent();
bool initializeSharedGLObjects();
int getTextureId(LayerChromium*);
int assignTextureForLayer(LayerChromium*);
// GL shader program object IDs.
unsigned int m_layerProgramObject;
unsigned int m_borderProgramObject;
unsigned int m_scrollProgramObject;
unsigned int m_rootLayerTextureId;
int m_rootLayerTextureWidth;
int m_rootLayerTextureHeight;
// Shader uniform and attribute locations.
const int m_positionLocation;
const int m_texCoordLocation;
int m_samplerLocation;
int m_matrixLocation;
int m_alphaLocation;
int m_scrollMatrixLocation;
int m_scrollSamplerLocation;
int m_borderMatrixLocation;
int m_borderColorLocation;
unsigned int m_quadVboIds[3];
TransformationMatrix m_projectionMatrix;
RefPtr<LayerChromium> m_rootLayer;
bool m_needsDisplay;
SkIRect m_scrollFrame;
IntPoint m_scrollPosition;
bool m_hardwareCompositing;
// Map associating layers with textures ids used by the GL compositor.
typedef HashMap<LayerChromium*, unsigned int> TextureIdMap;
TextureIdMap m_textureIdMap;
OwnPtr<GLES2Context> m_gles2Context;
// The WebCore Page that the compositor renders into.
Page* m_page;
};
}
......
2010-05-19 Vangelis Kokkevis <vangelis@chromium.org>
Reviewed by Darin Fisher.
Modifying WebViewImpl to support new hardware compositing for
LayerChromium layers.
https://bugs.webkit.org/show_bug.cgi?id=38783
* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::paint):
(WebKit::WebViewImpl::setIsAcceleratedCompositingActive):
(WebKit::WebViewImpl::updateRootLayerContents):
(WebKit::WebViewImpl::setRootLayerNeedsDisplay):
2010-05-19 Tony Chang <tony@chromium.org>
Reviewed by Kent Tamura.
......
......@@ -970,12 +970,19 @@ void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect)
// Draw the contents of the root layer.
updateRootLayerContents(rect);
// Composite everything into the canvas that's passed to us.
#if PLATFORM(SKIA)
m_layerRenderer->drawLayersInCanvas(static_cast<skia::PlatformCanvas*>(canvas), IntRect(rect));
#elif PLATFORM(CG)
#error "Need to implement CG version"
#endif
WebFrameImpl* webframe = mainFrameImpl();
if (!webframe)
return;
FrameView* view = webframe->frameView();
if (!view)
return;
// The visibleRect includes scrollbars whereas the contentRect doesn't.
IntRect visibleRect = view->visibleContentRect(true);
IntRect contentRect = view->visibleContentRect(false);
// Ask the layer compositor to redraw all the layers.
m_layerRenderer->drawLayers(rect, visibleRect, contentRect, IntPoint(view->scrollX(), view->scrollY()));
}
#endif
}
......@@ -2074,9 +2081,13 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
return;
if (active) {
m_layerRenderer = LayerRendererChromium::create();
if (m_layerRenderer)
m_layerRenderer = LayerRendererChromium::create(page());
if (m_layerRenderer->hardwareCompositing())
m_isAcceleratedCompositingActive = true;
else {
m_layerRenderer.clear();
m_isAcceleratedCompositingActive = false;
}
} else {
m_layerRenderer = 0;
m_isAcceleratedCompositingActive = false;
......@@ -2088,6 +2099,12 @@ void WebViewImpl::updateRootLayerContents(const WebRect& rect)
if (!isAcceleratedCompositingActive())
return;
// FIXME: The accelerated compositing path invalidates a 1x1 rect at (0, 0)
// in order to get the renderer to ask the compositor to redraw. This is only
// temporary until we get the compositor to render directly from its own thread.
if (!rect.x && !rect.y && rect.width == 1 && rect.height == 1)
return;
WebFrameImpl* webframe = mainFrameImpl();
if (!webframe)
return;
......@@ -2095,24 +2112,28 @@ void WebViewImpl::updateRootLayerContents(const WebRect& rect)
if (!view)
return;
WebRect viewRect = view->frameRect();
SkIRect scrollFrame;
scrollFrame.set(view->scrollX(), view->scrollY(), view->layoutWidth() + view->scrollX(), view->layoutHeight() + view->scrollY());
m_layerRenderer->setScrollFrame(scrollFrame);
LayerChromium* rootLayer = m_layerRenderer->rootLayer();
if (rootLayer) {
IntRect visibleRect = view->visibleContentRect(true);
// Set the backing store size used by the root layer to be the size of the visible
// area. Note that the root layer bounds could be larger than the backing store size,
// but there's no reason to waste memory by allocating backing store larger than the
// visible portion.
rootLayer->setBackingStoreRect(IntSize(visibleRect.width(), visibleRect.height()));
// Update the root layer's backing store to be the size of the dirty rect.
// Unlike other layers the root layer doesn't have persistent storage for its
// contents in system memory.
rootLayer->setBackingStoreSize(IntSize(rect.width, rect.height));
GraphicsContext* rootLayerContext = rootLayer->graphicsContext();
skia::PlatformCanvas* platformCanvas = rootLayer->platformCanvas();
platformCanvas->save();
// Bring the canvas into the coordinate system of the paint rect.
platformCanvas->translate(static_cast<SkScalar>(-rect.x), static_cast<SkScalar>(-rect.y));
rootLayerContext->save();
webframe->paintWithContext(*(rootLayer->graphicsContext()), rect);
rootLayerContext->restore();
platformCanvas->restore();
}
}
......@@ -2121,8 +2142,10 @@ void WebViewImpl::setRootLayerNeedsDisplay()
// FIXME: For now we're posting a repaint event for the entire page which is an overkill.
if (WebFrameImpl* webframe = mainFrameImpl()) {
if (FrameView* view = webframe->frameView()) {
// FIXME: Temporary hack to invalidate part of the page so that we get called to render
// again.
IntRect visibleRect = view->visibleContentRect(true);
m_client->didInvalidateRect(visibleRect);
m_client->didInvalidateRect(IntRect(0, 0, 1, 1));
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment