diff options
author | Kristian Monsen <kristianm@google.com> | 2010-07-30 10:46:49 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-08-04 13:01:34 +0100 |
commit | 0617145a89917ae7735fe1c9538688ab9a577df5 (patch) | |
tree | 56206078694427c37ed7bdf27eb5221398b833c0 /WebCore/platform/graphics/skia | |
parent | ef1adcdfc805d4d13103f6f15cc5b4d96828a60f (diff) | |
download | external_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.cpp | 108 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/ImageBufferSkia.cpp | 12 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PlatformContextSkia.cpp | 127 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PlatformContextSkia.h | 38 |
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 |