summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-07-30 10:46:49 +0100
committerKristian Monsen <kristianm@google.com>2010-08-04 13:01:34 +0100
commit0617145a89917ae7735fe1c9538688ab9a577df5 (patch)
tree56206078694427c37ed7bdf27eb5221398b833c0 /WebCore/platform/graphics
parentef1adcdfc805d4d13103f6f15cc5b4d96828a60f (diff)
downloadexternal_webkit-0617145a89917ae7735fe1c9538688ab9a577df5.zip
external_webkit-0617145a89917ae7735fe1c9538688ab9a577df5.tar.gz
external_webkit-0617145a89917ae7735fe1c9538688ab9a577df5.tar.bz2
Merge WebKit at r64264 : Initial merge by git.
Change-Id: Ic42bef02efef8217a0f84c47176a9c617c28d1f1
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/BitmapImage.h2
-rw-r--r--WebCore/platform/graphics/Font.cpp6
-rw-r--r--WebCore/platform/graphics/FontDescription.h7
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h10
-rw-r--r--WebCore/platform/graphics/Path.h1
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp6
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp2
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp12
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.cpp523
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Canvas.h115
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Texture.cpp128
-rw-r--r--WebCore/platform/graphics/chromium/GLES2Texture.h63
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp7
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp10
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp118
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp108
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp12
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp127
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h38
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWince.cpp18
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferWince.cpp20
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.cpp2
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformDataWx.cpp8
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp2
26 files changed, 1267 insertions, 82 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index 2cf30d3..72f3092 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -175,7 +175,7 @@ protected:
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
#if (OS(WINCE) && !PLATFORM(QT))
- virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
#endif
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 61f5707..0e93d4f 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -68,7 +68,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
, m_letterSpacing(letterSpacing)
, m_wordSpacing(wordSpacing)
, m_isPlatformFont(false)
- , m_needsTranscoding(fontTranscoder().needsTranscoding(family().family().string()))
+ , m_needsTranscoding(fontTranscoder().needsTranscoding(fd))
{
}
@@ -77,10 +77,10 @@ Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMo
, m_letterSpacing(0)
, m_wordSpacing(0)
, m_isPlatformFont(true)
- , m_needsTranscoding(fontTranscoder().needsTranscoding(family().family().string()))
{
m_fontDescription.setUsePrinterFont(isPrinterFont);
m_fontDescription.setFontSmoothing(fontSmoothingMode);
+ m_needsTranscoding = fontTranscoder().needsTranscoding(fontDescription());
m_fontList->setPlatformFont(fontData);
}
@@ -90,7 +90,7 @@ Font::Font(const Font& other)
, m_letterSpacing(other.m_letterSpacing)
, m_wordSpacing(other.m_wordSpacing)
, m_isPlatformFont(other.m_isPlatformFont)
- , m_needsTranscoding(fontTranscoder().needsTranscoding(family().family().string()))
+ , m_needsTranscoding(fontTranscoder().needsTranscoding(other.m_fontDescription))
{
}
diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h
index fc63db9..86a4349 100644
--- a/WebCore/platform/graphics/FontDescription.h
+++ b/WebCore/platform/graphics/FontDescription.h
@@ -65,6 +65,7 @@ public:
, m_keywordSize(0)
, m_fontSmoothing(AutoSmoothing)
, m_textRendering(AutoTextRendering)
+ , m_isSpecifiedFont(false)
{
}
@@ -92,6 +93,7 @@ public:
TextRenderingMode textRenderingMode() const { return static_cast<TextRenderingMode>(m_textRendering); }
FontTraitsMask traitsMask() const;
+ bool isSpecifiedFont() const { return m_isSpecifiedFont; }
void setFamily(const FontFamily& family) { m_familyList = family; }
void setComputedSize(float s) { m_computedSize = s; }
@@ -106,6 +108,7 @@ public:
void setKeywordSize(unsigned s) { m_keywordSize = s; }
void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; }
void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
+ void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; }
private:
FontFamily m_familyList; // The list of font families to be used.
@@ -130,6 +133,7 @@ private:
unsigned m_fontSmoothing : 2; // FontSmoothingMode
unsigned m_textRendering : 2; // TextRenderingMode
+ bool m_isSpecifiedFont : 1; // True if a web page specifies a non-generic font family as the first font family.
};
inline bool FontDescription::operator==(const FontDescription& other) const
@@ -146,7 +150,8 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_renderingMode == other.m_renderingMode
&& m_keywordSize == other.m_keywordSize
&& m_fontSmoothing == other.m_fontSmoothing
- && m_textRendering == other.m_textRendering;
+ && m_textRendering == other.m_textRendering
+ && m_isSpecifiedFont == other.m_isSpecifiedFont;
}
}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 457368b..d5df153 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -274,7 +274,7 @@ namespace WebCore {
void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
void clipPath(WindRule);
void clipToImageBuffer(const FloatRect&, const ImageBuffer*);
- void clipConvexPolygon(size_t numPoints, const FloatPoint*);
+ void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
int textDrawingMode();
void setTextDrawingMode(int);
@@ -342,16 +342,16 @@ namespace WebCore {
#if OS(WINCE) && !PLATFORM(QT)
void setBitmap(PassRefPtr<SharedBitmap>);
- const TransformationMatrix& affineTransform() const;
- TransformationMatrix& affineTransform();
+ const AffineTransform& affineTransform() const;
+ AffineTransform& affineTransform();
void resetAffineTransform();
void fillRect(const FloatRect&, const Gradient*);
void drawText(const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point);
void drawFrameControl(const IntRect& rect, unsigned type, unsigned state);
void drawFocusRect(const IntRect& rect);
void paintTextField(const IntRect& rect, unsigned state);
- void drawBitmap(SharedBitmap*, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator compositeOp);
- void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize);
+ void drawBitmap(SharedBitmap*, const IntRect& dstRect, const IntRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp);
+ void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize);
void drawIcon(HICON icon, const IntRect& dstRect, UINT flags);
HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = false, bool mayCreateBitmap = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = false, bool mayCreateBitmap = true); // The passed in HDC should be the one handed back by getWindowsContext.
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index f2ae2df..86b77f8 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -59,6 +59,7 @@ typedef BRegion PlatformPath;
namespace WebCore {
class PlatformPath;
}
+typedef WebCore::PlatformPath PlatformPath;
#else
typedef void PlatformPath;
#endif
diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp
index 974c195..1f94f5a 100644
--- a/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp
@@ -32,7 +32,9 @@
#include <cairo-ft.h>
#include <cairo.h>
#include <fontconfig/fcfreetype.h>
+#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
#include <gdk/gdk.h>
+#endif
namespace WebCore {
@@ -109,8 +111,10 @@ FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const
cairo_matrix_init_scale(&fontMatrix, fontDescription.computedPixelSize(), fontDescription.computedPixelSize());
cairo_matrix_init_identity(&ctm);
+#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
if (GdkScreen* screen = gdk_screen_get_default())
options = gdk_screen_get_font_options(screen);
+#endif
// gdk_screen_get_font_options() returns NULL if no default options are
// set, so we always have to check.
@@ -149,8 +153,10 @@ FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool
static const cairo_font_options_t* defaultOptions = cairo_font_options_create();
const cairo_font_options_t* options = NULL;
+#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
if (GdkScreen* screen = gdk_screen_get_default())
options = gdk_screen_get_font_options(screen);
+#endif
// gdk_screen_get_font_options() returns NULL if no default options are
// set, so we always have to check.
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 6ed8905..96cd4ee 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -504,7 +504,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
cairo_restore(cr);
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index a65874c..2de4d14 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -469,16 +469,24 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextSetShouldAntialias(context, shouldAntialias());
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialias)
{
if (paintingDisabled())
return;
if (numPoints <= 1)
return;
+
+ CGContextRef context = platformContext();
+
+ if (antialias != shouldAntialias())
+ CGContextSetShouldAntialias(context, antialias);
- addConvexPolygonToContext(platformContext(), numPoints, points);
+ addConvexPolygonToContext(context, numPoints, points);
clipPath(RULE_NONZERO);
+
+ if (antialias != shouldAntialias())
+ CGContextSetShouldAntialias(context, shouldAntialias());
}
void GraphicsContext::applyStrokePattern()
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index fe7f83a..feb8cec 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -80,7 +80,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
case GrayScale:
colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
break;
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER)
+#if ((PLATFORM(MAC) || PLATFORM(CHROMIUM)) && !defined(BUILDING_ON_TIGER))
case LinearRGB:
colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
break;
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
new file mode 100644
index 0000000..ec188c8
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(GLES2_RENDERING)
+
+#include "GLES2Canvas.h"
+
+#include "FloatRect.h"
+#include "GLES2Context.h"
+#include "GLES2Texture.h"
+
+#include <GLES2/gl2.h>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+static inline void affineTo3x3(const AffineTransform& transform, GLfloat mat[9])
+{
+ mat[0] = transform.a();
+ mat[1] = transform.b();
+ mat[2] = 0.0f;
+ mat[3] = transform.c();
+ mat[4] = transform.d();
+ mat[5] = 0.0f;
+ mat[6] = transform.e();
+ mat[7] = transform.f();
+ mat[8] = 1.0f;
+}
+
+struct GLES2Canvas::State {
+ State()
+ : m_fillColor(0, 0, 0, 255)
+ , m_alpha(1.0f)
+ , m_compositeOp(CompositeSourceOver)
+ {
+ }
+ Color m_fillColor;
+ float m_alpha;
+ CompositeOperator m_compositeOp;
+ AffineTransform m_ctm;
+};
+
+GLES2Canvas::GLES2Canvas(GLES2Context* context, const IntSize& size)
+ : m_gles2Context(context)
+ , m_quadVertices(0)
+ , m_quadIndices(0)
+ , m_simpleProgram(0)
+ , m_texProgram(0)
+ , m_simpleMatrixLocation(-1)
+ , m_simpleColorLocation(-1)
+ , m_simplePositionLocation(-1)
+ , m_texMatrixLocation(-1)
+ , m_texTexMatrixLocation(-1)
+ , m_texSamplerLocation(-1)
+ , m_texAlphaLocation(-1)
+ , m_texPositionLocation(-1)
+ , m_state(0)
+{
+ m_flipMatrix.translate(-1.0f, 1.0f);
+ m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height());
+
+ m_gles2Context->makeCurrent();
+ m_gles2Context->resizeOffscreenContent(size);
+ m_gles2Context->swapBuffers();
+ glViewport(0, 0, size.width(), size.height());
+
+ m_stateStack.append(State());
+ m_state = &m_stateStack.last();
+}
+
+GLES2Canvas::~GLES2Canvas()
+{
+ m_gles2Context->makeCurrent();
+ if (m_simpleProgram)
+ glDeleteProgram(m_simpleProgram);
+ if (m_texProgram)
+ glDeleteProgram(m_texProgram);
+ if (m_quadVertices)
+ glDeleteBuffers(1, &m_quadVertices);
+ if (m_quadIndices)
+ glDeleteBuffers(1, &m_quadVertices);
+}
+
+void GLES2Canvas::clearRect(const FloatRect& rect)
+{
+ m_gles2Context->makeCurrent();
+
+ glScissor(rect.x(), rect.y(), rect.width(), rect.height());
+ glEnable(GL_SCISSOR_TEST);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_SCISSOR_TEST);
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
+{
+ m_gles2Context->makeCurrent();
+
+ glBindBuffer(GL_ARRAY_BUFFER, getQuadVertices());
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getQuadIndices());
+
+ float rgba[4];
+ color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ glUniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect)
+{
+ m_gles2Context->makeCurrent();
+
+ applyCompositeOperator(m_state->m_compositeOp);
+
+ glBindBuffer(GL_ARRAY_BUFFER, getQuadVertices());
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getQuadIndices());
+
+ glUseProgram(getSimpleProgram());
+
+ float rgba[4];
+ m_state->m_fillColor.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ glUniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]);
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix.multLeft(m_state->m_ctm);
+ matrix.translate(rect.x(), rect.y());
+ matrix.scale(rect.width(), rect.height());
+ GLfloat mat[9];
+ affineTo3x3(matrix, mat);
+ glUniformMatrix3fv(m_simpleMatrixLocation, 1, GL_FALSE, mat);
+
+ glVertexAttribPointer(m_simplePositionLocation, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
+
+ glEnableVertexAttribArray(m_simplePositionLocation);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+}
+
+void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
+{
+ m_state->m_fillColor = color;
+}
+
+void GLES2Canvas::setAlpha(float alpha)
+{
+ m_state->m_alpha = alpha;
+}
+
+void GLES2Canvas::translate(float x, float y)
+{
+ m_state->m_ctm.translate(x, y);
+}
+
+void GLES2Canvas::rotate(float angleInRadians)
+{
+ m_state->m_ctm.rotate(angleInRadians * (180.0f / M_PI));
+}
+
+void GLES2Canvas::scale(const FloatSize& size)
+{
+ m_state->m_ctm.scale(size.width(), size.height());
+}
+
+void GLES2Canvas::concatCTM(const AffineTransform& affine)
+{
+ m_state->m_ctm.multLeft(affine);
+}
+
+void GLES2Canvas::save()
+{
+ m_stateStack.append(State(m_stateStack.last()));
+ m_state = &m_stateStack.last();
+}
+
+void GLES2Canvas::restore()
+{
+ ASSERT(!m_stateStack.isEmpty());
+ m_stateStack.removeLast();
+ m_state = &m_stateStack.last();
+}
+
+void GLES2Canvas::drawTexturedRect(GLES2Texture* 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);
+}
+
+void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp)
+{
+ m_gles2Context->makeCurrent();
+
+ applyCompositeOperator(compositeOp);
+
+ glBindBuffer(GL_ARRAY_BUFFER, getQuadVertices());
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getQuadIndices());
+ checkGLError("glBindBuffer");
+
+ glUseProgram(getTexProgram());
+ checkGLError("glUseProgram");
+
+ glActiveTexture(GL_TEXTURE0);
+ texture->bind();
+
+ glUniform1i(m_texSamplerLocation, 0);
+ checkGLError("glUniform1i");
+
+ glUniform1f(m_texAlphaLocation, alpha);
+ checkGLError("glUniform1f for alpha");
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix.multLeft(transform);
+ matrix.translate(dstRect.x(), dstRect.y());
+ matrix.scale(dstRect.width(), dstRect.height());
+ GLfloat mat[9];
+ affineTo3x3(matrix, mat);
+ glUniformMatrix3fv(m_texMatrixLocation, 1, GL_FALSE, mat);
+ checkGLError("glUniformMatrix3fv");
+
+ AffineTransform texMatrix;
+ texMatrix.scale(1.0f / texture->width(), 1.0f / texture->height());
+ texMatrix.translate(srcRect.x(), srcRect.y());
+ texMatrix.scale(srcRect.width(), srcRect.height());
+ GLfloat texMat[9];
+ affineTo3x3(texMatrix, texMat);
+ glUniformMatrix3fv(m_texTexMatrixLocation, 1, GL_FALSE, texMat);
+ checkGLError("glUniformMatrix3fv");
+
+ glVertexAttribPointer(m_texPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
+
+ glEnableVertexAttribArray(m_texPositionLocation);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+ checkGLError("glDrawElements");
+}
+
+void GLES2Canvas::setCompositeOperation(CompositeOperator op)
+{
+ m_state->m_compositeOp = op;
+}
+
+void GLES2Canvas::applyCompositeOperator(CompositeOperator op)
+{
+ if (op == m_lastCompositeOp)
+ return;
+
+ switch (op) {
+ case CompositeClear:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ZERO, GL_ZERO);
+ break;
+ case CompositeCopy:
+ glDisable(GL_BLEND);
+ break;
+ case CompositeSourceOver:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeSourceIn:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_DST_ALPHA, GL_ZERO);
+ break;
+ case CompositeSourceOut:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
+ break;
+ case CompositeSourceAtop:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeDestinationOver:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
+ break;
+ case CompositeDestinationIn:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
+ break;
+ case CompositeDestinationOut:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositeDestinationAtop:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);
+ break;
+ case CompositeXOR:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case CompositePlusDarker:
+ case CompositeHighlight:
+ // unsupported
+ glDisable(GL_BLEND);
+ break;
+ case CompositePlusLighter:
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ break;
+ }
+ m_lastCompositeOp = op;
+}
+
+unsigned GLES2Canvas::getQuadVertices()
+{
+ if (!m_quadVertices) {
+ GLfloat vertices[] = { 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ 0.0f, 1.0f, 1.0f };
+ glGenBuffers(1, &m_quadVertices);
+ glBindBuffer(GL_ARRAY_BUFFER, m_quadVertices);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ }
+ return m_quadVertices;
+}
+
+
+unsigned GLES2Canvas::getQuadIndices()
+{
+ if (!m_quadIndices) {
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3};
+
+ glGenBuffers(1, &m_quadIndices);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadIndices);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+ }
+ return m_quadIndices;
+}
+
+static GLuint loadShader(GLenum type, const char* shaderSource)
+{
+ GLuint shader = glCreateShader(type);
+ if (!shader)
+ return 0;
+
+ glShaderSource(shader, 1, &shaderSource, 0);
+ glCompileShader(shader);
+ GLint compileStatus;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+ if (!compileStatus) {
+ int length;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
+ OwnArrayPtr<char> log(new char[length]);
+ glGetShaderInfoLog(shader, length, 0, log.get());
+ LOG_ERROR(log.get());
+ glDeleteShader(shader);
+ return 0;
+ }
+ return shader;
+}
+
+unsigned GLES2Canvas::getSimpleProgram()
+{
+ if (!m_simpleProgram) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER,
+ "uniform mat3 matrix;\n"
+ "uniform vec4 color;\n"
+ "attribute vec3 position;\n"
+ "void main() {\n"
+ " gl_Position = vec4(matrix * position, 1.0);\n"
+ "}\n");
+ if (!vertexShader)
+ return 0;
+ GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER,
+ "precision mediump float;\n"
+ "uniform mat3 matrix;\n"
+ "uniform vec4 color;\n"
+ "void main() {\n"
+ " gl_FragColor = color;\n"
+ "}\n");
+ if (!fragmentShader)
+ return 0;
+ m_simpleProgram = glCreateProgram();
+ if (!m_simpleProgram)
+ return 0;
+ glAttachShader(m_simpleProgram, vertexShader);
+ glAttachShader(m_simpleProgram, fragmentShader);
+ glLinkProgram(m_simpleProgram);
+ GLint linkStatus;
+ glGetProgramiv(m_simpleProgram, GL_LINK_STATUS, &linkStatus);
+ if (!linkStatus) {
+ glDeleteProgram(m_simpleProgram);
+ m_simpleProgram = 0;
+ }
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ m_simplePositionLocation = glGetAttribLocation(m_simpleProgram, "position");
+ m_simpleMatrixLocation = glGetUniformLocation(m_simpleProgram, "matrix");
+ m_simpleColorLocation = glGetUniformLocation(m_simpleProgram, "color");
+ }
+ return m_simpleProgram;
+}
+
+unsigned GLES2Canvas::getTexProgram()
+{
+ if (!m_texProgram) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER,
+ "uniform mat3 matrix;\n"
+ "uniform mat3 texMatrix;\n"
+ "attribute vec3 position;\n"
+ "varying vec3 texCoord;\n"
+ "void main() {\n"
+ " texCoord = texMatrix * position;\n"
+ " gl_Position = vec4(matrix * position, 1.0);\n"
+ "}\n");
+ if (!vertexShader)
+ return 0;
+ GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER,
+ "precision mediump float;\n"
+ "uniform sampler2D sampler;\n"
+ "uniform float alpha;\n"
+ "varying vec3 texCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sampler, texCoord.xy)* vec4(alpha);\n"
+ "}\n");
+ if (!fragmentShader)
+ return 0;
+ m_texProgram = glCreateProgram();
+ if (!m_texProgram)
+ return 0;
+ glAttachShader(m_texProgram, vertexShader);
+ glAttachShader(m_texProgram, fragmentShader);
+ glLinkProgram(m_texProgram);
+ GLint linkStatus;
+ glGetProgramiv(m_texProgram, GL_LINK_STATUS, &linkStatus);
+ if (!linkStatus) {
+ glDeleteProgram(m_texProgram);
+ m_texProgram = 0;
+ }
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ m_texMatrixLocation = glGetUniformLocation(m_texProgram, "matrix");
+ m_texSamplerLocation = glGetUniformLocation(m_texProgram, "sampler");
+ m_texTexMatrixLocation = glGetUniformLocation(m_texProgram, "texMatrix");
+ m_texPositionLocation = glGetAttribLocation(m_texProgram, "position");
+ m_texAlphaLocation = glGetUniformLocation(m_texProgram, "alpha");
+ }
+ return m_texProgram;
+}
+
+GLES2Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, GLES2Texture::Format format, int width, int height)
+{
+ PassRefPtr<GLES2Texture> texture = m_textures.get(ptr);
+ if (texture)
+ return texture.get();
+
+ texture = GLES2Texture::create(format, width, height);
+ GLES2Texture* t = texture.get();
+ m_textures.set(ptr, texture);
+ return t;
+}
+
+GLES2Texture* GLES2Canvas::getTexture(NativeImagePtr ptr)
+{
+ PassRefPtr<GLES2Texture> texture = m_textures.get(ptr);
+ return texture ? texture.get() : 0;
+}
+
+void GLES2Canvas::checkGLError(const char* header)
+{
+#ifndef NDEBUG
+ GLenum err;
+ while ((err = glGetError()) != GL_NO_ERROR) {
+ const char* errorStr = "*** UNKNOWN ERROR ***";
+ switch (err) {
+ case GL_INVALID_ENUM:
+ errorStr = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ errorStr = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ errorStr = "GL_INVALID_OPERATION";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ errorStr = "GL_INVALID_FRAMEBUFFER_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ errorStr = "GL_OUT_OF_MEMORY";
+ break;
+ }
+ if (header)
+ LOG_ERROR("%s: %s", header, errorStr);
+ else
+ LOG_ERROR("%s", errorStr);
+ }
+#endif
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h
new file mode 100644
index 0000000..e3a7a3b
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GLES2Canvas_h
+#define GLES2Canvas_h
+
+#if USE(GLES2_RENDERING)
+
+#include "AffineTransform.h"
+#include "Color.h"
+#include "ColorSpace.h"
+#include "GLES2Texture.h"
+#include "GraphicsTypes.h"
+#include "ImageSource.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class FloatRect;
+class Color;
+class GLES2Context;
+
+typedef HashMap<NativeImagePtr, RefPtr<GLES2Texture> > TextureHashMap;
+
+class GLES2Canvas : public Noncopyable {
+public:
+ GLES2Canvas(GLES2Context*, const IntSize&);
+ ~GLES2Canvas();
+
+ void fillRect(const FloatRect&, const Color&, ColorSpace);
+ void fillRect(const FloatRect&);
+ void clearRect(const FloatRect&);
+ void setFillColor(const Color&, ColorSpace);
+ void setAlpha(float alpha);
+ void setCompositeOperation(CompositeOperator);
+ void translate(float x, float y);
+ void rotate(float angleInRadians);
+ void scale(const FloatSize&);
+ void concatCTM(const AffineTransform&);
+
+ void save();
+ void restore();
+
+ // non-standard functions
+ // These are not standard GraphicsContext functions, and should be pushed
+ // down into a PlatformContextGLES2 at some point.
+ void drawTexturedRect(GLES2Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator);
+ void drawTexturedRect(GLES2Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
+ GLES2Context* gles2Context() { return m_gles2Context; }
+ GLES2Texture* createTexture(NativeImagePtr, GLES2Texture::Format, int width, int height);
+ GLES2Texture* getTexture(NativeImagePtr);
+
+private:
+ void applyCompositeOperator(CompositeOperator);
+ void checkGLError(const char* header);
+ unsigned getQuadVertices();
+ unsigned getQuadIndices();
+ unsigned getSimpleProgram();
+ unsigned getTexProgram();
+
+ GLES2Context* m_gles2Context;
+ struct State;
+ WTF::Vector<State> m_stateStack;
+ State* m_state;
+ unsigned m_quadVertices;
+ unsigned m_quadIndices;
+ unsigned m_simpleProgram;
+ unsigned m_texProgram;
+ int m_simpleMatrixLocation;
+ int m_simpleColorLocation;
+ int m_simplePositionLocation;
+ int m_texMatrixLocation;
+ int m_texTexMatrixLocation;
+ int m_texSamplerLocation;
+ int m_texAlphaLocation;
+ int m_texPositionLocation;
+ AffineTransform m_flipMatrix;
+ TextureHashMap m_textures;
+ CompositeOperator m_lastCompositeOp; // This is the one last set, not necessarily the one in the state stack.
+};
+
+}
+
+#endif
+
+#endif // GLES2Canvas_h
diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.cpp b/WebCore/platform/graphics/chromium/GLES2Texture.cpp
new file mode 100644
index 0000000..26c8bf7
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GLES2Texture.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(GLES2_RENDERING)
+
+#include "GLES2Texture.h"
+
+#include <GLES2/gl2.h>
+
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+GLES2Texture::GLES2Texture(unsigned int textureId, Format format, int width, int height)
+ : m_textureId(textureId)
+ , m_format(format)
+ , m_width(width)
+ , m_height(height)
+{
+}
+
+GLES2Texture::~GLES2Texture()
+{
+ glDeleteTextures(1, &m_textureId);
+}
+
+PassRefPtr<GLES2Texture> GLES2Texture::create(Format format, int width, int height)
+{
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ if (!textureId)
+ return 0;
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ int max;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+ if (width > max || height > max)
+ ASSERT(!"texture too big");
+
+ return adoptRef(new GLES2Texture(textureId, format, width, height));
+}
+
+static void convertFormat(GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle)
+{
+ *swizzle = false;
+ switch (format) {
+ case GLES2Texture::RGBA8:
+ *glFormat = GL_RGBA;
+ *glType = GL_UNSIGNED_BYTE;
+ break;
+ case GLES2Texture::BGRA8:
+// FIXME: Once we have support for extensions, we should check for EXT_texture_format_BGRA8888,
+// and use that if present.
+ *glFormat = GL_RGBA;
+ *glType = GL_UNSIGNED_BYTE;
+ *swizzle = true;
+ break;
+ default:
+ ASSERT(!"bad format");
+ break;
+ }
+}
+
+void GLES2Texture::load(void* pixels)
+{
+ unsigned int glFormat, glType;
+ bool swizzle;
+ convertFormat(m_format, &glFormat, &glType, &swizzle);
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ if (swizzle) {
+ ASSERT(glFormat == GL_RGBA && glType == GL_UNSIGNED_BYTE);
+ // FIXME: This could use PBO's to save doing an extra copy here.
+ int size = m_width * m_height;
+ unsigned* pixels32 = static_cast<unsigned*>(pixels);
+ OwnArrayPtr<unsigned> buf(new unsigned[size]);
+ unsigned* bufptr = buf.get();
+ for (int i = 0; i < size; ++i) {
+ unsigned pixel = pixels32[i];
+ bufptr[i] = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16);
+ }
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, buf.get());
+ } else
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, glFormat, glType, pixels);
+}
+
+void GLES2Texture::bind()
+{
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.h b/WebCore/platform/graphics/chromium/GLES2Texture.h
new file mode 100644
index 0000000..346365a
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/GLES2Texture.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GLES2Texture_h
+#define GLES2Texture_h
+
+#if USE(GLES2_RENDERING)
+
+#include "RefCounted.h"
+#include "RefPtr.h"
+
+namespace WebCore {
+
+class GLES2Texture : public RefCounted<GLES2Texture> {
+public:
+ ~GLES2Texture();
+ enum Format { RGBA8, BGRA8 };
+ static PassRefPtr<GLES2Texture> create(Format, int width, int height);
+ void bind();
+ void load(void* pixels);
+ Format format() const { return m_format; }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+private:
+ GLES2Texture(unsigned int textureId, Format format, int width, int height);
+ unsigned int m_textureId;
+ Format m_format;
+ int m_width;
+ int m_height;
+};
+
+}
+
+#endif
+
+#endif // GLES2Texture_h
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 7869c45..7184439 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -1255,6 +1255,7 @@ static HashSet<String> mimeTypeCache()
|| g_str_equal(name, "audio/x-m4a")) {
cache.add(String("video/mp4"));
cache.add(String("audio/aac"));
+ cache.add(String("audio/mp4"));
cached = true;
}
@@ -1270,11 +1271,13 @@ static HashSet<String> mimeTypeCache()
if (g_str_equal(name, "audio/x-wav")) {
cache.add(String("audio/wav"));
+ cache.add(String("audio/x-wav"));
cached = true;
}
if (g_str_equal(name, "audio/mpeg")) {
cache.add(String(name));
+ cache.add(String("audio/x-mpeg"));
cached = true;
// This is what we are handling:
@@ -1289,8 +1292,10 @@ static HashSet<String> mimeTypeCache()
cache.add(String("audio/mp1"));
if (minLayer <= 2 && 2 <= maxLayer)
cache.add(String("audio/mp2"));
- if (minLayer <= 3 && 3 <= maxLayer)
+ if (minLayer <= 3 && 3 <= maxLayer) {
+ cache.add(String("audio/x-mp3"));
cache.add(String("audio/mp3"));
+ }
}
}
}
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
index f9e1980..6561c11 100644
--- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -152,7 +152,7 @@ void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* p
m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle());
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index a828070..e560e15 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -529,7 +529,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
p->restore();
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
@@ -793,9 +793,11 @@ void GraphicsContext::beginPath()
void GraphicsContext::addPath(const Path& path)
{
- QPainterPath newPath = m_data->currentPath;
- newPath.addPath(path.platformPath());
- m_data->currentPath = newPath;
+ if (!m_data->currentPath.elementCount()) {
+ m_data->currentPath = path.platformPath();
+ return;
+ }
+ m_data->currentPath.addPath(path.platformPath());
}
bool GraphicsContext::inTransparencyLayer() const
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index b4ca617..bc25003 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -175,32 +175,53 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i
endy = size.height();
int numRows = endy - originy;
- QImage image = imageData.m_pixmap.toImage();
- if (multiplied == Unmultiplied)
- image = image.convertToFormat(QImage::Format_ARGB32);
- else
- image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ // NOTE: For unmultiplied data, we undo the premultiplication below.
+ QImage image = imageData.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
ASSERT(!image.isNull());
- unsigned destBytesPerRow = 4 * rect.width();
- unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
- for (int y = 0; y < numRows; ++y) {
+ const int bytesPerLine = image.bytesPerLine();
#if QT_VERSION >= 0x040700
- const quint32* scanLine = reinterpret_cast<const quint32*>(image.constScanLine(y + originy));
+ const uchar* bits = image.constBits();
#else
- quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y + originy));
+ const uchar* bits = image.bits();
#endif
- for (int x = 0; x < numColumns; x++) {
- QRgb value = scanLine[x + originx];
- int basex = x * 4;
-
- destRows[basex] = qRed(value);
- destRows[basex + 1] = qGreen(value);
- destRows[basex + 2] = qBlue(value);
- destRows[basex + 3] = qAlpha(value);
+
+ quint32* destRows = reinterpret_cast<quint32*>(&data[desty * rect.width() + destx]);
+
+ if (multiplied == Unmultiplied) {
+ for (int y = 0; y < numRows; ++y) {
+ const quint32* scanLine = reinterpret_cast<const quint32*>(bits + (y + originy) * bytesPerLine);
+ for (int x = 0; x < numColumns; x++) {
+ QRgb pixel = scanLine[x + originx];
+ int alpha = qAlpha(pixel);
+ // Un-premultiply and convert RGB to BGR.
+ if (alpha == 255)
+ destRows[x] = (0xFF000000
+ | (qBlue(pixel) << 16)
+ | (qGreen(pixel) << 8)
+ | (qRed(pixel)));
+ else if (alpha > 0)
+ destRows[x] = ((alpha << 24)
+ | (((255 * qBlue(pixel)) / alpha)) << 16)
+ | (((255 * qGreen(pixel)) / alpha) << 8)
+ | ((255 * qRed(pixel)) / alpha);
+ else
+ destRows[x] = 0;
+ }
+ destRows += rect.width();
+ }
+ } else {
+ for (int y = 0; y < numRows; ++y) {
+ const quint32* scanLine = reinterpret_cast<const quint32*>(bits + (y + originy) * bytesPerLine);
+ for (int x = 0; x < numColumns; x++) {
+ QRgb pixel = scanLine[x + originx];
+ // Convert RGB to BGR.
+ destRows[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+
+ }
+ destRows += rect.width();
}
- destRows += destBytesPerRow;
}
return result;
@@ -216,6 +237,22 @@ PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect
return getImageData<Premultiplied>(rect, m_data, m_size);
}
+static inline unsigned int premultiplyABGRtoARGB(unsigned int x)
+{
+ unsigned int a = x >> 24;
+ if (a == 255)
+ return (x << 16) | ((x >> 16) & 0xff) | (x & 0xff00ff00);
+ unsigned int t = (x & 0xff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
+ t = ((t << 16) | (t >> 16)) & 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a;
+ x = (x + ((x >> 8) & 0xff) + 0x80);
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+
template <Multiply multiplied>
void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
{
@@ -247,22 +284,33 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
unsigned srcBytesPerRow = 4 * source->width();
- QRect destRect(destx, desty, endx - destx, endy - desty);
-
- QImage::Format format = multiplied == Unmultiplied ? QImage::Format_ARGB32 : QImage::Format_ARGB32_Premultiplied;
- QImage image(destRect.size(), format);
-
- unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
- for (int y = 0; y < numRows; ++y) {
- quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y));
- for (int x = 0; x < numColumns; x++) {
- // ImageData stores the pixels in RGBA while QImage is ARGB
- quint32 pixel = reinterpret_cast<quint32*>(srcRows + 4 * x)[0];
- pixel = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
- scanLine[x] = pixel;
+ // NOTE: For unmultiplied input data, we do the premultiplication below.
+ QImage image(numColumns, numRows, QImage::Format_ARGB32_Premultiplied);
+ uchar* bits = image.bits();
+ const int bytesPerLine = image.bytesPerLine();
+
+ const quint32* srcScanLine = reinterpret_cast<const quint32*>(source->data()->data()->data() + originy * srcBytesPerRow + originx * 4);
+
+ if (multiplied == Unmultiplied) {
+ for (int y = 0; y < numRows; ++y) {
+ quint32* destScanLine = reinterpret_cast<quint32*>(bits + y * bytesPerLine);
+ for (int x = 0; x < numColumns; x++) {
+ // Premultiply and convert BGR to RGB.
+ quint32 pixel = srcScanLine[x];
+ destScanLine[x] = premultiplyABGRtoARGB(pixel);
+ }
+ srcScanLine += source->width();
+ }
+ } else {
+ for (int y = 0; y < numRows; ++y) {
+ quint32* destScanLine = reinterpret_cast<quint32*>(bits + y * bytesPerLine);
+ for (int x = 0; x < numColumns; x++) {
+ // Convert BGR to RGB.
+ quint32 pixel = srcScanLine[x];
+ destScanLine[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+ }
+ srcScanLine += source->width();
}
-
- srcRows += srcBytesPerRow;
}
bool isPainting = data.m_painter->isActive();
@@ -278,7 +326,7 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
}
data.m_painter->setCompositionMode(QPainter::CompositionMode_Source);
- data.m_painter->drawImage(destRect, image);
+ data.m_painter->drawImage(destx, desty, image);
if (!isPainting)
data.m_painter->end();
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 0c1898b..7994244 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -54,6 +54,10 @@
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
+#if USE(GLES2_RENDERING)
+#include "GLES2Canvas.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -243,6 +247,11 @@ void GraphicsContext::savePlatformState()
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->save();
+#endif
+
// Save our private State.
platformContext()->save();
}
@@ -252,6 +261,11 @@ void GraphicsContext::restorePlatformState()
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->restore();
+#endif
+
// Restore our private State.
platformContext()->restore();
}
@@ -290,6 +304,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
if (!isRectSkiaSafe(getCTM(), r))
return;
+ platformContext()->prepareForSoftwareDraw();
SkPath path;
path.addOval(r, SkPath::kCW_Direction);
// only perform the inset if we won't invert r
@@ -307,6 +322,7 @@ void GraphicsContext::addPath(const Path& path)
{
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
platformContext()->addPath(*path.platformPath());
}
@@ -314,6 +330,7 @@ void GraphicsContext::beginPath()
{
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
platformContext()->beginPath();
}
@@ -329,6 +346,16 @@ void GraphicsContext::clearRect(const FloatRect& rect)
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU()) {
+ platformContext()->prepareForHardwareDraw();
+ platformContext()->gpuCanvas()->clearRect(rect);
+ return;
+ }
+#endif
+
+ platformContext()->prepareForSoftwareDraw();
+
SkRect r = rect;
if (!isRectSkiaSafe(getCTM(), r))
ClipRectToCanvas(*platformContext()->canvas(), r, &r);
@@ -348,6 +375,7 @@ void GraphicsContext::clip(const FloatRect& rect)
if (!isRectSkiaSafe(getCTM(), r))
return;
+ platformContext()->prepareForSoftwareDraw();
platformContext()->canvas()->clipRect(r);
}
@@ -360,6 +388,7 @@ void GraphicsContext::clip(const Path& path)
if (!isPathSkiaSafe(getCTM(), p))
return;
+ platformContext()->prepareForSoftwareDraw();
platformContext()->clipPathAntiAliased(p);
}
@@ -441,6 +470,12 @@ void GraphicsContext::concatCTM(const AffineTransform& affine)
{
if (paintingDisabled())
return;
+
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->concatCTM(affine);
+#endif
+
platformContext()->canvas()->concat(affine);
}
@@ -454,6 +489,8 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints,
if (numPoints <= 1)
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkPath path;
path.incReserve(numPoints);
@@ -478,7 +515,7 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints,
}
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
@@ -499,6 +536,7 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
if (!isRectSkiaSafe(getCTM(), rect))
return;
+ platformContext()->prepareForSoftwareDraw();
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawOval(rect, paint);
@@ -524,6 +562,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width *
if (!rectCount)
return;
+ platformContext()->prepareForSoftwareDraw();
SkRegion focusRingRegion;
const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.5);
for (unsigned i = 0; i < rectCount; i++) {
@@ -558,6 +597,8 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (!isPointSkiaSafe(getCTM(), point1) || !isPointSkiaSafe(getCTM(), point2))
return;
+ platformContext()->prepareForSoftwareDraw();
+
FloatPoint p1 = point1;
FloatPoint p2 = point2;
bool isVerticalLine = (p1.x() == p2.x());
@@ -604,6 +645,8 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
+
// Create the pattern we'll use to draw the underline.
static SkBitmap* misspellBitmap = 0;
if (!misspellBitmap) {
@@ -684,6 +727,8 @@ void GraphicsContext::drawLineForText(const IntPoint& pt,
if (width <= 0)
return;
+ platformContext()->prepareForSoftwareDraw();
+
int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
SkRect r;
r.fLeft = SkIntToScalar(pt.x());
@@ -704,6 +749,8 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkRect r = rect;
if (!isRectSkiaSafe(getCTM(), r)) {
// See the fillRect below.
@@ -722,6 +769,8 @@ void GraphicsContext::fillPath()
if (!isPathSkiaSafe(getCTM(), path))
return;
+ platformContext()->prepareForSoftwareDraw();
+
const GraphicsContextState& state = m_common->state;
path.setFillType(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
@@ -745,6 +794,16 @@ void GraphicsContext::fillRect(const FloatRect& rect)
ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient) {
+ platformContext()->prepareForHardwareDraw();
+ platformContext()->gpuCanvas()->fillRect(rect);
+ return;
+ }
+#endif
+
+ platformContext()->prepareForSoftwareDraw();
+
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawRect(r, paint);
@@ -757,6 +816,16 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient) {
+ platformContext()->prepareForHardwareDraw();
+ platformContext()->gpuCanvas()->fillRect(rect, color, colorSpace);
+ return;
+ }
+#endif
+
+ platformContext()->prepareForSoftwareDraw();
+
SkRect r = rect;
if (!isRectSkiaSafe(getCTM(), r)) {
// Special case when the rectangle overflows fixed point. This is a
@@ -789,6 +858,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkRect r = rect;
if (!isRectSkiaSafe(getCTM(), r))
// See fillRect().
@@ -872,6 +943,12 @@ void GraphicsContext::scale(const FloatSize& size)
{
if (paintingDisabled())
return;
+
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->scale(size);
+#endif
+
platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()),
WebCoreFloatToSkScalar(size.height()));
}
@@ -880,6 +957,10 @@ void GraphicsContext::setAlpha(float alpha)
{
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->setAlpha(alpha);
+#endif
platformContext()->setAlpha(alpha);
}
@@ -887,6 +968,10 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->setCompositeOperation(op);
+#endif
platformContext()->setXfermodeMode(WebCoreCompositeToSkiaComposite(op));
}
@@ -973,6 +1058,11 @@ void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorS
{
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->setFillColor(color, colorSpace);
+#endif
+
platformContext()->setFillColor(color.rgb());
}
@@ -1102,6 +1192,8 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
if (paintingDisabled())
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkPaint paint;
SkRect oval = r;
if (strokeStyle() == NoStroke) {
@@ -1133,6 +1225,8 @@ void GraphicsContext::strokePath()
if (!isPathSkiaSafe(getCTM(), path))
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
platformContext()->canvas()->drawPath(path, paint);
@@ -1146,6 +1240,8 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
if (!isRectSkiaSafe(getCTM(), rect))
return;
+ platformContext()->prepareForSoftwareDraw();
+
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
@@ -1157,6 +1253,11 @@ void GraphicsContext::rotate(float angleInRadians)
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->rotate(angleInRadians);
+#endif
+
platformContext()->canvas()->rotate(WebCoreFloatToSkScalar(
angleInRadians * (180.0f / 3.14159265f)));
}
@@ -1166,6 +1267,11 @@ void GraphicsContext::translate(float w, float h)
if (paintingDisabled())
return;
+#if USE(GLES2_RENDERING)
+ if (platformContext()->useGPU())
+ platformContext()->gpuCanvas()->translate(w, h);
+#endif
+
platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w),
WebCoreFloatToSkScalar(h));
}
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index f8192fe..26c44f2 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -74,10 +74,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
// Make the background transparent. It would be nice if this wasn't
// required, but the canvas is currently filled with the magic transparency
// color. Can we have another way to manage this?
- //
- // Avoid drawing on a zero-sized canvas. Skia can't handle it.
- if (!size.isZero())
- m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+ m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
success = true;
}
@@ -131,6 +128,13 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const SkBitmap& bitmap,
const IntSize& size)
{
RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
+
+ if (bitmap.config() == SkBitmap::kNo_Config) {
+ // This is an empty SkBitmap that could not be configured.
+ ASSERT(size.width() == 0 || size.height() == 0);
+ return result;
+ }
+
unsigned char* data = result->data()->data()->data();
if (rect.x() < 0 || rect.y() < 0 ||
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index 15bd9b4..65c6e95 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -44,7 +44,15 @@
#include "SkShader.h"
#include "SkDashPathEffect.h"
+#if USE(GLES2_RENDERING)
+#include "GLES2Canvas.h"
+#include "GLES2Context.h"
+#include "GLES2Texture.h"
+#include <GLES2/gl2.h>
+#endif
+
#include <wtf/MathExtras.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/Vector.h>
namespace WebCore
@@ -199,6 +207,11 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
#if OS(WINDOWS)
, m_drawingToImageBuffer(false)
#endif
+#if USE(GLES2_RENDERING)
+ , m_useGPU(false)
+ , m_gpuCanvas(0)
+ , m_backingStoreState(None)
+#endif
{
m_stateStack.append(State());
m_state = &m_stateStack.last();
@@ -661,3 +674,117 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
m_canvas->restore();
}
+
+#if USE(GLES2_RENDERING)
+void PlatformContextSkia::setGLES2Context(WebCore::GLES2Context* context, const WebCore::IntSize& size)
+{
+ m_useGPU = true;
+ m_gpuCanvas = new WebCore::GLES2Canvas(context, size);
+}
+
+void PlatformContextSkia::prepareForSoftwareDraw() const
+{
+ if (!m_useGPU)
+ return;
+
+ if (m_backingStoreState == Hardware) {
+ // Depending on the blend mode we need to do one of a few things:
+
+ // * For associative blend modes, we can draw into an initially empty
+ // canvas and then composite the results on top of the hardware drawn
+ // results before the next hardware draw or swapBuffers().
+
+ // * For non-associative blend modes we have to do a readback and then
+ // software draw. When we re-upload in this mode we have to blow
+ // away whatever is in the hardware backing store (do a copy instead
+ // of a compositing operation).
+
+ if (m_state->m_xferMode == SkXfermode::kSrcOver_Mode) {
+ // Last drawn on hardware; clear out the canvas.
+ m_canvas->save();
+ SkRect bounds = {0, 0, m_canvas->getDevice()->width(), m_canvas->getDevice()->height()};
+ m_canvas->clipRect(bounds, SkRegion::kReplace_Op);
+ m_canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+ m_canvas->restore();
+ // Start compositing into the empty canvas.
+ m_backingStoreState = Mixed;
+ } else {
+ readbackHardwareToSoftware();
+ // When we switch back to hardware copy the results, don't composite.
+ m_backingStoreState = Software;
+ }
+ } else if (m_backingStoreState == Mixed) {
+ if (m_state->m_xferMode != SkXfermode::kSrcOver_Mode) {
+ // Have to composite our currently software drawn data...
+ uploadSoftwareToHardware(WebCore::CompositeSourceOver);
+ // then do a readback so we can hardware draw stuff.
+ readbackHardwareToSoftware();
+ m_backingStoreState = Software;
+ }
+ }
+}
+
+void PlatformContextSkia::prepareForHardwareDraw() const
+{
+ if (!m_useGPU)
+ return;
+
+ if (m_backingStoreState == Software) {
+ // Last drawn in software; upload everything we've drawn.
+ uploadSoftwareToHardware(WebCore::CompositeCopy);
+ } else if (m_backingStoreState == Mixed) {
+ // Stuff in software/hardware, composite the software stuff on top of
+ // the hardware stuff.
+ uploadSoftwareToHardware(WebCore::CompositeSourceOver);
+ }
+ m_backingStoreState = Hardware;
+}
+
+void PlatformContextSkia::syncSoftwareCanvas() const
+{
+ if (!m_useGPU)
+ return;
+
+ if (m_backingStoreState == Hardware)
+ readbackHardwareToSoftware();
+ else if (m_backingStoreState == Mixed) {
+ // Have to composite our currently software drawn data..
+ uploadSoftwareToHardware(WebCore::CompositeSourceOver);
+ // then do a readback.
+ readbackHardwareToSoftware();
+ m_backingStoreState = Software;
+ }
+ m_backingStoreState = Software;
+}
+
+void PlatformContextSkia::uploadSoftwareToHardware(WebCore::CompositeOperator op) const
+{
+ const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(false);
+ SkAutoLockPixels lock(bitmap);
+ m_gpuCanvas->gles2Context()->makeCurrent();
+ // FIXME: Keep a texture around for this rather than constantly creating/destroying one.
+ RefPtr<WebCore::GLES2Texture> texture = WebCore::GLES2Texture::create(WebCore::GLES2Texture::BGRA8, bitmap.width(), bitmap.height());
+ texture->load(bitmap.getPixels());
+ WebCore::IntRect rect(0, 0, bitmap.width(), bitmap.height());
+ gpuCanvas()->drawTexturedRect(texture.get(), rect, rect, WebCore::DeviceColorSpace, op);
+}
+
+void PlatformContextSkia::readbackHardwareToSoftware() const
+{
+ const SkBitmap& bitmap = m_canvas->getDevice()->accessBitmap(true);
+ SkAutoLockPixels lock(bitmap);
+ m_gpuCanvas->gles2Context()->makeCurrent();
+ int width = bitmap.width(), height = bitmap.height();
+ OwnArrayPtr<uint32_t> buf(new uint32_t[width]);
+ // Flips the image vertically.
+ for (int y = 0; y < height; ++y) {
+ uint32_t* pixels = bitmap.getAddr32(0, y);
+ glReadPixels(0, height - 1 - y, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ for (int i = 0; i < width; ++i) {
+ uint32_t pixel = pixels[i];
+ // Swizzles from RGBA -> BGRA.
+ pixels[i] = pixel & 0xFF00FF00 | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16);
+ }
+ }
+}
+#endif
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 88a8ec7..2099dd0 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -41,6 +41,14 @@
#include "SkPaint.h"
#include "SkPath.h"
+#if USE(GLES2_RENDERING)
+namespace WebCore {
+enum CompositeOperator;
+class GLES2Canvas;
+class GLES2Context;
+}
+#endif
+
#include <wtf/Vector.h>
// This class holds the platform-specific state for GraphicsContext. We put
@@ -174,6 +182,24 @@ public:
void setImageResamplingHint(const WebCore::IntSize& srcSize, const WebCore::FloatSize& dstSize);
void clearImageResamplingHint();
bool hasImageResamplingHint() const;
+#if USE(GLES2_RENDERING)
+ bool useGPU() { return m_useGPU; }
+ void setGLES2Context(WebCore::GLES2Context*, const WebCore::IntSize&);
+ WebCore::GLES2Canvas* gpuCanvas() const { return m_gpuCanvas.get(); }
+#endif
+
+#if USE(GLES2_RENDERING)
+ // Call these before making a call that manipulates the underlying
+ // skia::PlatformCanvas or WebCore::GLES2Canvas
+ void prepareForSoftwareDraw() const;
+ void prepareForHardwareDraw() const;
+ // Call to force the skia::PlatformCanvas to contain all rendering results.
+ void syncSoftwareCanvas() const;
+#else
+ void prepareForSoftwareDraw() const {}
+ void prepareForHardwareDraw() const {}
+ void syncSoftwareCanvas() const {}
+#endif
private:
#if OS(LINUX) || OS(WINDOWS)
@@ -183,6 +209,11 @@ private:
#endif
void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths);
+#if USE(GLES2_RENDERING)
+ void uploadSoftwareToHardware(WebCore::CompositeOperator) const;
+ void readbackHardwareToSoftware() const;
+#endif
+
// Defines drawing style.
struct State;
@@ -206,6 +237,11 @@ private:
#if OS(WINDOWS)
bool m_drawingToImageBuffer;
#endif
+#if USE(GLES2_RENDERING)
+ bool m_useGPU;
+ OwnPtr<WebCore::GLES2Canvas> m_gpuCanvas;
+ mutable enum { None, Software, Mixed, Hardware } m_backingStoreState;
+#endif
};
-#endif // PlatformContextSkia_h
+#endif // PlatformContextSkia_h
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
index 5292b82..e4466c8 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
@@ -948,7 +948,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
}
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
@@ -1160,12 +1160,12 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
m_data->concatCTM(transform);
}
-TransformationMatrix& GraphicsContext::affineTransform()
+AffineTransform& GraphicsContext::affineTransform()
{
return m_data->m_transform;
}
-const TransformationMatrix& GraphicsContext::affineTransform() const
+const AffineTransform& GraphicsContext::affineTransform() const
{
return m_data->m_transform;
}
@@ -1268,8 +1268,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to
IntRect dstRect = fillRect;
- dstRect.move(shadowSize);
- dstRect.inflate(shadowBlur);
+ dstRect.move(stableRound(shadowSize.width()), stableRound(shadowSize.height()));
+ dstRect.inflate(stableRound(shadowBlur));
dstRect = m_data->mapRect(dstRect);
FloatSize newTopLeft(m_data->mapSize(topLeft));
@@ -1513,7 +1513,7 @@ void GraphicsContext::fillRect(const FloatRect& r, const Gradient* gradient)
int width = rect.width();
int height = rect.height();
FloatSize d = gradient->p1() - gradient->p0();
- bool vertical = abs(d.height()) > abs(d.width());
+ bool vertical = fabs(d.height()) > fabs(d.width());
for (size_t i = 0; i < numStops; ++i) {
const Gradient::ColorStop& stop = stops[i];
int iTv = i ? 2 * i - 1 : 0;
@@ -1868,7 +1868,7 @@ void GraphicsContext::paintTextField(const IntRect& rect, unsigned state)
FillRect(dc, &rectWin, reinterpret_cast<HBRUSH>(((state & DFCS_INACTIVE) ? COLOR_BTNFACE : COLOR_WINDOW) + 1));
}
-void GraphicsContext::drawBitmap(SharedBitmap* bmp, const IntRect& dstRectIn, const IntRect& srcRect, CompositeOperator compositeOp)
+void GraphicsContext::drawBitmap(SharedBitmap* bmp, const IntRect& dstRectIn, const IntRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
if (!m_data->m_opacity)
return;
@@ -1891,7 +1891,7 @@ void GraphicsContext::drawBitmap(SharedBitmap* bmp, const IntRect& dstRectIn, co
}
void GraphicsContext::drawBitmapPattern(SharedBitmap* bmp, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRectIn, const IntSize& origSourceSize)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRectIn, const IntSize& origSourceSize)
{
if (!m_data->m_opacity)
return;
@@ -1912,7 +1912,7 @@ void GraphicsContext::drawBitmapPattern(SharedBitmap* bmp, const FloatRect& tile
AffineTransform transform = m_data->m_transform;
transform.translate(moved.width(), moved.height());
- bmp->drawPattern(dc, transform, tileRectIn, patternTransform, phase, op, destRectIn, origSourceSize);
+ bmp->drawPattern(dc, transform, tileRectIn, patternTransform, phase, styleColorSpace, op, destRectIn, origSourceSize);
if (!bmp->hasAlpha())
transparentDC.fillAlphaChannel();
diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
index 4b739c8..1a25f4f 100644
--- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp
+++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
@@ -26,8 +26,10 @@
#include "Image.h"
#include "ImageData.h"
#include "JPEGEncoder.h"
+#include "NotImplemented.h"
#include "PNGEncoder.h"
#include "SharedBitmap.h"
+#include "UnusedParam.h"
#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -43,24 +45,24 @@ public:
virtual IntSize size() const { return IntSize(m_data->m_bitmap->width(), m_data->m_bitmap->height()); }
virtual void destroyDecodedData(bool destroyAll = true) {}
virtual unsigned decodedSize() const { return 0; }
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
const ImageBufferData* m_data;
};
-void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
IntRect intDstRect = enclosingIntRect(dstRect);
IntRect intSrcRect(srcRect);
- m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, compositeOp);
+ m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, styleColorSpace, compositeOp);
}
void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
- m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, op, destRect, size());
+ m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, size());
}
ImageBufferData::ImageBufferData(const IntSize& size)
@@ -216,6 +218,12 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get());
}
+void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
+{
+ UNUSED_PARAM(lookUpTable);
+ notImplemented();
+}
+
String ImageBuffer::toDataURL(const String& mimeType, const double*) const
{
if (!m_data.m_bitmap->bytes())
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
index cde5461..b42b52c 100644
--- a/WebCore/platform/graphics/wince/PlatformPathWince.cpp
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
@@ -671,7 +671,7 @@ void PlatformPath::addArcTo(const FloatPoint& fp1, const FloatPoint& fp2, float
double d01 = v01.length();
double d21 = v21.length();
- double angle = (piDouble - abs(asin(cross / (d01 * d21)))) * 0.5;
+ double angle = (piDouble - fabs(asin(cross / (d01 * d21)))) * 0.5;
double span = radius * tan(angle);
double rate = span / d01;
PathPoint startPoint;
diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index 2951223..b77a03b 100644
--- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -81,23 +81,23 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri
// this is a moot issue on Linux and Mac as they only accept the point argument. So,
// we use the pixel size constructor on Windows, but we use point size on Linux and Mac.
#if __WXMSW__
- m_font = new FontHolder(new wxFont( wxSize(0, -desc.computedPixelSize()),
+ m_font = adoptRef(new FontHolder(new wxFont( wxSize(0, -desc.computedPixelSize()),
fontFamilyToWxFontFamily(desc.genericFamily()),
italicToWxFontStyle(desc.italic()),
fontWeightToWxFontWeight(desc.weight()),
false,
family.string()
)
- );
+ ));
#else
- m_font = new FontHolder(new wxFont( desc.computedPixelSize(),
+ m_font = adoptRef(new FontHolder(new wxFont( desc.computedPixelSize(),
fontFamilyToWxFontFamily(desc.genericFamily()),
italicToWxFontStyle(desc.italic()),
fontWeightToWxFontWeight(desc.weight()),
false,
family.string()
)
- );
+ ));
#endif
#if OS(DARWIN) && !defined(wxOSX_USE_CORE_TEXT)
#if wxCHECK_VERSION(2,9,0)
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 01dce9e..4d5afd7 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -256,7 +256,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
delete [] polygon;
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points)
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;