2011-01-19 Stephen White <senorblanco@chromium.org>
authorsenorblanco@chromium.org <senorblanco@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 13:48:56 +0000 (13:48 +0000)
committersenorblanco@chromium.org <senorblanco@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 13:48:56 +0000 (13:48 +0000)
        [Re-land of r76159 with a compile fix for the Chromium linux shlib
        build.]

        Reviewed by James Robinson.

        Implement accelerated path drawing and clipping for the Canvas2D GPU
        path.
        https://bugs.webkit.org/show_bug.cgi?id=52627

        This is done with a simple curve interpolator and the GLU tesselator,
        which is good enough for a 3-5X speedup on
        http://ie.microsoft.com/testdrive/Performance/Galactic/Default.html.

        Covered by canvas/philip/2d.path.clip.basic.html, and many, many more.
        All tests canvas/philip and fast/canvas paths pass with no
        regressions, although two have minor pixel differences which require
        rebaselining.

        * WebCore.gyp/WebCore.gyp:
        Add internal_glu include path to chromium build.
        * WebCore.gypi:
        Add internal_glu files to chromium build.
        * html/canvas/CanvasRenderingContext2D.cpp:
        (WebCore::CanvasRenderingContext2D::reset):
        (WebCore::CanvasRenderingContext2D::platformLayer):
        Make CanvasRenderingContext2D more robust against failure to create
        a DrawingBuffer.
        * platform/graphics/chromium/DrawingBufferChromium.cpp:
        (WebCore::DrawingBuffer::DrawingBuffer):
        As in DrawingBufferMac.cpp, call reset() from the constructor.
        Also initialize size to (-1, -1), so reset() doesn't early-out.
        Add initializers for depthBuffer and stencilBuffer, and remove
        multisampleDepthStencilBuffer.
        * platform/graphics/chromium/GLES2Canvas.cpp:
        Remove some unused #includes.
        (WebCore::GLES2Canvas::State::State):
        Add clipping state, and implement save/restore via the copy constructor.
        (WebCore::operator*):
        (WebCore::Quadratic::Quadratic):
        (WebCore::Quadratic::fromBezier):
        (WebCore::Quadratic::evaluate):
        Quadratic Bezier curve class.
        (WebCore::Cubic::Cubic):
        (WebCore::Cubic::fromBezier):
        (WebCore::Cubic::evaluate):
        Cubic Bezier curve class.
        (WebCore::GLES2Canvas::clearRect):
        Add clipping support to clearRect().
        (WebCore::GLES2Canvas::fillPath):
        Implement fillPath().
        (WebCore::GLES2Canvas::fillRect):
        Add clipping support to fillRect().
        (WebCore::GLES2Canvas::clipPath):
        Implement clipPath().
        (WebCore::GLES2Canvas::clipOut):
        Stub out clipOut() (not called by Canvas 2D).
        (WebCore::GLES2Canvas::restore):
        When restoring, draw any remaining clipping paths to the stencil buffer.
        (WebCore::GLES2Canvas::drawTexturedRect):
        Add clipping support.
        (WebCore::interpolateQuadratic):
        (WebCore::interpolateCubic):
        Simple curve interpolation, using the Cubic and Quadratic classes.
        (WebCore::PolygonData::PolygonData):
        A struct to hold the tesselation data for callbacks.
        (WebCore::beginData):
        (WebCore::edgeFlagData):
        (WebCore::vertexData):
        (WebCore::endData):
        (WebCore::combineData):
        internal_glu tesselation callbacks.
        (WebCore::GLES2Canvas::createVertexBufferFromPath):
        Build an interpolated, tesselated vertex buffer and element array buffer from a given path, suitable for filling.
        (WebCore::GLES2Canvas::beginStencilDraw):
        Enable stencilling, and disable draws to the color buffer.
        (WebCore::GLES2Canvas::applyClipping):
        If clipping is enabled, set the appropriate GL state.
        * platform/graphics/chromium/GLES2Canvas.h:
        Document the flavours of drawTexturedRect() a bit, so I don't get confused.
        * platform/graphics/gpu/DrawingBuffer.cpp:
        (WebCore::DrawingBuffer::clear):
        (WebCore::DrawingBuffer::createSecondaryBuffers):
        (WebCore::DrawingBuffer::resizeDepthStencil):
        (WebCore::DrawingBuffer::reset):
        * platform/graphics/gpu/DrawingBuffer.h:
        Unify m_multisampleDepthStencilBuffer with m_depthStencilBuffer.
        Implement separate depth and stencil buffers for when
        OES_packed_depth_stencil is not available.  Refactor creation of
        multisampled and non-multisampled depth and stencil buffers into
        resizeDepthStencil().
        * platform/graphics/gpu/SharedGraphicsContext3D.cpp:
        (WebCore::SharedGraphicsContext3D::create):
        Turn on stencil, turn off depth, turn off antialiasing (for now).
        (WebCore::SharedGraphicsContext3D::enableStencil):
        * platform/graphics/gpu/SharedGraphicsContext3D.h:
        Implement stencil enable/disable.
        * platform/graphics/gpu/mac/DrawingBufferMac.mm:
        (WebCore::DrawingBuffer::DrawingBuffer):
        Remove m_multisampleDepthStencilBuffer.  Set the size to (-1, -1)
        on creation, so reset() doesn't early-out.  Initialize m_depthBuffer
        and m_stencilBuffer.
        * platform/graphics/skia/GraphicsContextSkia.cpp:
        (WebCore::GraphicsContext::canvasClip):
        (WebCore::GraphicsContext::clipOut):
        (WebCore::GraphicsContext::clipPath):
        (WebCore::GraphicsContext::fillPath):
        Put in GPU hooks for path clipping, and path drawing.
        * platform/graphics/skia/PlatformContextSkia.cpp:
        (WebCore::PlatformContextSkia::canAccelerate):
        Don't check for clipping paths in canAccelerate() (since we can
        now accelerate them).
        (WebCore::PlatformContextSkia::uploadSoftwareToHardware):
        Don't do clipping when uploading software draws to hardware.
        * thirdparty/glu/README.webkit:
        * thirdparty/glu/gluos.h:
        #undef MIN and MAX, to fix warnings-as-errors in Chrome/Mac build.
        * thirdparty/glu/libtess/geom.c:
        * thirdparty/glu/libtess/priorityq.c:
        * thirdparty/glu/libtess/render.c:
        Use do{}while(0) instead of if(1)else construct in macro.
        * thirdparty/glu/libtess/sweep.c:
        (IsWindingInside):
        (DoneEdgeDict):
        Fix some warnings treated as errors for the Linux Release build.

