summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/skia
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/skia
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/skia')
-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
4 files changed, 279 insertions, 6 deletions
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