From: jvanverth@google.com Date: Wed, 9 Jan 2013 21:04:52 +0000 (+0000) Subject: This takes the convex path tesselator from the Android code and hooks it into a X-Git-Tag: submit/tizen/20180928.044319~13873 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=74dda9018e8bdd650698e763404f19144c6d0a42;p=platform%2Fupstream%2FlibSkiaSharp.git This takes the convex path tesselator from the Android code and hooks it into a GrPathRenderer. GrAndroidPathRenderer is activated by gyp flag 'skia_android_path_rendering'. A few changes to get this to work: - Had to change SkPaint* param to SkStrokeRec& in ConvexPathVertices() - Had to copy the vertex buffer created by the Android code to GrDrawTarget-generated vertex buffer, and convert float alpha to GrColor for AA paths git-svn-id: http://skia.googlecode.com/svn/trunk@7110 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp index 051ed19738..6c3224863e 100644 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp +++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp @@ -12,7 +12,7 @@ #define VERTEX_DEBUG 0 #include -#include +#include #include #include @@ -520,12 +520,11 @@ static void getStrokeVerticesFromPerimeterAA(const SkTArray& perim #endif } -void PathRenderer::ConvexPathVertices(const SkPath &path, const SkPaint* paint, +void PathRenderer::ConvexPathVertices(const SkPath &path, const SkStrokeRec& stroke, bool isAA, const SkMatrix* transform, VertexBuffer* vertexBuffer) { SK_TRACE_EVENT0("PathRenderer::convexPathVertices"); - SkPaint::Style style = paint->getStyle(); - bool isAA = paint->isAntiAlias(); + SkStrokeRec::Style style = stroke.getStyle(); float inverseScaleX, inverseScaleY; computeInverseScales(transform, inverseScaleX, inverseScaleY); @@ -533,18 +532,18 @@ void PathRenderer::ConvexPathVertices(const SkPath &path, const SkPaint* paint, SkTArray tempVertices; float threshInvScaleX = inverseScaleX; float threshInvScaleY = inverseScaleY; - if (style == SkPaint::kStroke_Style) { + if (style == SkStrokeRec::kStroke_Style) { // alter the bezier recursion threshold values we calculate in order to compensate for // expansion done after the path vertices are found SkRect bounds = path.getBounds(); if (!bounds.isEmpty()) { - threshInvScaleX *= bounds.width() / (bounds.width() + paint->getStrokeWidth()); - threshInvScaleY *= bounds.height() / (bounds.height() + paint->getStrokeWidth()); + threshInvScaleX *= bounds.width() / (bounds.width() + stroke.getWidth()); + threshInvScaleY *= bounds.height() / (bounds.height() + stroke.getWidth()); } } // force close if we're filling the path, since fill path expects closed perimeter. - bool forceClose = style != SkPaint::kStroke_Style; + bool forceClose = style != SkStrokeRec::kStroke_Style; bool wasClosed = ConvexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX, threshInvScaleY * threshInvScaleY, &tempVertices); @@ -559,8 +558,8 @@ void PathRenderer::ConvexPathVertices(const SkPath &path, const SkPaint* paint, } #endif - if (style == SkPaint::kStroke_Style) { - float halfStrokeWidth = paint->getStrokeWidth() * 0.5f; + if (style == SkStrokeRec::kStroke_Style) { + float halfStrokeWidth = stroke.getWidth() * 0.5f; if (!isAA) { if (wasClosed) { getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer, diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.h b/experimental/AndroidPathRenderer/AndroidPathRenderer.h index 64aebfa59e..0e87aed1d1 100644 --- a/experimental/AndroidPathRenderer/AndroidPathRenderer.h +++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.h @@ -57,7 +57,7 @@ class PathRenderer { public: static SkRect ComputePathBounds(const SkPath& path, const SkPaint* paint); - static void ConvexPathVertices(const SkPath& path, const SkPaint* paint, + static void ConvexPathVertices(const SkPath& path, const SkStrokeRec& stroke, bool isAA, const SkMatrix* transform, VertexBuffer* vertexBuffer); private: diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp new file mode 100644 index 0000000000..c2bb708f13 --- /dev/null +++ b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp @@ -0,0 +1,75 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrAndroidPathRenderer.h" +#include "AndroidPathRenderer.h" +#include "Vertex.h" + +GrAndroidPathRenderer::GrAndroidPathRenderer() { +} + +bool GrAndroidPathRenderer::canDrawPath(const SkPath& path, + const SkStrokeRec& stroke, + const GrDrawTarget* target, + bool antiAlias) const { + return ((stroke.isFillStyle() || stroke.getStyle() == SkStrokeRec::kStroke_Style) + && !path.isInverseFillType() && path.isConvex()); +} + +struct ColorVertex { + SkPoint pos; + GrColor color; +}; + +bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, + const SkStrokeRec& stroke, + GrDrawTarget* target, + bool antiAlias) { + + // generate verts using Android algorithm + android::uirenderer::VertexBuffer vertices; + android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, + &vertices); + + // set vertex layout depending on anti-alias + GrVertexLayout layout = antiAlias ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; + + // allocate our vert buffer + int vertCount = vertices.getSize(); + GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0); + if (!geo.succeeded()) { + GrPrintf("Failed to get space for vertices!\n"); + return false; + } + + // copy android verts to our vertex buffer + if (antiAlias) { + ColorVertex* outVert = reinterpret_cast(geo.vertices()); + android::uirenderer::AlphaVertex* inVert = + reinterpret_cast(vertices.getBuffer()); + + for (int i = 0; i < vertCount; ++i) { + // copy vertex position + outVert->pos.set(inVert->position[0], inVert->position[1]); + // copy alpha + int coverage = static_cast(inVert->alpha * 0xff); + outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage); + ++outVert; + ++inVert; + } + } else { + size_t vsize = GrDrawTarget::VertexSize(layout); + size_t copySize = vsize*vertCount; + memcpy(geo.vertices(), vertices.getBuffer(), copySize); + } + + // render it + target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount); + + return true; +} diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h new file mode 100644 index 0000000000..38d2030468 --- /dev/null +++ b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h @@ -0,0 +1,29 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrPathRenderer.h" + + +class GrAndroidPathRenderer : public GrPathRenderer { +public: + GrAndroidPathRenderer(); + + virtual bool canDrawPath(const SkPath& path, + const SkStrokeRec& stroke, + const GrDrawTarget* target, + bool antiAlias) const SK_OVERRIDE; + +protected: + virtual bool onDrawPath(const SkPath& path, + const SkStrokeRec& stroke, + GrDrawTarget* target, + bool antiAlias) SK_OVERRIDE; + +private: + typedef GrPathRenderer INHERITED; +}; diff --git a/gyp/common_variables.gypi b/gyp/common_variables.gypi index fc2b3a93f4..5aca19c23b 100644 --- a/gyp/common_variables.gypi +++ b/gyp/common_variables.gypi @@ -82,6 +82,7 @@ 'skia_mesa%': 0, 'skia_nv_path_rendering%': 0, 'skia_stroke_path_rendering%': 0, + 'skia_android_path_rendering%': 0, 'skia_texture_cache_mb_limit%': 0, 'skia_angle%': 0, 'skia_directwrite%': 0, @@ -103,6 +104,7 @@ 'skia_mesa%': '<(skia_mesa)', 'skia_nv_path_rendering%': '<(skia_nv_path_rendering)', 'skia_stroke_path_rendering%': '<(skia_stroke_path_rendering)', + 'skia_android_path_rendering%': '<(skia_android_path_rendering)', 'skia_texture_cache_mb_limit%': '<(skia_texture_cache_mb_limit)', 'skia_angle%': '<(skia_angle)', 'skia_arch_width%': '<(skia_arch_width)', diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp index 09d5944b52..09711ac400 100644 --- a/gyp/experimental.gyp +++ b/gyp/experimental.gyp @@ -6,13 +6,11 @@ 'include_dirs': [ '../include/config', '../include/core', - '../experimental/AndroidPathRenderer', ], 'sources': [ '../experimental/SkSetPoly3To3.cpp', '../experimental/SkSetPoly3To3_A.cpp', '../experimental/SkSetPoly3To3_D.cpp', - '../experimental/AndroidPathRenderer/AndroidPathRenderer.cpp', ], 'direct_dependent_settings': { 'include_dirs': [ diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 474bdc146a..7438babe59 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -214,6 +214,18 @@ 'GR_STROKE_PATH_RENDERING=1', ], }], + [ 'skia_android_path_rendering', { + 'sources': [ + '../experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp', + '../experimental/AndroidPathRenderer/GrAndroidPathRenderer.h', + '../experimental/AndroidPathRenderer/AndroidPathRenderer.cpp', + '../experimental/AndroidPathRenderer/AndroidPathRenderer.h', + '../experimental/AndroidPathRenderer/Vertex.h', + ], + 'defines': [ + 'GR_ANDROID_PATH_RENDERING=1', + ], + }], [ 'skia_os == "linux"', { 'sources!': [ '../src/gpu/gl/GrGLDefaultInterface_none.cpp', diff --git a/src/gpu/GrAddPathRenderers_default.cpp b/src/gpu/GrAddPathRenderers_default.cpp index 618bd3100b..4f172434de 100644 --- a/src/gpu/GrAddPathRenderers_default.cpp +++ b/src/gpu/GrAddPathRenderers_default.cpp @@ -13,10 +13,16 @@ #if GR_STROKE_PATH_RENDERING #include "../../experimental/StrokePathRenderer/GrStrokePathRenderer.h" #endif +#if GR_ANDROID_PATH_RENDERING +#include "../../experimental/AndroidPathRenderer/GrAndroidPathRenderer.h" +#endif void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) { #if GR_STROKE_PATH_RENDERING chain->addPathRenderer(SkNEW(GrStrokePathRenderer))->unref(); +#endif +#if GR_ANDROID_PATH_RENDERING + chain->addPathRenderer(SkNEW(GrAndroidPathRenderer))->unref(); #endif if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) { chain->addPathRenderer(pr)->unref();