2011-01-19  Stephen White  <senorblanco@chromium.org>

        Reviewed by James Robinson.

        Add two to-be-rebaselined tests for the GPU path.

        * platform/chromium-gpu/test_expectations.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76235 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/chromium-gpu/test_expectations.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.gyp/WebCore.gyp
Source/WebCore/WebCore.gypi
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
Source/WebCore/platform/graphics/gpu/DrawingBuffer.h
Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
Source/WebCore/platform/graphics/gpu/mac/DrawingBufferMac.mm
Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
Source/WebCore/thirdparty/glu/README.webkit
Source/WebCore/thirdparty/glu/gluos.h
Source/WebCore/thirdparty/glu/libtess/geom.c
Source/WebCore/thirdparty/glu/libtess/priorityq.c
Source/WebCore/thirdparty/glu/libtess/render.c
Source/WebCore/thirdparty/glu/libtess/sweep.c

index a523b6f181a8aaec68129b6ae1df8cc33f4607d4..eb9ab32c0e9a24ac7ac0a08225fb29a52414c40b 100644 (file)
@@ -1,3 +1,11 @@
+2011-01-19  Stephen White  <senorblanco@chromium.org>
+
+        Reviewed by James Robinson. 
+        
+        Add two to-be-rebaselined tests for the GPU path. 
+        
+        * platform/chromium-gpu/test_expectations.txt: 
+
 2011-01-20  Pavel Feldman  <pfeldman@chromium.org>
 
         Not reviewed: rebaselined inspector tests.
index e8d6a39039a8ad90fadad745a63a149b5b57cd6a..31c3d36d9301f6fc992816cf2b784e0758a543fb 100644 (file)
@@ -388,3 +388,7 @@ BUGWK51989 WIN LINUX : fast/canvas/canvas-fillRect-gradient-shadow.html = TEXT
 
 // Started failing after r75648 on everything except Snow Leopard
 BUGWK52341 : fast/canvas/canvas-large-dimensions.html = TEXT
+
+// These will need to rebaselined after the new path drawing lands. 
+BUG_SENORBLANCO WIN LINUX : fast/canvas/canvas-composite.html = IMAGE 
+BUG_SENORBLANCO WIN LINUX : fast/canvas/canvas-transform-skewed.html = IMAGE 
index c817ce5dab9f75d120fa490bbdacba8a0efed076..b38ceb85a46c7a66e498d8597b1aa21b3925ff09 100644 (file)
@@ -1,3 +1,131 @@
+2011-01-19  Stephen White  <senorblanco@chromium.org>
+
+        [Re-land of r76159 with a compile fix for the Chromium linux shlib
+        build.]
+
+        Reviewed by James Robinson.
+
+        Implement accelerated path drawing and clipping for the Canvas2D GPU
+        path.
+        https://bugs.webkit.org/show_bug.cgi?id=52627
+        
+        This is done with a simple curve interpolator and the GLU tesselator,
+        which is good enough for a 3-5X speedup on
+        http://ie.microsoft.com/testdrive/Performance/Galactic/Default.html.
+
+        Covered by canvas/philip/2d.path.clip.basic.html, and many, many more.
+        All tests canvas/philip and fast/canvas paths pass with no
+        regressions, although two have minor pixel differences which require
+        rebaselining.
+
+        * WebCore.gyp/WebCore.gyp:
+        Add internal_glu include path to chromium build.
+        * WebCore.gypi:
+        Add internal_glu files to chromium build.
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::reset):
+        (WebCore::CanvasRenderingContext2D::platformLayer):
+        Make CanvasRenderingContext2D more robust against failure to create
+        a DrawingBuffer.
+        * platform/graphics/chromium/DrawingBufferChromium.cpp:
+        (WebCore::DrawingBuffer::DrawingBuffer):
+        As in DrawingBufferMac.cpp, call reset() from the constructor.
+        Also initialize size to (-1, -1), so reset() doesn't early-out.
+        Add initializers for depthBuffer and stencilBuffer, and remove
+        multisampleDepthStencilBuffer.
+        * platform/graphics/chromium/GLES2Canvas.cpp:
+        Remove some unused #includes.
+        (WebCore::GLES2Canvas::State::State):
+        Add clipping state, and implement save/restore via the copy constructor.
+        (WebCore::operator*):
+        (WebCore::Quadratic::Quadratic):
+        (WebCore::Quadratic::fromBezier):
+        (WebCore::Quadratic::evaluate):
+        Quadratic Bezier curve class.
+        (WebCore::Cubic::Cubic):
+        (WebCore::Cubic::fromBezier):
+        (WebCore::Cubic::evaluate):
+        Cubic Bezier curve class.
+        (WebCore::GLES2Canvas::clearRect):
+        Add clipping support to clearRect().
+        (WebCore::GLES2Canvas::fillPath):
+        Implement fillPath().
+        (WebCore::GLES2Canvas::fillRect):
+        Add clipping support to fillRect().
+        (WebCore::GLES2Canvas::clipPath):
+        Implement clipPath().
+        (WebCore::GLES2Canvas::clipOut):
+        Stub out clipOut() (not called by Canvas 2D).
+        (WebCore::GLES2Canvas::restore):
+        When restoring, draw any remaining clipping paths to the stencil buffer.
+        (WebCore::GLES2Canvas::drawTexturedRect):
+        Add clipping support.
+        (WebCore::interpolateQuadratic):
+        (WebCore::interpolateCubic):
+        Simple curve interpolation, using the Cubic and Quadratic classes.
+        (WebCore::PolygonData::PolygonData):
+        A struct to hold the tesselation data for callbacks.
+        (WebCore::beginData):
+        (WebCore::edgeFlagData):
+        (WebCore::vertexData):
+        (WebCore::endData):
+        (WebCore::combineData):
+        internal_glu tesselation callbacks.
+        (WebCore::GLES2Canvas::createVertexBufferFromPath):
+        Build an interpolated, tesselated vertex buffer and element array buffer from a given path, suitable for filling.
+        (WebCore::GLES2Canvas::beginStencilDraw):
+        Enable stencilling, and disable draws to the color buffer.
+        (WebCore::GLES2Canvas::applyClipping):
+        If clipping is enabled, set the appropriate GL state.
+        * platform/graphics/chromium/GLES2Canvas.h:
+        Document the flavours of drawTexturedRect() a bit, so I don't get confused.
+        * platform/graphics/gpu/DrawingBuffer.cpp:
+        (WebCore::DrawingBuffer::clear):
+        (WebCore::DrawingBuffer::createSecondaryBuffers):
+        (WebCore::DrawingBuffer::resizeDepthStencil):
+        (WebCore::DrawingBuffer::reset):
+        * platform/graphics/gpu/DrawingBuffer.h:
+        Unify m_multisampleDepthStencilBuffer with m_depthStencilBuffer. 
+        Implement separate depth and stencil buffers for when
+        OES_packed_depth_stencil is not available.  Refactor creation of
+        multisampled and non-multisampled depth and stencil buffers into
+        resizeDepthStencil().
+        * platform/graphics/gpu/SharedGraphicsContext3D.cpp:
+        (WebCore::SharedGraphicsContext3D::create):
+        Turn on stencil, turn off depth, turn off antialiasing (for now).
+        (WebCore::SharedGraphicsContext3D::enableStencil):
+        * platform/graphics/gpu/SharedGraphicsContext3D.h:
+        Implement stencil enable/disable.
+        * platform/graphics/gpu/mac/DrawingBufferMac.mm:
+        (WebCore::DrawingBuffer::DrawingBuffer):
+        Remove m_multisampleDepthStencilBuffer.  Set the size to (-1, -1)
+        on creation, so reset() doesn't early-out.  Initialize m_depthBuffer
+        and m_stencilBuffer.
+        * platform/graphics/skia/GraphicsContextSkia.cpp:
+        (WebCore::GraphicsContext::canvasClip):
+        (WebCore::GraphicsContext::clipOut):
+        (WebCore::GraphicsContext::clipPath):
+        (WebCore::GraphicsContext::fillPath):
+        Put in GPU hooks for path clipping, and path drawing.
+        * platform/graphics/skia/PlatformContextSkia.cpp:
+        (WebCore::PlatformContextSkia::canAccelerate):
+        Don't check for clipping paths in canAccelerate() (since we can
+        now accelerate them).
+        (WebCore::PlatformContextSkia::uploadSoftwareToHardware):
+        Don't do clipping when uploading software draws to hardware.
+        * thirdparty/glu/README.webkit:
+        * thirdparty/glu/gluos.h:
+        #undef MIN and MAX, to fix warnings-as-errors in Chrome/Mac build.
+        * thirdparty/glu/libtess/geom.c:
+        * thirdparty/glu/libtess/priorityq.c:
+        * thirdparty/glu/libtess/render.c:
+        Use do{}while(0) instead of if(1)else construct in macro.
+        * thirdparty/glu/libtess/sweep.c:
+        (IsWindingInside):
+        (DoneEdgeDict):
+        Fix some warnings treated as errors for the Linux Release build.
+
+
 2011-01-20  Pavel Feldman  <pfeldman@chromium.org>
 
         Web Inspector: move releaseObjectGroup to the new Runtime agent.
