Commit 1b1b979f authored by senorblanco@chromium.org's avatar senorblanco@chromium.org
Browse files

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-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
parent c5b4f94c
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.
......
......@@ -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
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.
......@@ -185,6 +185,7 @@
'../svg/graphics',
'../svg/graphics/filters',
'../svg/properties',
'../thirdparty/glu',
'../webaudio',
'../websockets',
'../workers',
......@@ -1117,6 +1118,8 @@
# Use LinkHashChromium.cpp instead
['exclude', 'platform/LinkHash\\.cpp$'],
['include', 'thirdparty/glu/libtess/'],
],
'conditions': [
['OS=="linux" or OS=="freebsd"', {
......
......@@ -4439,6 +4439,29 @@
'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',
......
......@@ -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
......
......@@ -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()
......
......@@ -34,12 +34,16 @@
#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
......@@ -50,17 +54,99 @@
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);