index 34066f7c840fc35f6301f3afc5e93d5e57916573..738960d53abe04ecac2c717f7360904b84a68efa 100644 (file)
       '../svg/graphics',
       '../svg/graphics/filters',
       '../svg/properties',
+      '../thirdparty/glu',
       '../webaudio',
       '../websockets',
       '../workers',
 
         # Use LinkHashChromium.cpp instead
         ['exclude', 'platform/LinkHash\\.cpp$'],
+
+        ['include', 'thirdparty/glu/libtess/'],
       ],
       'conditions': [
         ['OS=="linux" or OS=="freebsd"', {
index 2b275edea982b6382b04d40f2bfbe15b3ee60714..7fb3fbdd507d86bd131b70d839b0b545d6700f84 100644 (file)
             'svg/SVGZoomAndPan.h',
             'svg/SVGZoomEvent.cpp',
             'svg/SVGZoomEvent.h',
+            'thirdparty/glu/libtess/dict.h',
+            'thirdparty/glu/libtess/dict-list.h',
+            'thirdparty/glu/libtess/geom.h',
+            'thirdparty/glu/libtess/memalloc.h',
+            'thirdparty/glu/libtess/mesh.h',
+            'thirdparty/glu/libtess/normal.h',
+            'thirdparty/glu/libtess/priorityq-heap.h',
+            'thirdparty/glu/libtess/priorityq-sort.h',
+            'thirdparty/glu/libtess/priorityq.h',
+            'thirdparty/glu/libtess/render.h',
+            'thirdparty/glu/libtess/sweep.h',
+            'thirdparty/glu/libtess/tess.h',
+            'thirdparty/glu/libtess/tessmono.h',
+            'thirdparty/glu/libtess/dict.c',
+            'thirdparty/glu/libtess/geom.c',
+            'thirdparty/glu/libtess/memalloc.c',
+            'thirdparty/glu/libtess/mesh.c',
+            'thirdparty/glu/libtess/normal.c',
+            'thirdparty/glu/libtess/priorityq.c',
+            'thirdparty/glu/libtess/render.c',
+            'thirdparty/glu/libtess/sweep.c',
+            'thirdparty/glu/libtess/tess.c',
+            'thirdparty/glu/libtess/tessmono.c',
             'webaudio/AudioBasicProcessorNode.cpp',
             'webaudio/AudioBasicProcessorNode.h',
             'webaudio/AudioBuffer.h',
index d9acb77158090f466a55be478321a5dc0cfa9d02..e0291283a1ca117926632d304e4b6511fc10ee3d 100644 (file)
@@ -171,7 +171,7 @@ void CanvasRenderingContext2D::reset()
     m_path.clear();
 #if ENABLE(ACCELERATED_2D_CANVAS)
     if (GraphicsContext* c = drawingContext()) {
-        if (m_context3D) {
+        if (m_context3D && m_drawingBuffer) {
             m_drawingBuffer->reset(IntSize(canvas()->width(), canvas()->height()));
             c->setSharedGraphicsContext3D(m_context3D.get(), m_drawingBuffer.get(), IntSize(canvas()->width(), canvas()->height()));
         }
@@ -1896,7 +1896,7 @@ void CanvasRenderingContext2D::paintRenderingResultsToCanvas()
 #if ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING)
 PlatformLayer* CanvasRenderingContext2D::platformLayer() const
 {
-    return m_drawingBuffer->platformLayer();
+    return m_drawingBuffer ? m_drawingBuffer->platformLayer() : 0;
 }
 #endif
 
index 569dff4ca553dab9dde8756abfc8eda1dc4a9196..2d4ca417d5203ec28c5213c98db0b9963ecb2cdf 100644 (file)
@@ -72,15 +72,16 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
                              bool multisampleExtensionSupported,
                              bool packedDepthStencilExtensionSupported)
     : m_context(context)
-    , m_size(size)
+    , m_size(-1, -1)
     , m_multisampleExtensionSupported(multisampleExtensionSupported)
     , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
     , m_fbo(0)
     , m_colorBuffer(0)
     , m_depthStencilBuffer(0)
+    , m_depthBuffer(0)
+    , m_stencilBuffer(0)
     , m_multisampleFBO(0)
     , m_multisampleColorBuffer(0)
-    , m_multisampleDepthStencilBuffer(0)
     , m_internal(new DrawingBufferInternal)
 {
     if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) {
@@ -91,6 +92,7 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
     context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
     m_colorBuffer = generateColorTexture(context, size);
     createSecondaryBuffers();
+    reset(size);
 }
 
 DrawingBuffer::~DrawingBuffer()
index ae017deecde5425a35f9cfde4354bed86e3417e0..4393f97f8b82c23a11f5f2a6014e9eba18c86de7 100644 (file)
 
 #include "DrawingBuffer.h"
 #include "FloatRect.h"
+#include "FloatSize.h"
 #include "GraphicsContext3D.h"
+#include "internal_glu.h"
 #include "IntRect.h"
+#include "Path.h"
 #include "PlatformString.h"
 #include "SharedGraphicsContext3D.h"
-#include "SolidFillShader.h"
-#include "TexShader.h"
+#if PLATFORM(SKIA)
+#include "SkPath.h"
+#endif
 #include "Texture.h"
 
 #define _USE_MATH_DEFINES
 
 namespace WebCore {
 
+// Number of line segments used to approximate bezier curves.
+const int pathTesselation = 30;
+typedef void (GLAPIENTRY *TESSCB)();
+typedef WTF::Vector<float> FloatVector;
+typedef WTF::Vector<double> DoubleVector;
+
 struct GLES2Canvas::State {
     State()
         : m_fillColor(0, 0, 0, 255)
         , m_alpha(1.0f)
         , m_compositeOp(CompositeSourceOver)
+        , m_clippingEnabled(false)
+    {
+    }
+    State(const State& other)
+        : m_fillColor(other.m_fillColor)
+        , 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)
     {
     }
     Color m_fillColor;
     float m_alpha;
     CompositeOperator m_compositeOp;
     AffineTransform m_ctm;
+    WTF::Vector<Path> m_clippingPaths;
+    bool m_clippingEnabled;
+};
+
+static inline FloatPoint operator*(const FloatPoint& f, float scale)
+{
+    return FloatPoint(f.x() * scale, f.y() * scale);
+}
+
+static inline FloatPoint operator*(float scale, const FloatPoint& f)
+{
+    return FloatPoint(f.x() * scale, f.y() * scale);
+}
+
+static inline FloatSize operator*(const FloatSize& f, float scale)
+{
+    return FloatSize(f.width() * scale, f.height() * scale);
+}
+
+static inline FloatSize operator*(float scale, const FloatSize& f)
+{
+    return FloatSize(f.width() * scale, f.height() * scale);
+}
+
+class Quadratic {
+  public:
+    Quadratic(FloatPoint a, FloatPoint b, FloatPoint c) :
+        m_a(a), m_b(b), m_c(c)
+    {
+    }
+    static Quadratic fromBezier(FloatPoint p0, FloatPoint p1, FloatPoint p2)
+    {
+        FloatSize p1s(p1.x(), p1.y());
+        FloatSize p2s(p2.x(), p2.y());
+        FloatPoint b = -2.0f * p0 + 2.0f * p1s;
+        FloatPoint c =         p0 - 2.0f * p1s + p2s;
+        return Quadratic(p0, b, c);
+    }
+    inline FloatPoint evaluate(float t)
+    {
+        return m_a + t * (m_b + t * m_c);
+    }
+    FloatPoint m_a, m_b, m_c, m_d;
+};
+
+class Cubic {
+  public:
+    Cubic(FloatPoint a, FloatPoint b, FloatPoint c, FloatPoint d) :
+        m_a(a), m_b(b), m_c(c), m_d(d) 
+    {
+    }
+    static Cubic fromBezier(FloatPoint p0, FloatPoint p1, FloatPoint p2, FloatPoint p3)
+    {
+        FloatSize p1s(p1.x(), p1.y());
+        FloatSize p2s(p2.x(), p2.y());
+        FloatSize p3s(p3.x(), p3.y());
+        FloatPoint b = -3.0f * p0 + 3.0f * p1s;
+        FloatPoint c =  3.0f * p0 - 6.0f * p1s + 3.0f * p2s;
+        FloatPoint d = -1.0f * p0 + 3.0f * p1s - 3.0f * p2s + p3s;
+        return Cubic(p0, b, c, d);
+    }
+    FloatPoint evaluate(float t)
+    {
+        return m_a + t * (m_b + t * (m_c + t * m_d));
+    }
+    FloatPoint m_a, m_b, m_c, m_d;
 };
 
 GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const IntSize& size)
@@ -88,7 +174,7 @@ void GLES2Canvas::bindFramebuffer()
 void GLES2Canvas::clearRect(const FloatRect& rect)
 {
     bindFramebuffer();
-    if (m_state->m_ctm.isIdentity()) {
+    if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) {
         m_context->scissor(rect);
         m_context->enable(GraphicsContext3D::SCISSOR_TEST);
         m_context->clearColor(Color(RGBA32(0)));
@@ -102,9 +188,17 @@ void GLES2Canvas::clearRect(const FloatRect& rect)
     }
 }
 
+void GLES2Canvas::fillPath(const Path& path)
+{
+    m_context->applyCompositeOperator(m_state->m_compositeOp);
+    applyClipping(m_state->m_clippingEnabled);
+    fillPath(path, m_state->m_fillColor);
+}
+
 void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
 {
     m_context->applyCompositeOperator(m_state->m_compositeOp);
+    applyClipping(m_state->m_clippingEnabled);
     m_context->useQuadVertices();
 
     AffineTransform matrix(m_flipMatrix);
@@ -153,6 +247,23 @@ void GLES2Canvas::concatCTM(const AffineTransform& affine)
     m_state->m_ctm *= affine;
 }
 
+void GLES2Canvas::clipPath(const Path& path)
+{
+    bindFramebuffer();
+    checkGLError("bindFramebuffer");
+    beginStencilDraw();
+    // 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;
+}
+
+void GLES2Canvas::clipOut(const Path& path)
+{
+    ASSERT(!"clipOut is unsupported in GLES2Canvas.\n");
+}
+
 void GLES2Canvas::save()
 {
     m_stateStack.append(State(m_stateStack.last()));
@@ -162,13 +273,30 @@ 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);
+            }
+        }
+    }
 }
 
 void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
 {
     m_context->applyCompositeOperator(compositeOp);
+    applyClipping(false);
 
     m_context->useQuadVertices();
     m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
@@ -180,13 +308,14 @@ void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize,
 
 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);
+    drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->m_clippingEnabled);
 }
 
 
-void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp)
+void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip)
 {
     m_context->applyCompositeOperator(compositeOp);
+    applyClipping(clip);
     const TilingData& tiles = texture->tiles();
     IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect);
 
@@ -251,6 +380,214 @@ Texture* GLES2Canvas::getTexture(NativeImagePtr ptr)
     return m_context->getTexture(ptr);
 }
 
+#if PLATFORM(SKIA)
+// This is actually cross-platform code, but since its only caller is inside a
+// PLATFORM(SKIA), it will cause a warning-as-error on Chrome/Mac.
+static void interpolateQuadratic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
+{
+    float tIncrement = 1.0f / pathTesselation, t = tIncrement;
+    Quadratic c = Quadratic::fromBezier(p0, p1, p2);
+    for (int i = 0; i < pathTesselation; ++i, t += tIncrement) {
+        FloatPoint p = c.evaluate(t);
+        vertices->append(p.x());
+        vertices->append(p.y());
+        vertices->append(1.0);
+    }
+}
+
+static void interpolateCubic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3)
+{
+    float tIncrement = 1.0f / pathTesselation, t = tIncrement;
+    Cubic c = Cubic::fromBezier(p0, p1, p2, p3);
+    for (int i = 0; i < pathTesselation; ++i, t += tIncrement) {
+        FloatPoint p = c.evaluate(t);
+        vertices->append(p.x());
+        vertices->append(p.y());
+        vertices->append(1.0);
+    }
+}
+#endif
+
+struct PolygonData {
+    PolygonData(FloatVector* vertices, WTF::Vector<short>* indices)
+      : m_vertices(vertices)
+      , m_indices(indices)
+    {
+    }
+    FloatVector* m_vertices;
+    WTF::Vector<short>* m_indices;
+};
+
+static void beginData(GLenum type, void* data)
+{
+    ASSERT(type == GL_TRIANGLES);
+}
+
+static void edgeFlagData(GLboolean flag, void* data)
+{
+}
+
+static void vertexData(void* vertexData, void* data)
+{
+    static_cast<PolygonData*>(data)->m_indices->append(reinterpret_cast<long>(vertexData));
+}
+
+static void endData(void* data)
+{
+}
+
+static void combineData(GLdouble coords[3], void* vertexData[4],
+                                 GLfloat weight[4], void **outData, void* data)
+{
+    PolygonData* polygonData = static_cast<PolygonData*>(data);
+    int index = polygonData->m_vertices->size() / 3;
+    polygonData->m_vertices->append(static_cast<float>(coords[0]));
+    polygonData->m_vertices->append(static_cast<float>(coords[1]));
+    polygonData->m_vertices->append(1.0f);
+    *outData = reinterpret_cast<void*>(index);
+}
+
+typedef void (*TESSCB)();
+
+void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsigned* vertexBuffer, unsigned* indexBuffer)
+{
+    *vertexBuffer = m_context->graphicsContext3D()->createBuffer();
+    checkGLError("createVertexBufferFromPath, createBuffer");
+    *indexBuffer = m_context->graphicsContext3D()->createBuffer();
+    checkGLError("createVertexBufferFromPath, createBuffer");
+    DoubleVector inVertices;
+    WTF::Vector<size_t> contours;
+#if PLATFORM(SKIA)
+    const SkPath* skPath = path.platformPath();
+    SkPoint pts[4];
+    SkPath::Iter iter(*skPath, true);
+    SkPath::Verb verb;
+    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+        switch (verb) {
+        case SkPath::kMove_Verb:
+            inVertices.append(pts[0].fX);
+            inVertices.append(pts[0].fY);
+            inVertices.append(1.0);
+            break;
+        case SkPath::kLine_Verb:
+            inVertices.append(pts[1].fX);
+            inVertices.append(pts[1].fY);
+            inVertices.append(1.0);
+            break;
+        case SkPath::kQuad_Verb:
+            interpolateQuadratic(&inVertices, pts[0], pts[1], pts[2]);
+            break;
+        case SkPath::kCubic_Verb:
+            interpolateCubic(&inVertices, pts[0], pts[1], pts[2], pts[3]);
+            break;
+        case SkPath::kClose_Verb:
+            contours.append(inVertices.size() / 3);
+            break;
+        case SkPath::kDone_Verb:
+            break;
+        }
+    }
+#else
+    ASSERT(!"Path extraction not implemented on this platform.");
+#endif
+
+    GLUtesselator* tess = internal_gluNewTess();
+    internal_gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
+    internal_gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TESSCB) &beginData);
+    internal_gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (TESSCB) &vertexData);
+    internal_gluTessCallback(tess, GLU_TESS_END_DATA, (TESSCB) &endData);
+    internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, (TESSCB) &edgeFlagData);
+    internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (TESSCB) &combineData);
+    WTF::Vector<short> indices;
+    FloatVector vertices;
+    vertices.reserveInitialCapacity(inVertices.size());
+    PolygonData data(&vertices, &indices);
+    internal_gluTessBeginPolygon(tess, &data);
+    WTF::Vector<size_t>::const_iterator contour;
+    size_t i = 0;
+    for (contour = contours.begin(); contour != contours.end(); ++contour) {
+        internal_gluTessBeginContour(tess);
+        for (; i < *contour; ++i) {
+            vertices.append(inVertices[i * 3]);
+            vertices.append(inVertices[i * 3 + 1]);
+            vertices.append(1.0f);
+            internal_gluTessVertex(tess, &inVertices[i * 3], reinterpret_cast<void*>(i));
+        }
+        internal_gluTessEndContour(tess);
+    }
+    internal_gluTessEndPolygon(tess);
+    internal_gluDeleteTess(tess);
+
+    m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, *vertexBuffer);
+    checkGLError("createVertexBufferFromPath, bindBuffer ARRAY_BUFFER");
+    m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GraphicsContext3D::STREAM_DRAW);
+    checkGLError("createVertexBufferFromPath, bufferData ARRAY_BUFFER");
+
+    m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, *indexBuffer);
+    checkGLError("createVertexBufferFromPath, bindBuffer ELEMENT_ARRAY_BUFFER");
+    m_context->graphicsContext3D()->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(short), indices.data(), GraphicsContext3D::STREAM_DRAW);
+    checkGLError("createVertexBufferFromPath, bufferData ELEMENT_ARRAY_BUFFER");
+    *count = indices.size();
+}
+
+void GLES2Canvas::fillPath(const Path& path, const Color& color)
+{
+    int count;
+    unsigned vertexBuffer, indexBuffer;
+    createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer);
+    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");
+
+    m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0);
+    checkGLError("drawArrays");
+
+    m_context->graphicsContext3D()->deleteBuffer(vertexBuffer);
+    checkGLError("deleteBuffer");
+
+    m_context->graphicsContext3D()->deleteBuffer(indexBuffer);
+    checkGLError("deleteBuffer");
+}
+
+void GLES2Canvas::beginStencilDraw()
+{
+    // Turn on stencil test.
+    m_context->enableStencil(true);
+    checkGLError("enable STENCIL_TEST");
+
+    // Stencil test never passes, so colorbuffer is not drawn.
+    m_context->graphicsContext3D()->stencilFunc(GraphicsContext3D::NEVER, 1, 1);
+    checkGLError("stencilFunc");
+
+    // All writes incremement the stencil buffer.
+    m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::INCR,
+                                              GraphicsContext3D::INCR,
+                                              GraphicsContext3D::INCR);
+    checkGLError("stencilOp");
+}
+
+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);
+        checkGLError("stencilFunc");
+        // Keep all stencil values the same.
+        m_context->graphicsContext3D()->stencilOp(GraphicsContext3D::KEEP,
+                                                  GraphicsContext3D::KEEP,
+                                                  GraphicsContext3D::KEEP);
+        checkGLError("stencilOp");
+    }
+}
+
 void GLES2Canvas::checkGLError(const char* header)
 {
 #ifndef NDEBUG
@@ -283,4 +620,3 @@ void GLES2Canvas::checkGLError(const char* header)
 }
 
 }
-
index 6fc1a0e69dcf2c987f9503161471dece46399613..f38c364b6f9a2d7dd72923649874ae0da8f8d12f 100644 (file)
@@ -48,6 +48,7 @@ class Color;
 class DrawingBuffer;
 class FloatRect;
 class GraphicsContext3D;
+class Path;
 class SharedGraphicsContext3D;
 
 class GLES2Canvas : public Noncopyable {
@@ -55,6 +56,7 @@ public:
     GLES2Canvas(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
     ~GLES2Canvas();
 
+    void fillPath(const Path&);
     void fillRect(const FloatRect&, const Color&, ColorSpace);
     void fillRect(const FloatRect&);
     void clearRect(const FloatRect&);
@@ -65,6 +67,8 @@ public:
     void rotate(float angleInRadians);
     void scale(const FloatSize&);
     void concatCTM(const AffineTransform&);
+    void clipPath(const Path&);
+    void clipOut(const Path&);
 
     void save();
     void restore();
@@ -72,9 +76,13 @@ public:
     // non-standard functions
     // These are not standard GraphicsContext functions, and should be pushed
     // down into a PlatformContextGLES2 at some point.
+
+    // This version is called by the canvas->canvas draws.
     void drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
-    void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator);
+    // This version is called by BitmapImage::draw().
     void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
+    // This version is called by the above, and by the software->hardware uploads.
+    void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator, bool clip);
     Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height);
     Texture* getTexture(NativeImagePtr);
 
@@ -88,6 +96,10 @@ private:
     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 applyCompositeOperator(CompositeOperator);
+    void createVertexBufferFromPath(const Path&, int* count, unsigned* vertexBuffer, unsigned* indexBuffer);
+    void fillPath(const Path&, const Color&);
+    void beginStencilDraw();
+    void applyClipping(bool enable);
     void checkGLError(const char* header);
 
     IntSize m_size;
@@ -96,7 +108,8 @@ private:
     DrawingBuffer* m_drawingBuffer;
 
     struct State;
-    WTF::Vector<State> m_stateStack;
+    typedef WTF::Vector<State> StateVector;
+    StateVector m_stateStack;
     State* m_state;
     AffineTransform m_flipMatrix;
 };
index c2830680ccac35b643a643c07cf0ff07d1c02f7e..dae83a2f3b979980f2038c9b4544e469f187507a 100644 (file)
@@ -67,16 +67,21 @@ void DrawingBuffer::clear()
         m_multisampleColorBuffer = 0;
     }
     
-    if (m_multisampleDepthStencilBuffer) {
-        m_context->deleteRenderbuffer(m_multisampleDepthStencilBuffer);
-        m_multisampleDepthStencilBuffer = 0;
-    }
-    
     if (m_depthStencilBuffer) {
         m_context->deleteRenderbuffer(m_depthStencilBuffer);
         m_depthStencilBuffer = 0;
     }
     
+    if (m_depthBuffer) {
+        m_context->deleteRenderbuffer(m_depthBuffer);
+        m_depthBuffer = 0;
+    }
+    
+    if (m_stencilBuffer) {
+        m_context->deleteRenderbuffer(m_stencilBuffer);
+        m_stencilBuffer = 0;
+    }
+    
     if (m_multisampleFBO) {
         m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
         m_context->deleteFramebuffer(m_multisampleFBO);
@@ -92,22 +97,52 @@ void DrawingBuffer::clear()
 
 void DrawingBuffer::createSecondaryBuffers()
 {
-    const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
-
-    // Create the stencil and depth buffer if needed
-    if (!multisample() && (attributes.stencil || attributes.depth))
-        m_depthStencilBuffer = m_context->createRenderbuffer();
-
     // create a multisample FBO
     if (multisample()) {
         m_multisampleFBO = m_context->createFramebuffer();
         m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
         m_multisampleColorBuffer = m_context->createRenderbuffer();
-        if (attributes.stencil || attributes.depth)
-            m_multisampleDepthStencilBuffer = m_context->createRenderbuffer();
     }
 }
 
+void DrawingBuffer::resizeDepthStencil(int sampleCount)
+{
+    const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
+    if (attributes.depth && attributes.stencil && m_packedDepthStencilExtensionSupported) {
+        if (!m_depthStencilBuffer)
+            m_depthStencilBuffer = m_context->createRenderbuffer();
+        m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
+        if (multisample())
+            m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, m_size.width(), m_size.height());
+        else
+            m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, m_size.width(), m_size.height());
+        m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
+        m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
+    } else {
+        if (attributes.depth) {
+            if (!m_depthBuffer)
+                m_depthBuffer = m_context->createRenderbuffer();
+            m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+            if (multisample())
+                m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, m_size.width(), m_size.height());
+            else
+                m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, m_size.width(), m_size.height());
+            m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+        }
+        if (attributes.stencil) {
+            if (!m_stencilBuffer)
+                m_stencilBuffer = m_context->createRenderbuffer();
+            m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer);
+            if (multisample())
+                m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, m_size.width(), m_size.height());
+            else 
+                m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_size.width(), m_size.height());
+            m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer);
+        }
+    }
+    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+}
+
 void DrawingBuffer::reset(const IntSize& newSize)
 {
     if (m_size == newSize)
@@ -120,7 +155,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
     m_context->makeContextCurrent();
     
     const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes();
-    unsigned long internalColorFormat, colorFormat, internalDepthStencilFormat = 0;
+    unsigned long internalColorFormat, colorFormat;
     if (attributes.alpha) {
         internalColorFormat = GraphicsContext3D::RGBA;
         colorFormat = GraphicsContext3D::RGBA;
@@ -128,17 +163,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
         internalColorFormat = GraphicsContext3D::RGB;
         colorFormat = GraphicsContext3D::RGB;
     }
-    if (attributes.stencil || attributes.depth) {
-        // We don't allow the logic where stencil is required and depth is not.
-        // See GraphicsContext3D constructor.
 
-        // FIXME:  If packed depth/stencil is not supported, we should
-        // create separate renderbuffers for depth and stencil.
-        if (attributes.stencil && attributes.depth && m_packedDepthStencilExtensionSupported)
-            internalDepthStencilFormat = Extensions3D::DEPTH24_STENCIL8;
-        else
-            internalDepthStencilFormat = GraphicsContext3D::DEPTH_COMPONENT16;
-    }
 
     // resize multisample FBO
     if (multisample()) {
@@ -152,15 +177,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
         m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
         m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalColorFormat, m_size.width(), m_size.height());
         m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
-        if (attributes.stencil || attributes.depth) {
-            m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer);
-            m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalDepthStencilFormat, m_size.width(), m_size.height());
-            if (attributes.stencil)
-                m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer);
-            if (attributes.depth)
-                m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_multisampleDepthStencilBuffer);
-        }
-        m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
+        resizeDepthStencil(sampleCount);
         if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
             // Cleanup
             clear();
@@ -175,15 +192,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
     m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
     m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
-    if (!multisample() && (attributes.stencil || attributes.depth)) {
-        m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
-        m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, internalDepthStencilFormat, m_size.width(), m_size.height());
-        if (attributes.stencil)
-            m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
-        if (attributes.depth)
-            m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer);
-        m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
-    }
+    resizeDepthStencil(0);
     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
         // Cleanup
         clear();
index e0e0ee17d19734a2ee5392b30dc089cbd32e67c1..9da5c9ae3508ed053d38aeac3d0fd1b79bb747f3 100644 (file)
@@ -67,6 +67,8 @@ public:
     // Create the depth/stencil and multisample buffers, if needed.
     void createSecondaryBuffers();
     
+    void resizeDepthStencil(int sampleCount);
+
     // Copies the multisample color buffer to the normal color buffer and leaves m_fbo bound
     void commit(long x = 0, long y = 0, long width = -1, long height = -1);
     
@@ -106,13 +108,18 @@ private:
     bool m_packedDepthStencilExtensionSupported;
     Platform3DObject m_fbo;
     Platform3DObject m_colorBuffer;
+
+    // This is used when we have OES_packed_depth_stencil.
     Platform3DObject m_depthStencilBuffer;
 
+    // These are used when we don't.
+    Platform3DObject m_depthBuffer;
+    Platform3DObject m_stencilBuffer;
+
     // For multisampling
     Platform3DObject m_multisampleFBO;
     Platform3DObject m_multisampleColorBuffer;
-    Platform3DObject m_multisampleDepthStencilBuffer;
-    
+
 #if PLATFORM(CHROMIUM)
     OwnPtr<WillPublishCallback> m_callback;
     OwnPtr<DrawingBufferInternal> m_internal;
index 9d1298faa86302b115edfe24199baf8e998b102e..9c590777bdec08c732d727b6e129410e060a556c 100644 (file)
@@ -51,6 +51,9 @@ namespace WebCore {
 PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* hostWindow)
 {
     GraphicsContext3D::Attributes attr;
+    attr.depth = false;
+    attr.stencil = true;
+    attr.antialias = false;
     attr.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts.
     RefPtr<GraphicsContext3D> context = GraphicsContext3D::create(attr, hostWindow);
     if (!context)
@@ -293,6 +296,14 @@ void SharedGraphicsContext3D::applyCompositeOperator(CompositeOperator op)
     }
 }
 
+void SharedGraphicsContext3D::enableStencil(bool enable)
+{
+    if (enable)
+        m_context->enable(GraphicsContext3D::STENCIL_TEST);
+    else
+        m_context->disable(GraphicsContext3D::STENCIL_TEST);
+}
+
 void SharedGraphicsContext3D::useQuadVertices()
 {
     if (!m_quadVertices) {
index ea1810d835d02b32702d70bed1bf305a77f32d74..1e032d7a366d94d650509cff6b4092f8010a5d61 100644 (file)
@@ -90,6 +90,7 @@ public:
 
     // Shared logic for canvas 2d
     void applyCompositeOperator(CompositeOperator);
+    void enableStencil(bool enable);
     void useQuadVertices();
 
     void useFillSolidProgram(const AffineTransform&, const Color&);
index 601454e3cd15727f1f91db24cccf480c92e5d132..e6dfdb8a97b212334139830ce8f0e57621d002bd 100644 (file)
@@ -41,15 +41,16 @@ DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
                              bool multisampleExtensionSupported,
                              bool packedDepthStencilExtensionSupported)
     : m_context(context)
-    , m_size(size)
+    , m_size(-1, -1)
     , m_multisampleExtensionSupported(multisampleExtensionSupported)
     , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
     , m_fbo(context->createFramebuffer())
     , m_colorBuffer(0)
     , m_depthStencilBuffer(0)
+    , m_depthBuffer(0)
+    , m_stencilBuffer(0)
     , m_multisampleFBO(0)
     , m_multisampleColorBuffer(0)
-    , m_multisampleDepthStencilBuffer(0)
 {
     ASSERT(m_fbo);
     if (!m_fbo) {
index 51e247702f3fbd56b9a53c4a2449deab9d6c0efe..1a7112b2ce83dcca21a05c8142cdecf82f71abce 100644 (file)
@@ -386,6 +386,9 @@ void GraphicsContext::canvasClip(const Path& path)
     if (paintingDisabled())
         return;
 
+    if (platformContext()->useGPU())
+        platformContext()->gpuCanvas()->clipPath(path);
+
     const SkPath& p = *path.platformPath();
     if (!isPathSkiaSafe(getCTM(), p))
         return;
@@ -410,6 +413,9 @@ void GraphicsContext::clipOut(const Path& p)
     if (paintingDisabled())
         return;
 
+    if (platformContext()->useGPU())
+        platformContext()->gpuCanvas()->clipOut(p);
+
     const SkPath& path = *p.platformPath();
     if (!isPathSkiaSafe(getCTM(), path))
         return;
@@ -422,6 +428,9 @@ void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
     if (paintingDisabled())
         return;
 
+    if (platformContext()->useGPU())
+        platformContext()->gpuCanvas()->clipPath(pathToClip);
+
     // FIXME: Be smarter about this.
     beginPath();
     addPath(pathToClip);
@@ -733,6 +742,12 @@ void GraphicsContext::fillPath(const Path& pathToFill)
     beginPath();
     addPath(pathToFill);
 
+    if (platformContext()->useGPU() && platformContext()->canAccelerate()) {
+        platformContext()->prepareForHardwareDraw();
+        platformContext()->gpuCanvas()->fillPath(pathToFill);
+        return;
+    }
+
     SkPath path = platformContext()->currentPathInLocalCoordinates();
     if (!isPathSkiaSafe(getCTM(), path))
       return;
index d3c0e00782ce8de8844a91d8e25172fc434a11e1..d852e9beb7782100ba707350034ec530cc05312b 100644 (file)
@@ -702,8 +702,7 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
 bool PlatformContextSkia::canAccelerate() const
 {
     return !m_state->m_fillShader // Can't accelerate with a fill gradient or pattern.
-        && !m_state->m_looper // Can't accelerate with a shadow.
-        && !m_state->m_canvasClipApplied; // Can't accelerate with a clip to path applied.
+        && !m_state->m_looper; // Can't accelerate with a shadow.
 }
 
 bool PlatformContextSkia::canvasClipApplied() const
@@ -848,7 +847,7 @@ void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const
 
     m_uploadTexture->updateSubRect(bitmap.getPixels(), m_softwareDirtyRect);
     AffineTransform identity;
-    gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), m_softwareDirtyRect, m_softwareDirtyRect, identity, 1.0, ColorSpaceDeviceRGB, op);
+    gpuCanvas()->drawTexturedRect(m_uploadTexture.get(), m_softwareDirtyRect, m_softwareDirtyRect, identity, 1.0, ColorSpaceDeviceRGB, op, false);
     // Clear out the region of the software canvas we just uploaded.
     m_canvas->save();
     m_canvas->resetMatrix();
index 3fcac849866d2d3e1ae246f8088b369a7fa9642d..57c47725f5ca33a90cccf08c80e4447e9494fd37 100644 (file)
@@ -31,3 +31,12 @@ The following changes were made in order to incorporate this code:
     of the unused Normalize function.
 
   - In priorityq-heap.c, an #include of <limits.h> was added.
+
+  - In sweep.c, IsWindingInside() was given a return value to silence a
+    warning-as-error in release builds.
+
+  - In sweep.c, DoneEdgeDict()'s fixedEdges was wrapped in #indef NDEBUG, to
+    silence a warning-as-error in release builds.
+
+  - In priorityq.c, render.c, and others:  the construct "if(1)...else" was
+  replaced with "do{...}while(1)" to silence a warning-as-error in Mac builds.
index 600dc0bced0370f2c872db306c9c6ed2f1e3a235..6380cb23771912265b371d8107d376a5d8384f3b 100644 (file)
@@ -42,4 +42,7 @@ typedef unsigned int GLenum;
 typedef float GLfloat;
 typedef void GLvoid;
 
+#undef MIN
+#undef MAX
+
 #endif  // GLUOS_H_
index 2db2699847d5b35b2a0d9b5001df527e783017b4..ce578ddf5c22aa455f533a5063d26e150583a2c9 100644 (file)
@@ -205,7 +205,7 @@ printf("*********************%d\n",RandomInterpolate);
 
 #endif
 
-#define Swap(a,b)      if (1) { GLUvertex *t = a; a = b; b = t; } else
+#define Swap(a,b)      do { GLUvertex *t = a; a = b; b = t; } while(0)
 
 void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
                         GLUvertex *o2, GLUvertex *d2,
index 4b0bea1b3032579d3b0d3d0534313468f3f4dd8c..6614db01489fb70ac21240caaf890fff6433fe92 100644 (file)
@@ -92,7 +92,7 @@ void pqDeletePriorityQ( PriorityQ *pq )
 
 #define LT(x,y)                (! LEQ(y,x))
 #define GT(x,y)                (! LEQ(x,y))
-#define Swap(a,b)      if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else
+#define Swap(a,b)      do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0)
 
 /* really __gl_pqSortInit */
 int pqInit( PriorityQ *pq )
index 0e944a25c977abcd6089c08edc7ccd3785b1cbac..79386e8cbacc2647f1df47394748ff8160654ed1 100644 (file)
@@ -150,11 +150,11 @@ static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
 
 #define AddToTrail(f,t)        ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
 
-#define FreeTrail(t)   if( 1 ) { \
+#define FreeTrail(t)   do { \
                          while( (t) != NULL ) { \
                            (t)->marked = FALSE; t = (t)->trail; \
                          } \
-                       } else /* absorb trailing semicolon */
+                       } while(0) /* absorb trailing semicolon */
 
 
 
index e85757c6fcb42509e670d33991c7d38c83ece54e..233b2da00fc1b1a261ce05d55e294dc957bdd613 100644 (file)
@@ -253,6 +253,7 @@ static GLboolean IsWindingInside( GLUtesselator *tess, int n )
   /*LINTED*/
   assert( FALSE );
   /*NOTREACHED*/
+  return 0;
 }
 
 
@@ -1173,7 +1174,9 @@ static void InitEdgeDict( GLUtesselator *tess )
 static void DoneEdgeDict( GLUtesselator *tess )
 {
   ActiveRegion *reg;
+#ifndef NDEBUG
   int fixedEdges = 0;
+#endif
 
   /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
   while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {