diff options
178 files changed, 12183 insertions, 5011 deletions
@@ -30,9 +30,6 @@ LOCAL_SRC_FILES:= \ src/core/SkCordic.cpp \ src/core/SkDebug.cpp \ src/core/SkFloatBits.cpp \ - src/core/SkMath.cpp \ - src/core/SkMatrix.cpp \ - src/core/SkMemory_stdlib.cpp \ src/core/SkPoint.cpp \ src/core/SkRect.cpp \ src/core/SkRegion.cpp \ @@ -140,6 +137,10 @@ LOCAL_SRC_FILES:= \ src/core/SkMMapStream.cpp \ src/core/SkMask.cpp \ src/core/SkMaskFilter.cpp \ + src/core/SkMath.cpp \ + src/core/SkMatrix.cpp \ + src/core/SkMemory_stdlib.cpp \ + src/core/SkMetaData.cpp \ src/core/SkPackBits.cpp \ src/core/SkPaint.cpp \ src/core/SkPath.cpp \ @@ -260,9 +261,12 @@ LOCAL_SRC_FILES:= \ gpu/src/GrAtlas.cpp \ gpu/src/GrClip.cpp \ gpu/src/GrContext.cpp \ + gpu/src/GrCreatePathRenderer_none.cpp \ gpu/src/GrDrawTarget.cpp \ + gpu/src/GrGLDefaultInterface_none.cpp \ gpu/src/GrGLIndexBuffer.cpp \ gpu/src/GrGLInterface.cpp \ + gpu/src/GrGLProgram.cpp \ gpu/src/GrGLTexture.cpp \ gpu/src/GrGLVertexBuffer.cpp \ gpu/src/GrGpu.cpp \ @@ -271,11 +275,15 @@ LOCAL_SRC_FILES:= \ gpu/src/GrGpuFactory.cpp \ gpu/src/GrGLUtil.cpp \ gpu/src/GrGpuGL.cpp \ + gpu/src/GrGpuGLShaders.cpp \ gpu/src/GrInOrderDrawBuffer.cpp \ gpu/src/GrMatrix.cpp \ gpu/src/GrMemory.cpp \ gpu/src/GrPath.cpp \ + gpu/src/GrPathUtils.cpp \ gpu/src/GrRectanizer_fifo.cpp \ + gpu/src/GrResource.cpp \ + gpu/src/GrTexture.cpp \ gpu/src/GrTextureCache.cpp \ gpu/src/GrTextContext.cpp \ gpu/src/GrTextStrike.cpp \ diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp new file mode 100644 index 0000000..19e3aae --- /dev/null +++ b/bench/PathBench.cpp @@ -0,0 +1,189 @@ +#include "SkBenchmark.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkColorPriv.h" +#include "SkPaint.h" +#include "SkShader.h" +#include "SkString.h" + +enum Flags { + kStroke_Flag = 1 << 0, + kBig_Flag = 1 << 1 +}; + +#define FLAGS00 Flags(0) +#define FLAGS01 Flags(kStroke_Flag) +#define FLAGS10 Flags(kBig_Flag) +#define FLAGS11 Flags(kStroke_Flag | kBig_Flag) + +class PathBench : public SkBenchmark { + SkPaint fPaint; + SkString fName; + Flags fFlags; + enum { N = 1000 }; +public: + PathBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) { + fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style : + SkPaint::kFill_Style); + fPaint.setStrokeWidth(SkIntToScalar(5)); + fPaint.setStrokeJoin(SkPaint::kBevel_Join); + } + + virtual void appendName(SkString*) = 0; + virtual void makePath(SkPath*) = 0; + virtual bool iscomplex() { return false; } + +protected: + virtual const char* onGetName() { + fName.printf("path_%s_%s_", + fFlags & kStroke_Flag ? "stroke" : "fill", + fFlags & kBig_Flag ? "big" : "small"); + this->appendName(&fName); + return fName.c_str(); + } + + virtual void onDraw(SkCanvas* canvas) { + SkPaint paint(fPaint); + this->setupPaint(&paint); + + SkPath path; + this->makePath(&path); + if (fFlags & kBig_Flag) { + SkMatrix m; + m.setScale(SkIntToScalar(10), SkIntToScalar(10)); + path.transform(m); + } + + int count = N; + if (fFlags & kBig_Flag) { + count >>= 2; + } + if (this->iscomplex()) { + count >>= 3; + } + + for (int i = 0; i < count; i++) { + canvas->drawPath(path, paint); + } + } + +private: + typedef SkBenchmark INHERITED; +}; + +class TrianglePathBench : public PathBench { +public: + TrianglePathBench(void* param, Flags flags) : INHERITED(param, flags) {} + + virtual void appendName(SkString* name) { + name->append("triangle"); + } + virtual void makePath(SkPath* path) { + static const int gCoord[] = { + 10, 10, 15, 5, 20, 20 + }; + path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); + path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); + path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); + path->close(); + } +private: + typedef PathBench INHERITED; +}; + +class RectPathBench : public PathBench { +public: + RectPathBench(void* param, Flags flags) : INHERITED(param, flags) {} + + virtual void appendName(SkString* name) { + name->append("rect"); + } + virtual void makePath(SkPath* path) { + SkRect r = { 10, 10, 20, 20 }; + path->addRect(r); + } +private: + typedef PathBench INHERITED; +}; + +class OvalPathBench : public PathBench { +public: + OvalPathBench(void* param, Flags flags) : INHERITED(param, flags) {} + + virtual void appendName(SkString* name) { + name->append("oval"); + } + virtual void makePath(SkPath* path) { + SkRect r = { 10, 10, 20, 20 }; + path->addOval(r); + } +private: + typedef PathBench INHERITED; +}; + +class SawToothPathBench : public PathBench { +public: + SawToothPathBench(void* param, Flags flags) : INHERITED(param, flags) {} + + virtual void appendName(SkString* name) { + name->append("sawtooth"); + } + virtual void makePath(SkPath* path) { + SkScalar x = SkIntToScalar(20); + SkScalar y = SkIntToScalar(20); + const SkScalar x0 = x; + const SkScalar dx = SK_Scalar1 * 5; + const SkScalar dy = SK_Scalar1 * 10; + + path->moveTo(x, y); + for (int i = 0; i < 32; i++) { + x += dx; + path->lineTo(x, y - dy); + x += dx; + path->lineTo(x, y + dy); + } + path->lineTo(x, y + 2 * dy); + path->lineTo(x0, y + 2 * dy); + path->close(); + } + virtual bool iscomplex() { return true; } +private: + typedef PathBench INHERITED; +}; + +static SkBenchmark* FactT00(void* p) { return new TrianglePathBench(p, FLAGS00); } +static SkBenchmark* FactT01(void* p) { return new TrianglePathBench(p, FLAGS01); } +static SkBenchmark* FactT10(void* p) { return new TrianglePathBench(p, FLAGS10); } +static SkBenchmark* FactT11(void* p) { return new TrianglePathBench(p, FLAGS11); } + +static SkBenchmark* FactR00(void* p) { return new RectPathBench(p, FLAGS00); } +static SkBenchmark* FactR01(void* p) { return new RectPathBench(p, FLAGS01); } +static SkBenchmark* FactR10(void* p) { return new RectPathBench(p, FLAGS10); } +static SkBenchmark* FactR11(void* p) { return new RectPathBench(p, FLAGS11); } + +static SkBenchmark* FactO00(void* p) { return new OvalPathBench(p, FLAGS00); } +static SkBenchmark* FactO01(void* p) { return new OvalPathBench(p, FLAGS01); } +static SkBenchmark* FactO10(void* p) { return new OvalPathBench(p, FLAGS10); } +static SkBenchmark* FactO11(void* p) { return new OvalPathBench(p, FLAGS11); } + +static SkBenchmark* FactS00(void* p) { return new SawToothPathBench(p, FLAGS00); } +static SkBenchmark* FactS01(void* p) { return new SawToothPathBench(p, FLAGS01); } + +static BenchRegistry gRegT00(FactT00); +static BenchRegistry gRegT01(FactT01); +static BenchRegistry gRegT10(FactT10); +static BenchRegistry gRegT11(FactT11); + +static BenchRegistry gRegR00(FactR00); +static BenchRegistry gRegR01(FactR01); +static BenchRegistry gRegR10(FactR10); +static BenchRegistry gRegR11(FactR11); + +static BenchRegistry gRegO00(FactO00); +static BenchRegistry gRegO01(FactO01); +static BenchRegistry gRegO10(FactO10); +static BenchRegistry gRegO11(FactO11); + +static BenchRegistry gRegS00(FactS00); +static BenchRegistry gRegS01(FactS01); + diff --git a/bench/RectBench.cpp b/bench/RectBench.cpp index a6f300e..fb54640 100644 --- a/bench/RectBench.cpp +++ b/bench/RectBench.cpp @@ -7,7 +7,7 @@ class RectBench : public SkBenchmark { public: - int fShift; + int fShift, fStroke; enum { W = 640, H = 480, @@ -16,8 +16,9 @@ public: SkRect fRects[N]; SkColor fColors[N]; - RectBench(void* param, int shift) : INHERITED(param), fShift(shift) { + RectBench(void* param, int shift, int stroke = 0) : INHERITED(param), fShift(shift), fStroke(stroke) { SkRandom rand; + const SkScalar offset = SK_Scalar1/3; for (int i = 0; i < N; i++) { int x = rand.nextU() % W; int y = rand.nextU() % H; @@ -29,14 +30,17 @@ public: y -= h/2; fRects[i].set(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x+w), SkIntToScalar(y+h)); + fRects[i].offset(offset, offset); fColors[i] = rand.nextU() | 0xFF808080; } } SkString fName; const char* computeName(const char root[]) { - fName.set(root); - fName.appendS32(fShift); + fName.printf("%s_%d", root, fShift); + if (fStroke > 0) { + fName.appendf("_stroke_%d", fStroke); + } return fName.c_str(); } @@ -48,6 +52,10 @@ protected: virtual const char* onGetName() { return computeName("rects"); } virtual void onDraw(SkCanvas* canvas) { SkPaint paint; + if (fStroke > 0) { + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(SkIntToScalar(fStroke)); + } for (int i = 0; i < N; i++) { paint.setColor(fColors[i]); this->setupPaint(&paint); @@ -192,8 +200,10 @@ private: }; -static SkBenchmark* RectFactory1(void* p) { return SkNEW_ARGS(RectBench, (p, 1)); } -static SkBenchmark* RectFactory2(void* p) { return SkNEW_ARGS(RectBench, (p, 3)); } +static SkBenchmark* RectFactory1F(void* p) { return SkNEW_ARGS(RectBench, (p, 1)); } +static SkBenchmark* RectFactory1S(void* p) { return SkNEW_ARGS(RectBench, (p, 1, 4)); } +static SkBenchmark* RectFactory2F(void* p) { return SkNEW_ARGS(RectBench, (p, 3)); } +static SkBenchmark* RectFactory2S(void* p) { return SkNEW_ARGS(RectBench, (p, 3, 4)); } static SkBenchmark* OvalFactory1(void* p) { return SkNEW_ARGS(OvalBench, (p, 1)); } static SkBenchmark* OvalFactory2(void* p) { return SkNEW_ARGS(OvalBench, (p, 3)); } static SkBenchmark* RRectFactory1(void* p) { return SkNEW_ARGS(RRectBench, (p, 1)); } @@ -234,8 +244,11 @@ static SkBenchmark* BlitMaskShaderFactory(void* p) { BlitMaskBench::KMaskShader, "maskshader") ); } -static BenchRegistry gRectReg1(RectFactory1); -static BenchRegistry gRectReg2(RectFactory2); + +static BenchRegistry gRectReg1F(RectFactory1F); +static BenchRegistry gRectReg1S(RectFactory1S); +static BenchRegistry gRectReg2F(RectFactory2F); +static BenchRegistry gRectReg2S(RectFactory2S); static BenchRegistry gOvalReg1(OvalFactory1); static BenchRegistry gOvalReg2(OvalFactory2); static BenchRegistry gRRectReg1(RRectFactory1); diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp index 3b6dfdf..4f6d81c 100644 --- a/bench/benchmain.cpp +++ b/bench/benchmain.cpp @@ -317,6 +317,14 @@ int main (int argc, char * const argv[]) { } } + // report our current settings + { + SkString str; + str.printf("skia bench: alpha=0x%02X antialias=%d filter=%d\n", + forceAlpha, forceAA, forceFilter); + log_progress(str); + } + Iter iter(&defineDict); SkBenchmark* bench; while ((bench = iter.next()) != NULL) { @@ -340,7 +348,7 @@ int main (int argc, char * const argv[]) { { SkString str; - str.printf("running bench [%d %d] %16s", dim.fX, dim.fY, + str.printf("running bench [%d %d] %28s", dim.fX, dim.fY, bench->getName()); log_progress(str); } @@ -397,8 +405,7 @@ int main (int argc, char * const argv[]) { if (repeatDraw > 1) { double duration = SkTime::GetMSecs() - now; SkString str; - str.printf(" %4s: msecs = %7.2f, fps = %7.2f", configName, - duration / repeatDraw, repeatDraw * 1000.0 / duration); + str.printf(" %4s: msecs = %5.2f", configName, duration / repeatDraw); log_progress(str); } if (outDir.size() > 0) { diff --git a/gm/Android.mk b/gm/Android.mk index e7960d4..b3aeadf 100644 --- a/gm/Android.mk +++ b/gm/Android.mk @@ -8,11 +8,13 @@ LOCAL_SRC_FILES := \ complexclip.cpp \ filltypes.cpp \ gradients.cpp \ + pathfill.cpp \ points.cpp \ poly2poly.cpp \ shadertext.cpp \ shadows.cpp \ shapes.cpp \ + strokerects.cpp \ tilemodes.cpp \ xfermodes.cpp \ gmmain.cpp diff --git a/gm/gm_files.mk b/gm/gm_files.mk new file mode 100644 index 0000000..e867820 --- /dev/null +++ b/gm/gm_files.mk @@ -0,0 +1,16 @@ +SOURCE := \ + bitmapfilters.cpp \ + blurs.cpp \ + filltypes.cpp \ + gradients.cpp \ + pathfill.cpp \ + points.cpp \ + poly2poly.cpp \ + shadows.cpp \ + shapes.cpp \ + strokerects.cpp \ + tilemodes.cpp \ + xfermodes.cpp \ + shadertext.cpp \ + complexclip.cpp \ + gmmain.cpp diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp index 357a54e..cb4e036 100644 --- a/gm/gmmain.cpp +++ b/gm/gmmain.cpp @@ -261,7 +261,10 @@ int main (int argc, char * const argv[]) { if (gRec[i].fBackend == kPDF_Backend && writePath) { #ifdef SK_SUPPORT_PDF SkISize size = gm->getISize(); - SkPDFDevice* dev = new SkPDFDevice(size.width(), size.height()); + SkMatrix identity; + identity.reset(); + SkPDFDevice* dev = new SkPDFDevice(size.width(), size.height(), + identity); SkAutoUnref aur(dev); SkCanvas c(dev); diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp new file mode 100644 index 0000000..ec56942 --- /dev/null +++ b/gm/pathfill.cpp @@ -0,0 +1,143 @@ +#include "gm.h" +#include "SkPicture.h" +#include "SkRectShape.h" +#include "SkGroupShape.h" + +typedef SkScalar (*MakePathProc)(SkPath*); + +static SkScalar make_frame(SkPath* path) { + SkRect r = { 10, 10, 630, 470 }; + path->addRoundRect(r, 15, 15); + + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(5); + paint.getFillPath(*path, path); + return 15; +} + +static SkScalar make_triangle(SkPath* path) { + static const int gCoord[] = { + 10, 20, 15, 5, 30, 30 + }; + path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1])); + path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3])); + path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5])); + path->close(); + path->offset(10, 0); + return SkIntToScalar(30); +} + +static SkScalar make_rect(SkPath* path) { + SkRect r = { 10, 10, 30, 30 }; + path->addRect(r); + path->offset(10, 0); + return SkIntToScalar(30); +} + +static SkScalar make_oval(SkPath* path) { + SkRect r = { 10, 10, 30, 30 }; + path->addOval(r); + path->offset(10, 0); + return SkIntToScalar(30); +} + +static SkScalar make_sawtooth(SkPath* path) { + SkScalar x = SkIntToScalar(20); + SkScalar y = SkIntToScalar(20); + const SkScalar x0 = x; + const SkScalar dx = SK_Scalar1 * 5; + const SkScalar dy = SK_Scalar1 * 10; + + path->moveTo(x, y); + for (int i = 0; i < 32; i++) { + x += dx; + path->lineTo(x, y - dy); + x += dx; + path->lineTo(x, y + dy); + } + path->lineTo(x, y + 2 * dy); + path->lineTo(x0, y + 2 * dy); + path->close(); + return SkIntToScalar(30); +} + +static SkScalar make_star(SkPath* path, int n) { + const SkScalar c = SkIntToScalar(45); + const SkScalar r = SkIntToScalar(20); + + SkScalar rad = -SK_ScalarPI / 2; + const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; + + path->moveTo(c, c - r); + for (int i = 1; i < n; i++) { + rad += drad; + SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); + path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); + } + path->close(); + return r * 2 * 6 / 5; +} + +static SkScalar make_star_5(SkPath* path) { return make_star(path, 5); } +static SkScalar make_star_13(SkPath* path) { return make_star(path, 13); } + +static const MakePathProc gProcs[] = { + make_frame, + make_triangle, + make_rect, + make_oval, + make_sawtooth, + make_star_5, + make_star_13 +}; + +#define N SK_ARRAY_COUNT(gProcs) + +namespace skiagm { + +class PathFillGM : public GM { + SkPath fPath[N]; + SkScalar fDY[N]; +public: + PathFillGM() { + for (size_t i = 0; i < N; i++) { + fDY[i] = gProcs[i](&fPath[i]); + } + } + +protected: + virtual SkString onShortName() { + return SkString("pathfill"); + } + + virtual SkISize onISize() { + return make_isize(640, 480); + } + + void drawBG(SkCanvas* canvas) { + canvas->drawColor(SK_ColorWHITE); + } + + virtual void onDraw(SkCanvas* canvas) { + this->drawBG(canvas); + + SkPaint paint; + paint.setAntiAlias(true); + + for (size_t i = 0; i < N; i++) { + canvas->drawPath(fPath[i], paint); + canvas->translate(0, fDY[i]); + } + } + +private: + typedef GM INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new PathFillGM; } +static GMRegistry reg(MyFactory); + +} diff --git a/gm/strokerects.cpp b/gm/strokerects.cpp new file mode 100644 index 0000000..b716407 --- /dev/null +++ b/gm/strokerects.cpp @@ -0,0 +1,88 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#include "gm.h" +#include "SkRandom.h" + +namespace skiagm { + +#define W 400 +#define H 400 +#define N 100 + +static const SkScalar SW = SkIntToScalar(W); +static const SkScalar SH = SkIntToScalar(H); + +class StrokeRectGM : public GM { +public: + StrokeRectGM() {} + +protected: + virtual SkString onShortName() { + return SkString("strokerects"); + } + + virtual SkISize onISize() { + return make_isize(W*2, H*2); + } + + static void rnd_rect(SkRect* r, SkRandom& rand) { + SkScalar x = rand.nextUScalar1() * W; + SkScalar y = rand.nextUScalar1() * H; + SkScalar w = rand.nextUScalar1() * (W >> 2); + SkScalar h = rand.nextUScalar1() * (H >> 2); + + r->set(x, y, x + w, y + h); + r->offset(-w/2 + rand.nextSScalar1(), -h/2 + + rand.nextSScalar1()); + } + + virtual void onDraw(SkCanvas* canvas) { + canvas->drawColor(SK_ColorWHITE); + + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + + for (int y = 0; y < 2; y++) { + paint.setAntiAlias(!!y); + for (int x = 0; x < 2; x++) { + paint.setStrokeWidth(x * SkIntToScalar(3)); + + SkAutoCanvasRestore acr(canvas, true); + canvas->translate(SW * x, SH * y); + canvas->clipRect(SkRect::MakeLTRB(2, 2, SW - 2, SH - 2)); + + SkRandom rand; + for (int i = 0; i < N; i++) { + SkRect r; + rnd_rect(&r, rand); + canvas->drawRect(r, paint); + } + } + } + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +static GM* MyFactory(void*) { return new StrokeRectGM; } +static GMRegistry reg(MyFactory); + +} + diff --git a/gpu/include/GrAtlas.h b/gpu/include/GrAtlas.h index a933842..406b45c 100644 --- a/gpu/include/GrAtlas.h +++ b/gpu/include/GrAtlas.h @@ -80,8 +80,6 @@ public: // to be called by ~GrAtlas() void freePlot(int x, int y); - void abandonAll(); - private: GrGpu* fGpu; GrTexture* fTexture[kCount_GrMaskFormats]; diff --git a/gpu/include/GrConfig.h b/gpu/include/GrConfig.h index 7805074..6f519b5 100644 --- a/gpu/include/GrConfig.h +++ b/gpu/include/GrConfig.h @@ -112,13 +112,24 @@ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +#if GR_WIN32_BUILD +// VC8 doesn't support stdint.h, so we define those types here. +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +#else /* - * Pull stdint.h in before user-config, to be sure our __STDC... macros are - * defined before anyone else might try to include stdint.h + * Include stdint.h with defines that trigger declaration of C99 limit/const + * macros here before anyone else has a chance to include stdint.h without + * these. */ #define __STDC_LIMIT_MACROS #define __STDC_CONSTANT_MACROS #include <stdint.h> +#endif /* * The "user config" file can be empty, and everything should work. It is @@ -141,6 +152,33 @@ /////////////////////////////////////////////////////////////////////////////// // postconfig section: // + +// GR_IMPLEMENTATION should be define to 1 when building Gr and 0 when including +// it in another dependent build. The Gr makefile/ide-project should define this +// to 1. +#if !defined(GR_IMPLEMENTATION) + #define GR_IMPLEMENTATION 0 +#endif + +// If Gr is built as a shared library then GR_DLL should be defined to 1 (both +// when building Gr and when including its headers in dependent builds). Only +// currently supported minimally for Chrome's Win32 Multi-DLL build (TODO: +// correctly exort all of the public API correctly and support shared lib on +// other platforms). +#if !defined(GR_DLL) + #define GR_DLL 0 +#endif + +#if GR_WIN32_BUILD && GR_DLL + #if GR_IMPLEMENTATION + #define GR_API __declspec(dllexport) + #else + #define GR_API __declspec(dllimport) + #endif +#else + #define GR_API +#endif + // By now we must have a GR_..._BUILD symbol set to 1, and a decision about // debug -vs- release // @@ -290,6 +328,10 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #define GR_DUMP_TEXTURE_UPLOAD 0 #endif +#ifndef GR_USE_NEW_GLSHADERS + #define GR_USE_NEW_GLSHADERS 0 +#endif + /** * GR_COLLECT_STATS controls whether the GrGpu class collects stats. * If not already defined then collect in debug build but not release. diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h index 1f90603..7b6803c 100644 --- a/gpu/include/GrContext.h +++ b/gpu/include/GrContext.h @@ -21,15 +21,15 @@ #include "GrGpu.h" #include "GrTextureCache.h" #include "GrPaint.h" +#include "GrPathRenderer.h" class GrFontCache; class GrPathIter; class GrVertexBufferAllocPool; class GrIndexBufferAllocPool; class GrInOrderDrawBuffer; -class GrPathRenderer; -class GrContext : public GrRefCnt { +class GR_API GrContext : public GrRefCnt { public: /** * Creates a GrContext from within a 3D context. @@ -52,14 +52,27 @@ public: */ void resetContext(); - /////////////////////////////////////////////////////////////////////////// - // Textures + /** + * Abandons all gpu resources, assumes 3D API state is unknown. Call this + * if you have lost the associated GPU context, and thus internal texture, + * buffer, etc. references/IDs are now invalid. Should be called even when + * GrContext is no longer going to be used for two reasons: + * 1) ~GrContext will not try to free the objects in the 3D API. + * 2) If you've created GrResources that outlive the GrContext they will + * be marked as invalid (GrResource::isValid()) and won't attempt to + * free their underlying resource in the 3D API. + * Content drawn since the last GrContext::flush() may be lost. + */ + void contextLost(); /** - * Abandons all textures. Call this if you have lost the associated GPU - * context, and thus internal texture references/IDs are now invalid. + * Frees gpu created by the context. Can be called to reduce GPU memory + * pressure. */ - void abandonAllTextures(); + void freeGpuResources(); + + /////////////////////////////////////////////////////////////////////////// + // Textures /** * Search for an entry with the same Key. If found, "lock" it and return it. @@ -145,20 +158,69 @@ public: // Render targets /** + * Sets the render target. + * @param target the render target to set. (should not be NULL.) + */ + void setRenderTarget(GrRenderTarget* target); + + /** + * Gets the current render target. + * @return the currently bound render target. Should never be NULL. + */ + const GrRenderTarget* getRenderTarget() const; + GrRenderTarget* getRenderTarget(); + + /////////////////////////////////////////////////////////////////////////// + // Platform Surfaces + + // GrContext provides an interface for wrapping externally created textures + // and rendertargets in their Gr-equivalents. + + /** + * Wraps an existing 3D API surface in a GrObject. desc.fFlags determines + * the type of object returned. If kIsTexture is set the returned object + * will be a GrTexture*. Otherwise, it will be a GrRenderTarget*. If both + * are set the render target object is accessible by + * GrTexture::asRenderTarget(). + * + * GL: if the object is a texture Gr may change its GL texture parameters + * when it is drawn. + * + * @param desc description of the object to create. + * @return either a GrTexture* or GrRenderTarget* depending on desc. NULL + * on failure. + */ + GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc); + + /** + * DEPRECATED, WILL BE REMOVED SOON. USE createPlatformSurface. + * * Wraps an externally-created rendertarget in a GrRenderTarget. * @param platformRenderTarget 3D API-specific render target identifier * e.g. in GL platforamRenderTarget is an FBO * id. * @param stencilBits the number of stencil bits that the render * target has. + * @param isMultisampled specify whether the render target is + * multisampled. * @param width width of the render target. * @param height height of the render target. */ GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget, int stencilBits, - int width, int height); + bool isMultisampled, + int width, int height) { + #if GR_DEBUG + GrPrintf("Using deprecated createPlatformRenderTarget API."); + #endif + return fGpu->createPlatformRenderTarget(platformRenderTarget, + stencilBits, isMultisampled, + width, height); + } /** + * DEPRECATED, WILL BE REMOVED SOON. USE createPlatformSurface. + * * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and * viewport state from the underlying 3D API and wraps it in a * GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the @@ -168,22 +230,12 @@ public: * @return the newly created GrRenderTarget */ GrRenderTarget* createRenderTargetFrom3DApiState() { + #if GR_DEBUG + GrPrintf("Using deprecated createRenderTargetFrom3DApiState API."); + #endif return fGpu->createRenderTargetFrom3DApiState(); } - /** - * Sets the render target. - * @param target the render target to set. (should not be NULL.) - */ - void setRenderTarget(GrRenderTarget* target); - - /** - * Gets the current render target. - * @return the currently bound render target. Should never be NULL. - */ - const GrRenderTarget* getRenderTarget() const; - GrRenderTarget* getRenderTarget(); - /////////////////////////////////////////////////////////////////////////// // Matrix state @@ -409,21 +461,50 @@ public: * @param flagsBitfield flags that control the flushing behavior. See * FlushBits. */ - void flush(int flagsBitfield); - /** - * Return true on success, i.e. if we could copy the specified range of - * pixels from the current render-target into the buffer, converting into - * the specified pixel-config. + void flush(int flagsBitfield = 0); + + /** + * Reads a rectangle of pixels from a render target. + * @param renderTarget the render target to read from. NULL means the + * current render target. + * @param left left edge of the rectangle to read (inclusive) + * @param top top edge of the rectangle to read (inclusive) + * @param width width of rectangle to read in pixels. + * @param height height of rectangle to read in pixels. + * @param config the pixel config of the destination buffer + * @param buffer memory to read the rectangle into. + * + * @return true if the read succeeded, false if not. The read can fail + * because of a unsupported pixel config or because no render + * target is currently set. + */ + bool readRenderTargetPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer); + + /** + * Reads a rectangle of pixels from a texture. + * @param texture the render target to read from. + * @param left left edge of the rectangle to read (inclusive) + * @param top top edge of the rectangle to read (inclusive) + * @param width width of rectangle to read in pixels. + * @param height height of rectangle to read in pixels. + * @param config the pixel config of the destination buffer + * @param buffer memory to read the rectangle into. + * + * @return true if the read succeeded, false if not. The read can fail + * because of a unsupported pixel config. */ - bool readPixels(int left, int top, int width, int height, - GrTexture::PixelConfig, void* buffer); + bool readTexturePixels(GrTexture* target, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer); /** * Copy the src pixels [buffer, stride, pixelconfig] into the current * render-target at the specified rectangle. */ void writePixels(int left, int top, int width, int height, - GrTexture::PixelConfig, const void* buffer, size_t stride); + GrPixelConfig, const void* buffer, size_t stride); /////////////////////////////////////////////////////////////////////////// @@ -479,13 +560,18 @@ private: GrGpu* fGpu; GrTextureCache* fTextureCache; GrFontCache* fFontCache; - GrPathRenderer* fPathRenderer; + + GrPathRenderer* fCustomPathRenderer; + GrDefaultPathRenderer fDefaultPathRenderer; GrVertexBufferAllocPool* fDrawBufferVBAllocPool; GrIndexBufferAllocPool* fDrawBufferIBAllocPool; GrInOrderDrawBuffer* fDrawBuffer; GrContext(GrGpu* gpu); + + void setupDrawBuffer(); + void flushDrawBuffer(); static void SetPaint(const GrPaint& paint, GrDrawTarget* target); @@ -495,6 +581,11 @@ private: GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType); void drawClipIntoStencil(); + + GrPathRenderer* getPathRenderer(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill); + }; /** diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h index 35f912b..349cafd 100644 --- a/gpu/include/GrDrawTarget.h +++ b/gpu/include/GrDrawTarget.h @@ -30,6 +30,7 @@ class GrTexture; class GrClipIterator; class GrVertexBuffer; class GrIndexBuffer; +class GrEffect; class GrDrawTarget : public GrRefCnt { public: @@ -138,6 +139,7 @@ protected: GrBlendCoeff fDstBlend; GrColor fBlendConstant; GrTexture* fTextures[kNumStages]; + GrEffect* fEffects[kNumStages]; GrSamplerState fSamplerStates[kNumStages]; GrRenderTarget* fRenderTarget; GrColor fColor; @@ -1001,20 +1003,20 @@ protected: { return sds.fState; } // implemented by subclass - virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, - void** vertices, - void** indices) = 0; + virtual bool onAcquireGeometry(GrVertexLayout vertexLayout, + void** vertices, + void** indices) = 0; - virtual void releaseGeometryHelper() = 0; + virtual void onReleaseGeometry() = 0; // subclass overrides to be notified when clip is set. virtual void clipWillBeSet(const GrClip& clip) = 0; - virtual void setVertexSourceToArrayHelper(const void* vertexArray, - int vertexCount) = 0; + virtual void onSetVertexSourceToArray(const void* vertexArray, + int vertexCount) = 0; - virtual void setIndexSourceToArrayHelper(const void* indexArray, - int indexCount) = 0; + virtual void onSetIndexSourceToArray(const void* indexArray, + int indexCount) = 0; // Helpers for drawRect, protected so subclasses that override drawRect // can use them. diff --git a/gpu/include/GrGLConfig.h b/gpu/include/GrGLConfig.h index 0a86e72..f251a23 100644 --- a/gpu/include/GrGLConfig.h +++ b/gpu/include/GrGLConfig.h @@ -19,13 +19,24 @@ #define GrGLConfig_DEFINED #include "GrTypes.h" -#include "GrGLInterface.h" +#include "GrGLDefines.h" + +/** + * Optional GL config file. + */ +#ifdef GR_GL_CUSTOM_SETUP_HEADER + #include GR_GL_CUSTOM_SETUP_HEADER +#endif + +#if !defined(GR_GL_FUNCTION_TYPE) + #define GR_GL_FUNCTION_TYPE +#endif /** * The following are optional defines that can be enabled at the compiler * command line, in a IDE project, in a GrUserConfig.h file, or in a GL custom - * file (if one is in use). They don't require GR_GL_CUSTOM_SETUP or - * setup GR_GL_CUSTOM_SETUP_HEADER to be enabled: + * file (if one is in use). If a GR_GL_CUSTOM_SETUP_HEADER is used they can + * also be placed there. * * GR_GL_LOG_CALLS: if 1 Gr can print every GL call using GrPrintf. Defaults to * 0. Logging can be enabled and disabled at runtime using a debugger via to @@ -63,22 +74,34 @@ //////////////////////////////////////////////////////////////////////////////// +/** + * The following macros are used to staticlly configure the default + * GrGLInterface, but should not be used outside of the GrGLInterface + * scaffolding. Undefine here to prevent accidental use. + */ +#undef GR_SUPPORT_GLDESKTOP +#undef GR_SUPPORT_GLES1 +#undef GR_SUPPORT_GLES2 +#undef GR_SUPPORT_GLES + +//////////////////////////////////////////////////////////////////////////////// + #if GR_SCALAR_IS_FIXED #define GrGLType GL_FIXED #elif GR_SCALAR_IS_FLOAT - #define GrGLType GL_FLOAT + #define GrGLType GR_GL_FLOAT #else #error "unknown GR_SCALAR type" #endif #if GR_TEXT_SCALAR_IS_USHORT - #define GrGLTextType GL_UNSIGNED_SHORT + #define GrGLTextType GR_GL_UNSIGNED_SHORT #define GR_GL_TEXT_TEXTURE_NORMALIZED 1 #elif GR_TEXT_SCALAR_IS_FLOAT - #define GrGLTextType GL_FLOAT + #define GrGLTextType GR_GL_FLOAT #define GR_GL_TEXT_TEXTURE_NORMALIZED 0 #elif GR_TEXT_SCALAR_IS_FIXED - #define GrGLTextType GL_FIXED + #define GrGLTextType GR_GL_FIXED #define GR_GL_TEXT_TEXTURE_NORMALIZED 0 #else #error "unknown GR_TEXT_SCALAR type" @@ -88,57 +111,17 @@ // Windows where we match GDI's order). #ifndef GR_GL_32BPP_COLOR_FORMAT #if GR_WIN32_BUILD - #define GR_GL_32BPP_COLOR_FORMAT GR_BGRA //use GR prefix because this - #else //may be an extension. - #define GR_GL_32BPP_COLOR_FORMAT GL_RGBA + #define GR_GL_32BPP_COLOR_FORMAT GR_GL_BGRA + #else + #define GR_GL_32BPP_COLOR_FORMAT GR_GL_RGBA #endif #endif - - -// BGRA format -#define GR_BGRA 0x80E1 - -// FBO / stencil formats -#define GR_FRAMEBUFFER 0x8D40 -#define GR_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GR_COLOR_ATTACHMENT0 0x8CE0 -#define GR_FRAMEBUFFER_BINDING 0x8CA6 -#define GR_RENDERBUFFER 0x8D41 -#define GR_STENCIL_ATTACHMENT 0x8D20 -#define GR_STENCIL_INDEX4 0x8D47 -#define GR_STENCIL_INDEX8 0x8D48 -#define GR_STENCIL_INDEX16 0x8D49 -#define GR_DEPTH24_STENCIL8 0x88F0 -#define GR_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GR_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GR_DEPTH_STENCIL 0x84F9 -#define GR_RGBA8 0x8058 -#define GR_RGB565 0x8D62 - - -// Multisampling - -// IMG MAX_SAMPLES uses a different value than desktop, Apple ES extension. -#define GR_MAX_SAMPLES 0x8D57 -#define GR_MAX_SAMPLES_IMG 0x9135 -#define GR_READ_FRAMEBUFFER 0x8CA8 -#define GR_DRAW_FRAMEBUFFER 0x8CA9 - -// Buffer mapping -#define GR_WRITE_ONLY 0x88B9 -#define GR_BUFFER_MAPPED 0x88BC - -// Palette texture -#define GR_PALETTE8_RGBA8 0x8B91 - //////////////////////////////////////////////////////////////////////////////// extern void GrGLCheckErr(const char* location, const char* call); -static inline void GrGLClearErr() { - while (GL_NO_ERROR != GrGLGetGLInterface()->fGetError()) {} -} +extern void GrGLClearErr(); #if GR_GL_CHECK_ERROR extern bool gCheckErrorGL; @@ -157,19 +140,18 @@ static inline void GrGLClearErr() { #define GR_GL(X) GrGLGetGLInterface()->f##X;; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X); #define GR_GL_NO_ERR(X) GrGLGetGLInterface()->f##X;; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X); +#define GR_GL_SUPPORT_DESKTOP (kDesktop_GrGLBinding == GrGLGetGLInterface()->fBindingsExported) +#define GR_GL_SUPPORT_ES1 (kES1_GrGLBinding == GrGLGetGLInterface()->fBindingsExported) +#define GR_GL_SUPPORT_ES2 (kES2_GrGLBinding == GrGLGetGLInterface()->fBindingsExported) +#define GR_GL_SUPPORT_ES (GR_GL_SUPPORT_ES1 || GR_GL_SUPPORT_ES2) + //////////////////////////////////////////////////////////////////////////////// /** - * GrGL_RestoreResetRowLength() will reset GL_UNPACK_ROW_LENGTH to 0. We write + * GrGLRestoreResetRowLength() will reset GL_UNPACK_ROW_LENGTH to 0. We write * this wrapper, since GL_UNPACK_ROW_LENGTH is not available on all GL versions */ -#if GR_SUPPORT_GLDESKTOP - static inline void GrGL_RestoreResetRowLength() { - GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH, 0)); - } -#else - #define GrGL_RestoreResetRowLength() -#endif +extern void GrGLRestoreResetRowLength(); //////////////////////////////////////////////////////////////////////////////// diff --git a/gpu/include/GrGLConfig_chrome.h b/gpu/include/GrGLConfig_chrome.h index ff0d7b7..08f7547 100644 --- a/gpu/include/GrGLConfig_chrome.h +++ b/gpu/include/GrGLConfig_chrome.h @@ -1,34 +1,10 @@ #ifndef GrGLConfig_chrome_DEFINED #define GrGLConfig_chrome_DEFINED -#define GR_SUPPORT_GLES2 1 - -// gl2ext.h will define these extensions macros but Chrome doesn't provide -// prototypes. -#define GL_OES_mapbuffer 0 -#define GL_IMG_multisampled_render_to_texture 0 - -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#define GR_GL_FUNC - -#define GR_GL_PROC_ADDRESS(X) &X - // chrome always assumes BGRA -#define GR_GL_32BPP_COLOR_FORMAT GR_BGRA +#define GR_GL_32BPP_COLOR_FORMAT GR_GL_BGRA // glGetError() forces a sync with gpu process on chrome #define GR_GL_CHECK_ERROR_START 0 -// Using the static vb precludes batching rect-to-rect draws -// because there are matrix changes between each one. -// Chrome was getting top performance on Windows with -// batched rect-to-rect draws. But there seems to be some -// regression that now causes any dynamic VB data to perform -// very poorly. In any event the static VB seems to get equal -// perf to what batching was producing and it always seems to -// be better on Linux. -#define GR_STATIC_RECT_VB 1 - #endif diff --git a/gpu/include/GrGLDefines.h b/gpu/include/GrGLDefines.h new file mode 100644 index 0000000..29e56f3 --- /dev/null +++ b/gpu/include/GrGLDefines.h @@ -0,0 +1,644 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGLDefines_DEFINED +#define GrGLDefines_DEFINED + +// The following constants consist of the intersection of GL constants +// exported by GLES 1.0, GLES 2.0, and desktop GL required by the system. + +#define GR_GL_DEPTH_BUFFER_BIT 0x00000100 +#define GR_GL_STENCIL_BUFFER_BIT 0x00000400 +#define GR_GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GR_GL_FALSE 0 +#define GR_GL_TRUE 1 + +/* BeginMode */ +#define GR_GL_POINTS 0x0000 +#define GR_GL_LINES 0x0001 +#define GR_GL_LINE_LOOP 0x0002 +#define GR_GL_LINE_STRIP 0x0003 +#define GR_GL_TRIANGLES 0x0004 +#define GR_GL_TRIANGLE_STRIP 0x0005 +#define GR_GL_TRIANGLE_FAN 0x0006 + +/* AlphaFunction (not supported in ES20) */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* BlendingFactorDest */ +#define GR_GL_ZERO 0 +#define GR_GL_ONE 1 +#define GR_GL_SRC_COLOR 0x0300 +#define GR_GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GR_GL_SRC_ALPHA 0x0302 +#define GR_GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GR_GL_DST_ALPHA 0x0304 +#define GR_GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GR_GL_DST_COLOR 0x0306 +#define GR_GL_ONE_MINUS_DST_COLOR 0x0307 +#define GR_GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GR_GL_FUNC_ADD 0x8006 +#define GR_GL_BLEND_EQUATION 0x8009 +#define GR_GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GR_GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GR_GL_FUNC_SUBTRACT 0x800A +#define GR_GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GR_GL_BLEND_DST_RGB 0x80C8 +#define GR_GL_BLEND_SRC_RGB 0x80C9 +#define GR_GL_BLEND_DST_ALPHA 0x80CA +#define GR_GL_BLEND_SRC_ALPHA 0x80CB +#define GR_GL_CONSTANT_COLOR 0x8001 +#define GR_GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GR_GL_CONSTANT_ALPHA 0x8003 +#define GR_GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GR_GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GR_GL_ARRAY_BUFFER 0x8892 +#define GR_GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GR_GL_ARRAY_BUFFER_BINDING 0x8894 +#define GR_GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GR_GL_STREAM_DRAW 0x88E0 +#define GR_GL_STATIC_DRAW 0x88E4 +#define GR_GL_DYNAMIC_DRAW 0x88E8 + +#define GR_GL_BUFFER_SIZE 0x8764 +#define GR_GL_BUFFER_USAGE 0x8765 + +#define GR_GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GR_GL_FRONT 0x0404 +#define GR_GL_BACK 0x0405 +#define GR_GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GR_GL_TEXTURE_2D 0x0DE1 +#define GR_GL_CULL_FACE 0x0B44 +#define GR_GL_BLEND 0x0BE2 +#define GR_GL_DITHER 0x0BD0 +#define GR_GL_STENCIL_TEST 0x0B90 +#define GR_GL_DEPTH_TEST 0x0B71 +#define GR_GL_SCISSOR_TEST 0x0C11 +#define GR_GL_POLYGON_OFFSET_FILL 0x8037 +#define GR_GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GR_GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GR_GL_NO_ERROR 0 +#define GR_GL_INVALID_ENUM 0x0500 +#define GR_GL_INVALID_VALUE 0x0501 +#define GR_GL_INVALID_OPERATION 0x0502 +#define GR_GL_OUT_OF_MEMORY 0x0505 +#define GR_GL_CONTEXT_LOST 0x300E // TODO(gman): What value? + +/* FrontFaceDirection */ +#define GR_GL_CW 0x0900 +#define GR_GL_CCW 0x0901 + +/* GetPName */ +#define GR_GL_LINE_WIDTH 0x0B21 +#define GR_GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GR_GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GR_GL_CULL_FACE_MODE 0x0B45 +#define GR_GL_FRONT_FACE 0x0B46 +#define GR_GL_DEPTH_RANGE 0x0B70 +#define GR_GL_DEPTH_WRITEMASK 0x0B72 +#define GR_GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GR_GL_DEPTH_FUNC 0x0B74 +#define GR_GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GR_GL_STENCIL_FUNC 0x0B92 +#define GR_GL_STENCIL_FAIL 0x0B94 +#define GR_GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GR_GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GR_GL_STENCIL_REF 0x0B97 +#define GR_GL_STENCIL_VALUE_MASK 0x0B93 +#define GR_GL_STENCIL_WRITEMASK 0x0B98 +#define GR_GL_STENCIL_BACK_FUNC 0x8800 +#define GR_GL_STENCIL_BACK_FAIL 0x8801 +#define GR_GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GR_GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GR_GL_STENCIL_BACK_REF 0x8CA3 +#define GR_GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GR_GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GR_GL_VIEWPORT 0x0BA2 +#define GR_GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GR_GL_COLOR_CLEAR_VALUE 0x0C22 +#define GR_GL_COLOR_WRITEMASK 0x0C23 +#define GR_GL_UNPACK_ALIGNMENT 0x0CF5 +#define GR_GL_PACK_ALIGNMENT 0x0D05 +#define GR_GL_MAX_TEXTURE_SIZE 0x0D33 +#define GR_GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GR_GL_SUBPIXEL_BITS 0x0D50 +#define GR_GL_RED_BITS 0x0D52 +#define GR_GL_GREEN_BITS 0x0D53 +#define GR_GL_BLUE_BITS 0x0D54 +#define GR_GL_ALPHA_BITS 0x0D55 +#define GR_GL_DEPTH_BITS 0x0D56 +#define GR_GL_STENCIL_BITS 0x0D57 +#define GR_GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GR_GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GR_GL_TEXTURE_BINDING_2D 0x8069 +#define GR_GL_SAMPLE_BUFFERS 0x80A8 +#define GR_GL_SAMPLES 0x80A9 +#define GR_GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GR_GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GR_GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GR_GL_DONT_CARE 0x1100 +#define GR_GL_FASTEST 0x1101 +#define GR_GL_NICEST 0x1102 + +/* HintTarget */ +#define GR_GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GR_GL_BYTE 0x1400 +#define GR_GL_UNSIGNED_BYTE 0x1401 +#define GR_GL_SHORT 0x1402 +#define GR_GL_UNSIGNED_SHORT 0x1403 +#define GR_GL_INT 0x1404 +#define GR_GL_UNSIGNED_INT 0x1405 +#define GR_GL_FLOAT 0x1406 +#define GR_GL_FIXED 0x140C + +/* Lighting */ +#define GR_GL_LIGHTING 0x0B50 +#define GR_GL_LIGHT0 0x4000 +#define GR_GL_LIGHT1 0x4001 +#define GR_GL_LIGHT2 0x4002 +#define GR_GL_LIGHT3 0x4003 +#define GR_GL_LIGHT4 0x4004 +#define GR_GL_LIGHT5 0x4005 +#define GR_GL_LIGHT6 0x4006 +#define GR_GL_LIGHT7 0x4007 +#define GR_GL_SPOT_EXPONENT 0x1205 +#define GR_GL_SPOT_CUTOFF 0x1206 +#define GR_GL_CONSTANT_ATTENUATION 0x1207 +#define GR_GL_LINEAR_ATTENUATION 0x1208 +#define GR_GL_QUADRATIC_ATTENUATION 0x1209 +#define GR_GL_AMBIENT 0x1200 +#define GR_GL_DIFFUSE 0x1201 +#define GR_GL_SPECULAR 0x1202 +#define GR_GL_SHININESS 0x1601 +#define GR_GL_EMISSION 0x1600 +#define GR_GL_POSITION 0x1203 +#define GR_GL_SPOT_DIRECTION 0x1204 +#define GR_GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GR_GL_COLOR_INDEXES 0x1603 +#define GR_GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GR_GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GR_GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GR_GL_FRONT_AND_BACK 0x0408 +#define GR_GL_SHADE_MODEL 0x0B54 +#define GR_GL_FLAT 0x1D00 +#define GR_GL_SMOOTH 0x1D01 +#define GR_GL_COLOR_MATERIAL 0x0B57 +#define GR_GL_COLOR_MATERIAL_FACE 0x0B55 +#define GR_GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GR_GL_NORMALIZE 0x0BA1 + +/* Matrix Mode */ +#define GR_GL_MATRIX_MODE 0x0BA0 +#define GR_GL_MODELVIEW 0x1700 +#define GR_GL_PROJECTION 0x1701 +#define GR_GL_TEXTURE 0x1702 + +/* multisample */ +#define GR_GL_MULTISAMPLE 0x809D + +/* Points */ +#define GR_GL_POINT_SMOOTH 0x0B10 +#define GR_GL_POINT_SIZE 0x0B11 +#define GR_GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GR_GL_POINT_SIZE_RANGE 0x0B12 + +/* Lines */ +#define GR_GL_LINE_SMOOTH 0x0B20 +#define GR_GL_LINE_STIPPLE 0x0B24 +#define GR_GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GR_GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GR_GL_LINE_WIDTH 0x0B21 +#define GR_GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GR_GL_LINE_WIDTH_RANGE 0x0B22 + +/* PixelFormat */ +#define GR_GL_DEPTH_COMPONENT 0x1902 +#define GR_GL_ALPHA 0x1906 +#define GR_GL_RGB 0x1907 +#define GR_GL_RGBA 0x1908 +#define GR_GL_BGRA 0x80E1 +#define GR_GL_LUMINANCE 0x1909 +#define GR_GL_LUMINANCE_ALPHA 0x190A +#define GR_GL_PALETTE8_RGBA8 0x8B96 + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GR_GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GR_GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GR_GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GR_GL_FRAGMENT_SHADER 0x8B30 +#define GR_GL_VERTEX_SHADER 0x8B31 +#define GR_GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GR_GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GR_GL_MAX_VARYING_VECTORS 0x8DFC +#define GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GR_GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GR_GL_SHADER_TYPE 0x8B4F +#define GR_GL_DELETE_STATUS 0x8B80 +#define GR_GL_LINK_STATUS 0x8B82 +#define GR_GL_VALIDATE_STATUS 0x8B83 +#define GR_GL_ATTACHED_SHADERS 0x8B85 +#define GR_GL_ACTIVE_UNIFORMS 0x8B86 +#define GR_GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GR_GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GR_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GR_GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GR_GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GR_GL_NEVER 0x0200 +#define GR_GL_LESS 0x0201 +#define GR_GL_EQUAL 0x0202 +#define GR_GL_LEQUAL 0x0203 +#define GR_GL_GREATER 0x0204 +#define GR_GL_NOTEQUAL 0x0205 +#define GR_GL_GEQUAL 0x0206 +#define GR_GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GR_GL_KEEP 0x1E00 +#define GR_GL_REPLACE 0x1E01 +#define GR_GL_INCR 0x1E02 +#define GR_GL_DECR 0x1E03 +#define GR_GL_INVERT 0x150A +#define GR_GL_INCR_WRAP 0x8507 +#define GR_GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GR_GL_VENDOR 0x1F00 +#define GR_GL_RENDERER 0x1F01 +#define GR_GL_VERSION 0x1F02 +#define GR_GL_EXTENSIONS 0x1F03 + +/* Pixel Mode / Transfer */ +#define GR_GL_UNPACK_ROW_LENGTH 0x0CF2 + +/* TextureMagFilter */ +#define GR_GL_NEAREST 0x2600 +#define GR_GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GR_GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GR_GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GR_GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GR_GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GR_GL_TEXTURE_MAG_FILTER 0x2800 +#define GR_GL_TEXTURE_MIN_FILTER 0x2801 +#define GR_GL_TEXTURE_WRAP_S 0x2802 +#define GR_GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GR_GL_TEXTURE 0x1702 +#define GR_GL_TEXTURE_CUBE_MAP 0x8513 +#define GR_GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GR_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GR_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GR_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GR_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GR_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GR_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GR_GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GR_GL_TEXTURE0 0x84C0 +#define GR_GL_TEXTURE1 0x84C1 +#define GR_GL_TEXTURE2 0x84C2 +#define GR_GL_TEXTURE3 0x84C3 +#define GR_GL_TEXTURE4 0x84C4 +#define GR_GL_TEXTURE5 0x84C5 +#define GR_GL_TEXTURE6 0x84C6 +#define GR_GL_TEXTURE7 0x84C7 +#define GR_GL_TEXTURE8 0x84C8 +#define GR_GL_TEXTURE9 0x84C9 +#define GR_GL_TEXTURE10 0x84CA +#define GR_GL_TEXTURE11 0x84CB +#define GR_GL_TEXTURE12 0x84CC +#define GR_GL_TEXTURE13 0x84CD +#define GR_GL_TEXTURE14 0x84CE +#define GR_GL_TEXTURE15 0x84CF +#define GR_GL_TEXTURE16 0x84D0 +#define GR_GL_TEXTURE17 0x84D1 +#define GR_GL_TEXTURE18 0x84D2 +#define GR_GL_TEXTURE19 0x84D3 +#define GR_GL_TEXTURE20 0x84D4 +#define GR_GL_TEXTURE21 0x84D5 +#define GR_GL_TEXTURE22 0x84D6 +#define GR_GL_TEXTURE23 0x84D7 +#define GR_GL_TEXTURE24 0x84D8 +#define GR_GL_TEXTURE25 0x84D9 +#define GR_GL_TEXTURE26 0x84DA +#define GR_GL_TEXTURE27 0x84DB +#define GR_GL_TEXTURE28 0x84DC +#define GR_GL_TEXTURE29 0x84DD +#define GR_GL_TEXTURE30 0x84DE +#define GR_GL_TEXTURE31 0x84DF +#define GR_GL_ACTIVE_TEXTURE 0x84E0 +#define GR_GL_MAX_TEXTURE_UNITS 0x84E2 + +/* TextureWrapMode */ +#define GR_GL_REPEAT 0x2901 +#define GR_GL_CLAMP_TO_EDGE 0x812F +#define GR_GL_MIRRORED_REPEAT 0x8370 + +/* Texture mapping */ +#define GR_GL_TEXTURE_ENV 0x2300 +#define GR_GL_TEXTURE_ENV_MODE 0x2200 +#define GR_GL_TEXTURE_1D 0x0DE0 +#define GR_GL_TEXTURE_2D 0x0DE1 +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +#define GR_GL_TEXTURE_ENV_COLOR 0x2201 +#define GR_GL_TEXTURE_GEN_S 0x0C60 +#define GR_GL_TEXTURE_GEN_T 0x0C61 +#define GR_GL_TEXTURE_GEN_MODE 0x2500 +#define GR_GL_TEXTURE_BORDER_COLOR 0x1004 +#define GR_GL_TEXTURE_WIDTH 0x1000 +#define GR_GL_TEXTURE_HEIGHT 0x1001 +#define GR_GL_TEXTURE_BORDER 0x1005 +#define GR_GL_TEXTURE_COMPONENTS 0x1003 +#define GR_GL_TEXTURE_RED_SIZE 0x805C +#define GR_GL_TEXTURE_GREEN_SIZE 0x805D +#define GR_GL_TEXTURE_BLUE_SIZE 0x805E +#define GR_GL_TEXTURE_ALPHA_SIZE 0x805F +#define GR_GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GR_GL_TEXTURE_INTENSITY_SIZE 0x8061 +/* GL_NEAREST_MIPMAP_NEAREST */ +/* GL_NEAREST_MIPMAP_LINEAR */ +/* GL_LINEAR_MIPMAP_NEAREST */ +/* GL_LINEAR_MIPMAP_LINEAR */ +#define GR_GL_OBJECT_LINEAR 0x2401 +#define GR_GL_OBJECT_PLANE 0x2501 +#define GR_GL_EYE_LINEAR 0x2400 +#define GR_GL_EYE_PLANE 0x2502 +#define GR_GL_SPHERE_MAP 0x2402 +#define GR_GL_DECAL 0x2101 +#define GR_GL_MODULATE 0x2100 +/* GL_NEAREST */ +/* GL_REPEAT */ +#define GR_GL_CLAMP 0x2900 +#define GR_GL_S 0x2000 +#define GR_GL_T 0x2001 +#define GR_GL_R 0x2002 +#define GR_GL_Q 0x2003 +#define GR_GL_TEXTURE_GEN_R 0x0C62 +#define GR_GL_TEXTURE_GEN_Q 0x0C63 + +/* texture_env_combine */ +#define GR_GL_COMBINE 0x8570 +#define GR_GL_COMBINE_RGB 0x8571 +#define GR_GL_COMBINE_ALPHA 0x8572 +#define GR_GL_SOURCE0_RGB 0x8580 +#define GR_GL_SOURCE1_RGB 0x8581 +#define GR_GL_SOURCE2_RGB 0x8582 +#define GR_GL_SOURCE0_ALPHA 0x8588 +#define GR_GL_SOURCE1_ALPHA 0x8589 +#define GR_GL_SOURCE2_ALPHA 0x858A +#define GR_GL_OPERAND0_RGB 0x8590 +#define GR_GL_OPERAND1_RGB 0x8591 +#define GR_GL_OPERAND2_RGB 0x8592 +#define GR_GL_OPERAND0_ALPHA 0x8598 +#define GR_GL_OPERAND1_ALPHA 0x8599 +#define GR_GL_OPERAND2_ALPHA 0x859A +#define GR_GL_RGB_SCALE 0x8573 +#define GR_GL_ADD_SIGNED 0x8574 +#define GR_GL_INTERPOLATE 0x8575 +#define GR_GL_SUBTRACT 0x84E7 +#define GR_GL_CONSTANT 0x8576 +#define GR_GL_PRIMARY_COLOR 0x8577 +#define GR_GL_PREVIOUS 0x8578 +#define GR_GL_SRC0_RGB 0x8580 +#define GR_GL_SRC1_RGB 0x8581 +#define GR_GL_SRC2_RGB 0x8582 +#define GR_GL_SRC0_ALPHA 0x8588 +#define GR_GL_SRC1_ALPHA 0x8589 +#define GR_GL_SRC2_ALPHA 0x858A + +/* Uniform Types */ +#define GR_GL_FLOAT_VEC2 0x8B50 +#define GR_GL_FLOAT_VEC3 0x8B51 +#define GR_GL_FLOAT_VEC4 0x8B52 +#define GR_GL_INT_VEC2 0x8B53 +#define GR_GL_INT_VEC3 0x8B54 +#define GR_GL_INT_VEC4 0x8B55 +#define GR_GL_BOOL 0x8B56 +#define GR_GL_BOOL_VEC2 0x8B57 +#define GR_GL_BOOL_VEC3 0x8B58 +#define GR_GL_BOOL_VEC4 0x8B59 +#define GR_GL_FLOAT_MAT2 0x8B5A +#define GR_GL_FLOAT_MAT3 0x8B5B +#define GR_GL_FLOAT_MAT4 0x8B5C +#define GR_GL_SAMPLER_2D 0x8B5E +#define GR_GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GR_GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GR_GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GR_GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GR_GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GR_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GR_GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GR_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GR_GL_VERTEX_ARRAY 0x8074 +#define GR_GL_NORMAL_ARRAY 0x8075 +#define GR_GL_COLOR_ARRAY 0x8076 +#define GR_GL_INDEX_ARRAY 0x8077 +#define GR_GL_TEXTURE_COORD_ARRAY 0x8078 +#define GR_GL_EDGE_FLAG_ARRAY 0x8079 +#define GR_GL_VERTEX_ARRAY_SIZE 0x807A +#define GR_GL_VERTEX_ARRAY_TYPE 0x807B +#define GR_GL_VERTEX_ARRAY_STRIDE 0x807C +#define GR_GL_NORMAL_ARRAY_TYPE 0x807E +#define GR_GL_NORMAL_ARRAY_STRIDE 0x807F +#define GR_GL_COLOR_ARRAY_SIZE 0x8081 +#define GR_GL_COLOR_ARRAY_TYPE 0x8082 +#define GR_GL_COLOR_ARRAY_STRIDE 0x8083 +#define GR_GL_INDEX_ARRAY_TYPE 0x8085 +#define GR_GL_INDEX_ARRAY_STRIDE 0x8086 +#define GR_GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GR_GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GR_GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GR_GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GR_GL_VERTEX_ARRAY_POINTER 0x808E +#define GR_GL_NORMAL_ARRAY_POINTER 0x808F +#define GR_GL_COLOR_ARRAY_POINTER 0x8090 +#define GR_GL_INDEX_ARRAY_POINTER 0x8091 +#define GR_GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GR_GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GR_GL_V2F 0x2A20 +#define GR_GL_V3F 0x2A21 +#define GR_GL_C4UB_V2F 0x2A22 +#define GR_GL_C4UB_V3F 0x2A23 +#define GR_GL_C3F_V3F 0x2A24 +#define GR_GL_N3F_V3F 0x2A25 +#define GR_GL_C4F_N3F_V3F 0x2A26 +#define GR_GL_T2F_V3F 0x2A27 +#define GR_GL_T4F_V4F 0x2A28 +#define GR_GL_T2F_C4UB_V3F 0x2A29 +#define GR_GL_T2F_C3F_V3F 0x2A2A +#define GR_GL_T2F_N3F_V3F 0x2A2B +#define GR_GL_T2F_C4F_N3F_V3F 0x2A2C +#define GR_GL_T4F_C4F_N3F_V4F 0x2A2D + +/* Vertex Buffer Object */ +#define GR_GL_WRITE_ONLY 0x88B9 +#define GR_GL_BUFFER_MAPPED 0x88BC +/* Read Format */ +#define GR_GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GR_GL_COMPILE_STATUS 0x8B81 +#define GR_GL_INFO_LOG_LENGTH 0x8B84 +#define GR_GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GR_GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GR_GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GR_GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GR_GL_LOW_FLOAT 0x8DF0 +#define GR_GL_MEDIUM_FLOAT 0x8DF1 +#define GR_GL_HIGH_FLOAT 0x8DF2 +#define GR_GL_LOW_INT 0x8DF3 +#define GR_GL_MEDIUM_INT 0x8DF4 +#define GR_GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GR_GL_FRAMEBUFFER 0x8D40 +#define GR_GL_READ_FRAMEBUFFER 0x8CA8 +#define GR_GL_DRAW_FRAMEBUFFER 0x8CA9 + +#define GR_GL_RENDERBUFFER 0x8D41 + +#define GR_GL_RGBA4 0x8056 +#define GR_GL_RGB5_A1 0x8057 +#define GR_GL_RGB565 0x8D62 +#define GR_GL_RGBA8 0x8058 +#define GR_GL_DEPTH_COMPONENT16 0x81A5 +#define GR_GL_STENCIL_INDEX 0x1901 +#define GR_GL_STENCIL_INDEX4 0x8D47 +#define GR_GL_STENCIL_INDEX8 0x8D48 +#define GR_GL_STENCIL_INDEX16 0x8D49 +#define GR_GL_DEPTH_STENCIL 0x84F9 +#define GR_GL_DEPTH24_STENCIL8 0x88F0 + +#define GR_GL_MAX_SAMPLES 0x8D57 + +#define GR_GL_RENDERBUFFER_WIDTH 0x8D42 +#define GR_GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GR_GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GR_GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GR_GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GR_GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GR_GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GR_GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GR_GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GR_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GR_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GR_GL_COLOR_ATTACHMENT0 0x8CE0 +#define GR_GL_DEPTH_ATTACHMENT 0x8D00 +#define GR_GL_STENCIL_ATTACHMENT 0x8D20 +#define GR_GL_DEPTH_STENCIL_ATTACHMENT 0x821A + +#define GR_GL_NONE 0 + +#define GR_GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GR_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GR_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GR_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GR_GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GR_GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GR_GL_RENDERBUFFER_BINDING 0x8CA7 +#define GR_GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GR_GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +#endif diff --git a/gpu/include/GrGLIRect.h b/gpu/include/GrGLIRect.h index 80237d9..ec60029 100644 --- a/gpu/include/GrGLIRect.h +++ b/gpu/include/GrGLIRect.h @@ -1,17 +1,34 @@ -#include "GrGLConfig.h" +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + #ifndef GrGLIRect_DEFINED #define GrGLIRect_DEFINED +#include "GrGLInterface.h" + /** * Helper struct for dealing with the fact that Ganesh and GL use different * window coordinate systems (top-down vs bottom-up) */ struct GrGLIRect { - GLint fLeft; - GLint fBottom; - GLsizei fWidth; - GLsizei fHeight; + GrGLint fLeft; + GrGLint fBottom; + GrGLsizei fWidth; + GrGLsizei fHeight; void pushToGLViewport() const { GR_GL(Viewport(fLeft, fBottom, fWidth, fHeight)); @@ -22,8 +39,8 @@ struct GrGLIRect { } void setFromGLViewport() { - GR_STATIC_ASSERT(sizeof(GrGLIRect) == 4*sizeof(GLint)); - GR_GL_GetIntegerv(GL_VIEWPORT, (GLint*) this); + GR_STATIC_ASSERT(sizeof(GrGLIRect) == 4*sizeof(GrGLint)); + GR_GL_GetIntegerv(GR_GL_VIEWPORT, (GrGLint*) this); } // sometimes we have a GrIRect from the client that we diff --git a/gpu/include/GrGLIndexBuffer.h b/gpu/include/GrGLIndexBuffer.h index 5755c07..3565059 100644 --- a/gpu/include/GrGLIndexBuffer.h +++ b/gpu/include/GrGLIndexBuffer.h @@ -1,5 +1,5 @@ /* - Copyright 2010 Google Inc. + Copyright 2011 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,38 +19,43 @@ #define GrGLIndexBuffer_DEFINED #include "GrIndexBuffer.h" -#include "GrGLConfig.h" +#include "GrGLInterface.h" class GrGpuGL; class GrGLIndexBuffer : public GrIndexBuffer { -protected: - GrGLIndexBuffer(GLuint id, - GrGpuGL* gl, - size_t sizeInBytes, - bool dynamic); + public: - virtual ~GrGLIndexBuffer(); - GLuint bufferID() const; + virtual ~GrGLIndexBuffer() { this->release(); } + + GrGLuint bufferID() const; // overrides of GrIndexBuffer - virtual void abandon(); virtual void* lock(); virtual void* lockPtr() const; virtual void unlock(); virtual bool isLocked() const; virtual bool updateData(const void* src, size_t srcSizeInBytes); - virtual bool updateSubData(const void* src, - size_t srcSizeInBytes, + virtual bool updateSubData(const void* src, + size_t srcSizeInBytes, size_t offset); +protected: + GrGLIndexBuffer(GrGpuGL* gpu, + GrGLuint id, + size_t sizeInBytes, + bool dynamic); + + // overrides of GrResource + virtual void onAbandon(); + virtual void onRelease(); + private: void bind() const; - - GrGpuGL* fGL; - GLuint fBufferID; + + GrGLuint fBufferID; void* fLockPtr; - + friend class GrGpuGL; typedef GrIndexBuffer INHERITED; diff --git a/gpu/include/GrGLInterface.h b/gpu/include/GrGLInterface.h index 0a41905..c9592a5 100644 --- a/gpu/include/GrGLInterface.h +++ b/gpu/include/GrGLInterface.h @@ -18,7 +18,7 @@ #ifndef GrGLInterface_DEFINED #define GrGLInterface_DEFINED -#include "GrGLPlatformIncludes.h" +#include "GrGLConfig.h" #if !defined(GR_GL_FUNCTION_TYPE) #define GR_GL_FUNCTION_TYPE @@ -29,23 +29,58 @@ /** * Helpers for glGetString() */ + +void gl_version_from_string(int* major, int* minor, + const char* versionString); +bool has_gl_extension_from_string(const char* ext, + const char* extensionString); + bool has_gl_extension(const char* ext); void gl_version(int* major, int* minor); + //////////////////////////////////////////////////////////////////////////////// /* * Routines managing the global interface used to invoke OpenGL calls. */ struct GrGLInterface; -extern GrGLInterface* GrGLGetGLInterface(); -extern void GrGLSetGLInterface(GrGLInterface* gl_interface); +GR_API GrGLInterface* GrGLGetGLInterface(); +GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface); /* - * Populates the global GrGLInterface pointer with an instance pointing to the - * GL implementation linked with the executable. + * This is called when GrGLSetGLInterface() hasn't been called before creating a + * GrGpuGL object. It provides a default implementation. The actual implementation + * depends on which GrGLDefaultInterface_*.cpp has been linked. There are some + * platform-specific implementations provided as well as + * GrGLDefaultInterface_none.cpp which does nothing (effectively requiring an + * explicit GrGLSetGLInterface call by the host). */ -extern void GrGLSetDefaultGLInterface(); +void GrGLSetDefaultGLInterface(); + +typedef unsigned int GrGLenum; +typedef unsigned char GrGLboolean; +typedef unsigned int GrGLbitfield; +typedef signed char GrGLbyte; +typedef short GrGLshort; +typedef int GrGLint; +typedef int GrGLsizei; +typedef unsigned char GrGLubyte; +typedef unsigned short GrGLushort; +typedef unsigned int GrGLuint; +typedef float GrGLfloat; +typedef float GrGLclampf; +typedef double GrGLdouble; +typedef double GrGLclampd; +typedef void GrGLvoid; +typedef long GrGLintptr; +typedef long GrGLsizeiptr; + +enum GrGLBinding { + kDesktop_GrGLBinding = 0x01, + kES1_GrGLBinding = 0x02, + kES2_GrGLBinding = 0x04 +}; extern "C" { /* @@ -58,117 +93,118 @@ extern "C" { * extension pointer will be valid across contexts. */ struct GrGLInterface { - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLActiveTextureProc)(GLenum texture); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLAttachShaderProc)(GLuint program, GLuint shader); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindAttribLocationProc)(GLuint program, GLuint index, const char* name); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindBufferProc)(GLenum target, GLuint buffer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindTextureProc)(GLenum target, GLuint texture); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendColorProc)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendFuncProc)(GLenum sfactor, GLenum dfactor); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferDataProc)(GLenum target, GLsizei size, const void* data, GLenum usage); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferSubDataProc)(GLenum target, GLint offset, GLsizei size, const void* data); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearProc)(GLbitfield mask); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearColorProc)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearStencilProc)(GLint s); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClientActiveTextureProc)(GLenum texture); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColor4ubProc)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColorMaskProc)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColorPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCompileShaderProc)(GLuint shader); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCompressedTexImage2DProc)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); - typedef GLuint (GR_GL_FUNCTION_TYPE *GrGLCreateProgramProc)(void); - typedef GLuint (GR_GL_FUNCTION_TYPE *GrGLCreateShaderProc)(GLenum type); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCullFaceProc)(GLenum mode); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteBuffersProc)(GLsizei n, const GLuint* buffers); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteProgramProc)(GLuint program); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteShaderProc)(GLuint shader); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteTexturesProc)(GLsizei n, const GLuint* textures); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDepthMaskProc)(GLboolean flag); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableProc)(GLenum cap); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableClientStateProc)(GLenum array); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableVertexAttribArrayProc)(GLuint index); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawArraysProc)(GLenum mode, GLint first, GLsizei count); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawElementsProc)(GLenum mode, GLsizei count, GLenum type, const void* indices); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableProc)(GLenum cap); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableClientStateProc)(GLenum cap); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableVertexAttribArrayProc)(GLuint index); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFrontFaceProc)(GLenum mode); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenBuffersProc)(GLsizei n, GLuint* buffers); - typedef GLenum (GR_GL_FUNCTION_TYPE *GrGLGetErrorProc)(void); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenTexturesProc)(GLsizei n, GLuint* textures); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetBufferParameterivProc)(GLenum target, GLenum pname, GLint* params); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetIntegervProc)(GLenum pname, GLint* params); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramInfoLogProc)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramivProc)(GLuint program, GLenum pname, GLint* params); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderInfoLogProc)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderivProc)(GLuint shader, GLenum pname, GLint* params); - typedef const GLubyte* (GR_GL_FUNCTION_TYPE *GrGLGetStringProc)(GLenum name); - typedef GLint (GR_GL_FUNCTION_TYPE *GrGLGetUniformLocationProc)(GLuint program, const char* name); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLineWidthProc)(GLfloat width); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLinkProgramProc)(GLuint program); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLoadMatrixfProc)(const GLfloat* m); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLMatrixModeProc)(GLenum mode); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLPixelStoreiProc)(GLenum pname, GLint param); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLPointSizeProc)(GLfloat size); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLReadPixelsProc)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLScissorProc)(GLint x, GLint y, GLsizei width, GLsizei height); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLShadeModelProc)(GLenum mode); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLShaderSourceProc)(GLuint shader, GLsizei count, const char** str, const GLint* length); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncProc)(GLenum func, GLint ref, GLuint mask); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncSeparateProc)(GLenum face, GLenum func, GLint ref, GLuint mask); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskProc)(GLuint mask); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskSeparateProc)(GLenum face, GLuint mask); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpProc)(GLenum fail, GLenum zfail, GLenum zpass); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpSeparateProc)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexCoordPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexEnviProc)(GLenum target, GLenum pname, GLint param); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexImage2DProc)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexParameteriProc)(GLenum target, GLenum pname, GLint param); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexSubImage2DProc)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1fvProc)(GLint location, GLsizei count, const GLfloat* v); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1iProc)(GLint location, GLint x); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform4fvProc)(GLint location, GLsizei count, const GLfloat* v); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniformMatrix3fvProc)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUseProgramProc)(GLuint program); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttrib4fvProc)(GLuint indx, const GLfloat* values); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttribPointerProc)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLViewportProc)(GLint x, GLint y, GLsizei width, GLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLActiveTextureProc)(GrGLenum texture); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLAttachShaderProc)(GrGLuint program, GrGLuint shader); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindAttribLocationProc)(GrGLuint program, GrGLuint index, const char* name); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindBufferProc)(GrGLenum target, GrGLuint buffer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindTextureProc)(GrGLenum target, GrGLuint texture); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendFuncProc)(GrGLenum sfactor, GrGLenum dfactor); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferDataProc)(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferSubDataProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid* data); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLClearProc)(GrGLbitfield mask); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLClearColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLClearStencilProc)(GrGLint s); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLClientActiveTextureProc)(GrGLenum texture); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLColor4ubProc)(GrGLubyte red, GrGLubyte green, GrGLubyte blue, GrGLubyte alpha); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLColorMaskProc)(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLColorPointerProc)(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLCompileShaderProc)(GrGLuint shader); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLCompressedTexImage2DProc)(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data); + typedef GrGLuint (GR_GL_FUNCTION_TYPE *GrGLCreateProgramProc)(void); + typedef GrGLuint (GR_GL_FUNCTION_TYPE *GrGLCreateShaderProc)(GrGLenum type); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLCullFaceProc)(GrGLenum mode); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteBuffersProc)(GrGLsizei n, const GrGLuint* buffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteProgramProc)(GrGLuint program); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteShaderProc)(GrGLuint shader); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteTexturesProc)(GrGLsizei n, const GrGLuint* textures); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDepthMaskProc)(GrGLboolean flag); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableProc)(GrGLenum cap); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableClientStateProc)(GrGLenum array); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableVertexAttribArrayProc)(GrGLuint index); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableProc)(GrGLenum cap); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableClientStateProc)(GrGLenum cap); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableVertexAttribArrayProc)(GrGLuint index); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLFrontFaceProc)(GrGLenum mode); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGenBuffersProc)(GrGLsizei n, GrGLuint* buffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGenTexturesProc)(GrGLsizei n, GrGLuint* textures); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetBufferParameterivProc)(GrGLenum target, GrGLenum pname, GrGLint* params); + typedef GrGLenum (GR_GL_FUNCTION_TYPE *GrGLGetErrorProc)(void); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetIntegervProc)(GrGLenum pname, GrGLint* params); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramInfoLogProc)(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, char* infolog); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramivProc)(GrGLuint program, GrGLenum pname, GrGLint* params); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderInfoLogProc)(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length, char* infolog); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderivProc)(GrGLuint shader, GrGLenum pname, GrGLint* params); + typedef const GrGLubyte* (GR_GL_FUNCTION_TYPE *GrGLGetStringProc)(GrGLenum name); + typedef GrGLint (GR_GL_FUNCTION_TYPE *GrGLGetUniformLocationProc)(GrGLuint program, const char* name); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLLineWidthProc)(GrGLfloat width); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLLinkProgramProc)(GrGLuint program); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLLoadMatrixfProc)(const GrGLfloat* m); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLMatrixModeProc)(GrGLenum mode); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLPixelStoreiProc)(GrGLenum pname, GrGLint param); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLPointSizeProc)(GrGLfloat size); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLScissorProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLShadeModelProc)(GrGLenum mode); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char** str, const GrGLint* length); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncProc)(GrGLenum func, GrGLint ref, GrGLuint mask); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncSeparateProc)(GrGLenum face, GrGLenum func, GrGLint ref, GrGLuint mask); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskProc)(GrGLuint mask); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskSeparateProc)(GrGLenum face, GrGLuint mask); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpProc)(GrGLenum fail, GrGLenum zfail, GrGLenum zpass); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpSeparateProc)(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLTexCoordPointerProc)(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLTexEnviProc)(GrGLenum target, GrGLenum pname, GrGLint param); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLTexImage2DProc)(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLTexParameteriProc)(GrGLenum target, GrGLenum pname, GrGLint param); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1iProc)(GrGLint location, GrGLint x); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform4fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLUniformMatrix3fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLUseProgramProc)(GrGLuint program); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexPointerProc)(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height); // FBO Extension Functions - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindFramebufferProc)(GLenum target, GLuint framebuffer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindRenderbufferProc)(GLenum target, GLuint renderbuffer); - typedef GLenum (GR_GL_FUNCTION_TYPE *GrGLCheckFramebufferStatusProc)(GLenum target); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteFramebuffersProc)(GLsizei n, const GLuint *framebuffers); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteRenderbuffersProc)(GLsizei n, const GLuint *renderbuffers); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferRenderbufferProc)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferTexture2DProc)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenFramebuffersProc)(GLsizei n, GLuint *framebuffers); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenRenderbuffersProc)(GLsizei n, GLuint *renderbuffers); - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageProc)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindFramebufferProc)(GrGLenum target, GrGLuint framebuffer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindRenderbufferProc)(GrGLenum target, GrGLuint renderbuffer); + typedef GrGLenum (GR_GL_FUNCTION_TYPE *GrGLCheckFramebufferStatusProc)(GrGLenum target); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteFramebuffersProc)(GrGLsizei n, const GrGLuint *framebuffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteRenderbuffersProc)(GrGLsizei n, const GrGLuint *renderbuffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferRenderbufferProc)(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferTexture2DProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGenFramebuffersProc)(GrGLsizei n, GrGLuint *framebuffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLGenRenderbuffersProc)(GrGLsizei n, GrGLuint *renderbuffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageProc)(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); // Multisampling Extension Functions // same prototype for ARB_FBO, EXT_FBO, GL 3.0, & Apple ES extension - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageMultisampleProc)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageMultisampleProc)(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); // desktop: ext_fbo_blit, arb_fbo, gl 3.0 - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlitFramebufferProc)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBlitFramebufferProc)(GrGLint srcX0, GrGLint srcY0, GrGLint srcX1, GrGLint srcY1, GrGLint dstX0, GrGLint dstY0, GrGLint dstX1, GrGLint dstY1, GrGLbitfield mask, GrGLenum filter); // apple's es extension - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLResolveMultisampleFramebufferProc)(); - - // IMG'e es extension - typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferTexture2DMultisampleProc)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLResolveMultisampleFramebufferProc)(); // Buffer mapping (extension in ES). - typedef GLvoid* (GR_GL_FUNCTION_TYPE *GrGLMapBufferProc)(GLenum target, GLenum access); - typedef GLboolean (GR_GL_FUNCTION_TYPE *GrGLUnmapBufferProc)(GLenum target); + typedef GrGLvoid* (GR_GL_FUNCTION_TYPE *GrGLMapBufferProc)(GrGLenum target, GrGLenum access); + typedef GrGLboolean (GR_GL_FUNCTION_TYPE *GrGLUnmapBufferProc)(GrGLenum target); + + // Indicator variable specifying the type of GL implementation + // exported: GLES{1|2} or Desktop. + GrGLBinding fBindingsExported; GrGLActiveTextureProc fActiveTexture; GrGLAttachShaderProc fAttachShader; GrGLBindAttribLocationProc fBindAttribLocation; GrGLBindBufferProc fBindBuffer; GrGLBindTextureProc fBindTexture; - GrGLBlendFuncProc fBlendFunc; GrGLBlendColorProc fBlendColor; + GrGLBlendFuncProc fBlendFunc; GrGLBufferDataProc fBufferData; GrGLBufferSubDataProc fBufferSubData; GrGLClearProc fClear; @@ -259,12 +295,14 @@ struct GrGLInterface { // apple's es extension GrGLResolveMultisampleFramebufferProc fResolveMultisampleFramebuffer; - // IMG'e es extension - GrGLFramebufferTexture2DMultisampleProc fFramebufferTexture2DMultisample; - // Buffer mapping (extension in ES). GrGLMapBufferProc fMapBuffer; GrGLUnmapBufferProc fUnmapBuffer; + + // Code that initializes this struct using a static initializer should + // make this the last entry in the static initializer. It can help to guard + // against failing to initialize newly-added members of this struct. + enum { kStaticInitEndGuard } fStaticInitEndGuard; }; } // extern "C" diff --git a/gpu/include/GrGLPlatformIncludes.h b/gpu/include/GrGLPlatformIncludes.h deleted file mode 100644 index 978a992..0000000 --- a/gpu/include/GrGLPlatformIncludes.h +++ /dev/null @@ -1,522 +0,0 @@ -/* - Copyright 2011 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - - -#ifndef GrGLPlatformIncludes_DEFINED -#define GrGLPlatformIncludes_DEFINED - -#include "GrConfig.h" - -#if !defined(GR_GL_CUSTOM_SETUP) - #define GR_GL_CUSTOM_SETUP 0 -#endif - -/** - * We need to pull in the right GL headers and determine whether we are - * compiling for ES1, ES2, or desktop GL. (We allow ES1 and ES2 to both be - * supported in the same build but not ESx and desktop). We also need to know - * the platform-specific way to get extension function pointers (e.g. - * eglGetProcAddress). The port specifies this info explicitly or we will infer - * it from the GR_*_BUILD flag. - * - * To specify GL setup directly define GR_GL_CUSTOM_SETUP to 1 and define: - * GR_SUPPORT_GLDESKTOP or (GR_SUPPORT_GLES1 and/or GR_SUPPORT_GLES2) to 1 - * - * if GR_SUPPORT_GLDESKTOP is 1 then provide: - * 1. The name of your GL header in GR_INCLUDE_GLDESKTOP - * 2. If necessary, the name of a file that includes extension - * definitions in GR_INCLUDE_GLDESKTOPext. - * if GR_SUPPORT_GLES1 is 1 then provide: - * 1. The name of your GL header in GR_INCLUDE_GLES1 - * 2. If necessary, the name of a file that includes extension - * definitions in GR_INCLUDE_GLES1ext. - * if GR_SUPPORT_GLES2 is 1 then provide: - * 1. The name of your GL header in GR_INCLUDE_GLES2 - * 2. If necessary, the name of a file that includes extension - * definitions in GR_INCLUDE_GLES2ext. - * - * Optionally, define GR_GL_FUNC to any qualifier needed on GL function - * pointer declarations (e.g. __stdcall). - * - * Define GR_GL_PROC_ADDRESS to take a gl function and produce a - * function pointer. Two examples: - * 1. Your platform doesn't require a proc address function, just take - * the address of the function: - * #define GR_GL_PROC_ADDRESS(X) &X - * 2. Your platform uses eglGetProcAddress: - * #define GR_GL_PROC_ADDRESS eglGetProcAddress(#X) - * - * Optionally define GR_GL_PROC_ADDRESS_HEADER to include any additional - * header necessary to use GR_GL_PROC_ADDRESS (e.g. <EGL/egl.h>) - * - * Alternatively, define GR_GL_CUSTOM_SETUP_HEADER (and not GR_GL_CUSTOM_SETUP) - * to a header that can be included. This file should: - * 1. Define the approprate GR_SUPPORT_GL* macro(s) to 1 - * 2. Includes all necessary GL headers. - * 3. Optionally define GR_GL_FUNC. - * 4. Define GR_GL_PROC_ADDRESS. - * 5. Optionally define GR_GL_PROC_ADDRESS_HEADER - */ - -#if GR_GL_CUSTOM_SETUP - - #ifdef GR_SUPPORT_GLES1 - #include GR_INCLUDE_GLES1 - #if defined(GR_INCLUDE_GLES1ext) - #include GR_INCLUDE_GLES1ext - #endif - #endif - - #ifdef GR_SUPPORT_GLES2 - #include GR_INCLUDE_GLES2 - #if defined(GR_INCLUDE_GLES2ext) - #include GR_INCLUDE_GLES2ext - #endif - #endif - - #ifdef GR_SUPPORT_GLDESKTOP - #include GR_INCLUDE_GLDESKTOP - #if defined(GR_INCLUDE_GLDESKTOPext) - #include GR_INCLUDE_GLDESKTOPext - #endif - #endif - -#elif defined(GR_GL_CUSTOM_SETUP_HEADER) - - #include GR_GL_CUSTOM_SETUP_HEADER - -#else - #undef GR_GL_FUNCTION_TYPE - #undef GR_GL_PROC_ADDRESS - #undef GR_GL_PROC_ADDRESS_HEADER - - #if GR_WIN32_BUILD - #define GR_SUPPORT_GLDESKTOP 1 - #include <Windows.h> - #include <GL/gl.h> - // remove stupid windows defines - #undef near - #undef far - #define GR_GL_EMIT_GL_CONSTANTS 1 - #define GR_GL_FUNCTION_TYPE __stdcall - #define GR_GL_PROC_ADDRESS(X) wglGetProcAddress(#X) - #define GR_GL_PROC_ADDRESS_HEADER <windows.h> - - // Force querying for the existence of these extensions on Windows - // builds. - #define GL_APPLE_framebuffer_multisample 1 - #define GL_EXT_framebuffer_object 1 - #define GL_IMG_multisampled_render_to_texture 1 - #define GL_OES_mapbuffer 1 - #define GL_OES_mapbuffer 1 - #elif GR_MAC_BUILD - #define GR_SUPPORT_GLDESKTOP 1 - #include <OpenGL/gl.h> - #include <OpenGL/glext.h> - #define GR_GL_PROC_ADDRESS(X) &X - #elif GR_IOS_BUILD - #define GR_SUPPORT_GLES1 1 - #include <OpenGLES/ES1/gl.h> - #include <OpenGLES/ES1/glext.h> - #define GR_SUPPORT_GLES2 1 - #include <OpenGLES/ES2/gl.h> - #include <OpenGLES/ES2/glext.h> - #define GR_GL_PROC_ADDRESS(X) &X - #elif GR_ANDROID_BUILD - #ifndef GL_GLEXT_PROTOTYPES - #define GL_GLEXT_PROTOTYPES - #endif - #define GR_SUPPORT_GLES2 1 - #include <GLES2/gl2.h> - #include <GLES2/gl2ext.h> - #define GR_GL_PROC_ADDRESS(X) eglGetProcAddress(#X) - #define GR_GL_PROC_ADDRESS_HEADER <EGL/egl.h> - #elif GR_QNX_BUILD - #ifndef GL_GLEXT_PROTOTYPES - #define GL_GLEXT_PROTOTYPES - #endif - #define GR_SUPPORT_GLES2 1 - // This is needed by the QNX GLES2 headers - #define GL_API_EXT - #include <GLES2/gl2.h> - #include <GLES2/gl2ext.h> - #define GR_GL_PROC_ADDRESS(X) eglGetProcAddress(#X) - #define GR_GL_PROC_ADDRESS_HEADER <EGL/egl.h> - #elif GR_LINUX_BUILD - #ifndef GL_GLEXT_PROTOTYPES - #define GL_GLEXT_PROTOTYPES - #endif - #include <GL/gl.h> - #include <GL/glext.h> - #define GR_GL_PROC_ADDRESS(X) glXGetProcAddress(reinterpret_cast<const GLubyte*>(#X)) - #define GR_SUPPORT_GLDESKTOP 1 - #define GR_GL_PROC_ADDRESS_HEADER <GL/glx.h> - #else - #error "unsupported GR_???_BUILD" - #endif - -#endif - -#if !defined(GR_SUPPORT_GLDESKTOP) - #define GR_SUPPORT_GLDESKTOP 0 -#endif -#if !defined(GR_SUPPORT_GLES1) - #define GR_SUPPORT_GLES1 0 -#endif -#if !defined(GR_SUPPORT_GLES2) - #define GR_SUPPORT_GLES2 0 -#endif - -#define GR_SUPPORT_GLES ((GR_SUPPORT_GLES1) || (GR_SUPPORT_GLES2)) - -#if !GR_SUPPORT_GLES && !GR_SUPPORT_GLDESKTOP - #error "Either desktop or ES GL must be supported" -#elif GR_SUPPORT_GLES && GR_SUPPORT_GLDESKTOP - #error "Cannot support both desktop and ES GL" -#endif - -#if GR_WIN32_BUILD && GR_GL_EMIT_GL_CONSTANTS - -// The windows GL headers do not provide the constants used for extensions and -// some versions of GL. Define them here. - -// OpenGL 1.2 Defines -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_RESCALE_NORMAL 0x803A -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SINGLE_COLOR 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E - -// OpenGL 1.3 Multi-Sample Constant Values -#define GL_MULTISAMPLE 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE 0x809F -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_CLAMP_TO_BORDER 0x812D -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 -#define GL_SUBTRACT 0x84E7 -#define GL_COMPRESSED_ALPHA 0x84E9 -#define GL_COMPRESSED_LUMINANCE 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB -#define GL_COMPRESSED_INTENSITY 0x84EC -#define GL_COMPRESSED_RGB 0x84ED -#define GL_COMPRESSED_RGBA 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT 0x84EF -#define GL_NORMAL_MAP 0x8511 -#define GL_REFLECTION_MAP 0x8512 -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_COMBINE 0x8570 -#define GL_COMBINE_RGB 0x8571 -#define GL_COMBINE_ALPHA 0x8572 -#define GL_RGB_SCALE 0x8573 -#define GL_ADD_SIGNED 0x8574 -#define GL_INTERPOLATE 0x8575 -#define GL_CONSTANT 0x8576 -#define GL_PRIMARY_COLOR 0x8577 -#define GL_PREVIOUS 0x8578 -#define GL_SOURCE0_RGB 0x8580 -#define GL_SOURCE1_RGB 0x8581 -#define GL_SOURCE2_RGB 0x8582 -#define GL_SOURCE0_ALPHA 0x8588 -#define GL_SOURCE1_ALPHA 0x8589 -#define GL_SOURCE2_ALPHA 0x858A -#define GL_OPERAND0_RGB 0x8590 -#define GL_OPERAND1_RGB 0x8591 -#define GL_OPERAND2_RGB 0x8592 -#define GL_OPERAND0_ALPHA 0x8598 -#define GL_OPERAND1_ALPHA 0x8599 -#define GL_OPERAND2_ALPHA 0x859A -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 -#define GL_TEXTURE_COMPRESSED 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_DOT3_RGB 0x86AE -#define GL_DOT3_RGBA 0x86AF -#define GL_MULTISAMPLE_BIT 0x20000000 - -// OpenGL 1.4 Defines -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_POINT_SIZE_MIN 0x8126 -#define GL_POINT_SIZE_MAX 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 -#define GL_POINT_DISTANCE_ATTENUATION 0x8129 -#define GL_GENERATE_MIPMAP 0x8191 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_DEPTH_COMPONENT32 0x81A7 -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_FOG_COORDINATE_SOURCE 0x8450 -#define GL_FOG_COORDINATE 0x8451 -#define GL_FRAGMENT_DEPTH 0x8452 -#define GL_CURRENT_FOG_COORDINATE 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 -#define GL_FOG_COORDINATE_ARRAY 0x8457 -#define GL_COLOR_SUM 0x8458 -#define GL_CURRENT_SECONDARY_COLOR 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D -#define GL_SECONDARY_COLOR_ARRAY 0x845E -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_FILTER_CONTROL 0x8500 -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_TEXTURE_DEPTH_SIZE 0x884A -#define GL_DEPTH_TEXTURE_MODE 0x884B -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#define GL_COMPARE_R_TO_TEXTURE 0x884E - -// OpenGL 1.5 Defines -#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE -#define GL_FOG_COORD GL_FOG_COORDINATE -#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY -#define GL_SRC0_RGB GL_SOURCE0_RGB -#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER -#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE -#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA -#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE -#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE -#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA -#define GL_SRC1_RGB GL_SOURCE1_RGB -#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING -#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA -#define GL_SRC2_RGB GL_SOURCE2_RGB -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_QUERY_COUNTER_BITS 0x8864 -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D -#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_READ_WRITE 0x88BA -#define GL_BUFFER_ACCESS 0x88BB -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_SAMPLES_PASSED 0x8914 - -// OpenGL 2.0 Defines -#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_POINT_SPRITE 0x8861 -#define GL_COORD_REPLACE 0x8862 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_MAX_TEXTURE_COORDS 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_MAX_VARYING_FLOATS 0x8B4B -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_SHADER_TYPE 0x8B4F -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_1D 0x8B5D -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_SAMPLER_1D_SHADOW 0x8B61 -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_DELETE_STATUS 0x8B80 -#define GL_COMPILE_STATUS 0x8B81 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 -#define GL_LOWER_LEFT 0x8CA1 -#define GL_UPPER_LEFT 0x8CA2 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 - -#endif // GR_WIN32_BUILD - -#endif diff --git a/gpu/include/GrGLTexture.h b/gpu/include/GrGLTexture.h index 7b7480c..cb50a1e 100644 --- a/gpu/include/GrGLTexture.h +++ b/gpu/include/GrGLTexture.h @@ -14,7 +14,6 @@ limitations under the License. */ - #ifndef GrGLTexture_DEFINED #define GrGLTexture_DEFINED @@ -29,123 +28,143 @@ class GrGLTexture; * A ref counted tex id that deletes the texture in its destructor. */ class GrGLTexID : public GrRefCnt { + public: - GrGLTexID(GLuint texID) : fTexID(texID) {} + GrGLTexID(GrGLuint texID, bool ownsID) : fTexID(texID), fOwnsID(ownsID) {} virtual ~GrGLTexID() { - if (0 != fTexID) { + if (0 != fTexID && fOwnsID) { GR_GL(DeleteTextures(1, &fTexID)); } } void abandon() { fTexID = 0; } - GLuint id() const { return fTexID; } + GrGLuint id() const { return fTexID; } private: - GLuint fTexID; + GrGLuint fTexID; + bool fOwnsID; }; -class GrGLRenderTarget : public GrRenderTarget { -public: - virtual ~GrGLRenderTarget(); - - bool resolveable() const { return fRTFBOID != fTexFBOID; } - bool needsResolve() const { return fNeedsResolve; } - void setDirty(bool dirty) { fNeedsResolve = resolveable() && dirty; } - - GLuint renderFBOID() const { return fRTFBOID; } - GLuint textureFBOID() const { return fTexFBOID; } +//////////////////////////////////////////////////////////////////////////////// - void abandon(); +class GrGLRenderTarget : public GrRenderTarget { -protected: +public: + // set fTexFBOID to this value to indicate that it is multisampled but + // Gr doesn't know how to resolve it. + enum { kUnresolvableFBOID = 0 }; struct GLRenderTargetIDs { - GLuint fRTFBOID; - GLuint fTexFBOID; - GLuint fStencilRenderbufferID; - GLuint fMSColorRenderbufferID; - bool fOwnIDs; + GrGLuint fRTFBOID; + GrGLuint fTexFBOID; + GrGLuint fStencilRenderbufferID; + GrGLuint fMSColorRenderbufferID; + bool fOwnIDs; + void reset() { memset(this, 0, sizeof(GLRenderTargetIDs)); } }; - - GrGLRenderTarget(const GLRenderTargetIDs& ids, + + GrGLRenderTarget(GrGpuGL* gpu, + const GLRenderTargetIDs& ids, GrGLTexID* texID, - GLuint stencilBits, + GrGLuint stencilBits, + bool isMultisampled, const GrGLIRect& fViewport, - GrGLTexture* texture, - GrGpuGL* gl); - + GrGLTexture* texture); + + virtual ~GrGLRenderTarget() { this->release(); } + void setViewport(const GrGLIRect& rect) { fViewport = rect; } const GrGLIRect& getViewport() const { return fViewport; } + + // The following two functions return the same ID when a + // texture-rendertarget is multisampled, and different IDs when + // it is. + // FBO ID used to render into + GrGLuint renderFBOID() const { return fRTFBOID; } + // FBO ID that has texture ID attached. + GrGLuint textureFBOID() const { return fTexFBOID; } + + // override of GrRenderTarget + virtual ResolveType getResolveType() const { + if (fRTFBOID == fTexFBOID) { + // catches FBO 0 and non MSAA case + return kAutoResolves_ResolveType; + } else if (kUnresolvableFBOID == fTexFBOID) { + return kCantResolve_ResolveType; + } else { + return kCanResolve_ResolveType; + } + } + +protected: + // override of GrResource + virtual void onAbandon(); + virtual void onRelease(); + private: - GrGpuGL* fGL; - GLuint fRTFBOID; - GLuint fTexFBOID; - GLuint fStencilRenderbufferID; - GLuint fMSColorRenderbufferID; - + GrGLuint fRTFBOID; + GrGLuint fTexFBOID; + GrGLuint fStencilRenderbufferID; + GrGLuint fMSColorRenderbufferID; + // Should this object delete IDs when it is destroyed or does someone // else own them. bool fOwnIDs; - - // If there separate Texture and RenderTarget FBO IDs then the rendertarget - // must be resolved to the texture FBO before it is used as a texture. - bool fNeedsResolve; - - // when we switch to this rendertarget we want to set the viewport to + + // when we switch to this rendertarget we want to set the viewport to // only render to to content area (as opposed to the whole allocation) and - // we want the rendering to be at top left (GL has origin in bottom left) + // we want the rendering to be at top left (GL has origin in bottom left) GrGLIRect fViewport; // non-NULL if this RT was created by Gr with an associated GrGLTexture. GrGLTexID* fTexIDObj; - friend class GrGpuGL; - friend class GrGLTexture; - typedef GrRenderTarget INHERITED; }; +//////////////////////////////////////////////////////////////////////////////// + class GrGLTexture : public GrTexture { + public: enum Orientation { kBottomUp_Orientation, kTopDown_Orientation, }; - + struct TexParams { - GLenum fFilter; - GLenum fWrapS; - GLenum fWrapT; + GrGLenum fFilter; + GrGLenum fWrapS; + GrGLenum fWrapT; + void invalidate() { memset(this, 0xff, sizeof(TexParams)); } }; -protected: struct GLTextureDesc { - uint32_t fContentWidth; - uint32_t fContentHeight; - uint32_t fAllocWidth; - uint32_t fAllocHeight; - PixelConfig fFormat; - GLuint fTextureID; - GLenum fUploadFormat; - GLenum fUploadByteCount; - GLenum fUploadType; - GLuint fStencilBits; - Orientation fOrientation; + uint32_t fContentWidth; + uint32_t fContentHeight; + uint32_t fAllocWidth; + uint32_t fAllocHeight; + GrPixelConfig fFormat; + GrGLuint fTextureID; + bool fOwnsID; + GrGLenum fUploadFormat; + GrGLenum fUploadByteCount; + GrGLenum fUploadType; + GrGLuint fStencilBits; + Orientation fOrientation; }; + typedef GrGLRenderTarget::GLRenderTargetIDs GLRenderTargetIDs; - GrGLTexture(const GLTextureDesc& textureDesc, + + GrGLTexture(GrGpuGL* gpu, + const GLTextureDesc& textureDesc, const GLRenderTargetIDs& rtIDs, - const TexParams& initialTexParams, - GrGpuGL* gl); + const TexParams& initialTexParams); -public: - virtual ~GrGLTexture(); - - // overloads of GrTexture - virtual void abandon(); - virtual GrRenderTarget* asRenderTarget(); - virtual void releaseRenderTarget(); + virtual ~GrGLTexture() { this->release(); } + + // overrides of GrTexture virtual void uploadTextureData(uint32_t x, uint32_t y, uint32_t width, @@ -155,11 +174,11 @@ public: const TexParams& getTexParams() const { return fTexParams; } void setTexParams(const TexParams& texParams) { fTexParams = texParams; } - GLuint textureID() const { return fTexIDObj->id(); } + GrGLuint textureID() const { return fTexIDObj->id(); } - GLenum uploadFormat() const { return fUploadFormat; } - GLenum uploadByteCount() const { return fUploadByteCount; } - GLenum uploadType() const { return fUploadType; } + GrGLenum uploadFormat() const { return fUploadFormat; } + GrGLenum uploadByteCount() const { return fUploadByteCount; } + GrGLenum uploadType() const { return fUploadType; } /** * Retrieves the texture width actually allocated in texels. @@ -189,31 +208,34 @@ public: // in the top-left corner of the image. OpenGL, however, // has the origin in the lower-left corner. For content that // is loaded by Ganesh we just push the content "upside down" - // (by GL's understanding of the world ) in glTex*Image and the - // addressing just works out. However, content generated by GL - // (FBO or externally imported texture) will be updside down + // (by GL's understanding of the world ) in glTex*Image and the + // addressing just works out. However, content generated by GL + // (FBO or externally imported texture) will be updside down // and it is up to the GrGpuGL derivative to handle y-mirroing. Orientation orientation() const { return fOrientation; } + static const GrGLenum* WrapMode2GLWrap(); + +protected: + + // overrides of GrTexture + virtual void onAbandon(); + virtual void onRelease(); + private: TexParams fTexParams; GrGLTexID* fTexIDObj; - GLenum fUploadFormat; - GLenum fUploadByteCount; - GLenum fUploadType; + GrGLenum fUploadFormat; + GrGLenum fUploadByteCount; + GrGLenum fUploadType; int fAllocWidth; int fAllocHeight; // precomputed content / alloc ratios GrScalar fScaleX; GrScalar fScaleY; Orientation fOrientation; - GrGLRenderTarget* fRenderTarget; GrGpuGL* fGpuGL; - static const GLenum gWrapMode2GLWrap[]; - - friend class GrGpuGL; - typedef GrTexture INHERITED; }; diff --git a/gpu/include/GrGLVertexBuffer.h b/gpu/include/GrGLVertexBuffer.h index 30ae734..b2ada31 100644 --- a/gpu/include/GrGLVertexBuffer.h +++ b/gpu/include/GrGLVertexBuffer.h @@ -1,5 +1,5 @@ /* - Copyright 2010 Google Inc. + Copyright 2011 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,37 +19,39 @@ #define GrGLVertexBuffer_DEFINED #include "GrVertexBuffer.h" -#include "GrGLConfig.h" +#include "GrGLInterface.h" class GrGpuGL; class GrGLVertexBuffer : public GrVertexBuffer { -protected: - GrGLVertexBuffer(GLuint id, - GrGpuGL* gl, - size_t sizeInBytes, - bool dynamic); public: - virtual ~GrGLVertexBuffer(); - + virtual ~GrGLVertexBuffer() { this->release(); } // overrides of GrVertexBuffer - virtual void abandon(); virtual void* lock(); virtual void* lockPtr() const; virtual void unlock(); virtual bool isLocked() const; virtual bool updateData(const void* src, size_t srcSizeInBytes); - virtual bool updateSubData(const void* src, - size_t srcSizeInBytes, + virtual bool updateSubData(const void* src, + size_t srcSizeInBytes, size_t offset); - GLuint bufferID() const; + GrGLuint bufferID() const; + +protected: + GrGLVertexBuffer(GrGpuGL* gpu, + GrGLuint id, + size_t sizeInBytes, + bool dynamic); + + // overrides of GrResource + virtual void onAbandon(); + virtual void onRelease(); private: void bind() const; - - GrGpuGL* fGL; - GLuint fBufferID; + + GrGLuint fBufferID; void* fLockPtr; friend class GrGpuGL; diff --git a/gpu/include/GrGeometryBuffer.h b/gpu/include/GrGeometryBuffer.h index 1447e73..98f58bd 100644 --- a/gpu/include/GrGeometryBuffer.h +++ b/gpu/include/GrGeometryBuffer.h @@ -1,12 +1,12 @@ /* Copyright 2011 Google Inc. - + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,47 +17,40 @@ #ifndef GrGeometryBuffer_DEFINED #define GrGeometryBuffer_DEFINED -#include "GrRefCnt.h" +#include "GrResource.h" + +class GrGpu; /** * Parent class for vertex and index buffers */ -class GrGeometryBuffer : public GrRefCnt { +class GrGeometryBuffer : public GrResource { public: - virtual ~GrGeometryBuffer() {} - /** * Retrieves the size of the buffer * * @return the size of the buffer in bytes */ size_t size() const { return fSizeInBytes; } - + /** *Retrieves whether the buffer was created with the dynamic flag * * @return true if the buffer was created with the dynamic flag */ bool dynamic() const { return fDynamic; } - - /** - * Indicates that GPU context in which this veretx buffer was created is - * destroyed and that Ganesh should not attempt to free the buffer in the - * underlying API. - */ - virtual void abandon() = 0; - + /** * Locks the buffer to be written by the CPU. - * + * * The previous content of the buffer is invalidated. It is an error * to draw from the buffer while it is locked. It is an error to call lock * on an already locked buffer. - * + * * @return a pointer to the data or NULL if the lock fails. */ virtual void* lock() = 0; - + /** * Returns the same ptr that lock() returned at time of lock or NULL if the * is not locked. @@ -65,52 +58,53 @@ public: * @return ptr to locked buffer data or undefined if buffer is not locked. */ virtual void* lockPtr() const = 0; - - /** - * Unlocks the buffer. - * + + /** + * Unlocks the buffer. + * * The pointer returned by the previous lock call will no longer be valid. */ virtual void unlock() = 0; - - /** + + /** Queries whether the buffer has been locked. - + @return true if the buffer is locked, false otherwise. */ virtual bool isLocked() const = 0; - + /** - * Updates the buffer data. - * - * The size of the buffer will be preserved. The src data will be + * Updates the buffer data. + * + * The size of the buffer will be preserved. The src data will be * placed at the begining of the buffer and any remaining contents will * be undefined. - * + * * @return returns true if the update succeeds, false otherwise. */ virtual bool updateData(const void* src, size_t srcSizeInBytes) = 0; - + /** - * Updates a portion of the buffer data. - * + * Updates a portion of the buffer data. + * * The contents of the buffer outside the update region are preserved. - * + * * @return returns true if the update succeeds, false otherwise. */ - virtual bool updateSubData(const void* src, - size_t srcSizeInBytes, + virtual bool updateSubData(const void* src, + size_t srcSizeInBytes, size_t offset) = 0; protected: - GrGeometryBuffer(size_t sizeInBytes, bool dynamic) : - fSizeInBytes(sizeInBytes), - fDynamic(dynamic) {} + GrGeometryBuffer(GrGpu* gpu, size_t sizeInBytes, bool dynamic) + : INHERITED(gpu) + , fSizeInBytes(sizeInBytes) + , fDynamic(dynamic) {} private: size_t fSizeInBytes; bool fDynamic; - typedef GrRefCnt INHERITED; + typedef GrResource INHERITED; }; #endif diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h index 75fb1f4..61dae2c 100644 --- a/gpu/include/GrGpu.h +++ b/gpu/include/GrGpu.h @@ -17,14 +17,16 @@ #ifndef GrGpu_DEFINED #define GrGpu_DEFINED +#include "GrDrawTarget.h" +#include "GrPathRenderer.h" #include "GrRect.h" #include "GrRefCnt.h" -#include "GrDrawTarget.h" #include "GrTexture.h" -class GrVertexBufferAllocPool; +class GrContext; class GrIndexBufferAllocPool; -class GrPathRenderer; +class GrResource; +class GrVertexBufferAllocPool; class GrGpu : public GrDrawTarget { @@ -77,9 +79,11 @@ public: // rendered to by calling // GrGpu::setRenderTarget() with // GrTexture::asRenderTarget(). - kNoPathRendering_TextureFlag = 0x2, //<! If the texture is used as a - // rendertarget but paths will not - // be rendered to it. + kNoStencil_TextureFlag = 0x2, //<! If the texture is used as a + // rendertarget but a stencil + // buffer is not required. Stencil + // may be required for clipping and + // path rendering. kDynamicUpdate_TextureFlag = 0x4 //!< Hint that the CPU may modify // this texture after creation }; @@ -101,7 +105,7 @@ public: // kRenderTarget_TextureFlag. uint32_t fWidth; //!< Width of the texture uint32_t fHeight; //!< Height of the texture - GrTexture::PixelConfig fFormat; //!< Format of source data of the + GrPixelConfig fFormat; //!< Format of source data of the // texture. Not guaraunteed to be the // same as internal format used by // 3D API. @@ -140,6 +144,14 @@ public: GrGpu(); virtual ~GrGpu(); + // The GrContext sets itself as the owner of this Gpu object + void setContext(GrContext* context) { + GrAssert(NULL == fContext); + fContext = context; + } + GrContext* getContext() { return fContext; } + const GrContext* getContext() const { return fContext; } + /** * The GrGpu object normally assumes that no outsider is setting state * within the underlying 3D API's context/device/whatever. This call informs @@ -156,7 +168,7 @@ public: * will be embedded in a power of two texture. The extra width and height * is filled as though srcData were rendered clamped into the texture. * - * If kRenderTarget_TextureFlag is specified the GrRenderTarget is + * If kRenderTarget_TextureFlag is specified the GrRenderTarget is * accessible via GrTexture::asRenderTarget(). The texture will hold a ref * on the render target until its releaseRenderTarget() is called or it is * destroyed. @@ -176,14 +188,17 @@ public: * underlying 3D API. Interpretation depends on * GrGpu subclass in use. * @param stencilBits number of stencil bits the target has + * @param isMultisampled specify whether the RT is multisampled * @param width width of the render target * @param height height of the render target */ - virtual GrRenderTarget* createPlatformRenderTarget( - intptr_t platformRenderTarget, + GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget, int stencilBits, + bool isMultisampled, int width, int height); + GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc); + /** * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and * viewport state from the underlying 3D API and wraps it in a @@ -306,6 +321,14 @@ public: int vertexCount); /** + * Installs a path renderer that will be used to draw paths that are + * part of the clip. + */ + void setClipPathRenderer(GrPathRenderer* pathRenderer) { + GrSafeAssign(fClientPathRenderer, pathRenderer); + } + + /** * Returns an index buffer that can be used to render quads. * Six indices per quad: 0, 1, 2, 0, 2, 3, etc. * The max number of quads can be queried using GrIndexBuffer::maxQuads(). @@ -329,25 +352,52 @@ public: void forceRenderTargetFlush(); /** - * Reads a rectangle of pixels from the current render target. - * @param left left edge of the rectangle to read (inclusive) - * @param top top edge of the rectangle to read (inclusive) - * @param width width of rectangle to read in pixels. - * @param height height of rectangle to read in pixels. - * @param buffer memory to read the rectangle into. + * Reads a rectangle of pixels from a render target. + * @param renderTarget the render target to read from. NULL means the + * current render target. + * @param left left edge of the rectangle to read (inclusive) + * @param top top edge of the rectangle to read (inclusive) + * @param width width of rectangle to read in pixels. + * @param height height of rectangle to read in pixels. + * @param config the pixel config of the destination buffer + * @param buffer memory to read the rectangle into. * * @return true if the read succeeded, false if not. The read can fail * because of a unsupported pixel config or because no render * target is currently set. */ - bool readPixels(int left, int top, int width, int height, - GrTexture::PixelConfig, void* buffer); - + bool readPixels(GrRenderTarget* renderTarget, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer); const Stats& getStats() const; void resetStats(); void printStats() const; + /** + * Called to tell Gpu object that all GrResources have been lost and should + * be abandoned. + */ + void abandonResources(); + + /** + * Called to tell Gpu object to release all GrResources. + */ + void releaseResources(); + + /** + * Add resource to list of resources. Should only be called by GrResource. + * @param resource the resource to add. + */ + void insertResource(GrResource* resource); + + /** + * Remove resource from list of resources. Should only be called by + * GrResource. + * @param resource the resource to remove. + */ + void removeResource(GrResource* resource); + protected: enum PrivateStateBits { kFirstBit = (kLastPublicStateBit << 1), @@ -414,16 +464,16 @@ protected: int fCurrPoolStartIndex; // GrDrawTarget overrides - virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, - void** vertices, - void** indices); - virtual void releaseGeometryHelper(); + virtual bool onAcquireGeometry(GrVertexLayout vertexLayout, + void** vertices, + void** indices); + virtual void onReleaseGeometry(); - virtual void setVertexSourceToArrayHelper(const void* vertexArray, - int vertexCount); + virtual void onSetVertexSourceToArray(const void* vertexArray, + int vertexCount); - virtual void setIndexSourceToArrayHelper(const void* indexArray, - int indexCount); + virtual void onSetIndexSourceToArray(const void* indexArray, + int indexCount); // Helpers for setting up geometry state void finalizeReservedVertices(); void finalizeReservedIndices(); @@ -433,39 +483,42 @@ protected: virtual void resetContext() = 0; // overridden by API-specific derived class to create objects. - virtual GrTexture* createTextureHelper(const TextureDesc& desc, - const void* srcData, - size_t rowBytes) = 0; - virtual GrRenderTarget* createPlatformRenderTargetHelper( + virtual GrTexture* onCreateTexture(const TextureDesc& desc, + const void* srcData, + size_t rowBytes) = 0; + virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) = 0; + virtual GrRenderTarget* onCreatePlatformRenderTarget( intptr_t platformRenderTarget, int stencilBits, + bool isMultisampled, int width, int height) = 0; - virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper() = 0; - virtual GrVertexBuffer* createVertexBufferHelper(uint32_t size, - bool dynamic) = 0; - virtual GrIndexBuffer* createIndexBufferHelper(uint32_t size, - bool dynamic) = 0; + virtual GrRenderTarget* onCreateRenderTargetFrom3DApiState() = 0; + virtual GrVertexBuffer* onCreateVertexBuffer(uint32_t size, + bool dynamic) = 0; + virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size, + bool dynamic) = 0; // overridden by API-specific derivated class to perform the erase. - virtual void eraseColorHelper(GrColor color) = 0; + virtual void onEraseColor(GrColor color) = 0; // overridden by API-specific derived class to perform the draw call. - virtual void drawIndexedHelper(GrPrimitiveType type, - uint32_t startVertex, - uint32_t startIndex, - uint32_t vertexCount, - uint32_t indexCount) = 0; + virtual void onDrawIndexed(GrPrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount) = 0; - virtual void drawNonIndexedHelper(GrPrimitiveType type, - uint32_t vertexCount, - uint32_t numVertices) = 0; + virtual void onDrawNonIndexed(GrPrimitiveType type, + uint32_t vertexCount, + uint32_t numVertices) = 0; // overridden by API-specific derived class to perform flush - virtual void forceRenderTargetFlushHelper() = 0; + virtual void onForceRenderTargetFlush() = 0; // overridden by API-specific derived class to perform the read pixels. - virtual bool readPixelsHelper(int left, int top, int width, int height, - GrTexture::PixelConfig, void* buffer) = 0; + virtual bool onReadPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig, void* buffer) = 0; // called to program the vertex data, indexCount will be 0 if drawing non- // indexed geometry. The subclass may adjust the startVertex and/or @@ -489,18 +542,7 @@ protected: virtual void eraseStencilClip(const GrIRect& rect) = 0; private: - // readies the pools to provide vertex/index data. - void prepareVertexPool(); - void prepareIndexPool(); - - GrPathRenderer* getPathRenderer(); - - void handleDirtyContext() { - if (fContextIsDirty) { - this->resetContext(); - fContextIsDirty = false; - } - } + GrContext* fContext; // not reffed (context refs gpu) GrVertexBufferAllocPool* fVertexPool; @@ -512,7 +554,8 @@ private: mutable GrVertexBuffer* fUnitSquareVertexBuffer; // mutable so it can be // created on-demand - GrPathRenderer* fPathRenderer; + GrDefaultPathRenderer* fDefaultPathRenderer; + GrPathRenderer* fClientPathRenderer; bool fContextIsDirty; @@ -522,6 +565,23 @@ private: bool fVertexPoolInUse; bool fIndexPoolInUse; + GrResource* fResourceHead; + + // readies the pools to provide vertex/index data. + void prepareVertexPool(); + void prepareIndexPool(); + + // determines the path renderer used to draw a clip path element. + GrPathRenderer* getClipPathRenderer(GrPathIter* path, + GrPathFill fill); + + void handleDirtyContext() { + if (fContextIsDirty) { + this->resetContext(); + fContextIsDirty = false; + } + } + // used to save and restore state when the GrGpu needs // to make its geometry pools available internally class AutoInternalDrawGeomRestore { diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h index 79ec458..9d3f91a 100644 --- a/gpu/include/GrInOrderDrawBuffer.h +++ b/gpu/include/GrInOrderDrawBuffer.h @@ -115,17 +115,17 @@ private: const GrIndexBuffer* fIndexBuffer; }; - virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout, - void** vertices, - void** indices); - virtual void releaseGeometryHelper(); + virtual bool onAcquireGeometry(GrVertexLayout vertexLayout, + void** vertices, + void** indices); + virtual void onReleaseGeometry(); virtual void clipWillBeSet(const GrClip& newClip); - virtual void setVertexSourceToArrayHelper(const void* vertexArray, - int vertexCount); + virtual void onSetVertexSourceToArray(const void* vertexArray, + int vertexCount); - virtual void setIndexSourceToArrayHelper(const void* indexArray, - int indexCount); + virtual void onSetIndexSourceToArray(const void* indexArray, + int indexCount); bool needsNewState() const; bool needsNewClip() const; diff --git a/gpu/include/GrIndexBuffer.h b/gpu/include/GrIndexBuffer.h index 09d1977..366640e 100644 --- a/gpu/include/GrIndexBuffer.h +++ b/gpu/include/GrIndexBuffer.h @@ -29,8 +29,8 @@ public: */ int maxQuads() const { return size() / (sizeof(uint16_t) * 6); } protected: - GrIndexBuffer(size_t sizeInBytes, bool dynamic) : - INHERITED(sizeInBytes, dynamic) {} + GrIndexBuffer(GrGpu* gpu, size_t sizeInBytes, bool dynamic) + : INHERITED(gpu, sizeInBytes, dynamic) {} private: typedef GrGeometryBuffer INHERITED; }; diff --git a/gpu/include/GrNoncopyable.h b/gpu/include/GrNoncopyable.h index 888e3b1..ab5d8ec 100644 --- a/gpu/include/GrNoncopyable.h +++ b/gpu/include/GrNoncopyable.h @@ -24,7 +24,7 @@ * Base for classes that want to disallow copying themselves. It makes its * copy-constructor and assignment operators private (and unimplemented). */ -class GrNoncopyable { +class GR_API GrNoncopyable { public: GrNoncopyable() {} diff --git a/gpu/src/GrPathRenderer.h b/gpu/include/GrPathRenderer.h index 19e284f..91d9086 100644 --- a/gpu/src/GrPathRenderer.h +++ b/gpu/include/GrPathRenderer.h @@ -25,9 +25,21 @@ struct GrPoint; /** * Base class for drawing paths into a GrDrawTarget. */ -class GrPathRenderer { +class GR_API GrPathRenderer : public GrRefCnt { public: - virtual ~GrPathRenderer() { }; + /** + * Returns true if this path renderer is able to render the path. + * Returning false allows the caller to fallback to another path renderer. + * + * @param target The target to draw into + * @param path The path to draw + * @param fill The fill rule to use + * + * @return true if the path can be drawn by this object, false otherwise. + */ + virtual bool canDrawPath(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) const = 0; /** * Draws a path into the draw target. The target will already have its draw @@ -49,15 +61,6 @@ public: GrPathFill fill, const GrPoint* translate) = 0; - void drawPath(GrDrawTarget* target, - GrDrawTarget::StageBitfield stages, - const GrPath& path, - GrPathFill fill, - const GrPoint* translate) { - GrPath::Iter iter(path); - this->drawPath(target, stages, &iter, fill, translate); - } - /** * For complex clips Gr uses the stencil buffer. The path renderer must be * able to render paths into the stencil buffer. However, the path renderer @@ -68,7 +71,8 @@ public: * * @param target target that the path will be rendered to * @param path the path that will be drawn - * @param fill the fill rule that will be used + * @param fill the fill rule that will be used, will never be an inverse + * rule. * * @return false if this path renderer can generate interior-only fragments * without changing the stencil settings on the target. If it @@ -79,20 +83,13 @@ public: GrPathIter* path, GrPathFill fill) const { return false; } - bool requiresStencilPass(const GrDrawTarget* target, - const GrPath& path, - GrPathFill fill) const { - GrPath::Iter iter(path); - return requiresStencilPass(target, &iter, fill); - } - /** * Draws a path to the stencil buffer. Assume the writable stencil bits * are already initialized to zero. Fill will always be either * kWinding_PathFill or kEvenOdd_PathFill. * * Only called if requiresStencilPass returns true for the same combo of - * target, path, and fill (or inverse of the fill). + * target, path, and fill. Never called with an inverse fill. * * The default implementation assumes the path filling algorithm doesn't * require a separate stencil pass and so crashes. @@ -110,25 +107,32 @@ public: const GrPoint* translate) { GrCrash("Unexpected call to drawPathToStencil."); } + + /** + * This is called to install a custom path renderer in every GrContext at + * create time. The default implementation in GrCreatePathRenderer_none.cpp + * returns NULL. Link against another implementation to install your own. + */ + static GrPathRenderer* CreatePathRenderer(); - void drawPathToStencil(GrDrawTarget* target, - const GrPath& path, - GrPathFill fill, - const GrPoint* translate) { - GrPath::Iter iter(path); - this->drawPathToStencil(target, &iter, fill, translate); - } +private: + + typedef GrRefCnt INHERITED; }; /** * Subclass that renders the path using the stencil buffer to resolve fill * rules (e.g. winding, even-odd) */ -class GrDefaultPathRenderer : public GrPathRenderer { +class GR_API GrDefaultPathRenderer : public GrPathRenderer { public: GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport); + virtual bool canDrawPath(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) const { return true; } + virtual void drawPath(GrDrawTarget* target, GrDrawTarget::StageBitfield stages, GrPathIter* path, @@ -143,15 +147,17 @@ public: const GrPoint* translate); private: - void drawPathHelper(GrDrawTarget* target, - GrDrawTarget::StageBitfield stages, - GrPathIter* path, - GrPathFill fill, - const GrPoint* translate, - bool stencilOnly); + void onDrawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate, + bool stencilOnly); bool fSeparateStencil; bool fStencilWrapOps; + + typedef GrPathRenderer INHERITED; }; #endif diff --git a/gpu/include/GrRect.h b/gpu/include/GrRect.h index 552fa5e..67e366c 100644 --- a/gpu/include/GrRect.h +++ b/gpu/include/GrRect.h @@ -233,6 +233,15 @@ struct GrRect { } /** + * Inset the rectangle by dx,dy. If dx > 0 the rect becomes narrower, + * if dx < 0 the rect becomes wider. + */ + void inset(GrScalar dx, GrScalar dy) { + fLeft += dx; fTop += dy; + fRight -= dx; fBottom -= dy; + } + + /** * Initialize a rectangle to a point. * @param pt the point used to initialize the rectangle. */ diff --git a/gpu/include/GrRefCnt.h b/gpu/include/GrRefCnt.h index 7204aff..9c9fed1 100644 --- a/gpu/include/GrRefCnt.h +++ b/gpu/include/GrRefCnt.h @@ -29,7 +29,7 @@ * It is an error (though only checked for in the debug build) to call unref() * such that the reference count becomes 0. */ -class GrRefCnt : GrNoncopyable { +class GR_API GrRefCnt : GrNoncopyable { public: GrRefCnt() : fRefCnt(1) {} virtual ~GrRefCnt() { @@ -93,7 +93,8 @@ static inline void GrSafeUnref(const GrRefCnt* obj) { * Assigns src to dst, checking for NULLs in each, and correctly incrementing * the reference count of src, and decrementing the reference count of dst */ -static inline void GrSafeAssign(GrRefCnt*& dst, GrRefCnt* src) { +template<typename T> +static inline void GrSafeAssign(T*& dst, T* src) { if (src) { src->ref(); } @@ -103,6 +104,14 @@ static inline void GrSafeAssign(GrRefCnt*& dst, GrRefCnt* src) { dst = src; } +template<typename T> +static inline void GrSafeSetNull(T*& obj) { + if (NULL != obj) { + obj->unref(); + obj = NULL; + } +} + /////////////////////////////////////////////////////////////////////////////// class GrAutoRef : GrNoncopyable { diff --git a/gpu/include/GrResource.h b/gpu/include/GrResource.h new file mode 100644 index 0000000..8cc4d57 --- /dev/null +++ b/gpu/include/GrResource.h @@ -0,0 +1,77 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrResource_DEFINED +#define GrResource_DEFINED + +#include "GrRefCnt.h" + +class GrGpu; + +class GrResource : public GrRefCnt { +public: + explicit GrResource(GrGpu* gpu); + + virtual ~GrResource() { + // subclass should have released this. + GrAssert(!isValid()); + } + + /** + * Frees the resource in the underlying 3D API. It must be safe to call this + * when the resource has been previously abandoned. + */ + void release(); + + /** + * Removes references to objects in the underlying 3D API without freeing + * them. Used when the API context has been torn down before the GrContext. + */ + void abandon(); + + /** + * Tests whether a resource has been abandoned or released. All resources + * will be in this state after their creating GrContext is destroyed or has + * contextLost called. It's up to the client to test isValid() before + * attempting to use a resource if it holds refs on resources across + * ~GrContext, freeResources with the force flag, or contextLost. + * + * @return true if the resource has been released or abandoned, + * false otherwise. + */ + bool isValid() const { return NULL != fGpu; } + +protected: + + virtual void onRelease() = 0; + virtual void onAbandon() = 0; + + GrGpu* getGpu() const { return fGpu; } + +private: + GrResource(); // unimpl + + GrGpu* fGpu; // not reffed. This can outlive the GrGpu. + + friend class GrGpu; // GrGpu manages list of resources. + + GrResource* fNext; // dl-list of resources per-GrGpu + GrResource* fPrevious; + + typedef GrRefCnt INHERITED; +}; + +#endif diff --git a/gpu/include/GrTesselatedPathRenderer.h b/gpu/include/GrTesselatedPathRenderer.h new file mode 100644 index 0000000..3efc471 --- /dev/null +++ b/gpu/include/GrTesselatedPathRenderer.h @@ -0,0 +1,44 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrTesselatedPathRenderer_DEFINED +#define GrTesselatedPathRenderer_DEFINED + +#include "GrPathRenderer.h" + +class GrTesselatedPathRenderer : public GrPathRenderer { +public: + GrTesselatedPathRenderer(); + + virtual void drawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate); + virtual bool canDrawPath(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) const; + + virtual bool requiresStencilPass(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) const { return false; } + virtual void drawPathToStencil(GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate); +}; + +#endif diff --git a/gpu/include/GrTextStrike.h b/gpu/include/GrTextStrike.h index 610222c..2bdcc90 100644 --- a/gpu/include/GrTextStrike.h +++ b/gpu/include/GrTextStrike.h @@ -85,7 +85,6 @@ public: inline GrTextStrike* getStrike(GrFontScaler*); void freeAll(); - void abandonAll(); void purgeExceptFor(GrTextStrike*); diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h index 0a65ff7..6d4f4d7 100644 --- a/gpu/include/GrTexture.h +++ b/gpu/include/GrTexture.h @@ -20,6 +20,7 @@ #include "GrRefCnt.h" #include "GrClip.h" +#include "GrResource.h" class GrTexture; @@ -30,7 +31,8 @@ class GrTexture; * Additionally, GrContext provides methods for creating GrRenderTargets * that wrap externally created render targets. */ -class GrRenderTarget : public GrRefCnt { +class GrRenderTarget : public GrResource { + public: /** * @return the width of the rendertarget @@ -51,21 +53,92 @@ public: */ GrTexture* asTexture() {return fTexture;} + /** + * @return true if the render target is multisampled, false otherwise + */ + bool isMultisampled() { return fIsMultisampled; } + + /** + * Call to indicate the multisample contents were modified such that the + * render target needs to be resolved before it can be used as texture. Gr + * tracks this for its own drawing and thus this only needs to be called + * when the render target has been modified outside of Gr. Only meaningful + * for Gr-created RT/Textures and Platform RT/Textures created with the + * kGrCanResolve flag. + */ + void flagAsNeedingResolve() { + fNeedsResolve = kCanResolve_ResolveType == getResolveType(); + } + + /** + * Call to indicate that GrRenderTarget was externally resolved. This may + * allow Gr to skip a redundant resolve step. + */ + void flagAsResolved() { fNeedsResolve = false; } + + /** + * @return true if the GrRenderTarget requires MSAA resolving + */ + bool needsResolve() { return fNeedsResolve; } + + /** + * Reads a rectangle of pixels from the render target. + * @param left left edge of the rectangle to read (inclusive) + * @param top top edge of the rectangle to read (inclusive) + * @param width width of rectangle to read in pixels. + * @param height height of rectangle to read in pixels. + * @param config the pixel config of the destination buffer + * @param buffer memory to read the rectangle into. + * + * @return true if the read succeeded, false if not. The read can fail + * because of a unsupported pixel config. + */ + bool readPixels(int left, int top, int width, int height, + GrPixelConfig config, void* buffer); + + // a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO + // 0 in GL), or be unresolvable because the client didn't give us the + // resolve destination. + enum ResolveType { + kCanResolve_ResolveType, + kAutoResolves_ResolveType, + kCantResolve_ResolveType, + }; + virtual ResolveType getResolveType() const = 0; + protected: - GrRenderTarget(GrTexture* texture, + GrRenderTarget(GrGpu* gpu, + GrTexture* texture, int width, int height, - int stencilBits) - : fTexture(texture), - fWidth(width), - fHeight(height), - fStencilBits(stencilBits) {} + int stencilBits, + bool isMultisampled) + : INHERITED(gpu) + , fTexture(texture) + , fWidth(width) + , fHeight(height) + , fStencilBits(stencilBits) + , fIsMultisampled(isMultisampled) + , fNeedsResolve(false) + {} + friend class GrTexture; + // When a texture unrefs an owned rendertarget this func + // removes the back pointer. This could be done called from + // texture's destructor but would have to be done in derived + // class. By the time of texture base destructor it has already + // lost its pointer to the rt. + void onTextureReleaseRenderTarget() { + GrAssert(NULL != fTexture); + fTexture = NULL; + } - GrTexture* fTexture; + GrTexture* fTexture; // not ref'ed int fWidth; int fHeight; int fStencilBits; + bool fIsMultisampled; + bool fNeedsResolve; private: // GrGpu keeps a cached clip in the render target to avoid redundantly @@ -73,44 +146,19 @@ private: friend class GrGpu; GrClip fLastStencilClip; - typedef GrRefCnt INHERITED; + typedef GrResource INHERITED; }; -class GrTexture : public GrRefCnt { -public: - enum PixelConfig { - kUnknown_PixelConfig, - kAlpha_8_PixelConfig, - kIndex_8_PixelConfig, - kRGB_565_PixelConfig, - kRGBA_4444_PixelConfig, //!< premultiplied - kRGBA_8888_PixelConfig, //!< premultiplied - kRGBX_8888_PixelConfig, //!< treat the alpha channel as opaque - }; - static size_t BytesPerPixel(PixelConfig); - static bool PixelConfigIsOpaque(PixelConfig); - static bool PixelConfigIsAlphaOnly(PixelConfig); +class GrTexture : public GrResource { -protected: - GrTexture(int width, - int height, - PixelConfig config) : - fWidth(width), - fHeight(height), - fConfig(config) { - // only make sense if alloc size is pow2 - fShiftFixedX = 31 - Gr_clz(fWidth); - fShiftFixedY = 31 - Gr_clz(fHeight); - } public: - virtual ~GrTexture(); - /** * Retrieves the width of the texture. * * @return the width in texels */ int width() const { return fWidth; } + /** * Retrieves the height of the texture. * @@ -130,13 +178,13 @@ public: /** * Retrieves the pixel config specified when the texture was created. */ - PixelConfig config() const { return fConfig; } + GrPixelConfig config() const { return fConfig; } /** * Approximate number of bytes used by the texture */ size_t sizeInBytes() const { - return fWidth * fHeight * BytesPerPixel(fConfig); + return fWidth * fHeight * GrBytesPerPixel(fConfig); } /** @@ -154,28 +202,44 @@ public: uint32_t width, uint32_t height, const void* srcData) = 0; + /** - * Indicates that GPU context in which this texture was created is destroyed - * and that Ganesh should not attempt to free the texture with the - * underlying API. + * Reads a rectangle of pixels from the texture. + * @param left left edge of the rectangle to read (inclusive) + * @param top top edge of the rectangle to read (inclusive) + * @param width width of rectangle to read in pixels. + * @param height height of rectangle to read in pixels. + * @param config the pixel config of the destination buffer + * @param buffer memory to read the rectangle into. + * + * @return true if the read succeeded, false if not. The read can fail + * because of a unsupported pixel config. */ - virtual void abandon() = 0; + bool readPixels(int left, int top, int width, int height, + GrPixelConfig config, void* buffer); /** * Retrieves the render target underlying this texture that can be passed to * GrGpu::setRenderTarget(). * - * @return handle to render target or undefined if the texture is not a + * @return handle to render target or NULL if the texture is not a * render target */ - virtual GrRenderTarget* asRenderTarget() = 0; + GrRenderTarget* asRenderTarget() { return fRenderTarget; } /** * Removes the reference on the associated GrRenderTarget held by this - * texture. Afterwards asRenderTarget() will return NULL. The + * texture. Afterwards asRenderTarget() will return NULL. The * GrRenderTarget survives the release if another ref is held on it. */ - virtual void releaseRenderTarget() = 0; + void releaseRenderTarget() { + if (NULL != fRenderTarget) { + GrAssert(fRenderTarget->asTexture() == this); + fRenderTarget->onTextureReleaseRenderTarget(); + fRenderTarget->unref(); + fRenderTarget = NULL; + } + } /** * Return the native ID or handle to the texture, depending on the @@ -191,6 +255,36 @@ public: void validate() const {} #endif +protected: + GrRenderTarget* fRenderTarget; // texture refs its rt representation + // base class cons sets to NULL + // subclass cons can create and set + + GrTexture(GrGpu* gpu, + int width, + int height, + GrPixelConfig config) + : INHERITED(gpu) + , fRenderTarget(NULL) + , fWidth(width) + , fHeight(height) + , fConfig(config) { + // only make sense if alloc size is pow2 + fShiftFixedX = 31 - Gr_clz(fWidth); + fShiftFixedY = 31 - Gr_clz(fHeight); + } + + // GrResource overrides + virtual void onRelease() { + releaseRenderTarget(); + } + + virtual void onAbandon() { + if (NULL != fRenderTarget) { + fRenderTarget->abandon(); + } + } + private: int fWidth; int fHeight; @@ -198,9 +292,10 @@ private: // for this texture if the texture is power of two sized. int fShiftFixedX; int fShiftFixedY; - PixelConfig fConfig; - typedef GrRefCnt INHERITED; + GrPixelConfig fConfig; + + typedef GrResource INHERITED; }; #endif diff --git a/gpu/include/GrTextureCache.h b/gpu/include/GrTextureCache.h index 68e1daa..466dafa 100644 --- a/gpu/include/GrTextureCache.h +++ b/gpu/include/GrTextureCache.h @@ -191,7 +191,7 @@ private: class GrTextureCache { public: GrTextureCache(int maxCount, size_t maxBytes); - ~GrTextureCache(); // uses kFreeTexture_DeleteMode + ~GrTextureCache(); /** * Return the current texture cache limits. @@ -250,11 +250,7 @@ public: */ void unlock(GrTextureEntry*); - enum DeleteMode { - kFreeTexture_DeleteMode, - kAbandonTexture_DeleteMode - }; - void deleteAll(DeleteMode); + void removeAll(); #if GR_DEBUG void validate() const; diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h index cc78c3e..fb62333 100644 --- a/gpu/include/GrTypes.h +++ b/gpu/include/GrTypes.h @@ -154,6 +154,50 @@ template <typename Dst, typename Src> Dst GrTCast(Src src) { /////////////////////////////////////////////////////////////////////////////// +// saves value of T* in and restores in destructor +// e.g.: +// { +// GrAutoTPtrValueRestore<int*> autoCountRestore; +// if (useExtra) { +// autoCountRestore.save(&fCount); +// fCount += fExtraCount; +// } +// ... +// } // fCount is restored +// +template <typename T> +class GrAutoTPtrValueRestore { +public: + GrAutoTPtrValueRestore() : fPtr(NULL), fVal() {} + + GrAutoTPtrValueRestore(T* ptr) { + fPtr = ptr; + if (NULL != ptr) { + fVal = *ptr; + } + } + + ~GrAutoTPtrValueRestore() { + if (NULL != fPtr) { + *fPtr = fVal; + } + } + + // restores previously saved value (if any) and saves value for passed T* + void save(T* ptr) { + if (NULL != fPtr) { + *fPtr = fVal; + } + fPtr = ptr; + fVal = *ptr; + } +private: + T* fPtr; + T fVal; +}; + +/////////////////////////////////////////////////////////////////////////////// + /** * Type used to describe format of vertices in arrays * Values are defined in GrDrawTarget @@ -172,6 +216,16 @@ enum GrPrimitiveType { kLineStrip_PrimitiveType }; +static inline bool GrIsPrimTypeLines(GrPrimitiveType type) { + return kLines_PrimitiveType == type || kLineStrip_PrimitiveType == type; +} + +static inline bool GrIsPrimTypeTris(GrPrimitiveType type) { + return kTriangles_PrimitiveType == type || + kTriangleStrip_PrimitiveType == type || + kTriangleFan_PrimitiveType == type; +} + /** * Coeffecients for alpha-blending. */ @@ -213,6 +267,54 @@ static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) { } /** + * Pixel configurations. + */ +enum GrPixelConfig { + kUnknown_GrPixelConfig, + kAlpha_8_GrPixelConfig, + kIndex_8_GrPixelConfig, + kRGB_565_GrPixelConfig, + kRGBA_4444_GrPixelConfig, //!< premultiplied + kRGBA_8888_GrPixelConfig, //!< premultiplied + kRGBX_8888_GrPixelConfig, //!< treat the alpha channel as opaque +}; + +static inline size_t GrBytesPerPixel(GrPixelConfig config) { + switch (config) { + case kAlpha_8_GrPixelConfig: + case kIndex_8_GrPixelConfig: + return 1; + case kRGB_565_GrPixelConfig: + case kRGBA_4444_GrPixelConfig: + return 2; + case kRGBA_8888_GrPixelConfig: + case kRGBX_8888_GrPixelConfig: + return 4; + default: + return 0; + } +} + +static inline bool GrPixelConfigIsOpaque(GrPixelConfig config) { + switch (config) { + case kRGB_565_GrPixelConfig: + case kRGBX_8888_GrPixelConfig: + return true; + default: + return false; + } +} + +static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) { + switch (config) { + case kAlpha_8_GrPixelConfig: + return true; + default: + return false; + } +} + +/** * Set Operations used to construct clips. */ enum GrSetOp { @@ -332,6 +434,139 @@ enum GrConvexHint { /////////////////////////////////////////////////////////////////////////////// +enum GrPlatformSurfaceType { + /** + * Specifies that the object being created is a render target. + */ + kRenderTarget_GrPlatformSurfaceType, + /** + * Specifies that the object being created is a texture. + */ + kTexture_GrPlatformSurfaceType, + /** + * Specifies that the object being created is a texture and a render + * target. + */ + kTextureRenderTarget_GrPlatformSurfaceType, +}; + +enum GrPlatformRenderTargetFlags { + kNone_GrPlatformRenderTargetFlagBit = 0x0, + /** + * Specifies that the object being created is multisampled. + */ + kIsMultisampled_GrPlatformRenderTargetFlagBit = 0x1, + /** + * Gives permission to Gr to perform the downsample-resolve of a + * multisampled render target. If this is not set then read pixel + * operations may fail. If the object is both a texture and render target + * then this *must* be set. Otherwise, if the client wants do its own + * resolves it must create separate GrRenderTarget and GrTexture objects + * and insert appropriate flushes and resolves betweeen data hazards. + * GrRenderTarget has a flagForResolve() + */ + kGrCanResolve_GrPlatformRenderTargetFlagBit = 0x2, +}; + +static inline GrPlatformRenderTargetFlags operator | (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) { + return (GrPlatformRenderTargetFlags) (+a | +b); +} + +static inline GrPlatformRenderTargetFlags operator & (GrPlatformRenderTargetFlags a, GrPlatformRenderTargetFlags b) { + return (GrPlatformRenderTargetFlags) (+a & +b); +} + +// opaque type for 3D API object handles +typedef intptr_t GrPlatform3DObject; + +/** + * Description of platform surface to create. See below for GL example. + */ +struct GrPlatformSurfaceDesc { + GrPlatformSurfaceType fSurfaceType; // type of surface to create + /** + * Flags for kRenderTarget and kTextureRenderTarget surface types + */ + GrPlatformRenderTargetFlags fRenderTargetFlags; + + int fWidth; // width in pixels + int fHeight; // height in pixels + GrPixelConfig fConfig; // color format + /** + * Number of per sample stencil buffer. Only relevant if kIsRenderTarget is + * set in fFlags. + */ + int fStencilBits; + /** + * Texture object in 3D API. Only relevant if fSurfaceType is kTexture or + * kTextureRenderTarget. + * GL: this is a texture object (glGenTextures) + */ + GrPlatform3DObject fPlatformTexture; + /** + * Render target object in 3D API. Only relevant if fSurfaceType is + * kRenderTarget or kTextureRenderTarget + * GL: this is a FBO object (glGenFramebuffers) + */ + GrPlatform3DObject fPlatformRenderTarget; + /** + * 3D API object used as destination of resolve. Only relevant if + * fSurfaceType is kRenderTarget or kTextureRenderTarget and + * kGrCanResolve is set in fRenderTargetFlags. + * fFlags. + * GL: this is a FBO object (glGenFramebuffers) + */ + GrPlatform3DObject fPlatformResolveDestination; + + void reset() { memset(this, 0, sizeof(GrPlatformSurfaceDesc)); } +}; + +/** + * Example of how to wrap render-to-texture-with-MSAA GL objects with a GrPlatformSurace + * + * GLint colorBufferID; + * glGenRenderbuffers(1, &colorID); + * glBindRenderbuffer(GL_RENDERBUFFER, colorBufferID); + * glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_RGBA, W, H); + * + * GLint stencilBufferID; + * glGenRenderBuffers(1, &stencilBufferID); + * glBindRenderbuffer(GL_RENDERBUFFER, stencilBufferID); + * glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_STENCIL_INDEX8, W, H); + * + * GLint drawFBOID; + * glGenFramebuffers(1, &drawFBOID); + * glBindFramebuffer(GL_FRAMEBUFFER, drawFBOID); + * glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferID); + * glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilBufferID); + * + * GLint textureID; + * glGenTextures(1, &textureID); + * glBindTexture(GL_TEXTURE_2D, textureID); + * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, H, ...); + * + * GLint readFBOID; + * glGenFramebuffers(1, &readFBOID); + * glBindFramebuffer(GL_FRAMEBUFFER, readFBOID); + * glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0); + * + * GrPlatformSurfaceDesc renderTargetTextureDesc; + * renderTargetTextureDesc.fSurfaceType = kTextureRenderTarget_GrPlatformSurfaceType; + * renderTargetTextureDesc.fRenderTargetFlags = (kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit); + * renderTargetTextureDesc.fWidth = W; + * renderTargetTextureDesc.fHeight = H; + * renderTargetTextureDesc.fConfig = kRGBA_8888_GrPixelConfig + * renderTargetTextureDesc.fStencilBits = 8; + * renderTargetTextureDesc.fPlatformTexture = textureID; + * renderTargetTextureDesc.fPlatformRenderTarget = drawFBOID; + * renderTargetTextureDesc.fPlatformResolveDestination = readFBOID; + * + * GrTexture* texture = static_cast<GrTexture*>(grContext->createPlatrformSurface(renderTargetTextureDesc)); + */ + + +/////////////////////////////////////////////////////////////////////////////// + // this is included only to make it easy to use this debugging facility #include "GrInstanceCounter.h" diff --git a/gpu/include/GrVertexBuffer.h b/gpu/include/GrVertexBuffer.h index 3792c15..34abe2c 100644 --- a/gpu/include/GrVertexBuffer.h +++ b/gpu/include/GrVertexBuffer.h @@ -22,8 +22,8 @@ class GrVertexBuffer : public GrGeometryBuffer { protected: - GrVertexBuffer(size_t sizeInBytes, bool dynamic) : - INHERITED(sizeInBytes, dynamic) {} + GrVertexBuffer(GrGpu* gpu, size_t sizeInBytes, bool dynamic) + : INHERITED(gpu, sizeInBytes, dynamic) {} private: typedef GrGeometryBuffer INHERITED; }; diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp index ab99d9a..dfc0a69 100644 --- a/gpu/src/GrAtlas.cpp +++ b/gpu/src/GrAtlas.cpp @@ -142,16 +142,16 @@ GrAtlasMgr::~GrAtlasMgr() { fGpu->unref(); } -static GrTexture::PixelConfig maskformat2pixelconfig(GrMaskFormat format) { +static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) { switch (format) { case kA8_GrMaskFormat: - return GrTexture::kAlpha_8_PixelConfig; + return kAlpha_8_GrPixelConfig; case kA565_GrMaskFormat: - return GrTexture::kRGB_565_PixelConfig; + return kRGB_565_GrPixelConfig; default: GrAssert(!"unknown maskformat"); } - return GrTexture::kUnknown_PixelConfig; + return kUnknown_GrPixelConfig; } GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas, @@ -203,16 +203,4 @@ void GrAtlasMgr::freePlot(int x, int y) { fPlotMgr->freePlot(x, y); } -void GrAtlasMgr::abandonAll() { -#if 0 - GrAtlas** curr = fList.begin(); - GrAtlas** stop = fList.end(); - for (; curr < stop; curr++) { - (*curr)->texture()->abandon(); - delete *curr; - } - fList.reset(); -#endif -} - diff --git a/gpu/src/GrBinHashKey.h b/gpu/src/GrBinHashKey.h new file mode 100644 index 0000000..683528b --- /dev/null +++ b/gpu/src/GrBinHashKey.h @@ -0,0 +1,221 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrBinHashKey_DEFINED +#define GrBinHashKey_DEFINED + +#include "GrTypes.h" + +/** + * Abstract base class that presents the building interface of GrBinHashKey. + * This base class allows builder methods to not know the exact template + * parameters of GrBinHashKey + */ +class GrBinHashKeyBuilder { +public: + GrBinHashKeyBuilder() {} + virtual ~GrBinHashKeyBuilder() {} + virtual void keyData(const uint8_t *dataToAdd, size_t len) = 0; +}; + +/** + * Hash function class than can take a data stream of indeterminate length. + * It also has the ability to recieve data in several chunks (steamed). The + * hash function used is Adler-32. + * + * Keys are built in two passes the first pass builds the key until the + * allocated storage for the key runs out, raw data accumulation stops, but + * the calculation of the 32-bit hash value and total key length continue. + * The second pass is only necessary if storage ran-out during the first pass. + * If that is the case, the heap storage portion of the key will be + * re-allocated so that the entire key can be stored in the second pass. + * + * Code for building a key: + * + * GrBinHashKey<MyEntryStruct, MyStackSize> MyKey; + * while( MyKey->doPass() ) + * { + * MyObject->buildKey(&MyKey); //invoke a builder method + * } + * + * All the builder method needs to do is make calls to the keyData method to + * append binary data to the key. + */ +template<typename Entry, size_t StackSize> +class GrBinHashKey : public GrBinHashKeyBuilder { +public: + GrBinHashKey() + : fA(1) + , fB(0) + , fLength(0) + , fHeapData(NULL) + , fPhysicalSize(StackSize) + , fUseHeap(false) + , fPass(0) +#if GR_DEBUG + , fIsValid(true) +#endif + {} + +private: + // Illegal: must choose explicitly between copyAndTakeOwnership + // and deepCopyFrom. + // Not inheriting GrNoncopyable, because it causes very obscure compiler + // errors with template classes, which are hard to trace back to the use + // of assignment. + GrBinHashKey(const GrBinHashKey<Entry, StackSize>&) {} + GrBinHashKey<Entry, StackSize>& operator=(const GrBinHashKey<Entry, + StackSize>&) { + return this; + } + +public: + void copyAndTakeOwnership(GrBinHashKey<Entry, StackSize>& key) { + memcpy(this, &key, sizeof(*this)); + GrAssert(key.fIsValid); + if (fUseHeap) { + key.fHeapData = NULL; // ownership transfer + } + // Consistency Checking + // To avoid the overhead of copying or ref-counting the dynamically + // allocated portion of the key, we use ownership transfer + // Key usability is only tracked in debug builds. + GR_DEBUGCODE(key.fIsValid = false;) + } + + void deepCopyFrom(const GrBinHashKey<Entry, StackSize>& key) { + GrAssert(key.fIsValid); + memcpy(this, &key, sizeof(key)); + if (fUseHeap) { + fHeapData = reinterpret_cast<uint8_t*>( + GrMalloc(sizeof(uint8_t) * fPhysicalSize)); + memcpy(fHeapData, key.fHeapData, fLength); + } + } + + virtual ~GrBinHashKey() { + if (fUseHeap) { + GrFree(fHeapData); + } + } + + bool doPass() { + GrAssert(fIsValid); + if (0 == fPass) { + fPass++; + return true; + } + if (1 == fPass) { + bool passNeeded = false; + if (fLength > fPhysicalSize) { + // If the first pass ran out of space the we need to + // re-allocate and perform a second pass + GrFree(fHeapData); + fHeapData = reinterpret_cast<uint8_t*>( + GrMalloc(sizeof(uint8_t) * fLength)); + fPhysicalSize = fLength; + fUseHeap = true; + passNeeded = true; + fLength = 0; + } + fPass++; + return passNeeded; + } + return false; + } + + void keyData(const uint8_t *dataToAdd, size_t len) { + GrAssert(fIsValid); + GrAssert(fPass); + if (fUseHeap) { + GrAssert(fHeapData); + GrAssert(fLength + len <= fPhysicalSize); + memcpy(&fHeapData[fLength], dataToAdd, len ); + } else { + if (fLength + len <= StackSize) { + memcpy(&fStackData[fLength], dataToAdd, len); + } else { + GrAssert(1 == fPass); + } + } + + fLength += len; + + if (1 == fPass) { + // update the 32-bit hash + while (len) { + fA = (fA + *dataToAdd) % kBigPrime; + fB = (fB + fA) % kBigPrime; + dataToAdd++; + len--; + } + } + } + + int compare(const GrBinHashKey<Entry, StackSize>& key) const { + GrAssert(fIsValid); + if (fLength == key.fLength) { + GrAssert(fUseHeap == key.fUseHeap); + if(fUseHeap) { + return memcmp(fHeapData, key.fHeapData, fLength); + } else { + return memcmp(fStackData, key.fStackData, fLength); + } + } + + return (fLength - key.fLength); + } + + static bool + EQ(const Entry& entry, const GrBinHashKey<Entry, StackSize>& key) { + GrAssert(key.fIsValid); + return 0 == entry.compare(key); + } + + static bool + LT(const Entry& entry, const GrBinHashKey<Entry, StackSize>& key) { + GrAssert(key.fIsValid); + return entry.compare(key) < 0; + } + + uint32_t getHash() const { + GrAssert(fIsValid); + return (fB << 16) | fA; + } + +private: + // For computing the Adler-32 hash + enum Constants { + kBigPrime = 65521 // largest prime smaller than 2^16 + }; + uint32_t fA; + uint32_t fB; + + // For accumulating the variable length binary key + size_t fLength; // length of data accumulated so far + uint8_t fStackData[StackSize]; //Buffer for key storage + uint8_t* fHeapData; //Dynamically allocated extended key storage + size_t fPhysicalSize; //Total size available for key storage + bool fUseHeap; //Using a dynamically allocated key storage + int fPass; //Key generation pass counter + +#if GR_DEBUG +public: + bool fIsValid; +#endif +}; + +#endif diff --git a/gpu/src/GrBufferAllocPool.cpp b/gpu/src/GrBufferAllocPool.cpp index 35f0c5e..0db12fe 100644 --- a/gpu/src/GrBufferAllocPool.cpp +++ b/gpu/src/GrBufferAllocPool.cpp @@ -34,11 +34,14 @@ GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, size_t blockSize, int preallocBufferCnt) : fBlocks(GrMax(8, 2*preallocBufferCnt)) { + GrAssert(NULL != gpu); fGpu = gpu; + fGpu->ref(); + fGpuIsReffed = true; + fBufferType = bufferType; fFrequentResetHint = frequentResetHint; - fGpu->ref(); fBufferPtr = NULL; fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize); @@ -61,11 +64,18 @@ GrBufferAllocPool::~GrBufferAllocPool() { buffer->unlock(); } } - fPreallocBuffers.unrefAll(); while (!fBlocks.empty()) { destroyBlock(); } - fGpu->unref(); + fPreallocBuffers.unrefAll(); + releaseGpuRef(); +} + +void GrBufferAllocPool::releaseGpuRef() { + if (fGpuIsReffed) { + fGpu->unref(); + fGpuIsReffed = false; + } } void GrBufferAllocPool::reset() { diff --git a/gpu/src/GrBufferAllocPool.h b/gpu/src/GrBufferAllocPool.h index 80f16ab..7d70ebb 100644 --- a/gpu/src/GrBufferAllocPool.h +++ b/gpu/src/GrBufferAllocPool.h @@ -39,38 +39,6 @@ class GrGpu; * be allocated at the min size and kept around until the pool is destroyed. */ class GrBufferAllocPool : GrNoncopyable { -protected: - - // We could make the createBuffer a virtual except that we want to use it - // in the cons for pre-allocated buffers. - enum BufferType { - kVertex_BufferType, - kIndex_BufferType, - }; - - /** - * Constructor - * - * @param gpu The GrGpu used to create the buffers. - * @param bufferType The type of buffers to create. - * @param frequentResetHint A hint that indicates that the pool - * should expect frequent unlock() calls - * (as opposed to many makeSpace / acquires - * between resets). - * @param bufferSize The minimum size of created buffers. - * This value will be clamped to some - * reasonable minimum. - * @param preallocBufferCnt The pool will allocate this number of - * buffers at bufferSize and keep them until it - * is destroyed. - */ - GrBufferAllocPool(GrGpu* gpu, - BufferType bufferType, - bool frequentResetHint, - size_t bufferSize = 0, - int preallocBufferCnt = 0); - - virtual ~GrBufferAllocPool(); public: /** @@ -94,7 +62,6 @@ public: */ int preallocatedBufferCount() const; - /** * Frees data from makeSpaces in LIFO order. */ @@ -107,6 +74,40 @@ public: protected: /** + * Used to determine what type of buffers to create. We could make the + * createBuffer a virtual except that we want to use it in the cons for + * pre-allocated buffers. + */ + enum BufferType { + kVertex_BufferType, + kIndex_BufferType, + }; + + /** + * Constructor + * + * @param gpu The GrGpu used to create the buffers. + * @param bufferType The type of buffers to create. + * @param frequentResetHint A hint that indicates that the pool + * should expect frequent unlock() calls + * (as opposed to many makeSpace / acquires + * between resets). + * @param bufferSize The minimum size of created buffers. + * This value will be clamped to some + * reasonable minimum. + * @param preallocBufferCnt The pool will allocate this number of + * buffers at bufferSize and keep them until it + * is destroyed. + */ + GrBufferAllocPool(GrGpu* gpu, + BufferType bufferType, + bool frequentResetHint, + size_t bufferSize = 0, + int preallocBufferCnt = 0); + + virtual ~GrBufferAllocPool(); + + /** * Gets the size of the preallocated buffers. * * @return the size of preallocated buffers. @@ -155,6 +156,10 @@ protected: private: + // The GrGpu must be able to clear the ref of pools it creates as members + friend class GrGpu; + void releaseGpuRef(); + struct BufferBlock { size_t fBytesFree; GrGeometryBuffer* fBuffer; @@ -168,6 +173,7 @@ private: #endif GrGpu* fGpu; + bool fGpuIsReffed; bool fFrequentResetHint; GrTDArray<GrGeometryBuffer*> fPreallocBuffers; size_t fMinBlockSize; diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index cf51cc9..8017f73 100644 --- a/gpu/src/GrContext.cpp +++ b/gpu/src/GrContext.cpp @@ -57,18 +57,41 @@ GrContext* GrContext::CreateGLShaderContext() { } GrContext::~GrContext() { + this->flush(); fGpu->unref(); delete fTextureCache; delete fFontCache; delete fDrawBuffer; delete fDrawBufferVBAllocPool; delete fDrawBufferIBAllocPool; - delete fPathRenderer; + GrSafeUnref(fCustomPathRenderer); } -void GrContext::abandonAllTextures() { - fTextureCache->deleteAll(GrTextureCache::kAbandonTexture_DeleteMode); - fFontCache->abandonAll(); +void GrContext::contextLost() { + delete fDrawBuffer; + fDrawBuffer = NULL; + delete fDrawBufferVBAllocPool; + fDrawBufferVBAllocPool = NULL; + delete fDrawBufferIBAllocPool; + fDrawBufferIBAllocPool = NULL; + + fTextureCache->removeAll(); + fFontCache->freeAll(); + fGpu->markContextDirty(); + + fGpu->abandonResources(); + + this->setupDrawBuffer(); +} + +void GrContext::resetContext() { + fGpu->markContextDirty(); +} + +void GrContext::freeGpuResources() { + this->flush(); + fTextureCache->removeAll(); + fFontCache->freeAll(); } GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key, @@ -133,7 +156,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key, } GrGpu::TextureDesc rtDesc = desc; rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag | - GrGpu::kNoPathRendering_TextureFlag; + GrGpu::kNoStencil_TextureFlag; rtDesc.fWidth = GrNextPow2(GrMax<int>(desc.fWidth, fGpu->minRenderTargetWidth())); rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight, @@ -183,7 +206,7 @@ GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key, // no longer need to clamp at min RT size. rtDesc.fWidth = GrNextPow2(desc.fWidth); rtDesc.fHeight = GrNextPow2(desc.fHeight); - int bpp = GrTexture::BytesPerPixel(desc.fFormat); + int bpp = GrBytesPerPixel(desc.fFormat); GrAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight); @@ -244,14 +267,26 @@ int GrContext::getMaxTextureDimension() { /////////////////////////////////////////////////////////////////////////////// -GrRenderTarget* GrContext::createPlatformRenderTarget( - intptr_t platformRenderTarget, - int stencilBits, - int width, int height) { - return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits, - width, height); +GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) { + // validate flags here so that GrGpu subclasses don't have to check + if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType && + 0 != desc.fRenderTargetFlags) { + return NULL; + } + if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) && + (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) { + return NULL; + } + if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType && + (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) && + !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) { + return NULL; + } + return fGpu->createPlatformSurface(desc); } +/////////////////////////////////////////////////////////////////////////////// + bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler, int width, int height) { if (!fGpu->supports8BitPalette()) { @@ -546,7 +581,8 @@ void GrContext::drawPath(const GrPaint& paint, if (NULL != paint.getTexture()) { enabledStages |= 1; } - fPathRenderer->drawPath(target, enabledStages, path, fill, translate); + GrPathRenderer* pr = getPathRenderer(target, path, fill); + pr->drawPath(target, enabledStages, path, fill, translate); } void GrContext::drawPath(const GrPaint& paint, @@ -585,14 +621,39 @@ void GrContext::flushDrawBuffer() { #endif } -bool GrContext::readPixels(int left, int top, int width, int height, - GrTexture::PixelConfig config, void* buffer) { - this->flush(true); - return fGpu->readPixels(left, top, width, height, config, buffer); +bool GrContext::readTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + + // TODO: code read pixels for textures that aren't rendertargets + + this->flush(); + GrRenderTarget* target = texture->asRenderTarget(); + if (NULL != target) { + return fGpu->readPixels(target, + left, top, width, height, + config, buffer); + } else { + return false; + } +} + +bool GrContext::readRenderTargetPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + uint32_t flushFlags = 0; + if (NULL == target) { + flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit; + } + + this->flush(flushFlags); + return fGpu->readPixels(target, + left, top, width, height, + config, buffer); } void GrContext::writePixels(int left, int top, int width, int height, - GrTexture::PixelConfig config, const void* buffer, + GrPixelConfig config, const void* buffer, size_t stride) { // TODO: when underlying api has a direct way to do this we should use it @@ -687,12 +748,8 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint, //////////////////////////////////////////////////////////////////////////////// -void GrContext::resetContext() { - fGpu->markContextDirty(); -} - void GrContext::setRenderTarget(GrRenderTarget* target) { - flush(false); + this->flush(false); fGpu->setRenderTarget(target); } @@ -738,38 +795,53 @@ void GrContext::printStats() const { fGpu->printStats(); } -GrContext::GrContext(GrGpu* gpu) { +GrContext::GrContext(GrGpu* gpu) : + fDefaultPathRenderer(gpu->supportsTwoSidedStencil(), + gpu->supportsStencilWrapOps()) { + fGpu = gpu; fGpu->ref(); + fGpu->setContext(this); + + fCustomPathRenderer = GrPathRenderer::CreatePathRenderer(); + fGpu->setClipPathRenderer(fCustomPathRenderer); + fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT, MAX_TEXTURE_CACHE_BYTES); fFontCache = new GrFontCache(fGpu); fLastDrawCategory = kUnbuffered_DrawCategory; + fDrawBuffer = NULL; + fDrawBufferVBAllocPool = NULL; + fDrawBufferIBAllocPool = NULL; + + this->setupDrawBuffer(); +} + +void GrContext::setupDrawBuffer() { + + GrAssert(NULL == fDrawBuffer); + GrAssert(NULL == fDrawBufferVBAllocPool); + GrAssert(NULL == fDrawBufferIBAllocPool); + #if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT fDrawBufferVBAllocPool = - new GrVertexBufferAllocPool(gpu, false, + new GrVertexBufferAllocPool(fGpu, false, DRAW_BUFFER_VBPOOL_BUFFER_SIZE, DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS); fDrawBufferIBAllocPool = - new GrIndexBufferAllocPool(gpu, false, + new GrIndexBufferAllocPool(fGpu, false, DRAW_BUFFER_IBPOOL_BUFFER_SIZE, DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS); fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool, fDrawBufferIBAllocPool); -#else - fDrawBuffer = NULL; - fDrawBufferVBAllocPool = NULL; - fDrawBufferIBAllocPool = NULL; #endif #if BATCH_RECT_TO_RECT fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer()); #endif - fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsTwoSidedStencil(), - fGpu->supportsStencilWrapOps()); } bool GrContext::finalizeTextureKey(GrTextureKey* key, @@ -808,3 +880,15 @@ GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) { const GrIndexBuffer* GrContext::getQuadIndexBuffer() const { return fGpu->getQuadIndexBuffer(); } + +GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) { + if (NULL != fCustomPathRenderer && + fCustomPathRenderer->canDrawPath(target, path, fill)) { + return fCustomPathRenderer; + } else { + GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill)); + return &fDefaultPathRenderer; + } +} diff --git a/gpu/src/GrCreatePathRenderer_none.cpp b/gpu/src/GrCreatePathRenderer_none.cpp new file mode 100644 index 0000000..fafecff --- /dev/null +++ b/gpu/src/GrCreatePathRenderer_none.cpp @@ -0,0 +1,20 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrPathRenderer.h" + + +GrPathRenderer* GrPathRenderer::CreatePathRenderer() { return NULL; } diff --git a/gpu/src/GrCreatePathRenderer_tesselated.cpp b/gpu/src/GrCreatePathRenderer_tesselated.cpp new file mode 100644 index 0000000..b00cf35 --- /dev/null +++ b/gpu/src/GrCreatePathRenderer_tesselated.cpp @@ -0,0 +1,20 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrTesselatedPathRenderer.h" + + +GrPathRenderer* GrPathRenderer::CreatePathRenderer() { return new GrTesselatedPathRenderer(); } diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp index 7973361..1413c6d 100644 --- a/gpu/src/GrDrawTarget.cpp +++ b/gpu/src/GrDrawTarget.cpp @@ -402,9 +402,9 @@ bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout, fReservedGeometry.fVertexCount = vertexCount; fReservedGeometry.fIndexCount = indexCount; - fReservedGeometry.fLocked = acquireGeometryHelper(vertexLayout, - vertices, - indices); + fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout, + vertices, + indices); if (fReservedGeometry.fLocked) { if (vertexCount) { fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType; @@ -432,7 +432,7 @@ bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout, void GrDrawTarget::releaseReservedGeometry() { GrAssert(fReservedGeometry.fLocked); - releaseGeometryHelper(); + this->onReleaseGeometry(); fReservedGeometry.fLocked = false; } @@ -441,13 +441,13 @@ void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout, int vertexCount) { fGeometrySrc.fVertexSrc = kArray_GeometrySrcType; fGeometrySrc.fVertexLayout = vertexLayout; - setVertexSourceToArrayHelper(vertexArray, vertexCount); + this->onSetVertexSourceToArray(vertexArray, vertexCount); } void GrDrawTarget::setIndexSourceToArray(const void* indexArray, int indexCount) { fGeometrySrc.fIndexSrc = kArray_GeometrySrcType; - setIndexSourceToArrayHelper(indexArray, indexCount); + this->onSetIndexSourceToArray(indexArray, indexCount); } void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout, @@ -492,10 +492,10 @@ bool GrDrawTarget::canDisableBlend() const { for (int s = 0; s < kNumStages; ++s) { if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) { GrAssert(NULL != fCurrDrawState.fTextures[s]); - GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config(); + GrPixelConfig config = fCurrDrawState.fTextures[s]->config(); - if (GrTexture::kRGB_565_PixelConfig != config && - GrTexture::kRGBX_8888_PixelConfig != config) { + if (kRGB_565_GrPixelConfig != config && + kRGBX_8888_GrPixelConfig != config) { return false; } } diff --git a/gpu/src/GrGLDefaultInterface_none.cpp b/gpu/src/GrGLDefaultInterface_none.cpp new file mode 100644 index 0000000..d355589 --- /dev/null +++ b/gpu/src/GrGLDefaultInterface_none.cpp @@ -0,0 +1,18 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +void GrGLSetDefaultGLInterface() { +} diff --git a/gpu/src/GrGLEffect.h b/gpu/src/GrGLEffect.h new file mode 100644 index 0000000..7c85b6d --- /dev/null +++ b/gpu/src/GrGLEffect.h @@ -0,0 +1,52 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrGLEffect_DEFINED +#define GrGLEffect_DEFINED + +#include "GrGLInterface.h" +#include "GrStringBuilder.h" + +class GrEffect; + +struct ShaderCodeSegments { + GrSStringBuilder<256> fVSUnis; + GrSStringBuilder<256> fVSAttrs; + GrSStringBuilder<256> fVaryings; + GrSStringBuilder<256> fFSUnis; + GrSStringBuilder<512> fVSCode; + GrSStringBuilder<512> fFSCode; +}; + +/** + * This class is currently a stub. This will be a base class for "effects", + * which extend the data model of GrPaint and extend the capability of + * GrGLProgram in a modular fashion. + */ +class GrGLEffect { +protected: + GrGLEffect(GrEffect* effect) {} +public: + virtual ~GrGLEffect() {} + static GrGLEffect* Create(GrEffect* effect) { return NULL; } + void genShaderCode(ShaderCodeSegments* segments) {} + bool doGLSetup(GrPrimitiveType type, GrGLint program) { return true; } + bool doGLPost() { return true; } + void buildKey(GrBinHashKeyBuilder& key) const {} + GrGLEffect* nextEffect() { return NULL; } +}; + +#endif diff --git a/gpu/src/GrGLIndexBuffer.cpp b/gpu/src/GrGLIndexBuffer.cpp index 9539c8a..4fb1e99 100644 --- a/gpu/src/GrGLIndexBuffer.cpp +++ b/gpu/src/GrGLIndexBuffer.cpp @@ -18,46 +18,50 @@ #include "GrGLIndexBuffer.h" #include "GrGpuGL.h" -GrGLIndexBuffer::GrGLIndexBuffer(GLuint id, GrGpuGL* gl, size_t sizeInBytes, - bool dynamic) : - INHERITED(sizeInBytes, dynamic), - fGL(gl), - fBufferID(id), - fLockPtr(NULL) { +#define GPUGL static_cast<GrGpuGL*>(getGpu()) + +GrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu, + GrGLuint id, + size_t sizeInBytes, + bool dynamic) + : INHERITED(gpu, sizeInBytes, dynamic) + , fBufferID(id) + , fLockPtr(NULL) { + } -GrGLIndexBuffer::~GrGLIndexBuffer() { +void GrGLIndexBuffer::onRelease() { // make sure we've not been abandoned if (fBufferID) { - fGL->notifyIndexBufferDelete(this); + GPUGL->notifyIndexBufferDelete(this); GR_GL(DeleteBuffers(1, &fBufferID)); + fBufferID = 0; } } -void GrGLIndexBuffer::bind() const { - GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID)); - fGL->notifyIndexBufferBind(this); +void GrGLIndexBuffer::onAbandon() { + fBufferID = 0; + fLockPtr = NULL; } -GLuint GrGLIndexBuffer::bufferID() const { - return fBufferID; +void GrGLIndexBuffer::bind() const { + GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID)); + GPUGL->notifyIndexBufferBind(this); } -void GrGLIndexBuffer::abandon() { - fBufferID = 0; - fGL = NULL; - fLockPtr = NULL; +GrGLuint GrGLIndexBuffer::bufferID() const { + return fBufferID; } void* GrGLIndexBuffer::lock() { GrAssert(fBufferID); GrAssert(!isLocked()); - if (fGL->supportsBufferLocking()) { - bind(); + if (GPUGL->supportsBufferLocking()) { + this->bind(); // Let driver know it can discard the old data - GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL, - dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)); - fLockPtr = GR_GL(MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY)); + GR_GL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size(), NULL, + dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + fLockPtr = GR_GL(MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, GR_GL_WRITE_ONLY)); return fLockPtr; } @@ -71,21 +75,20 @@ void* GrGLIndexBuffer::lockPtr() const { void GrGLIndexBuffer::unlock() { GrAssert(fBufferID); GrAssert(isLocked()); - GrAssert(fGL->supportsBufferLocking()); + GrAssert(GPUGL->supportsBufferLocking()); - bind(); - GR_GL(UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); + this->bind(); + GR_GL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER)); fLockPtr = NULL; } bool GrGLIndexBuffer::isLocked() const { - GrAssert(fBufferID); #if GR_DEBUG - if (fGL->supportsBufferLocking()) { - bind(); - GLint mapped; - GR_GL(GetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, - GR_BUFFER_MAPPED, &mapped)); + if (this->isValid() && GPUGL->supportsBufferLocking()) { + this->bind(); + GrGLint mapped; + GR_GL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER, + GR_GL_BUFFER_MAPPED, &mapped)); GrAssert(!!mapped == !!fLockPtr); } #endif @@ -98,13 +101,13 @@ bool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) { if (srcSizeInBytes > size()) { return false; } - bind(); - GLenum usage = dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; + this->bind(); + GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; if (size() == srcSizeInBytes) { - GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, srcSizeInBytes, src, usage)); + GR_GL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, srcSizeInBytes, src, usage)); } else { - GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL, usage)); - GR_GL(BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, srcSizeInBytes, src)); + GR_GL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size(), NULL, usage)); + GR_GL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER, 0, srcSizeInBytes, src)); } return true; } @@ -117,8 +120,8 @@ bool GrGLIndexBuffer::updateSubData(const void* src, if (srcSizeInBytes + offset > size()) { return false; } - bind(); - GR_GL(BufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, srcSizeInBytes, src)); + this->bind(); + GR_GL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER, offset, srcSizeInBytes, src)); return true; } diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp index fa6aa92..5dfc03c 100644 --- a/gpu/src/GrGLInterface.cpp +++ b/gpu/src/GrGLInterface.cpp @@ -15,37 +15,13 @@ */ -#include "GrGLInterface.h" #include "GrTypes.h" +#include "GrGLInterface.h" +#include "GrGLDefines.h" #include <stdio.h> -#if defined(GR_GL_PROC_ADDRESS_HEADER) - #include GR_GL_PROC_ADDRESS_HEADER -#endif - -#if !defined(GR_GL_PROC_ADDRESS) - #error "Must define GR_GL_PROC_ADDRESS" -#endif - -#define GR_GL_GET_PROC(PROC_NAME) \ - glBindings->f##PROC_NAME = \ - reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \ - GR_GL_PROC_ADDRESS(gl##PROC_NAME)); \ - GrAssert(NULL != glBindings->f##PROC_NAME && \ - "Missing GL binding: " #PROC_NAME); - -#define GR_GL_GET_PROC_SUFFIX(PROC_NAME, SUFFIX) \ - glBindings->f##PROC_NAME = \ - reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \ - GR_GL_PROC_ADDRESS(gl##PROC_NAME##SUFFIX)); \ - GrAssert(NULL != glBindings->f##PROC_NAME && \ - "Missing GL binding: " #PROC_NAME); - -#define GR_GL_GET_PROC_SYMBOL(PROC_NAME) \ - glBindings->f##PROC_NAME = reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>(gl##PROC_NAME); - -namespace { +GrGLInterface* gGLInterface = NULL; void gl_version_from_string(int* major, int* minor, const char* versionString) { @@ -55,30 +31,27 @@ void gl_version_from_string(int* major, int* minor, *minor = 0; return; } -#if GR_SUPPORT_GLDESKTOP + int n = sscanf(versionString, "%d.%d", major, minor); - if (n != 2) { - GrAssert(0); - *major = 0; - *minor = 0; - return; + if (2 == n) { + return; } -#else + char profile[2]; - int n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, - major, minor); + n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, + major, minor); bool ok = 4 == n; if (!ok) { - int n = sscanf(versionString, "OpenGL ES %d.%d", major, minor); + n = sscanf(versionString, "OpenGL ES %d.%d", major, minor); ok = 2 == n; } + if (!ok) { GrAssert(0); *major = 0; *minor = 0; return; } -#endif } bool has_gl_extension_from_string(const char* ext, @@ -99,253 +72,24 @@ bool has_gl_extension_from_string(const char* ext, return false; } -GrGLInterface* gGLInterface = NULL; - -void InitializeGLInterfaceExtensions(GrGLInterface* glBindings) { - int major, minor; - const char* versionString = reinterpret_cast<const char*>( - glBindings->fGetString(GL_VERSION)); - const char* extensionString = reinterpret_cast<const char*>( - glBindings->fGetString(GL_EXTENSIONS)); - gl_version_from_string(&major, &minor, versionString); - - bool fboFound = false; -#if GR_SUPPORT_GLDESKTOP - if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object", - extensionString)) { - // GL_ARB_framebuffer_object doesn't use ARB suffix. - GR_GL_GET_PROC(GenFramebuffers); - GR_GL_GET_PROC(BindFramebuffer); - GR_GL_GET_PROC(FramebufferTexture2D); - GR_GL_GET_PROC(CheckFramebufferStatus); - GR_GL_GET_PROC(DeleteFramebuffers); - GR_GL_GET_PROC(RenderbufferStorage); - GR_GL_GET_PROC(GenRenderbuffers); - GR_GL_GET_PROC(DeleteRenderbuffers); - GR_GL_GET_PROC(FramebufferRenderbuffer); - GR_GL_GET_PROC(BindRenderbuffer); - GR_GL_GET_PROC(RenderbufferStorageMultisample); - GR_GL_GET_PROC(BlitFramebuffer); - fboFound = true; - } - - #if GL_EXT_framebuffer_object && !GR_MAC_BUILD - if (!fboFound && - has_gl_extension_from_string("GL_EXT_framebuffer_object", - extensionString)) { - GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT); - GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT); - GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT); - GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT); - GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT); - GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT); - GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT); - GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT); - GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT); - GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT); - fboFound = true; - - if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", - extensionString)) { - GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT); - } - if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", - extensionString)) { - GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT); - } - } - #endif - - // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5) - GrAssert((major == 1 && minor >= 5) || major >=2); - GR_GL_GET_PROC(MapBuffer); - GR_GL_GET_PROC(UnmapBuffer); -#else // !GR_SUPPORT_GLDESKTOP - #if GR_SUPPORT_GLES2 - if (!fboFound && major >= 2) {// ES 2.0 supports FBO - GR_GL_GET_PROC(GenFramebuffers); - GR_GL_GET_PROC(BindFramebuffer); - GR_GL_GET_PROC(FramebufferTexture2D); - GR_GL_GET_PROC(CheckFramebufferStatus); - GR_GL_GET_PROC(DeleteFramebuffers); - GR_GL_GET_PROC(RenderbufferStorage); - GR_GL_GET_PROC(GenRenderbuffers); - GR_GL_GET_PROC(DeleteRenderbuffers); - GR_GL_GET_PROC(FramebufferRenderbuffer); - GR_GL_GET_PROC(BindRenderbuffer); - fboFound = true; - } - #endif - - #if GL_OES_mapbuffer - if (!fboFound && - has_gl_extension_from_string("GL_OES_framebuffer_object", - extensionString)) { - GR_GL_GET_PROC_SUFFIX(GenFramebuffers, OES); - GR_GL_GET_PROC_SUFFIX(BindFramebuffer, OES); - GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, OES); - GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, OES); - GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, OES); - GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, OES); - GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, OES); - GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, OES); - GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, OES); - GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, OES); - fboFound = true; - } - #endif - - #if GL_APPLE_framebuffer_multisample - if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample", - extensionString)) { - GR_GL_GET_PROC_SUFFIX(ResolveMultisampleFramebuffer, APPLE); - } - #endif - - #if GL_IMG_multisampled_render_to_texture - if (has_gl_extension_from_string( - "GL_IMG_multisampled_render_to_texture", extensionString)) { - GR_GL_GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG); - } - #endif - - #if GL_OES_mapbuffer - if (has_gl_extension_from_string("GL_OES_mapbuffer", extensionString)) { - GR_GL_GET_PROC_SUFFIX(MapBuffer, OES); - GR_GL_GET_PROC_SUFFIX(UnmapBuffer, OES); - } - #endif -#endif // !GR_SUPPORT_GLDESKTOP - - if (!fboFound) { - // we require some form of FBO - GrAssert(!"No FBOs supported?"); - } -} - -void GrGLInitializeGLInterface(GrGLInterface* glBindings) { - Gr_bzero(glBindings, sizeof(GrGLInterface)); - -#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1 - // These entry points only exist on desktop GL implementations. - GR_GL_GET_PROC_SYMBOL(Color4ub); - GR_GL_GET_PROC_SYMBOL(ColorPointer); - GR_GL_GET_PROC_SYMBOL(DisableClientState); - GR_GL_GET_PROC_SYMBOL(EnableClientState); - GR_GL_GET_PROC_SYMBOL(LoadMatrixf); - GR_GL_GET_PROC_SYMBOL(MatrixMode); - GR_GL_GET_PROC_SYMBOL(PointSize); - GR_GL_GET_PROC_SYMBOL(ShadeModel); - GR_GL_GET_PROC_SYMBOL(TexCoordPointer); - GR_GL_GET_PROC_SYMBOL(TexEnvi); - GR_GL_GET_PROC_SYMBOL(VertexPointer); - GR_GL_GET_PROC(ClientActiveTexture); -#endif - - // The following gl entry points are part of GL 1.1, and will always be - // exported as symbols. - // Note that on windows, the wglGetProcAddress call will fail to retrieve - // these entry points. - GR_GL_GET_PROC_SYMBOL(BlendFunc); - GR_GL_GET_PROC_SYMBOL(Clear); - GR_GL_GET_PROC_SYMBOL(ClearColor); - GR_GL_GET_PROC_SYMBOL(ClearStencil); - GR_GL_GET_PROC_SYMBOL(ColorMask); - GR_GL_GET_PROC_SYMBOL(CullFace); - GR_GL_GET_PROC_SYMBOL(DeleteTextures); - GR_GL_GET_PROC_SYMBOL(DepthMask); - GR_GL_GET_PROC_SYMBOL(Disable); - GR_GL_GET_PROC_SYMBOL(DrawArrays); - GR_GL_GET_PROC_SYMBOL(DrawElements); - GR_GL_GET_PROC_SYMBOL(Enable); - GR_GL_GET_PROC_SYMBOL(FrontFace); - GR_GL_GET_PROC_SYMBOL(GenTextures); - GR_GL_GET_PROC_SYMBOL(GetError); - GR_GL_GET_PROC_SYMBOL(GetIntegerv); - GR_GL_GET_PROC_SYMBOL(GetString); - GR_GL_GET_PROC_SYMBOL(LineWidth); - GR_GL_GET_PROC_SYMBOL(PixelStorei); - GR_GL_GET_PROC_SYMBOL(ReadPixels); - GR_GL_GET_PROC_SYMBOL(Scissor); - GR_GL_GET_PROC_SYMBOL(StencilFunc); - GR_GL_GET_PROC_SYMBOL(StencilMask); - GR_GL_GET_PROC_SYMBOL(StencilOp); - GR_GL_GET_PROC_SYMBOL(TexImage2D); - GR_GL_GET_PROC_SYMBOL(TexParameteri); - GR_GL_GET_PROC_SYMBOL(TexSubImage2D); - GR_GL_GET_PROC_SYMBOL(Viewport); - - // Capture the remaining entry points as gl extensions. - GR_GL_GET_PROC(ActiveTexture); - GR_GL_GET_PROC(AttachShader); - GR_GL_GET_PROC(BindAttribLocation); - GR_GL_GET_PROC(BindBuffer); - GR_GL_GET_PROC(BindTexture); - GR_GL_GET_PROC(BlendColor); - GR_GL_GET_PROC(BufferData); - GR_GL_GET_PROC(BufferSubData); - GR_GL_GET_PROC(CompileShader); - GR_GL_GET_PROC(CompressedTexImage2D); - GR_GL_GET_PROC(CreateProgram); - GR_GL_GET_PROC(CreateShader); - GR_GL_GET_PROC(DeleteBuffers); - GR_GL_GET_PROC(DeleteProgram); - GR_GL_GET_PROC(DeleteShader); - GR_GL_GET_PROC(DisableVertexAttribArray); - GR_GL_GET_PROC(EnableVertexAttribArray); - GR_GL_GET_PROC(GenBuffers); - GR_GL_GET_PROC(GetBufferParameteriv); - GR_GL_GET_PROC(GetProgramInfoLog); - GR_GL_GET_PROC(GetProgramiv); - GR_GL_GET_PROC(GetShaderInfoLog); - GR_GL_GET_PROC(GetShaderiv); - GR_GL_GET_PROC(GetUniformLocation); - GR_GL_GET_PROC(LinkProgram); - GR_GL_GET_PROC(ShaderSource); - GR_GL_GET_PROC(StencilFuncSeparate); - GR_GL_GET_PROC(StencilMaskSeparate); - GR_GL_GET_PROC(StencilOpSeparate); - GR_GL_GET_PROC(Uniform1fv); - GR_GL_GET_PROC(Uniform1i); - GR_GL_GET_PROC(Uniform4fv); - GR_GL_GET_PROC(UniformMatrix3fv); - GR_GL_GET_PROC(UseProgram); - GR_GL_GET_PROC(VertexAttrib4fv); - GR_GL_GET_PROC(VertexAttribPointer); - - InitializeGLInterfaceExtensions(glBindings); -} - -} // unnamed namespace -void GrGLSetGLInterface(GrGLInterface* gl_interface) { +GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface) { gGLInterface = gl_interface; } -GrGLInterface* GrGLGetGLInterface() { +GR_API GrGLInterface* GrGLGetGLInterface() { return gGLInterface; } -void GrGLSetDefaultGLInterface() { - static GrGLInterface gDefaultInterface; - static bool gDefaultInitialized = false; - GrAssert(!gDefaultInitialized); - - if (!gDefaultInitialized) { - GrGLInitializeGLInterface(&gDefaultInterface); - GrGLSetGLInterface(&gDefaultInterface); - } -} - bool has_gl_extension(const char* ext) { const char* glstr = reinterpret_cast<const char*>( - GrGLGetGLInterface()->fGetString(GL_EXTENSIONS)); + GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS)); return has_gl_extension_from_string(ext, glstr); } void gl_version(int* major, int* minor) { const char* v = reinterpret_cast<const char*>( - GrGLGetGLInterface()->fGetString(GL_VERSION)); + GrGLGetGLInterface()->fGetString(GR_GL_VERSION)); gl_version_from_string(major, minor, v); } diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp new file mode 100644 index 0000000..5dd09f0 --- /dev/null +++ b/gpu/src/GrGLProgram.cpp @@ -0,0 +1,784 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrGLProgram.h" + +#include "GrBinHashKey.h" +#include "GrGLConfig.h" +#include "GrGLEffect.h" +#include "GrMemory.h" +#include "GrStringBuilder.h" + +namespace { + +const char* GrPrecision() { + if (GR_GL_SUPPORT_ES2) { + return "mediump"; + } else { + return ""; + } +} + +const char* GrShaderPrecision() { + if (GR_GL_SUPPORT_ES2) { + return "precision mediump float;\n"; + } else { + return ""; + } +} + +} // namespace + +#if ATTRIBUTE_MATRIX + #define VIEW_MATRIX_NAME "aViewM" +#else + #define VIEW_MATRIX_NAME "uViewM" +#endif + +#define POS_ATTR_NAME "aPosition" +#define COL_ATTR_NAME "aColor" + +// for variable names etc +typedef GrSStringBuilder<16> GrTokenString; + +static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) { + *s = "aTexCoord"; + s->appendInt(coordIdx); +} + +static inline const char* float_vector_type(int count) { + static const char* FLOAT_VECS[] = {"ERROR", "float", "vec2", "vec3", "vec4"}; + GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(FLOAT_VECS)); + return FLOAT_VECS[count]; +} + +static inline const char* vector_homog_coord(int count) { + static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"}; + GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS)); + return HOMOGS[count]; +} + +static inline const char* vector_nonhomog_coords(int count) { + static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"}; + GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS)); + return NONHOMOGS[count]; +} + +static inline const char* vector_all_coords(int count) { + static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"}; + GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL)); + return ALL[count]; +} + +static void tex_matrix_name(int stage, GrStringBuilder* s) { +#if ATTRIBUTE_MATRIX + *s = "aTexM"; +#else + *s = "uTexM"; +#endif + s->appendInt(stage); +} + +static void sampler_name(int stage, GrStringBuilder* s) { + *s = "uSampler"; + s->appendInt(stage); +} + +static void stage_varying_name(int stage, GrStringBuilder* s) { + *s = "vStage"; + s->appendInt(stage); +} + +static void radial2_param_name(int stage, GrStringBuilder* s) { + *s = "uRadial2Params"; + s->appendInt(stage); +} + +static void radial2_varying_name(int stage, GrStringBuilder* s) { + *s = "vB"; + s->appendInt(stage); +} + +GrGLProgram::GrGLProgram() { + for(int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) { + fStageEffects[stage] = NULL; + } +} + +GrGLProgram::~GrGLProgram() { + +} + +void GrGLProgram::buildKey(GrBinHashKeyBuilder& key) const { + // Add stage configuration to the key + key.keyData(reinterpret_cast<const uint8_t*>(&fProgramDesc), sizeof(ProgramDesc)); + + for(int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) { + // First pass: count effects and write the count to the key. + // This may seem like we are adding redundant data to the + // key, but in ensures the one key cannot be a prefix of + // another key, or identical to the key of a different program. + GrGLEffect* currentEffect = fStageEffects[stage]; + uint8_t effectCount = 0; + while (currentEffect) { + GrAssert(effectCount < 255); // overflow detection + ++effectCount; + currentEffect = currentEffect->nextEffect(); + } + key.keyData(reinterpret_cast<const uint8_t*>(&effectCount), sizeof(uint8_t)); + + // Second pass: continue building key using the effects + currentEffect = fStageEffects[stage]; + while (currentEffect) { + fStageEffects[stage]->buildKey(key); + } + } +} + +bool GrGLProgram::doGLSetup(GrPrimitiveType type, + GrGLProgram::CachedData* programData) const { + for (int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) { + GrGLEffect* effect = fStageEffects[stage]; + if (effect) { + if (!effect->doGLSetup(type, programData->fProgramID)) { + return false; + } + } + } + + return true; +} + +void GrGLProgram::doGLPost() const { + for (int stage = 0; stage < GrDrawTarget::kNumStages; ++stage) { + GrGLEffect* effect = fStageEffects[stage]; + if (effect) { + effect->doGLPost(); + } + } +} + +void GrGLProgram::genProgram(GrGLProgram::CachedData* programData, + const GrDrawTarget* target) const { + + ShaderCodeSegments segments; + const uint32_t& layout = fProgramDesc.fVertexLayout; + + memset(&programData->fUniLocations, 0, sizeof(UniLocations)); + + bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit & + fProgramDesc.fOptFlags); + +#if ATTRIBUTE_MATRIX + segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n"; +#else + segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n"; + segments.fVSAttrs = ""; +#endif + segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n"; + if (haveColor) { + segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n"; + segments.fVaryings = "varying vec4 vColor;\n"; + } else { + segments.fVaryings = ""; + } + + segments.fVSCode = "void main() {\n" + "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n" + "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n"; + if (haveColor) { + segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n"; + } + + if (!(fProgramDesc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)) { + segments.fVSCode += "\tgl_PointSize = 1.0;\n"; + } + segments.fFSCode = "void main() {\n"; + + // add texture coordinates that are used to the list of vertex attr decls + GrTokenString texCoordAttrs[GrDrawTarget::kMaxTexCoords]; + for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { + if (target->VertexUsesTexCoordIdx(t, layout)) { + tex_attr_name(t, texCoordAttrs + t); + + segments.fVSAttrs += "attribute vec2 "; + segments.fVSAttrs += texCoordAttrs[t]; + segments.fVSAttrs += ";\n"; + } + } + + // for each enabled stage figure out what the input coordinates are + // and count the number of stages in use. + const char* stageInCoords[GrDrawTarget::kNumStages]; + int numActiveStages = 0; + + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if (fProgramDesc.fStages[s].fEnabled) { + if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) { + stageInCoords[s] = POS_ATTR_NAME; + } else { + int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); + // we better have input tex coordinates if stage is enabled. + GrAssert(tcIdx >= 0); + GrAssert(texCoordAttrs[tcIdx].length()); + stageInCoords[s] = texCoordAttrs[tcIdx].cstr(); + } + ++numActiveStages; + } + } + + GrTokenString inColor = "vColor"; + + // if we have active stages string them together, feeding the output color + // of each to the next and generating code for each stage. + if (numActiveStages) { + int currActiveStage = 0; + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if (fProgramDesc.fStages[s].fEnabled) { + GrTokenString outColor; + if (currActiveStage < (numActiveStages - 1)) { + outColor = "color"; + outColor.appendInt(currActiveStage); + segments.fFSCode += "\tvec4 "; + segments.fFSCode += outColor; + segments.fFSCode += ";\n"; + } else { + outColor = "gl_FragColor"; + } + + genStageCode(s, + fProgramDesc.fStages[s], + haveColor ? inColor.cstr() : NULL, + outColor.cstr(), + stageInCoords[s], + &segments, + &programData->fUniLocations.fStages[s]); + ++currActiveStage; + inColor = outColor; + haveColor = true; + } + } + } else { + segments.fFSCode += "\tgl_FragColor = "; + if (haveColor) { + segments.fFSCode += inColor; + } else { + segments.fFSCode += "vec4(1,1,1,1)"; + } + segments.fFSCode += ";\n"; + } + segments.fFSCode += "}\n"; + segments.fVSCode += "}\n"; + + + const char* strings[4]; + int lengths[4]; + int stringCnt = 0; + + if (segments.fVSUnis.length()) { + strings[stringCnt] = segments.fVSUnis.cstr(); + lengths[stringCnt] = segments.fVSUnis.length(); + ++stringCnt; + } + if (segments.fVSAttrs.length()) { + strings[stringCnt] = segments.fVSAttrs.cstr(); + lengths[stringCnt] = segments.fVSAttrs.length(); + ++stringCnt; + } + if (segments.fVaryings.length()) { + strings[stringCnt] = segments.fVaryings.cstr(); + lengths[stringCnt] = segments.fVaryings.length(); + ++stringCnt; + } + + GrAssert(segments.fVSCode.length()); + strings[stringCnt] = segments.fVSCode.cstr(); + lengths[stringCnt] = segments.fVSCode.length(); + ++stringCnt; + +#if PRINT_SHADERS + GrPrintf("%s%s%s%s\n", + segments.fVSUnis.cstr(), + segments.fVSAttrs.cstr(), + segments.fVaryings.cstr(), + segments.fVSCode.cstr()); +#endif + programData->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER, + stringCnt, + strings, + lengths); + + stringCnt = 0; + + if (strlen(GrShaderPrecision()) > 1) { + strings[stringCnt] = GrShaderPrecision(); + lengths[stringCnt] = strlen(GrShaderPrecision()); + ++stringCnt; + } + if (segments.fFSUnis.length()) { + strings[stringCnt] = segments.fFSUnis.cstr(); + lengths[stringCnt] = segments.fFSUnis.length(); + ++stringCnt; + } + if (segments.fVaryings.length()) { + strings[stringCnt] = segments.fVaryings.cstr(); + lengths[stringCnt] = segments.fVaryings.length(); + ++stringCnt; + } + + GrAssert(segments.fFSCode.length()); + strings[stringCnt] = segments.fFSCode.cstr(); + lengths[stringCnt] = segments.fFSCode.length(); + ++stringCnt; + +#if PRINT_SHADERS + GrPrintf("%s%s%s%s\n", + GR_SHADER_PRECISION, + segments.fFSUnis.cstr(), + segments.fVaryings.cstr(), + segments.fFSCode.cstr()); +#endif + programData->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER, + stringCnt, + strings, + lengths); + + programData->fProgramID = GR_GL(CreateProgram()); + const GrGLint& progID = programData->fProgramID; + + GR_GL(AttachShader(progID, programData->fVShaderID)); + GR_GL(AttachShader(progID, programData->fFShaderID)); + + // Bind the attrib locations to same values for all shaders + GR_GL(BindAttribLocation(progID, POS_ATTR_LOCATION, POS_ATTR_NAME)); + for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) { + if (texCoordAttrs[t].length()) { + GR_GL(BindAttribLocation(progID, + TEX_ATTR_LOCATION(t), + texCoordAttrs[t].cstr())); + } + } + +#if ATTRIBUTE_MATRIX + // set unis to a bogus value so that checks against -1 before + // flushing will pass. + GR_GL(BindAttribLocation(progID, + VIEWMAT_ATTR_LOCATION, + VIEW_MATRIX_NAME)); + + program->fUniLocations.fViewMatrixUni = BOGUS_MATRIX_UNI_LOCATION; + + for (int s = 0; s < kNumStages; ++s) { + if (fProgramDesc.fStages[s].fEnabled) { + GrStringBuilder matName; + tex_matrix_name(s, &matName); + GR_GL(BindAttribLocation(progID, + TEXMAT_ATTR_LOCATION(s), + matName.cstr())); + program->fUniLocations.fStages[s].fTextureMatrixUni = + BOGUS_MATRIX_UNI_LOCATION; + } + } +#endif + + GR_GL(BindAttribLocation(progID, COL_ATTR_LOCATION, COL_ATTR_NAME)); + + GR_GL(LinkProgram(progID)); + + GrGLint linked = GR_GL_INIT_ZERO; + GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); + if (!linked) { + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); + GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger + if (infoLen > 0) { + GR_GL(GetProgramInfoLog(progID, + infoLen+1, + NULL, + (char*)log.get())); + GrPrintf((char*)log.get()); + } + GrAssert(!"Error linking program"); + GR_GL(DeleteProgram(progID)); + programData->fProgramID = 0; + return; + } + + // Get uniform locations +#if !ATTRIBUTE_MATRIX + programData->fUniLocations.fViewMatrixUni = + GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME)); + GrAssert(-1 != programData->fUniLocations.fViewMatrixUni); +#endif + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + StageUniLocations& locations = programData->fUniLocations.fStages[s]; + if (fProgramDesc.fStages[s].fEnabled) { +#if !ATTRIBUTE_MATRIX + if (locations.fTextureMatrixUni) { + GrTokenString texMName; + tex_matrix_name(s, &texMName); + locations.fTextureMatrixUni = GR_GL(GetUniformLocation( + progID, + texMName.cstr())); + GrAssert(-1 != locations.fTextureMatrixUni); + } else { + locations.fTextureMatrixUni = -1; + + } +#endif + + if (locations.fSamplerUni) { + GrTokenString samplerName; + sampler_name(s, &samplerName); + locations.fSamplerUni = GR_GL(GetUniformLocation( + progID, + samplerName.cstr())); + GrAssert(-1 != locations.fSamplerUni); + } else { + locations.fSamplerUni = -1; + } + + if (locations.fRadial2Uni) { + GrTokenString radial2ParamName; + radial2_param_name(s, &radial2ParamName); + locations.fRadial2Uni = GR_GL(GetUniformLocation( + progID, + radial2ParamName.cstr())); + GrAssert(-1 != locations.fRadial2Uni); + } else { + locations.fRadial2Uni = -1; + } + } else { + locations.fSamplerUni = -1; + locations.fRadial2Uni = -1; + locations.fTextureMatrixUni = -1; + } + } + GR_GL(UseProgram(progID)); + + // init sampler unis and set bogus values for state tracking + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if (-1 != programData->fUniLocations.fStages[s].fSamplerUni) { + GR_GL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); + } + programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); + programData->fRadial2CenterX1[s] = GR_ScalarMax; + programData->fRadial2Radius0[s] = -GR_ScalarMax; + } + programData->fViewMatrix = GrMatrix::InvalidMatrix(); +} + +GrGLuint GrGLProgram::CompileShader(GrGLenum type, + int stringCnt, + const char** strings, + int* stringLengths) { + GrGLuint shader = GR_GL(CreateShader(type)); + if (0 == shader) { + return 0; + } + + GrGLint compiled = GR_GL_INIT_ZERO; + GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths)); + GR_GL(CompileShader(shader)); + GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); + + if (!compiled) { + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); + GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger + if (infoLen > 0) { + GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get())); + for (int i = 0; i < stringCnt; ++i) { + if (NULL == stringLengths || stringLengths[i] < 0) { + GrPrintf(strings[i]); + } else { + GrPrintf("%.*s", stringLengths[i], strings[i]); + } + } + GrPrintf("\n%s", log.get()); + } + GrAssert(!"Shader compilation failed!"); + GR_GL(DeleteShader(shader)); + return 0; + } + return shader; +} + +//============================================================================ +// Stage code generation +//============================================================================ + +void GrGLProgram::genStageCode(int stageNum, + const GrGLProgram::ProgramDesc::StageDesc& desc, + const char* fsInColor, // NULL means no incoming color + const char* fsOutColor, + const char* vsInCoord, + ShaderCodeSegments* segments, + StageUniLocations* locations) const { + + GrAssert(stageNum >= 0 && stageNum <= 9); + + GrTokenString varyingName; + stage_varying_name(stageNum, &varyingName); + + // First decide how many coords are needed to access the texture + // Right now it's always 2 but we could start using 1D textures for + // gradients. + static const int coordDims = 2; + int varyingDims; + /// Vertex Shader Stuff + + // decide whether we need a matrix to transform texture coords + // and whether the varying needs a perspective coord. + GrTokenString texMName; + tex_matrix_name(stageNum, &texMName); + if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) { + varyingDims = coordDims; + } else { + #if ATTRIBUTE_MATRIX + segments->fVSAttrs += "attribute mat3 "; + segments->fVSAttrs += texMName; + segments->fVSAttrs += ";\n"; + #else + segments->fVSUnis += "uniform mat3 "; + segments->fVSUnis += texMName; + segments->fVSUnis += ";\n"; + locations->fTextureMatrixUni = 1; + #endif + if (desc.fOptFlags & ProgramDesc::StageDesc::kNoPerspective_OptFlagBit) { + varyingDims = coordDims; + } else { + varyingDims = coordDims + 1; + } + } + + GrTokenString samplerName; + sampler_name(stageNum, &samplerName); + segments->fFSUnis += "uniform sampler2D "; + segments->fFSUnis += samplerName; + segments->fFSUnis += ";\n"; + locations->fSamplerUni = 1; + + segments->fVaryings += "varying "; + segments->fVaryings += float_vector_type(varyingDims); + segments->fVaryings += " "; + segments->fVaryings += varyingName; + segments->fVaryings += ";\n"; + + if (desc.fOptFlags & ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit) { + GrAssert(varyingDims == coordDims); + segments->fVSCode += "\t"; + segments->fVSCode += varyingName; + segments->fVSCode += " = "; + segments->fVSCode += vsInCoord; + segments->fVSCode += ";\n"; + } else { + segments->fVSCode += "\t"; + segments->fVSCode += varyingName; + segments->fVSCode += " = ("; + segments->fVSCode += texMName; + segments->fVSCode += " * vec3("; + segments->fVSCode += vsInCoord; + segments->fVSCode += ", 1))"; + segments->fVSCode += vector_all_coords(varyingDims); + segments->fVSCode += ";\n"; + } + + GrTokenString radial2ParamsName; + radial2_param_name(stageNum, &radial2ParamsName); + // for radial grads without perspective we can pass the linear + // part of the quadratic as a varying. + GrTokenString radial2VaryingName; + radial2_varying_name(stageNum, &radial2VaryingName); + + if (ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) { + + segments->fVSUnis += "uniform "; + segments->fVSUnis += GrPrecision(); + segments->fVSUnis += " float "; + segments->fVSUnis += radial2ParamsName; + segments->fVSUnis += "[6];\n"; + + segments->fFSUnis += "uniform "; + segments->fFSUnis += GrPrecision(); + segments->fFSUnis += " float "; + segments->fFSUnis += radial2ParamsName; + segments->fFSUnis += "[6];\n"; + locations->fRadial2Uni = 1; + + // if there is perspective we don't interpolate this + if (varyingDims == coordDims) { + GrAssert(2 == coordDims); + segments->fVaryings += "varying float "; + segments->fVaryings += radial2VaryingName; + segments->fVaryings += ";\n"; + + segments->fVSCode += "\t"; + segments->fVSCode += radial2VaryingName; + segments->fVSCode += " = 2.0 * ("; + segments->fVSCode += radial2ParamsName; + segments->fVSCode += "[2] * "; + segments->fVSCode += varyingName; + segments->fVSCode += ".x "; + segments->fVSCode += " - "; + segments->fVSCode += radial2ParamsName; + segments->fVSCode += "[3]);\n"; + } + } + + /// Fragment Shader Stuff + GrTokenString fsCoordName; + // function used to access the shader, may be made projective + GrTokenString texFunc("texture2D"); + if (desc.fOptFlags & (ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit | + ProgramDesc::StageDesc::kNoPerspective_OptFlagBit)) { + GrAssert(varyingDims == coordDims); + fsCoordName = varyingName; + } else { + // if we have to do some non-matrix op on the varyings to get + // our final tex coords then when in perspective we have to + // do an explicit divide + if (ProgramDesc::StageDesc::kIdentity_CoordMapping == desc.fCoordMapping) { + texFunc += "Proj"; + fsCoordName = varyingName; + } else { + fsCoordName = "tCoord"; + fsCoordName.appendInt(stageNum); + + segments->fFSCode += "\t"; + segments->fFSCode += float_vector_type(coordDims); + segments->fFSCode += " "; + segments->fFSCode += fsCoordName; + segments->fFSCode += " = "; + segments->fFSCode += varyingName; + segments->fFSCode += vector_nonhomog_coords(varyingDims); + segments->fFSCode += " / "; + segments->fFSCode += varyingName; + segments->fFSCode += vector_homog_coord(varyingDims); + segments->fFSCode += ";\n"; + } + } + + GrSStringBuilder<96> sampleCoords; + switch (desc.fCoordMapping) { + case ProgramDesc::StageDesc::kIdentity_CoordMapping: + sampleCoords = fsCoordName; + break; + case ProgramDesc::StageDesc::kSweepGradient_CoordMapping: + sampleCoords = "vec2(atan(-"; + sampleCoords += fsCoordName; + sampleCoords += ".y, -"; + sampleCoords += fsCoordName; + sampleCoords += ".x)*0.1591549430918 + 0.5, 0.5)"; + break; + case ProgramDesc::StageDesc::kRadialGradient_CoordMapping: + sampleCoords = "vec2(length("; + sampleCoords += fsCoordName; + sampleCoords += ".xy), 0.5)"; + break; + case ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping: { + GrTokenString cName = "c"; + GrTokenString ac4Name = "ac4"; + GrTokenString rootName = "root"; + + cName.appendInt(stageNum); + ac4Name.appendInt(stageNum); + rootName.appendInt(stageNum); + + GrTokenString bVar; + if (coordDims == varyingDims) { + bVar = radial2VaryingName; + GrAssert(2 == varyingDims); + } else { + GrAssert(3 == varyingDims); + bVar = "b"; + bVar.appendInt(stageNum); + segments->fFSCode += "\tfloat "; + segments->fFSCode += bVar; + segments->fFSCode += " = 2.0 * ("; + segments->fFSCode += radial2ParamsName; + segments->fFSCode += "[2] * "; + segments->fFSCode += fsCoordName; + segments->fFSCode += ".x "; + segments->fFSCode += " - "; + segments->fFSCode += radial2ParamsName; + segments->fFSCode += "[3]);\n"; + } + + segments->fFSCode += "\tfloat "; + segments->fFSCode += cName; + segments->fFSCode += " = dot("; + segments->fFSCode += fsCoordName; + segments->fFSCode += ", "; + segments->fFSCode += fsCoordName; + segments->fFSCode += ") + "; + segments->fFSCode += " - "; + segments->fFSCode += radial2ParamsName; + segments->fFSCode += "[4];\n"; + + segments->fFSCode += "\tfloat "; + segments->fFSCode += ac4Name; + segments->fFSCode += " = "; + segments->fFSCode += radial2ParamsName; + segments->fFSCode += "[0] * 4.0 * "; + segments->fFSCode += cName; + segments->fFSCode += ";\n"; + + segments->fFSCode += "\tfloat "; + segments->fFSCode += rootName; + segments->fFSCode += " = sqrt(abs("; + segments->fFSCode += bVar; + segments->fFSCode += " * "; + segments->fFSCode += bVar; + segments->fFSCode += " - "; + segments->fFSCode += ac4Name; + segments->fFSCode += "));\n"; + + sampleCoords = "vec2((-"; + sampleCoords += bVar; + sampleCoords += " + "; + sampleCoords += radial2ParamsName; + sampleCoords += "[5] * "; + sampleCoords += rootName; + sampleCoords += ") * "; + sampleCoords += radial2ParamsName; + sampleCoords += "[1], 0.5)\n"; + break;} + }; + + segments->fFSCode += "\t"; + segments->fFSCode += fsOutColor; + segments->fFSCode += " = "; + if (NULL != fsInColor) { + segments->fFSCode += fsInColor; + segments->fFSCode += " * "; + } + segments->fFSCode += texFunc; + segments->fFSCode += "("; + segments->fFSCode += samplerName; + segments->fFSCode += ", "; + segments->fFSCode += sampleCoords; + segments->fFSCode += ")"; + if (desc.fModulation == ProgramDesc::StageDesc::kAlpha_Modulation) { + segments->fFSCode += ".aaaa"; + } + segments->fFSCode += ";\n"; + + if(fStageEffects[stageNum]) { + fStageEffects[stageNum]->genShaderCode(segments); + } +} + diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h new file mode 100644 index 0000000..1a15953 --- /dev/null +++ b/gpu/src/GrGLProgram.h @@ -0,0 +1,215 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrGLProgram_DEFINED +#define GrGLProgram_DEFINED + +#include "GrGLInterface.h" + +#define POS_ATTR_LOCATION 0 +#define TEX_ATTR_LOCATION(X) (1 + (X)) +#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords) + +#include "GrDrawTarget.h" + +class GrBinHashKeyBuilder; +class GrGLEffect; +struct ShaderCodeSegments; + +/** + * This class manages a GPU program and records per-program information. + * We can specify the attribute locations so that they are constant + * across our shaders. But the driver determines the uniform locations + * at link time. We don't need to remember the sampler uniform location + * because we will bind a texture slot to it and never change it + * Uniforms are program-local so we can't rely on fHWState to hold the + * previous uniform state after a program change. + */ +class GrGLProgram { +public: + class CachedData; + + GrGLProgram(); + ~GrGLProgram(); + + /** + * Streams data that can uniquely identifies the generated + * gpu program into a key, for cache indexing purposes. + * + * @param key The key object to receive the key data + */ + void buildKey(GrBinHashKeyBuilder& key) const; + + /** + * This is the heavy initilization routine for building a GLProgram. + * The result of heavy init is not stored in datamembers of GrGLProgam, + * but in a separate cacheable container. + */ + void genProgram(CachedData* programData, const GrDrawTarget* target) const; + + /** + * Routine that is called before rendering. Sets-up all the state and + * other initializations required for the Gpu Program to run. + */ + bool doGLSetup(GrPrimitiveType type, CachedData* programData) const; + + /** + * Routine that is called after rendering. Performs state restoration. + * May perform secondary render passes. + */ + void doGLPost() const; + + /** + * Configures the GrGLProgram based on the state of a GrDrawTarget + * object. This is the fast and light initialization. Retrieves all the + * state that is required for performing the heavy init (i.e. genProgram), + * or for retrieving heavy init results from cache. + */ + void buildFromTarget(const GrDrawTarget* target); + +private: + + //Parameters that affect code generation + struct ProgramDesc { + GrVertexLayout fVertexLayout; + + enum { + kNotPoints_OptFlagBit = 0x1, + kVertexColorAllOnes_OptFlagBit = 0x2, + }; + // we're assuming optflags and layout pack into 32 bits + // VS 2010 seems to require short rather than just unsigned + // for this to pack + unsigned short fOptFlags : 16; + + struct StageDesc { + enum OptFlagBits { + kNoPerspective_OptFlagBit = 0x1, + kIdentityMatrix_OptFlagBit = 0x2 + }; + + unsigned fOptFlags : 8; + unsigned fEnabled : 8; + + enum Modulation { + kColor_Modulation, + kAlpha_Modulation + } fModulation : 8; + + enum CoordMapping { + kIdentity_CoordMapping, + kRadialGradient_CoordMapping, + kSweepGradient_CoordMapping, + kRadial2Gradient_CoordMapping + } fCoordMapping : 8; + } fStages[GrDrawTarget::kNumStages]; + } fProgramDesc; + +public: + struct StageUniLocations { + GrGLint fTextureMatrixUni; + GrGLint fSamplerUni; + GrGLint fRadial2Uni; + }; + + struct UniLocations { + GrGLint fViewMatrixUni; + StageUniLocations fStages[GrDrawTarget::kNumStages]; + }; + + class CachedData : public ::GrNoncopyable { + public: + CachedData() { + GR_DEBUGCODE(fEffectUniCount = 0;) + fEffectUniLocationsExtended = NULL; + } + + ~CachedData() { + GrFree(fEffectUniLocationsExtended); + } + + void copyAndTakeOwnership(CachedData& other) { + memcpy(this, &other, sizeof(this)); + other.fEffectUniLocationsExtended = NULL; // ownership transfer + GR_DEBUGCODE(other.fEffectUniCount = 0;) + } + + void setEffectUniformCount(size_t effectUniforms) { + GR_DEBUGCODE(fEffectUniCount = effectUniforms;) + GrFree(fEffectUniLocationsExtended); + if (effectUniforms > kUniLocationPreAllocSize) { + fEffectUniLocationsExtended = (GrGLint*)GrMalloc(sizeof(GrGLint)*(effectUniforms-kUniLocationPreAllocSize)); + } else { + fEffectUniLocationsExtended = NULL; + } + } + + GrGLint& effectUniLocation(size_t index) { + GrAssert(index < fEffectUniCount); + return (index < kUniLocationPreAllocSize) ? + fEffectUniLocations[index] : + fEffectUniLocationsExtended[index - kUniLocationPreAllocSize]; + } + + public: + + // IDs + GrGLuint fVShaderID; + GrGLuint fFShaderID; + GrGLuint fProgramID; + // shader uniform locations (-1 if shader doesn't use them) + UniLocations fUniLocations; + + GrMatrix fViewMatrix; + + // these reflect the current values of uniforms + // (GL uniform values travel with program) + GrMatrix fTextureMatrices[GrDrawTarget::kNumStages]; + GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages]; + GrScalar fRadial2Radius0[GrDrawTarget::kNumStages]; + bool fRadial2PosRoot[GrDrawTarget::kNumStages]; + + private: + enum Constants { + kUniLocationPreAllocSize = 8 + }; + + GrGLint fEffectUniLocations[kUniLocationPreAllocSize]; + GrGLint* fEffectUniLocationsExtended; + GR_DEBUGCODE(size_t fEffectUniCount;) + }; // CachedData + + GrGLEffect* fStageEffects[GrDrawTarget::kNumStages]; + +private: + void genStageCode(int stageNum, + const ProgramDesc::StageDesc& desc, + const char* fsInColor, // NULL means no incoming color + const char* fsOutColor, + const char* vsInCoord, + ShaderCodeSegments* segments, + StageUniLocations* locations) const; + + // Compiles a GL shader, returns shader ID or 0 if failed + // params have same meaning as glShaderSource + static GrGLuint CompileShader(GrGLenum type, int stringCnt, + const char** strings, + int* stringLengths); + + friend class GrGpuGLShaders; +}; + +#endif diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp index 7488d0f..3c6504d 100644 --- a/gpu/src/GrGLTexture.cpp +++ b/gpu/src/GrGLTexture.cpp @@ -18,16 +18,17 @@ #include "GrGLTexture.h" #include "GrGpuGL.h" -GrGLRenderTarget::GrGLRenderTarget(const GLRenderTargetIDs& ids, +#define GPUGL static_cast<GrGpuGL*>(getGpu()) + +GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu, + const GLRenderTargetIDs& ids, GrGLTexID* texID, - GLuint stencilBits, + GrGLuint stencilBits, + bool isMultisampled, const GrGLIRect& viewport, - GrGLTexture* texture, - GrGpuGL* gl) : INHERITED(texture, - viewport.fWidth, - viewport.fHeight, - stencilBits) { - fGL = gl; + GrGLTexture* texture) + : INHERITED(gpu, texture, viewport.fWidth, + viewport.fHeight, stencilBits, isMultisampled) { fRTFBOID = ids.fRTFBOID; fTexFBOID = ids.fTexFBOID; fStencilRenderbufferID = ids.fStencilRenderbufferID; @@ -39,10 +40,10 @@ GrGLRenderTarget::GrGLRenderTarget(const GLRenderTargetIDs& ids, GrSafeRef(fTexIDObj); } -GrGLRenderTarget::~GrGLRenderTarget() { - fGL->notifyRenderTargetDelete(this); +void GrGLRenderTarget::onRelease() { if (fOwnIDs) { if (fTexFBOID) { + GPUGL->notifyRenderTargetDelete(this); GR_GL(DeleteFramebuffers(1, &fTexFBOID)); } if (fRTFBOID && fRTFBOID != fTexFBOID) { @@ -55,43 +56,60 @@ GrGLRenderTarget::~GrGLRenderTarget() { GR_GL(DeleteRenderbuffers(1, &fMSColorRenderbufferID)); } } + fRTFBOID = 0; + fTexFBOID = 0; + fStencilRenderbufferID = 0; + fMSColorRenderbufferID = 0; GrSafeUnref(fTexIDObj); + fTexIDObj = NULL; } -void GrGLRenderTarget::abandon() { +void GrGLRenderTarget::onAbandon() { fRTFBOID = 0; fTexFBOID = 0; fStencilRenderbufferID = 0; fMSColorRenderbufferID = 0; if (NULL != fTexIDObj) { fTexIDObj->abandon(); + fTexIDObj = NULL; } } //////////////////////////////////////////////////////////////////////////////// -const GLenum GrGLTexture::gWrapMode2GLWrap[] = { - GL_CLAMP_TO_EDGE, - GL_REPEAT, -#ifdef GL_MIRRORED_REPEAT - GL_MIRRORED_REPEAT -#else - GL_REPEAT // GL_MIRRORED_REPEAT not supported :( -#endif +const GrGLenum* GrGLTexture::WrapMode2GLWrap() { + static const GrGLenum mirrorRepeatModes[] = { + GR_GL_CLAMP_TO_EDGE, + GR_GL_REPEAT, + GR_GL_MIRRORED_REPEAT + }; + + static const GrGLenum repeatModes[] = { + GR_GL_CLAMP_TO_EDGE, + GR_GL_REPEAT, + GR_GL_REPEAT + }; + + if (GR_GL_SUPPORT_ES1 && !GR_GL_SUPPORT_ES2) { + return repeatModes; // GL_MIRRORED_REPEAT not supported. + } else { + return mirrorRepeatModes; + } }; - -GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc, +GrGLTexture::GrGLTexture(GrGpuGL* gpu, + const GLTextureDesc& textureDesc, const GLRenderTargetIDs& rtIDs, - const TexParams& initialTexParams, - GrGpuGL* gl) - : INHERITED(textureDesc.fContentWidth, - textureDesc.fContentHeight, - textureDesc.fFormat) { + const TexParams& initialTexParams) + : INHERITED(gpu, + textureDesc.fContentWidth, + textureDesc.fContentHeight, + textureDesc.fFormat) { fTexParams = initialTexParams; - fTexIDObj = new GrGLTexID(textureDesc.fTextureID); + fTexIDObj = new GrGLTexID(textureDesc.fTextureID, + textureDesc.fOwnsID); fUploadFormat = textureDesc.fUploadFormat; fUploadByteCount = textureDesc.fUploadByteCount; fUploadType = textureDesc.fUploadType; @@ -102,8 +120,6 @@ GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc, textureDesc.fAllocWidth; fScaleY = GrIntToScalar(textureDesc.fContentHeight) / textureDesc.fAllocHeight; - fRenderTarget = NULL; - fGpuGL = gl; GrAssert(0 != textureDesc.fTextureID); @@ -115,32 +131,27 @@ GrGLTexture::GrGLTexture(const GLTextureDesc& textureDesc, vp.fHeight = textureDesc.fContentHeight; vp.fBottom = textureDesc.fAllocHeight - textureDesc.fContentHeight; - fRenderTarget = new GrGLRenderTarget(rtIDs, fTexIDObj, + fRenderTarget = new GrGLRenderTarget(gpu, rtIDs, fTexIDObj, textureDesc.fStencilBits, - vp, this, gl); + rtIDs.fRTFBOID != rtIDs.fTexFBOID, + vp, this); } } -GrGLTexture::~GrGLTexture() { - fGpuGL->notifyTextureDelete(this); - fTexIDObj->unref(); - GrSafeUnref(fRenderTarget); -} - -void GrGLTexture::abandon() { - fTexIDObj->abandon(); - if (NULL != fRenderTarget) { - fRenderTarget->abandon(); +void GrGLTexture::onRelease() { + INHERITED::onRelease(); + if (NULL != fTexIDObj) { + GPUGL->notifyTextureDelete(this); + fTexIDObj->unref(); + fTexIDObj = NULL; } } -GrRenderTarget* GrGLTexture::asRenderTarget() { - return (GrRenderTarget*)fRenderTarget; -} - -void GrGLTexture::releaseRenderTarget() { - GrSafeUnref(fRenderTarget); - fRenderTarget = NULL; +void GrGLTexture::onAbandon() { + INHERITED::onAbandon(); + if (NULL != fTexIDObj) { + fTexIDObj->abandon(); + } } void GrGLTexture::uploadTextureData(uint32_t x, @@ -148,19 +159,19 @@ void GrGLTexture::uploadTextureData(uint32_t x, uint32_t width, uint32_t height, const void* srcData) { - - fGpuGL->setSpareTextureUnit(); + + GPUGL->setSpareTextureUnit(); // glCompressedTexSubImage2D doesn't support any formats // (at least without extensions) - GrAssert(fUploadFormat != GR_PALETTE8_RGBA8); + GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8); // If we need to update textures that are created upside down // then we have to modify this code to flip the srcData GrAssert(kTopDown_Orientation == fOrientation); - GR_GL(BindTexture(GL_TEXTURE_2D, fTexIDObj->id())); - GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, fUploadByteCount)); - GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, + GR_GL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id())); + GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, fUploadByteCount)); + GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height, fUploadFormat, fUploadType, srcData)); } @@ -169,5 +180,3 @@ intptr_t GrGLTexture::getTextureHandle() { return fTexIDObj->id(); } - - diff --git a/gpu/src/GrGLUtil.cpp b/gpu/src/GrGLUtil.cpp index 2cb887a..5234453 100644 --- a/gpu/src/GrGLUtil.cpp +++ b/gpu/src/GrGLUtil.cpp @@ -15,10 +15,15 @@ */ #include "GrGLConfig.h" +#include "GrGLInterface.h" + +void GrGLClearErr() { + while (GR_GL_NO_ERROR != GrGLGetGLInterface()->fGetError()) {} +} void GrGLCheckErr(const char* location, const char* call) { uint32_t err = GrGLGetGLInterface()->fGetError(); - if (GL_NO_ERROR != err) { + if (GR_GL_NO_ERROR != err) { GrPrintf("---- glGetError %x", err); if (NULL != location) { GrPrintf(" at\n\t%s", location); @@ -30,6 +35,12 @@ void GrGLCheckErr(const char* location, const char* call) { } } +void GrGLRestoreResetRowLength() { + if (GR_GL_SUPPORT_DESKTOP) { + GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); + } +} + /////////////////////////////////////////////////////////////////////////////// bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START); diff --git a/gpu/src/GrGLVertexBuffer.cpp b/gpu/src/GrGLVertexBuffer.cpp index 69913bf..3fa1425 100644 --- a/gpu/src/GrGLVertexBuffer.cpp +++ b/gpu/src/GrGLVertexBuffer.cpp @@ -18,46 +18,49 @@ #include "GrGLVertexBuffer.h" #include "GrGpuGL.h" -GrGLVertexBuffer::GrGLVertexBuffer(GLuint id, GrGpuGL* gl, size_t sizeInBytes, - bool dynamic) : - INHERITED(sizeInBytes, dynamic), - fGL(gl), - fBufferID(id), - fLockPtr(NULL) { +#define GPUGL static_cast<GrGpuGL*>(getGpu()) + +GrGLVertexBuffer::GrGLVertexBuffer(GrGpuGL* gpu, + GrGLuint id, + size_t sizeInBytes, + bool dynamic) + : INHERITED(gpu, sizeInBytes, dynamic) + , fBufferID(id) + , fLockPtr(NULL) { } -GrGLVertexBuffer::~GrGLVertexBuffer() { +void GrGLVertexBuffer::onRelease() { // make sure we've not been abandoned if (fBufferID) { - fGL->notifyVertexBufferDelete(this); + GPUGL->notifyVertexBufferDelete(this); GR_GL(DeleteBuffers(1, &fBufferID)); + fBufferID = 0; } } -void GrGLVertexBuffer::bind() const { - GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID)); - fGL->notifyVertexBufferBind(this); +void GrGLVertexBuffer::onAbandon() { + fBufferID = 0; + fLockPtr = NULL; } -GLuint GrGLVertexBuffer::bufferID() const { - return fBufferID; +void GrGLVertexBuffer::bind() const { + GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, fBufferID)); + GPUGL->notifyVertexBufferBind(this); } -void GrGLVertexBuffer::abandon() { - fBufferID = 0; - fGL = NULL; - fLockPtr = NULL; +GrGLuint GrGLVertexBuffer::bufferID() const { + return fBufferID; } void* GrGLVertexBuffer::lock() { GrAssert(fBufferID); GrAssert(!isLocked()); - if (fGL->supportsBufferLocking()) { - bind(); + if (GPUGL->supportsBufferLocking()) { + this->bind(); // Let driver know it can discard the old data - GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL, - dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)); - fLockPtr = GR_GL(MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY)); + GR_GL(BufferData(GR_GL_ARRAY_BUFFER, size(), NULL, + dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + fLockPtr = GR_GL(MapBuffer(GR_GL_ARRAY_BUFFER, GR_GL_WRITE_ONLY)); return fLockPtr; } return NULL; @@ -68,22 +71,23 @@ void* GrGLVertexBuffer::lockPtr() const { } void GrGLVertexBuffer::unlock() { + GrAssert(fBufferID); GrAssert(isLocked()); - GrAssert(fGL->supportsBufferLocking()); + GrAssert(GPUGL->supportsBufferLocking()); - bind(); - GR_GL(UnmapBuffer(GL_ARRAY_BUFFER)); + this->bind(); + GR_GL(UnmapBuffer(GR_GL_ARRAY_BUFFER)); fLockPtr = NULL; } bool GrGLVertexBuffer::isLocked() const { - GrAssert(fBufferID); + GrAssert(!this->isValid() || fBufferID); #if GR_DEBUG - if (fGL->supportsBufferLocking()) { - GLint mapped; - bind(); - GR_GL(GetBufferParameteriv(GL_ARRAY_BUFFER, GR_BUFFER_MAPPED, &mapped)); + if (this->isValid() && GPUGL->supportsBufferLocking()) { + GrGLint mapped; + this->bind(); + GR_GL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER, GR_GL_BUFFER_MAPPED, &mapped)); GrAssert(!!mapped == !!fLockPtr); } #endif @@ -96,13 +100,13 @@ bool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) { if (srcSizeInBytes > size()) { return false; } - bind(); - GLenum usage = dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; + this->bind(); + GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW; if (size() == srcSizeInBytes) { - GR_GL(BufferData(GL_ARRAY_BUFFER, srcSizeInBytes, src, usage)); + GR_GL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage)); } else { - GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL, usage)); - GR_GL(BufferSubData(GL_ARRAY_BUFFER, 0, srcSizeInBytes, src)); + GR_GL(BufferData(GR_GL_ARRAY_BUFFER, size(), NULL, usage)); + GR_GL(BufferSubData(GR_GL_ARRAY_BUFFER, 0, srcSizeInBytes, src)); } return true; } @@ -115,8 +119,8 @@ bool GrGLVertexBuffer::updateSubData(const void* src, if (srcSizeInBytes + offset > size()) { return false; } - bind(); - GR_GL(BufferSubData(GL_ARRAY_BUFFER, offset, srcSizeInBytes, src)); + this->bind(); + GR_GL(BufferSubData(GR_GL_ARRAY_BUFFER, offset, srcSizeInBytes, src)); return true; } diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index 2d763e2..43fe648 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -28,60 +28,29 @@ static const size_t VERTEX_POOL_VB_SIZE = 1 << 12; static const int VERTEX_POOL_VB_COUNT = 1; -//////////////////////////////////////////////////////////////////////////////// - -size_t GrTexture::BytesPerPixel(PixelConfig config) { - switch (config) { - case kAlpha_8_PixelConfig: - case kIndex_8_PixelConfig: - return 1; - case kRGB_565_PixelConfig: - case kRGBA_4444_PixelConfig: - return 2; - case kRGBA_8888_PixelConfig: - case kRGBX_8888_PixelConfig: - return 4; - default: - return 0; - } -} - -bool GrTexture::PixelConfigIsOpaque(PixelConfig config) { - switch (config) { - case GrTexture::kRGB_565_PixelConfig: - case GrTexture::kRGBX_8888_PixelConfig: - return true; - default: - return false; - } -} - -bool GrTexture::PixelConfigIsAlphaOnly(PixelConfig config) { - switch (config) { - case GrTexture::kAlpha_8_PixelConfig: - return true; - default: - return false; - } -} //////////////////////////////////////////////////////////////////////////////// extern void gr_run_unittests(); -GrGpu::GrGpu() : f8bitPaletteSupport(false), - fCurrPoolVertexBuffer(NULL), - fCurrPoolStartVertex(0), - fCurrPoolIndexBuffer(NULL), - fCurrPoolStartIndex(0), - fVertexPool(NULL), - fIndexPool(NULL), - fQuadIndexBuffer(NULL), - fUnitSquareVertexBuffer(NULL), - fPathRenderer(NULL), - fContextIsDirty(true), - fVertexPoolInUse(false), - fIndexPoolInUse(false) { +GrGpu::GrGpu() + : f8bitPaletteSupport(false) + , fCurrPoolVertexBuffer(NULL) + , fCurrPoolStartVertex(0) + , fCurrPoolIndexBuffer(NULL) + , fCurrPoolStartIndex(0) + , fContext(NULL) + , fVertexPool(NULL) + , fIndexPool(NULL) + , fQuadIndexBuffer(NULL) + , fUnitSquareVertexBuffer(NULL) + , fDefaultPathRenderer(NULL) + , fClientPathRenderer(NULL) + , fContextIsDirty(true) + , fVertexPoolInUse(false) + , fIndexPoolInUse(false) + , fResourceHead(NULL) { + #if GR_DEBUG //gr_run_unittests(); #endif @@ -89,16 +58,76 @@ GrGpu::GrGpu() : f8bitPaletteSupport(false), } GrGpu::~GrGpu() { - GrSafeUnref(fQuadIndexBuffer); - GrSafeUnref(fUnitSquareVertexBuffer); + releaseResources(); +} + +void GrGpu::abandonResources() { + + while (NULL != fResourceHead) { + fResourceHead->abandon(); + } + + GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); + GrAssert(NULL == fUnitSquareVertexBuffer || + !fUnitSquareVertexBuffer->isValid()); + GrSafeSetNull(fQuadIndexBuffer); + GrSafeSetNull(fUnitSquareVertexBuffer); + delete fVertexPool; + fVertexPool = NULL; + delete fIndexPool; + fIndexPool = NULL; +} + +void GrGpu::releaseResources() { + + while (NULL != fResourceHead) { + fResourceHead->release(); + } + + GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); + GrAssert(NULL == fUnitSquareVertexBuffer || + !fUnitSquareVertexBuffer->isValid()); + GrSafeSetNull(fQuadIndexBuffer); + GrSafeSetNull(fUnitSquareVertexBuffer); delete fVertexPool; + fVertexPool = NULL; delete fIndexPool; - delete fPathRenderer; + fIndexPool = NULL; +} + +void GrGpu::insertResource(GrResource* resource) { + GrAssert(NULL != resource); + GrAssert(this == resource->getGpu()); + GrAssert(NULL == resource->fNext); + GrAssert(NULL == resource->fPrevious); + + resource->fNext = fResourceHead; + if (NULL != fResourceHead) { + GrAssert(NULL == fResourceHead->fPrevious); + fResourceHead->fPrevious = resource; + } + fResourceHead = resource; } -void GrGpu::resetContext() { +void GrGpu::removeResource(GrResource* resource) { + GrAssert(NULL != resource); + GrAssert(NULL != fResourceHead); + + if (fResourceHead == resource) { + GrAssert(NULL == resource->fPrevious); + fResourceHead = resource->fNext; + } else { + GrAssert(NULL != fResourceHead); + resource->fPrevious->fNext = resource->fNext; + } + if (NULL != resource->fNext) { + resource->fNext->fPrevious = resource->fPrevious; + } + resource->fNext = NULL; + resource->fPrevious = NULL; } + void GrGpu::unimpl(const char msg[]) { #if GR_DEBUG GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg); @@ -110,47 +139,56 @@ void GrGpu::unimpl(const char msg[]) { GrTexture* GrGpu::createTexture(const TextureDesc& desc, const void* srcData, size_t rowBytes) { this->handleDirtyContext(); - return this->createTextureHelper(desc, srcData, rowBytes); + return this->onCreateTexture(desc, srcData, rowBytes); } GrRenderTarget* GrGpu::createPlatformRenderTarget(intptr_t platformRenderTarget, int stencilBits, + bool isMultisampled, int width, int height) { this->handleDirtyContext(); - return this->createPlatformRenderTargetHelper(platformRenderTarget, + return this->onCreatePlatformRenderTarget(platformRenderTarget, stencilBits, + isMultisampled, width, height); } GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() { this->handleDirtyContext(); - return this->createRenderTargetFrom3DApiStateHelper(); + return this->onCreateRenderTargetFrom3DApiState(); +} + +GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) { + this->handleDirtyContext(); + return this->onCreatePlatformSurface(desc); } GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) { this->handleDirtyContext(); - return this->createVertexBufferHelper(size, dynamic); + return this->onCreateVertexBuffer(size, dynamic); } GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) { this->handleDirtyContext(); - return this->createIndexBufferHelper(size, dynamic); + return this->onCreateIndexBuffer(size, dynamic); } void GrGpu::eraseColor(GrColor color) { this->handleDirtyContext(); - this->eraseColorHelper(color); + this->onEraseColor(color); } void GrGpu::forceRenderTargetFlush() { this->handleDirtyContext(); - this->forceRenderTargetFlushHelper(); + this->onForceRenderTargetFlush(); } -bool GrGpu::readPixels(int left, int top, int width, int height, - GrTexture::PixelConfig config, void* buffer) { +bool GrGpu::readPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + this->handleDirtyContext(); - return this->readPixelsHelper(left, top, width, height, config, buffer); + return this->onReadPixels(target, left, top, width, height, config, buffer); } //////////////////////////////////////////////////////////////////////////////// @@ -414,43 +452,68 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { // enabled at bottom of loop this->disableState(kModifyStencilClip_StateBit); - bool canDrawDirectToClip; + bool canRenderDirectToStencil; // can the clip element be drawn + // directly to the stencil buffer + // with a non-inverted fill rule + // without extra passes to + // resolve in/out status. + + GrPathRenderer* pr = NULL; + GrPath::Iter pathIter; if (kRect_ClipType == clip.getElementType(c)) { - canDrawDirectToClip = true; + canRenderDirectToStencil = true; fill = kEvenOdd_PathFill; } else { fill = clip.getPathFill(c); - GrPathRenderer* pr = this->getPathRenderer(); - canDrawDirectToClip = pr->requiresStencilPass(this, clip.getPath(c), fill); + const GrPath& path = clip.getPath(c); + pathIter.reset(path); + pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill)); + canRenderDirectToStencil = + !pr->requiresStencilPass(this, &pathIter, + NonInvertedFill(fill)); } GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c); int passes; GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; - canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, canDrawDirectToClip, - clipBit, IsFillInverted(fill), - &passes, stencilSettings); + bool canDrawDirectToClip; // Given the renderer, the element, + // fill rule, and set operation can + // we render the element directly to + // stencil bit used for clipping. + canDrawDirectToClip = + GrStencilSettings::GetClipPasses(op, + canRenderDirectToStencil, + clipBit, + IsFillInverted(fill), + &passes, stencilSettings); // draw the element to the client stencil bits if necessary if (!canDrawDirectToClip) { + static const GrStencilSettings gDrawToStencil = { + kIncClamp_StencilOp, kIncClamp_StencilOp, + kIncClamp_StencilOp, kIncClamp_StencilOp, + kAlways_StencilFunc, kAlways_StencilFunc, + 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, + }; + SET_RANDOM_COLOR if (kRect_ClipType == clip.getElementType(c)) { - static const GrStencilSettings gDrawToStencil = { - kIncClamp_StencilOp, kIncClamp_StencilOp, - kIncClamp_StencilOp, kIncClamp_StencilOp, - kAlways_StencilFunc, kAlways_StencilFunc, - 0xffffffff, 0xffffffff, - 0x00000000, 0x00000000, - 0xffffffff, 0xffffffff, - }; this->setStencil(gDrawToStencil); - SET_RANDOM_COLOR this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { - SET_RANDOM_COLOR - getPathRenderer()->drawPathToStencil(this, clip.getPath(c), - NonInvertedFill(fill), - NULL); + if (canRenderDirectToStencil) { + this->setStencil(gDrawToStencil); + pr->drawPath(this, 0, + &pathIter, + NonInvertedFill(fill), + NULL); + } else { + pr->drawPathToStencil(this, &pathIter, + NonInvertedFill(fill), + NULL); + } } } @@ -465,9 +528,8 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { SET_RANDOM_COLOR - getPathRenderer()->drawPath(this, 0, - clip.getPath(c), - fill, NULL); + GrAssert(!IsFillInverted(fill)); + pr->drawPath(this, 0, &pathIter, fill, NULL); } } else { SET_RANDOM_COLOR @@ -491,6 +553,23 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { return true; } +GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path, + GrPathFill fill) { + if (NULL != fClientPathRenderer && + fClientPathRenderer->canDrawPath(this, path, fill)) { + return fClientPathRenderer; + } else { + if (NULL == fDefaultPathRenderer) { + fDefaultPathRenderer = + new GrDefaultPathRenderer(this->supportsTwoSidedStencil(), + this->supportsStencilWrapOps()); + } + GrAssert(fDefaultPathRenderer->canDrawPath(this, path, fill)); + return fDefaultPathRenderer; + } +} + + //////////////////////////////////////////////////////////////////////////////// void GrGpu::drawIndexed(GrPrimitiveType type, @@ -519,8 +598,8 @@ void GrGpu::drawIndexed(GrPrimitiveType type, int sIndex = startIndex; setupGeometry(&sVertex, &sIndex, vertexCount, indexCount); - drawIndexedHelper(type, sVertex, sIndex, - vertexCount, indexCount); + this->onDrawIndexed(type, sVertex, sIndex, + vertexCount, indexCount); } void GrGpu::drawNonIndexed(GrPrimitiveType type, @@ -542,7 +621,7 @@ void GrGpu::drawNonIndexed(GrPrimitiveType type, int sVertex = startVertex; setupGeometry(&sVertex, NULL, vertexCount, 0); - drawNonIndexedHelper(type, sVertex, vertexCount); + this->onDrawNonIndexed(type, sVertex, vertexCount); } void GrGpu::finalizeReservedVertices() { @@ -560,6 +639,7 @@ void GrGpu::prepareVertexPool() { fVertexPool = new GrVertexBufferAllocPool(this, true, VERTEX_POOL_VB_SIZE, VERTEX_POOL_VB_COUNT); + fVertexPool->releaseGpuRef(); } else if (!fVertexPoolInUse) { // the client doesn't have valid data in the pool fVertexPool->reset(); @@ -567,17 +647,18 @@ void GrGpu::prepareVertexPool() { } void GrGpu::prepareIndexPool() { - if (NULL == fVertexPool) { + if (NULL == fIndexPool) { fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1); + fIndexPool->releaseGpuRef(); } else if (!fIndexPoolInUse) { // the client doesn't have valid data in the pool fIndexPool->reset(); } } -bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout, - void** vertices, - void** indices) { +bool GrGpu::onAcquireGeometry(GrVertexLayout vertexLayout, + void** vertices, + void** indices) { GrAssert(!fReservedGeometry.fLocked); size_t reservedVertexSpace = 0; @@ -613,11 +694,11 @@ bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout, return true; } -void GrGpu::releaseGeometryHelper() {} +void GrGpu::onReleaseGeometry() {} -void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) { +void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) { GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount); - prepareVertexPool(); + this->prepareVertexPool(); #if GR_DEBUG bool success = #endif @@ -629,9 +710,9 @@ void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCoun GR_DEBUGASSERT(success); } -void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) { +void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) { GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount); - prepareIndexPool(); + this->prepareIndexPool(); #if GR_DEBUG bool success = #endif @@ -644,16 +725,6 @@ void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) //////////////////////////////////////////////////////////////////////////////// -GrPathRenderer* GrGpu::getPathRenderer() { - if (NULL == fPathRenderer) { - fPathRenderer = new GrDefaultPathRenderer(this->supportsTwoSidedStencil(), - this->supportsStencilWrapOps()); - } - return fPathRenderer; -} - -//////////////////////////////////////////////////////////////////////////////// - const GrGpu::Stats& GrGpu::getStats() const { return fStats; } @@ -679,12 +750,6 @@ void GrGpu::printStats() const { } //////////////////////////////////////////////////////////////////////////////// - -GrTexture::~GrTexture() { - // use this to set a break-point if needed -// Gr_clz(3); -} - const GrSamplerState GrSamplerState::gClampNoFilter( GrSamplerState::kClamp_WrapMode, GrSamplerState::kClamp_WrapMode, diff --git a/gpu/src/GrGpuFactory.cpp b/gpu/src/GrGpuFactory.cpp index 7c2db2b..1715333 100644 --- a/gpu/src/GrGpuFactory.cpp +++ b/gpu/src/GrGpuFactory.cpp @@ -14,7 +14,6 @@ limitations under the License. */ - #include "GrTypes.h" // must be before GrGLConfig.h @@ -24,37 +23,42 @@ #include "GrGLConfig.h" - -#if GR_SUPPORT_GLES1 || GR_SUPPORT_GLDESKTOP - #include "GrGpuGLFixed.h" -#endif - -#if GR_SUPPORT_GLES2 || GR_SUPPORT_GLDESKTOP - #include "GrGpuGLShaders2.h" -#endif - #include "GrGpu.h" +#include "GrGpuGLFixed.h" +#include "GrGpuGLShaders.h" +#include "GrGpuGLShaders2.h" GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) { - // If no GL bindings have been installed, fall-back to calling the - // GL functions that have been linked with the executable. - if (!GrGLGetGLInterface()) - GrGLSetDefaultGLInterface(); + + if (kOpenGL_Shaders_Engine == engine || + kOpenGL_Fixed_Engine == engine) { + // If no GL bindings have been installed, fall-back to calling the + // GL functions that have been linked with the executable. + if (!GrGLGetGLInterface()) { + GrGLSetDefaultGLInterface(); + // If there is no platform-default then just fail. + if (!GrGLGetGLInterface()) { + return NULL; + } + } + } GrGpu* gpu = NULL; switch (engine) { case kOpenGL_Shaders_Engine: GrAssert(NULL == context3D); -#if GR_SUPPORT_GLES2 || GR_SUPPORT_GLDESKTOP - gpu = new GrGpuGLShaders2; + { +#if GR_USE_NEW_GLSHADERS + gpu = new GrGpuGLShaders; +#else + gpu = new GrGpuGLShaders2; #endif + } break; case kOpenGL_Fixed_Engine: GrAssert(NULL == context3D); -#if GR_SUPPORT_GLES1 || GR_SUPPORT_GLDESKTOP gpu = new GrGpuGLFixed; -#endif break; case kDirect3D9_Engine: GrAssert(NULL != context3D); @@ -69,6 +73,3 @@ GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) { return gpu; } - - - diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp index f2a2a8f..fe461cc 100644 --- a/gpu/src/GrGpuGL.cpp +++ b/gpu/src/GrGpuGL.cpp @@ -16,17 +16,9 @@ #include "GrGpuGL.h" #include "GrMemory.h" -#if GR_WIN32_BUILD - // need to get wglGetProcAddress - #undef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN 1 - #include <windows.h> - #undef WIN32_LEAN_AND_MEAN -#endif - -static const GLuint GR_MAX_GLUINT = ~0; -static const GLint GR_INVAL_GLINT = ~0; +static const GrGLuint GR_MAX_GLUINT = ~0; +static const GrGLint GR_INVAL_GLINT = ~0; // we use a spare texture unit to avoid // mucking with the state of any of the stages. @@ -34,21 +26,21 @@ static const int SPARE_TEX_UNIT = GrGpuGL::kNumStages; #define SKIP_CACHE_CHECK true -static const GLenum gXfermodeCoeff2Blend[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_CONSTANT_COLOR, - GL_ONE_MINUS_CONSTANT_COLOR, - GL_CONSTANT_ALPHA, - GL_ONE_MINUS_CONSTANT_ALPHA, +static const GrGLenum gXfermodeCoeff2Blend[] = { + GR_GL_ZERO, + GR_GL_ONE, + GR_GL_SRC_COLOR, + GR_GL_ONE_MINUS_SRC_COLOR, + GR_GL_DST_COLOR, + GR_GL_ONE_MINUS_DST_COLOR, + GR_GL_SRC_ALPHA, + GR_GL_ONE_MINUS_SRC_ALPHA, + GR_GL_DST_ALPHA, + GR_GL_ONE_MINUS_DST_ALPHA, + GR_GL_CONSTANT_COLOR, + GR_GL_ONE_MINUS_CONSTANT_COLOR, + GR_GL_CONSTANT_ALPHA, + GR_GL_ONE_MINUS_CONSTANT_ALPHA, }; bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) { @@ -147,35 +139,35 @@ static bool gPrintStartupSpew; static bool fbo_test(int w, int h) { - GLint savedFBO; - GLint savedTexUnit; - GR_GL_GetIntegerv(GL_ACTIVE_TEXTURE, &savedTexUnit); - GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, &savedFBO); + GrGLint savedFBO; + GrGLint savedTexUnit; + GR_GL_GetIntegerv(GR_GL_ACTIVE_TEXTURE, &savedTexUnit); + GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &savedFBO); - GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT)); + GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); - GLuint testFBO; + GrGLuint testFBO; GR_GL(GenFramebuffers(1, &testFBO)); - GR_GL(BindFramebuffer(GR_FRAMEBUFFER, testFBO)); - GLuint testRTTex; + GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, testFBO)); + GrGLuint testRTTex; GR_GL(GenTextures(1, &testRTTex)); - GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex)); + GR_GL(BindTexture(GR_GL_TEXTURE_2D, testRTTex)); // some implementations require texture to be mip-map complete before // FBO with level 0 bound as color attachment will be framebuffer complete. - GR_GL(TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - GR_GL(BindTexture(GL_TEXTURE_2D, 0)); - GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, testRTTex, 0)); - GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER)); + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST)); + GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, w, h, + 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, NULL)); + GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0)); + GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, + GR_GL_TEXTURE_2D, testRTTex, 0)); + GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); GR_GL(DeleteFramebuffers(1, &testFBO)); GR_GL(DeleteTextures(1, &testRTTex)); GR_GL(ActiveTexture(savedTexUnit)); - GR_GL(BindFramebuffer(GR_FRAMEBUFFER, savedFBO)); + GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, savedFBO)); - return status == GR_FRAMEBUFFER_COMPLETE; + return status == GR_GL_FRAMEBUFFER_COMPLETE; } GrGpuGL::GrGpuGL() { @@ -184,31 +176,31 @@ GrGpuGL::GrGpuGL() { GrPrintf("------------------------- create GrGpuGL %p --------------\n", this); GrPrintf("------ VENDOR %s\n", - GrGLGetGLInterface()->fGetString(GL_VENDOR)); + GrGLGetGLInterface()->fGetString(GR_GL_VENDOR)); GrPrintf("------ RENDERER %s\n", - GrGLGetGLInterface()->fGetString(GL_RENDERER)); + GrGLGetGLInterface()->fGetString(GR_GL_RENDERER)); GrPrintf("------ VERSION %s\n", - GrGLGetGLInterface()->fGetString(GL_VERSION)); + GrGLGetGLInterface()->fGetString(GR_GL_VERSION)); GrPrintf("------ EXTENSIONS\n %s \n", - GrGLGetGLInterface()->fGetString(GL_EXTENSIONS)); + GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS)); } GrGLClearErr(); resetDirtyFlags(); - GLint maxTextureUnits; + GrGLint maxTextureUnits; // check FS and fixed-function texture unit limits // we only use textures in the fragment stage currently. // checks are > to make sure we have a spare unit. -#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES2 - GR_GL_GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); - GrAssert(maxTextureUnits > kNumStages); -#endif -#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1 - GR_GL_GetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits); - GrAssert(maxTextureUnits > kNumStages); -#endif + if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES2) { + GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); + GrAssert(maxTextureUnits > kNumStages); + } + if (GR_GL_SUPPORT_DESKTOP || GR_GL_SUPPORT_ES1) { + GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_UNITS, &maxTextureUnits); + GrAssert(maxTextureUnits > kNumStages); + } //////////////////////////////////////////////////////////////////////////// // Check for supported features. @@ -216,12 +208,12 @@ GrGpuGL::GrGpuGL() { int major, minor; gl_version(&major, &minor); - GLint numFormats; - GR_GL_GetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); - GrAutoSTMalloc<10, GLint> formats(numFormats); - GR_GL_GetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); + GrGLint numFormats; + GR_GL_GetIntegerv(GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); + GrAutoSTMalloc<10, GrGLint> formats(numFormats); + GR_GL_GetIntegerv(GR_GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < numFormats; ++i) { - if (formats[i] == GR_PALETTE8_RGBA8) { + if (formats[i] == GR_GL_PALETTE8_RGBA8) { f8bitPaletteSupport = true; break; } @@ -238,41 +230,43 @@ GrGpuGL::GrGpuGL() { memset(fAASamples, 0, sizeof(fAASamples)); fMSFBOType = kNone_MSFBO; - if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) { - fMSFBOType = kIMG_MSFBO; - if (gPrintStartupSpew) { - GrPrintf("MSAA Support: IMG ES EXT.\n"); + if (GR_GL_SUPPORT_ES) { + if (has_gl_extension("GL_CHROMIUM_framebuffer_multisample")) { + // chrome's extension is equivalent to the EXT msaa + // and fbo_blit extensions. + fMSFBOType = kDesktopEXT_MSFBO; + } else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) { + fMSFBOType = kAppleES_MSFBO; } - } - else if (has_gl_extension("GL_APPLE_framebuffer_multisample")) { - fMSFBOType = kApple_MSFBO; - if (gPrintStartupSpew) { - GrPrintf("MSAA Support: APPLE ES EXT.\n"); + } else { + GrAssert(GR_GL_SUPPORT_DESKTOP); + if ((major >= 3) || has_gl_extension("GL_ARB_framebuffer_object")) { + fMSFBOType = kDesktopARB_MSFBO; + } else if (has_gl_extension("GL_EXT_framebuffer_multisample") && + has_gl_extension("GL_EXT_framebuffer_blit")) { + fMSFBOType = kDesktopEXT_MSFBO; } } -#if GR_SUPPORT_GLDESKTOP - else if ((major >= 3) || - has_gl_extension("GL_ARB_framebuffer_object") || - (has_gl_extension("GL_EXT_framebuffer_multisample") && - has_gl_extension("GL_EXT_framebuffer_blit"))) { - fMSFBOType = kDesktop_MSFBO; - if (gPrintStartupSpew) { - GrPrintf("MSAA Support: DESKTOP\n"); - } - } -#endif - else { - if (gPrintStartupSpew) { - GrPrintf("MSAA Support: NONE\n"); + if (gPrintStartupSpew) { + switch (fMSFBOType) { + case kNone_MSFBO: + GrPrintf("MSAA Support: NONE\n"); + break; + case kDesktopARB_MSFBO: + GrPrintf("MSAA Support: DESKTOP ARB.\n"); + break; + case kDesktopEXT_MSFBO: + GrPrintf("MSAA Support: DESKTOP EXT.\n"); + break; + case kAppleES_MSFBO: + GrPrintf("MSAA Support: APPLE ES.\n"); + break; } } if (kNone_MSFBO != fMSFBOType) { - GLint maxSamples; - GLenum maxSampleGetter = (kIMG_MSFBO == fMSFBOType) ? - GR_MAX_SAMPLES_IMG : - GR_MAX_SAMPLES; - GR_GL_GetIntegerv(maxSampleGetter, &maxSamples); + GrGLint maxSamples; + GR_GL_GetIntegerv(GR_GL_MAX_SAMPLES, &maxSamples); if (maxSamples > 1 ) { fAASamples[kNone_AALevel] = 0; fAASamples[kLow_AALevel] = GrMax(2, @@ -288,83 +282,84 @@ GrGpuGL::GrGpuGL() { } } -#if GR_SUPPORT_GLDESKTOP - fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) || - has_gl_extension("GL_EXT_stencil_wrap"); -#else - fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap"); -#endif + if (GR_GL_SUPPORT_DESKTOP) { + fHasStencilWrap = (major >= 2 || (major == 1 && minor >= 4)) || + has_gl_extension("GL_EXT_stencil_wrap"); + } else { + fHasStencilWrap = (major >= 2) || has_gl_extension("GL_OES_stencil_wrap"); + } if (gPrintStartupSpew) { GrPrintf("Stencil Wrap: %s\n", (fHasStencilWrap ? "YES" : "NO")); } -#if GR_SUPPORT_GLDESKTOP - // we could also look for GL_ATI_separate_stencil extension or - // GL_EXT_stencil_two_side but they use different function signatures - // than GL2.0+ (and than each other). - fTwoSidedStencilSupport = (major >= 2); - // supported on GL 1.4 and higher or by extension - fStencilWrapOpsSupport = (major > 1) || - ((1 == major) && (minor >= 4)) || - has_gl_extension("GL_EXT_stencil_wrap"); -#else - // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be - // an ES1 extension. - fTwoSidedStencilSupport = (major >= 2); - // stencil wrap support is in ES2, ES1 requires extension. - fStencilWrapOpsSupport = (major > 1) || - has_gl_extension("GL_OES_stencil_wrap"); - -#endif + if (GR_GL_SUPPORT_DESKTOP) { + // we could also look for GL_ATI_separate_stencil extension or + // GL_EXT_stencil_two_side but they use different function signatures + // than GL2.0+ (and than each other). + fTwoSidedStencilSupport = (major >= 2); + // supported on GL 1.4 and higher or by extension + fStencilWrapOpsSupport = (major > 1) || + ((1 == major) && (minor >= 4)) || + has_gl_extension("GL_EXT_stencil_wrap"); + } else { + // ES 2 has two sided stencil but 1.1 doesn't. There doesn't seem to be + // an ES1 extension. + fTwoSidedStencilSupport = (major >= 2); + // stencil wrap support is in ES2, ES1 requires extension. + fStencilWrapOpsSupport = (major > 1) || + has_gl_extension("GL_OES_stencil_wrap"); + } if (gPrintStartupSpew) { GrPrintf("Stencil Caps: TwoSide: %s, Wrap: %s\n", (fTwoSidedStencilSupport ? "YES" : "NO"), (fStencilWrapOpsSupport ? "YES" : "NO")); } -#if GR_SUPPORT_GLDESKTOP - fRGBA8Renderbuffer = true; -#else - fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8"); -#endif + if (GR_GL_SUPPORT_DESKTOP) { + fRGBA8Renderbuffer = true; + } else { + fRGBA8Renderbuffer = has_gl_extension("GL_OES_rgb8_rgba8"); + } if (gPrintStartupSpew) { GrPrintf("RGBA Renderbuffer: %s\n", (fRGBA8Renderbuffer ? "YES" : "NO")); } -#if GR_SUPPORT_GLES - if (GR_GL_32BPP_COLOR_FORMAT == GR_BGRA) { - GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888")); + + if (GR_GL_SUPPORT_ES) { + if (GR_GL_32BPP_COLOR_FORMAT == GR_GL_BGRA) { + GrAssert(has_gl_extension("GL_EXT_texture_format_BGRA8888")); + } } -#endif -#if GR_SUPPORT_GLDESKTOP - fBufferLockSupport = true; // we require VBO support and the desktop VBO - // extension includes glMapBuffer. -#else - fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer"); -#endif + if (GR_GL_SUPPORT_DESKTOP) { + fBufferLockSupport = true; // we require VBO support and the desktop VBO + // extension includes glMapBuffer. + } else { + fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer"); + } if (gPrintStartupSpew) { GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO")); } -#if GR_SUPPORT_GLDESKTOP - if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) { - fNPOTTextureTileSupport = true; - fNPOTTextureSupport = true; - } else { - fNPOTTextureTileSupport = false; - fNPOTTextureSupport = false; - } -#else - if (major >= 2) { - fNPOTTextureSupport = true; - fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot"); + if (GR_GL_SUPPORT_DESKTOP) { + if (major >= 2 || has_gl_extension("GL_ARB_texture_non_power_of_two")) { + fNPOTTextureTileSupport = true; + fNPOTTextureSupport = true; + } else { + fNPOTTextureTileSupport = false; + fNPOTTextureSupport = false; + } } else { - fNPOTTextureSupport = has_gl_extension("GL_APPLE_texture_2D_limited_npot"); - fNPOTTextureTileSupport = false; + if (major >= 2) { + fNPOTTextureSupport = true; + fNPOTTextureTileSupport = has_gl_extension("GL_OES_texture_npot"); + } else { + fNPOTTextureSupport = + has_gl_extension("GL_APPLE_texture_2D_limited_npot"); + fNPOTTextureTileSupport = false; + } } -#endif //////////////////////////////////////////////////////////////////////////// // Experiments to determine limitations that can't be queried. TODO: Make @@ -412,21 +407,25 @@ GrGpuGL::GrGpuGL() { } } + GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension); + /* The iPhone 4 has a restriction that for an FBO with texture color attachment with height <= 8 then the width must be <= height. Here we look for such a limitation. */ fMinRenderTargetHeight = GR_INVAL_GLINT; - GLint maxRenderSize; - GR_GL_GetIntegerv(GR_MAX_RENDERBUFFER_SIZE, &maxRenderSize); + GrGLint maxRenderSize; + GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &maxRenderSize); + // fbo_test creates FBOs with texture bound to the color attachment + maxRenderSize = GrMin(maxRenderSize, fMaxTextureDimension); if (gPrintStartupSpew) { GrPrintf("Small height FBO texture experiments\n"); } - for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) { - GLuint w = maxRenderSize; - GLuint h = i; + for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) { + GrGLuint w = maxRenderSize; + GrGLuint h = i; if (fbo_test(w, h)) { if (gPrintStartupSpew) { GrPrintf("\t[%d, %d]: PASSED\n", w, h); @@ -445,9 +444,9 @@ GrGpuGL::GrGpuGL() { GrPrintf("Small width FBO texture experiments\n"); } fMinRenderTargetWidth = GR_MAX_GLUINT; - for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) { - GLuint w = i; - GLuint h = maxRenderSize; + for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) { + GrGLuint w = i; + GrGLuint h = maxRenderSize; if (fbo_test(w, h)) { if (gPrintStartupSpew) { GrPrintf("\t[%d, %d]: PASSED\n", w, h); @@ -461,8 +460,6 @@ GrGpuGL::GrGpuGL() { } } GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth); - - GR_GL_GetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxTextureDimension); } GrGpuGL::~GrGpuGL() { @@ -471,24 +468,26 @@ GrGpuGL::~GrGpuGL() { void GrGpuGL::resetContext() { // We detect cases when blending is effectively off fHWBlendDisabled = false; - GR_GL(Enable(GL_BLEND)); + GR_GL(Enable(GR_GL_BLEND)); // we don't use the zb at all - GR_GL(Disable(GL_DEPTH_TEST)); - GR_GL(DepthMask(GL_FALSE)); + GR_GL(Disable(GR_GL_DEPTH_TEST)); + GR_GL(DepthMask(GR_GL_FALSE)); - GR_GL(Disable(GL_CULL_FACE)); - GR_GL(FrontFace(GL_CCW)); + GR_GL(Disable(GR_GL_CULL_FACE)); + GR_GL(FrontFace(GR_GL_CCW)); fHWDrawState.fDrawFace = kBoth_DrawFace; - GR_GL(Disable(GL_DITHER)); -#if GR_SUPPORT_GLDESKTOP - GR_GL(Disable(GL_LINE_SMOOTH)); - GR_GL(Disable(GL_POINT_SMOOTH)); - GR_GL(Disable(GL_MULTISAMPLE)); -#endif + GR_GL(Disable(GR_GL_DITHER)); + if (GR_GL_SUPPORT_DESKTOP) { + GR_GL(Disable(GR_GL_LINE_SMOOTH)); + GR_GL(Disable(GR_GL_POINT_SMOOTH)); + GR_GL(Disable(GR_GL_MULTISAMPLE)); + fHWAAState.fMSAAEnabled = false; + fHWAAState.fSmoothLineEnabled = false; + } - GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); + GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); fHWDrawState.fFlagBits = 0; // we only ever use lines in hairline mode @@ -519,7 +518,7 @@ void GrGpuGL::resetContext() { fHWBounds.fScissorRect.invalidate(); fHWBounds.fScissorEnabled = false; - GR_GL(Disable(GL_SCISSOR_TEST)); + GR_GL(Disable(GR_GL_SCISSOR_TEST)); fHWBounds.fViewportRect.invalidate(); fHWDrawState.fStencilSettings.invalidate(); @@ -528,17 +527,85 @@ void GrGpuGL::resetContext() { fHWGeometryState.fIndexBuffer = NULL; fHWGeometryState.fVertexBuffer = NULL; - GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0)); - GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, 0)); + GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); fHWGeometryState.fArrayPtrsDirty = true; - GR_GL(ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); + GR_GL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); fHWDrawState.fRenderTarget = NULL; } -GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper( +GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) { + + bool isTexture = kTexture_GrPlatformSurfaceType == desc.fSurfaceType || + kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType; + bool isRenderTarget = kRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType || + kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType; + + GrGLRenderTarget::GLRenderTargetIDs rtIDs; + if (isRenderTarget) { + rtIDs.fRTFBOID = desc.fPlatformRenderTarget; + if (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) { + if (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) { + rtIDs.fTexFBOID = desc.fPlatformResolveDestination; + } else { + GrAssert(!isTexture); // this should have been filtered by GrContext + rtIDs.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; + } + } else { + rtIDs.fTexFBOID = desc.fPlatformRenderTarget; + } + // we don't know what the RB ids are without glGets and we don't care + // since we aren't responsible for deleting them. + rtIDs.fStencilRenderbufferID = 0; + rtIDs.fMSColorRenderbufferID = 0; + + rtIDs.fOwnIDs = false; + } else { + rtIDs.reset(); + } + + if (isTexture) { + GrGLTexture::GLTextureDesc texDesc; + GrGLenum dontCare; + if (!canBeTexture(desc.fConfig, &dontCare, + &texDesc.fUploadFormat, + &texDesc.fUploadType)) { + return NULL; + } + + GrGLTexture::TexParams params; + + texDesc.fAllocWidth = texDesc.fContentWidth = desc.fWidth; + texDesc.fAllocHeight = texDesc.fContentHeight = desc.fHeight; + + texDesc.fFormat = texDesc.fFormat; + texDesc.fOrientation = GrGLTexture::kBottomUp_Orientation; + texDesc.fStencilBits = desc.fStencilBits; + texDesc.fTextureID = desc.fPlatformTexture; + texDesc.fUploadByteCount = GrBytesPerPixel(desc.fConfig); + texDesc.fOwnsID = false; + + params.invalidate(); // rather than do glGets. + + return new GrGLTexture(this, texDesc, rtIDs, params); + } else { + GrGLIRect viewport; + viewport.fLeft = 0; + viewport.fBottom = 0; + viewport.fWidth = desc.fWidth; + viewport.fHeight = desc.fHeight; + + return new GrGLRenderTarget(this, rtIDs, NULL, desc.fStencilBits, + kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags, + viewport, NULL); + } +} + +GrRenderTarget* GrGpuGL::onCreatePlatformRenderTarget( intptr_t platformRenderTarget, int stencilBits, + bool isMultisampled, int width, int height) { GrGLRenderTarget::GLRenderTargetIDs rtIDs; @@ -554,54 +621,71 @@ GrRenderTarget* GrGpuGL::createPlatformRenderTargetHelper( viewport.fWidth = width; viewport.fHeight = height; - rtIDs.fRTFBOID = (GLuint)platformRenderTarget; - rtIDs.fTexFBOID = (GLuint)platformRenderTarget; + rtIDs.fRTFBOID = (GrGLuint)platformRenderTarget; + rtIDs.fTexFBOID = (GrGLuint)platformRenderTarget; - return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this); + return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, + isMultisampled, viewport, NULL); } -GrRenderTarget* GrGpuGL::createRenderTargetFrom3DApiStateHelper() { +GrRenderTarget* GrGpuGL::onCreateRenderTargetFrom3DApiState() { GrGLRenderTarget::GLRenderTargetIDs rtIDs; - GR_GL_GetIntegerv(GR_FRAMEBUFFER_BINDING, (GLint*)&rtIDs.fRTFBOID); + GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, (GrGLint*)&rtIDs.fRTFBOID); rtIDs.fTexFBOID = rtIDs.fRTFBOID; rtIDs.fMSColorRenderbufferID = 0; rtIDs.fStencilRenderbufferID = 0; GrGLIRect viewport; viewport.setFromGLViewport(); - GLuint stencilBits; - GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&stencilBits); + GrGLuint stencilBits; + GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&stencilBits); + + GrGLint samples; + GR_GL_GetIntegerv(GR_GL_SAMPLES, &samples); rtIDs.fOwnIDs = false; - return new GrGLRenderTarget(rtIDs, NULL, stencilBits, viewport, NULL, this); + return new GrGLRenderTarget(this, rtIDs, NULL, stencilBits, + (samples > 0), viewport, NULL); } /////////////////////////////////////////////////////////////////////////////// -static const GLuint UNKNOWN_BITS = ~0; +static const GrGLuint UNKNOWN_BITS = ~0; -// defines stencil formats from more to less preferred -static const struct { - GLenum fEnum; - GLuint fBits; -} gStencilFormats[] = { - {GR_STENCIL_INDEX8, 8}, +struct StencilFormat { + GrGLenum fEnum; + GrGLuint fBits; + bool fPacked; +}; -#if GR_SUPPORT_GLDESKTOP - {GR_STENCIL_INDEX16, 16}, -#endif +const StencilFormat* GrGLStencilFormats() { + // defines stencil formats from more to less preferred + static const StencilFormat desktopStencilFormats[] = { + {GR_GL_STENCIL_INDEX8, 8, false}, + {GR_GL_STENCIL_INDEX16, 16, false}, + {GR_GL_DEPTH24_STENCIL8, 8, true }, + {GR_GL_STENCIL_INDEX4, 4, false}, + {GR_GL_STENCIL_INDEX, UNKNOWN_BITS, false}, + {GR_GL_DEPTH_STENCIL, UNKNOWN_BITS, true }, + {0, 0, false} + }; - {GR_DEPTH24_STENCIL8, 8}, - {GR_STENCIL_INDEX4, 4}, + static const StencilFormat esStencilFormats[] = { + {GR_GL_STENCIL_INDEX8, 8, false}, + {GR_GL_DEPTH24_STENCIL8, 8, true }, + {GR_GL_STENCIL_INDEX4, 4, false}, + {0, 0, false} + }; -#if GR_SUPPORT_GLDESKTOP - {GL_STENCIL_INDEX, UNKNOWN_BITS}, - {GR_DEPTH_STENCIL, UNKNOWN_BITS} -#endif -}; + if (GR_GL_SUPPORT_DESKTOP) { + return desktopStencilFormats; + } else { + return esStencilFormats; + } +} // good to set a break-point here to know when createTexture fails static GrTexture* return_null_texture() { @@ -615,24 +699,24 @@ static size_t as_size_t(int x) { } #endif -GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, - const void* srcData, - size_t rowBytes) { +GrTexture* GrGpuGL::onCreateTexture(const TextureDesc& desc, + const void* srcData, + size_t rowBytes) { #if GR_COLLECT_STATS ++fStats.fTextureCreateCnt; #endif - setSpareTextureUnit(); + this->setSpareTextureUnit(); static const GrGLTexture::TexParams DEFAULT_PARAMS = { - GL_NEAREST, - GL_CLAMP_TO_EDGE, - GL_CLAMP_TO_EDGE + GR_GL_NEAREST, + GR_GL_CLAMP_TO_EDGE, + GR_GL_CLAMP_TO_EDGE }; GrGLTexture::GLTextureDesc glDesc; - GLenum internalFormat; + GrGLenum internalFormat; glDesc.fContentWidth = desc.fWidth; glDesc.fContentHeight = desc.fHeight; @@ -640,6 +724,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, glDesc.fAllocHeight = desc.fHeight; glDesc.fStencilBits = 0; glDesc.fFormat = desc.fFormat; + glDesc.fOwnsID = true; bool renderTarget = 0 != (desc.fFlags & kRenderTarget_TextureFlag); if (!canBeTexture(desc.fFormat, @@ -650,7 +735,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, } GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples)); - GLint samples = fAASamples[desc.fAALevel]; + GrGLint samples = fAASamples[desc.fAALevel]; if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_AALevel) { GrPrintf("AA RT requested but not supported on this platform."); } @@ -660,36 +745,37 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, return return_null_texture(); } - glDesc.fUploadByteCount = GrTexture::BytesPerPixel(desc.fFormat); + glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat); + + // in case we need a temporary, trimmed copy of the src pixels + GrAutoSMalloc<128 * 128> trimStorage; /* * check if our srcData has extra bytes past each row. If so, we need * to trim those off here, since GL doesn't let us pass the rowBytes as * a parameter to glTexImage2D */ -#if GR_SUPPORT_GLDESKTOP - if (srcData) { - GR_GL(PixelStorei(GL_UNPACK_ROW_LENGTH, - rowBytes / glDesc.fUploadByteCount)); - } -#else - GrAutoSMalloc<128 * 128> trimStorage; - size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount; - if (srcData && (trimRowBytes < rowBytes)) { - size_t trimSize = desc.fHeight * trimRowBytes; - trimStorage.realloc(trimSize); - // now copy the data into our new storage, skipping the trailing bytes - const char* src = (const char*)srcData; - char* dst = (char*)trimStorage.get(); - for (uint32_t y = 0; y < desc.fHeight; y++) { - memcpy(dst, src, trimRowBytes); - src += rowBytes; - dst += trimRowBytes; + if (GR_GL_SUPPORT_DESKTOP) { + if (srcData) { + GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, + rowBytes / glDesc.fUploadByteCount)); + } + } else { + size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount; + if (srcData && (trimRowBytes < rowBytes)) { + // copy the data into our new storage, skipping the trailing bytes + size_t trimSize = desc.fHeight * trimRowBytes; + const char* src = (const char*)srcData; + char* dst = (char*)trimStorage.realloc(trimSize); + for (uint32_t y = 0; y < desc.fHeight; y++) { + memcpy(dst, src, trimRowBytes); + src += rowBytes; + dst += trimRowBytes; + } + // now point srcData to our trimmed version + srcData = trimStorage.get(); } - // now point srcData to our trimmed version - srcData = trimStorage.get(); } -#endif if (renderTarget) { if (!this->npotRenderTargetSupport()) { @@ -706,42 +792,42 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, glDesc.fAllocHeight = GrNextPow2(desc.fHeight); } - GR_GL(BindTexture(GL_TEXTURE_2D, glDesc.fTextureID)); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, + GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID)); + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_MAG_FILTER, DEFAULT_PARAMS.fFilter)); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_MIN_FILTER, DEFAULT_PARAMS.fFilter)); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_S, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_WRAP_S, DEFAULT_PARAMS.fWrapS)); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_T, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_WRAP_T, DEFAULT_PARAMS.fWrapT)); - GR_GL(PixelStorei(GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount)); - if (GrTexture::kIndex_8_PixelConfig == desc.fFormat && + GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glDesc.fUploadByteCount)); + if (kIndex_8_GrPixelConfig == desc.fFormat && supports8BitPalette()) { // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D GrAssert(desc.fWidth == glDesc.fAllocWidth); GrAssert(desc.fHeight == glDesc.fAllocHeight); - GLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight + - kColorTableSize; - GR_GL(CompressedTexImage2D(GL_TEXTURE_2D, 0, glDesc.fUploadFormat, + GrGLsizei imageSize = glDesc.fAllocWidth * glDesc.fAllocHeight + + kColorTableSize; + GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glDesc.fUploadFormat, glDesc.fAllocWidth, glDesc.fAllocHeight, 0, imageSize, srcData)); - GrGL_RestoreResetRowLength(); + GrGLRestoreResetRowLength(); } else { if (NULL != srcData && (glDesc.fAllocWidth != desc.fWidth || glDesc.fAllocHeight != desc.fHeight)) { - GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, + GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth, glDesc.fAllocHeight, 0, glDesc.fUploadFormat, glDesc.fUploadType, NULL)); - GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.fWidth, + GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth, desc.fHeight, glDesc.fUploadFormat, glDesc.fUploadType, srcData)); - GrGL_RestoreResetRowLength(); + GrGLRestoreResetRowLength(); uint32_t extraW = glDesc.fAllocWidth - desc.fWidth; uint32_t extraH = glDesc.fAllocHeight - desc.fHeight; @@ -761,7 +847,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, memcpy(extraRowStart, lastRowStart, rowSize); extraRowStart += rowSize; } - GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth, + GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth, extraH, glDesc.fUploadFormat, glDesc.fUploadType, texels.get())); } @@ -775,7 +861,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, } edgeTexel += rowSize; } - GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW, + GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW, desc.fHeight, glDesc.fUploadFormat, glDesc.fUploadType, texels.get())); } @@ -787,16 +873,16 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, memcpy(extraTexel, cornerTexel, glDesc.fUploadByteCount); extraTexel += glDesc.fUploadByteCount; } - GR_GL(TexSubImage2D(GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight, + GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight, extraW, extraH, glDesc.fUploadFormat, glDesc.fUploadType, texels.get())); } } else { - GR_GL(TexImage2D(GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth, + GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glDesc.fAllocWidth, glDesc.fAllocHeight, 0, glDesc.fUploadFormat, glDesc.fUploadType, srcData)); - GrGL_RestoreResetRowLength(); + GrGLRestoreResetRowLength(); } } @@ -808,15 +894,15 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, rtIDs.fRTFBOID = 0; rtIDs.fTexFBOID = 0; rtIDs.fOwnIDs = true; - GLenum msColorRenderbufferFormat = -1; + GrGLenum msColorRenderbufferFormat = -1; if (renderTarget) { #if GR_COLLECT_STATS ++fStats.fRenderTargetCreateCnt; #endif bool failed = true; - GLenum status; - GLint err; + GrGLenum status; + GrGLint err; // If need have both RT flag and srcData we have // to invert the data before uploading because FBO @@ -827,11 +913,9 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID)); GrAssert(rtIDs.fTexFBOID); - // If we are using multisampling and any extension other than the IMG - // one we will create two FBOs. We render to one and then resolve to - // the texture bound to the other. The IMG extension does an implicit - // resolve. - if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) { + // If we are using multisampling and we will create two FBOS We render + // to one and then resolve to the texture bound to the other. + if (samples > 1 && kNone_MSFBO != fMSFBOType) { GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID)); GrAssert(0 != rtIDs.fRTFBOID); GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID)); @@ -846,138 +930,119 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, } else { rtIDs.fRTFBOID = rtIDs.fTexFBOID; } - int attempts = 1; - if (!(kNoPathRendering_TextureFlag & desc.fFlags)) { + if (!(kNoStencil_TextureFlag & desc.fFlags)) { GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID)); GrAssert(0 != rtIDs.fStencilRenderbufferID); - attempts = GR_ARRAY_COUNT(gStencilFormats); } // someone suggested that some systems might require // unbinding the texture before we call FramebufferTexture2D // (seems unlikely) - GR_GL(BindTexture(GL_TEXTURE_2D, 0)); + GR_GL(BindTexture(GR_GL_TEXTURE_2D, 0)); + + err = ~GR_GL_NO_ERROR; - err = ~GL_NO_ERROR; - for (int i = 0; i < attempts; ++i) { + const StencilFormat* stencilFormats = GrGLStencilFormats(); + for (int i = 0; 0 != stencilFormats[i].fEnum; ++i) { if (rtIDs.fStencilRenderbufferID) { - GR_GL(BindRenderbuffer(GR_RENDERBUFFER, + GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER, rtIDs.fStencilRenderbufferID)); if (samples > 1) { GR_GL_NO_ERR(RenderbufferStorageMultisample( - GR_RENDERBUFFER, + GR_GL_RENDERBUFFER, samples, - gStencilFormats[i].fEnum, + stencilFormats[i].fEnum, glDesc.fAllocWidth, glDesc.fAllocHeight)); } else { - GR_GL_NO_ERR(RenderbufferStorage(GR_RENDERBUFFER, - gStencilFormats[i].fEnum, + GR_GL_NO_ERR(RenderbufferStorage(GR_GL_RENDERBUFFER, + stencilFormats[i].fEnum, glDesc.fAllocWidth, glDesc.fAllocHeight)); } - err = glGetError(); - if (err != GL_NO_ERROR) { + err = GrGLGetGLInterface()->fGetError(); + if (err != GR_GL_NO_ERROR) { continue; } } if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) { GrAssert(samples > 1); - GR_GL(BindRenderbuffer(GR_RENDERBUFFER, + GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER, rtIDs.fMSColorRenderbufferID)); GR_GL_NO_ERR(RenderbufferStorageMultisample( - GR_RENDERBUFFER, + GR_GL_RENDERBUFFER, samples, msColorRenderbufferFormat, glDesc.fAllocWidth, glDesc.fAllocHeight)); - err = glGetError(); - if (err != GL_NO_ERROR) { + err = GrGLGetGLInterface()->fGetError(); + if (err != GR_GL_NO_ERROR) { continue; } } - GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID)); + GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fTexFBOID)); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; #endif - if (kIMG_MSFBO == fMSFBOType && samples > 1) { - GR_GL(FramebufferTexture2DMultisample(GR_FRAMEBUFFER, - GR_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - glDesc.fTextureID, - 0, - samples)); - - } else { - GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER, - GR_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - glDesc.fTextureID, 0)); - } + GR_GL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, + GR_GL_COLOR_ATTACHMENT0, + GR_GL_TEXTURE_2D, + glDesc.fTextureID, 0)); if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) { - GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER)); - if (status != GR_FRAMEBUFFER_COMPLETE) { + GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { GrPrintf("-- glCheckFramebufferStatus %x %d %d\n", status, desc.fWidth, desc.fHeight); continue; } - GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID)); + GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rtIDs.fRTFBOID)); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; #endif - GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER, - GR_COLOR_ATTACHMENT0, - GR_RENDERBUFFER, + GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, + GR_GL_COLOR_ATTACHMENT0, + GR_GL_RENDERBUFFER, rtIDs.fMSColorRenderbufferID)); } if (rtIDs.fStencilRenderbufferID) { // bind the stencil to rt fbo if present, othewise the tex fbo - GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER, - GR_STENCIL_ATTACHMENT, - GR_RENDERBUFFER, - rtIDs.fStencilRenderbufferID)); - } - status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER)); - -#if GR_SUPPORT_GLDESKTOP - // On some implementations you have to be bound as DEPTH_STENCIL. - // (Even binding to DEPTH and STENCIL separately with the same - // buffer doesn't work.) - if (rtIDs.fStencilRenderbufferID && - status != GR_FRAMEBUFFER_COMPLETE) { - GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER, - GR_STENCIL_ATTACHMENT, - GR_RENDERBUFFER, - 0)); - GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER, - GR_DEPTH_STENCIL_ATTACHMENT, - GR_RENDERBUFFER, + GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, + GR_GL_STENCIL_ATTACHMENT, + GR_GL_RENDERBUFFER, rtIDs.fStencilRenderbufferID)); - status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER)); + // if it is a packed format bind to depth also, otherwise + // we may get an unsupported fbo completeness result + if (stencilFormats[i].fPacked) { + GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, + GR_GL_DEPTH_ATTACHMENT, + GR_GL_RENDERBUFFER, + rtIDs.fStencilRenderbufferID)); + } } -#endif - if (status != GR_FRAMEBUFFER_COMPLETE) { + status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { GrPrintf("-- glCheckFramebufferStatus %x %d %d\n", status, desc.fWidth, desc.fHeight); -#if GR_SUPPORT_GLDESKTOP - if (rtIDs.fStencilRenderbufferID) { - GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER, - GR_DEPTH_STENCIL_ATTACHMENT, - GR_RENDERBUFFER, - 0)); + // undo the depth bind + if (rtIDs.fStencilRenderbufferID && + stencilFormats[i].fPacked) { + GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, + GR_GL_DEPTH_ATTACHMENT, + GR_GL_RENDERBUFFER, + 0)); } -#endif continue; } // we're successful! failed = false; if (rtIDs.fStencilRenderbufferID) { - if (UNKNOWN_BITS == gStencilFormats[i].fBits) { - GR_GL_GetIntegerv(GL_STENCIL_BITS, (GLint*)&glDesc.fStencilBits); + if (UNKNOWN_BITS == stencilFormats[i].fBits) { + GR_GL_GetIntegerv(GR_GL_STENCIL_BITS, (GrGLint*)&glDesc.fStencilBits); } else { - glDesc.fStencilBits = gStencilFormats[i].fBits; + glDesc.fStencilBits = stencilFormats[i].fBits; } } break; @@ -1003,7 +1068,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, GrPrintf("--- new texture [%d] size=(%d %d) bpp=%d\n", tex->fTextureID, width, height, tex->fUploadByteCount); #endif - GrGLTexture* tex = new GrGLTexture(glDesc, rtIDs, DEFAULT_PARAMS, this); + GrGLTexture* tex = new GrGLTexture(this, glDesc, rtIDs, DEFAULT_PARAMS); if (0 != rtIDs.fTexFBOID) { GrRenderTarget* rt = tex->asRenderTarget(); @@ -1012,7 +1077,7 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, fHWDrawState.fRenderTarget = NULL; // clear the new stencil buffer if we have one - if (!(desc.fFlags & kNoPathRendering_TextureFlag)) { + if (!(desc.fFlags & kNoStencil_TextureFlag)) { GrRenderTarget* rtSave = fCurrDrawState.fRenderTarget; fCurrDrawState.fRenderTarget = rt; eraseStencil(0, ~0); @@ -1022,23 +1087,23 @@ GrTexture* GrGpuGL::createTextureHelper(const TextureDesc& desc, return tex; } -GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) { - GLuint id; +GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { + GrGLuint id; GR_GL(GenBuffers(1, &id)); if (id) { - GR_GL(BindBuffer(GL_ARRAY_BUFFER, id)); + GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, id)); fHWGeometryState.fArrayPtrsDirty = true; GrGLClearErr(); // make sure driver can allocate memory for this buffer - GR_GL_NO_ERR(BufferData(GL_ARRAY_BUFFER, size, NULL, - dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)); - if (glGetError() != GL_NO_ERROR) { + GR_GL_NO_ERR(BufferData(GR_GL_ARRAY_BUFFER, size, NULL, + dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) { GR_GL(DeleteBuffers(1, &id)); // deleting bound buffer does implicit bind to 0 fHWGeometryState.fVertexBuffer = NULL; return NULL; } - GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(id, this, + GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, id, size, dynamic); fHWGeometryState.fVertexBuffer = vertexBuffer; return vertexBuffer; @@ -1046,22 +1111,22 @@ GrVertexBuffer* GrGpuGL::createVertexBufferHelper(uint32_t size, bool dynamic) { return NULL; } -GrIndexBuffer* GrGpuGL::createIndexBufferHelper(uint32_t size, bool dynamic) { - GLuint id; +GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { + GrGLuint id; GR_GL(GenBuffers(1, &id)); if (id) { - GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, id)); + GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); GrGLClearErr(); // make sure driver can allocate memory for this buffer - GR_GL_NO_ERR(BufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, - dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)); - if (glGetError() != GL_NO_ERROR) { + GR_GL_NO_ERR(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, NULL, + dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); + if (GrGLGetGLInterface()->fGetError() != GR_GL_NO_ERROR) { GR_GL(DeleteBuffers(1, &id)); // deleting bound buffer does implicit bind to 0 fHWGeometryState.fIndexBuffer = NULL; return NULL; } - GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(id, this, + GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, id, size, dynamic); fHWGeometryState.fIndexBuffer = indexBuffer; return indexBuffer; @@ -1089,33 +1154,33 @@ void GrGpuGL::flushScissor(const GrIRect* rect) { fHWBounds.fScissorRect = scissor; } if (!fHWBounds.fScissorEnabled) { - GR_GL(Enable(GL_SCISSOR_TEST)); + GR_GL(Enable(GR_GL_SCISSOR_TEST)); fHWBounds.fScissorEnabled = true; } } else { if (fHWBounds.fScissorEnabled) { - GR_GL(Disable(GL_SCISSOR_TEST)); + GR_GL(Disable(GR_GL_SCISSOR_TEST)); fHWBounds.fScissorEnabled = false; } } } -void GrGpuGL::eraseColorHelper(GrColor color) { +void GrGpuGL::onEraseColor(GrColor color) { if (NULL == fCurrDrawState.fRenderTarget) { return; } flushRenderTarget(); if (fHWBounds.fScissorEnabled) { - GR_GL(Disable(GL_SCISSOR_TEST)); + GR_GL(Disable(GR_GL_SCISSOR_TEST)); fHWBounds.fScissorEnabled = false; } - GR_GL(ColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE)); + GR_GL(ColorMask(GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE,GR_GL_TRUE)); fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit; GR_GL(ClearColor(GrColorUnpackR(color)/255.f, GrColorUnpackG(color)/255.f, GrColorUnpackB(color)/255.f, GrColorUnpackA(color)/255.f)); - GR_GL(Clear(GL_COLOR_BUFFER_BIT)); + GR_GL(Clear(GR_GL_COLOR_BUFFER_BIT)); } void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) { @@ -1124,56 +1189,70 @@ void GrGpuGL::eraseStencil(uint32_t value, uint32_t mask) { } flushRenderTarget(); if (fHWBounds.fScissorEnabled) { - GR_GL(Disable(GL_SCISSOR_TEST)); + GR_GL(Disable(GR_GL_SCISSOR_TEST)); fHWBounds.fScissorEnabled = false; } GR_GL(StencilMask(mask)); GR_GL(ClearStencil(value)); - GR_GL(Clear(GL_STENCIL_BUFFER_BIT)); + GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT)); fHWDrawState.fStencilSettings.invalidate(); } void GrGpuGL::eraseStencilClip(const GrIRect& rect) { GrAssert(NULL != fCurrDrawState.fRenderTarget); #if 0 - GLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits(); + GrGLint stencilBitCount = fCurrDrawState.fRenderTarget->stencilBits(); GrAssert(stencilBitCount > 0); - GLint clipStencilMask = (1 << (stencilBitCount - 1)); + GrGLint clipStencilMask = (1 << (stencilBitCount - 1)); #else // we could just clear the clip bit but when we go through // angle a partial stencil mask will cause clears to be // turned into draws. Our contract on GrDrawTarget says that // changing the clip between stencil passes may or may not // zero the client's clip bits. So we just clear the whole thing. - static const GLint clipStencilMask = ~0; + static const GrGLint clipStencilMask = ~0; #endif flushRenderTarget(); flushScissor(&rect); GR_GL(StencilMask(clipStencilMask)); GR_GL(ClearStencil(0)); - GR_GL(Clear(GL_STENCIL_BUFFER_BIT)); + GR_GL(Clear(GR_GL_STENCIL_BUFFER_BIT)); fHWDrawState.fStencilSettings.invalidate(); } -void GrGpuGL::forceRenderTargetFlushHelper() { +void GrGpuGL::onForceRenderTargetFlush() { flushRenderTarget(); } -bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height, - GrTexture::PixelConfig config, void* buffer) { - GLenum internalFormat; // we don't use this for glReadPixels - GLenum format; - GLenum type; +bool GrGpuGL::onReadPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + GrGLenum internalFormat; // we don't use this for glReadPixels + GrGLenum format; + GrGLenum type; if (!this->canBeTexture(config, &internalFormat, &format, &type)) { return false; + } + GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target); + GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore; + switch (tgt->getResolveType()) { + case GrGLRenderTarget::kCantResolve_ResolveType: + return false; + case GrGLRenderTarget::kAutoResolves_ResolveType: + autoTargetRestore.save(&fCurrDrawState.fRenderTarget); + fCurrDrawState.fRenderTarget = target; + flushRenderTarget(); + break; + case GrGLRenderTarget::kCanResolve_ResolveType: + resolveRenderTarget(tgt); + // we don't track the state of the READ FBO ID. + GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID())); + break; + default: + GrCrash("Unknown resolve type"); } - if (NULL == fCurrDrawState.fRenderTarget) { - return false; - } - flushRenderTarget(); - - const GrGLIRect& glvp = ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport(); + const GrGLIRect& glvp = tgt->getViewport(); // the read rect is viewport-relative GrGLIRect readRect; @@ -1185,7 +1264,7 @@ bool GrGpuGL::readPixelsHelper(int left, int top, int width, int height, // now reverse the order of the rows, since GL's are bottom-to-top, but our // API presents top-to-bottom { - size_t stride = width * GrTexture::BytesPerPixel(config); + size_t stride = width * GrBytesPerPixel(config); GrAutoMalloc rowStorage(stride); void* tmp = rowStorage.get(); @@ -1209,14 +1288,14 @@ void GrGpuGL::flushRenderTarget() { if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) { GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget; - GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID())); + GR_GL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; #endif - rt->setDirty(true); + rt->flagAsNeedingResolve(); #if GR_DEBUG - GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER)); - if (status != GR_FRAMEBUFFER_COMPLETE) { + GrGLenum status = GR_GL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); + if (status != GR_GL_FRAMEBUFFER_COMPLETE) { GrPrintf("-- glCheckFramebufferStatus %x\n", status); } #endif @@ -1230,13 +1309,13 @@ void GrGpuGL::flushRenderTarget() { } } -GLenum gPrimitiveType2GLMode[] = { - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN, - GL_POINTS, - GL_LINES, - GL_LINE_STRIP +GrGLenum gPrimitiveType2GLMode[] = { + GR_GL_TRIANGLES, + GR_GL_TRIANGLE_STRIP, + GR_GL_TRIANGLE_FAN, + GR_GL_POINTS, + GR_GL_LINES, + GR_GL_LINE_STRIP }; #define SWAP_PER_DRAW 0 @@ -1260,14 +1339,14 @@ GLenum gPrimitiveType2GLMode[] = { #endif #endif -void GrGpuGL::drawIndexedHelper(GrPrimitiveType type, - uint32_t startVertex, - uint32_t startIndex, - uint32_t vertexCount, - uint32_t indexCount) { +void GrGpuGL::onDrawIndexed(GrPrimitiveType type, + uint32_t startVertex, + uint32_t startIndex, + uint32_t vertexCount, + uint32_t indexCount) { GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); - GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex); + GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * startIndex); GrAssert(NULL != fHWGeometryState.fIndexBuffer); GrAssert(NULL != fHWGeometryState.fVertexBuffer); @@ -1277,7 +1356,7 @@ void GrGpuGL::drawIndexedHelper(GrPrimitiveType type, GrAssert(0 == startVertex); GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount, - GL_UNSIGNED_SHORT, indices)); + GR_GL_UNSIGNED_SHORT, indices)); #if SWAP_PER_DRAW glFlush(); #if GR_MAC_BUILD @@ -1292,9 +1371,9 @@ void GrGpuGL::drawIndexedHelper(GrPrimitiveType type, #endif } -void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type, - uint32_t startVertex, - uint32_t vertexCount) { +void GrGpuGL::onDrawNonIndexed(GrPrimitiveType type, + uint32_t startVertex, + uint32_t vertexCount) { GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode)); GrAssert(NULL != fHWGeometryState.fVertexBuffer); @@ -1321,52 +1400,56 @@ void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type, #endif } -void GrGpuGL::resolveTextureRenderTarget(GrGLTexture* texture) { - GrGLRenderTarget* rt = (GrGLRenderTarget*) texture->asRenderTarget(); +void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) { - if (NULL != rt && rt->needsResolve()) { + if (rt->needsResolve()) { GrAssert(kNone_MSFBO != fMSFBOType); GrAssert(rt->textureFBOID() != rt->renderFBOID()); - GR_GL(BindFramebuffer(GR_READ_FRAMEBUFFER, + GR_GL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID())); - GR_GL(BindFramebuffer(GR_DRAW_FRAMEBUFFER, + GR_GL(BindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID())); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; #endif - // make sure we go through set render target + // make sure we go through flushRenderTarget() since we've modified + // the bound DRAW FBO ID. fHWDrawState.fRenderTarget = NULL; + const GrGLIRect& vp = rt->getViewport(); - GLint left = 0; - GLint right = texture->width(); - // we will have rendered to the top of the FBO. - GLint top = texture->allocHeight(); - GLint bottom = texture->allocHeight() - texture->height(); - if (kApple_MSFBO == fMSFBOType) { - GR_GL(Enable(GL_SCISSOR_TEST)); - GR_GL(Scissor(left, bottom, right-left, top-bottom)); + if (kAppleES_MSFBO == fMSFBOType) { + // Apple's extension uses the scissor as the blit bounds. + GR_GL(Enable(GR_GL_SCISSOR_TEST)); + GR_GL(Scissor(vp.fLeft, vp.fBottom, + vp.fWidth, vp.fHeight)); GR_GL(ResolveMultisampleFramebuffer()); fHWBounds.fScissorRect.invalidate(); fHWBounds.fScissorEnabled = true; } else { - GR_GL(BlitFramebuffer(left, bottom, right, top, - left, bottom, right, top, - GL_COLOR_BUFFER_BIT, GL_NEAREST)); + if (kDesktopARB_MSFBO != fMSFBOType) { + // this respects the scissor during the blit, so disable it. + GrAssert(kDesktopEXT_MSFBO == fMSFBOType); + flushScissor(NULL); + } + int right = vp.fLeft + vp.fWidth; + int top = vp.fBottom + vp.fHeight; + GR_GL(BlitFramebuffer(vp.fLeft, vp.fBottom, right, top, + vp.fLeft, vp.fBottom, right, top, + GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST)); } - rt->setDirty(false); - + rt->flagAsResolved(); } } -static const GLenum grToGLStencilFunc[] = { - GL_ALWAYS, // kAlways_StencilFunc - GL_NEVER, // kNever_StencilFunc - GL_GREATER, // kGreater_StencilFunc - GL_GEQUAL, // kGEqual_StencilFunc - GL_LESS, // kLess_StencilFunc - GL_LEQUAL, // kLEqual_StencilFunc, - GL_EQUAL, // kEqual_StencilFunc, - GL_NOTEQUAL, // kNotEqual_StencilFunc, +static const GrGLenum grToGLStencilFunc[] = { + GR_GL_ALWAYS, // kAlways_StencilFunc + GR_GL_NEVER, // kNever_StencilFunc + GR_GL_GREATER, // kGreater_StencilFunc + GR_GL_GEQUAL, // kGEqual_StencilFunc + GR_GL_LESS, // kLess_StencilFunc + GR_GL_LEQUAL, // kLEqual_StencilFunc, + GR_GL_EQUAL, // kEqual_StencilFunc, + GR_GL_NOTEQUAL, // kNotEqual_StencilFunc, }; GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilFunc) == kBasicStencilFuncCount); GR_STATIC_ASSERT(0 == kAlways_StencilFunc); @@ -1378,15 +1461,15 @@ GR_STATIC_ASSERT(5 == kLEqual_StencilFunc); GR_STATIC_ASSERT(6 == kEqual_StencilFunc); GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc); -static const GLenum grToGLStencilOp[] = { - GL_KEEP, // kKeep_StencilOp - GL_REPLACE, // kReplace_StencilOp - GL_INCR_WRAP, // kIncWrap_StencilOp - GL_INCR, // kIncClamp_StencilOp - GL_DECR_WRAP, // kDecWrap_StencilOp - GL_DECR, // kDecClamp_StencilOp - GL_ZERO, // kZero_StencilOp - GL_INVERT, // kInvert_StencilOp +static const GrGLenum grToGLStencilOp[] = { + GR_GL_KEEP, // kKeep_StencilOp + GR_GL_REPLACE, // kReplace_StencilOp + GR_GL_INCR_WRAP, // kIncWrap_StencilOp + GR_GL_INCR, // kIncClamp_StencilOp + GR_GL_DECR_WRAP, // kDecWrap_StencilOp + GR_GL_DECR, // kDecClamp_StencilOp + GR_GL_ZERO, // kZero_StencilOp + GR_GL_INVERT, // kInvert_StencilOp }; GR_STATIC_ASSERT(GR_ARRAY_COUNT(grToGLStencilOp) == kStencilOpCount); GR_STATIC_ASSERT(0 == kKeep_StencilOp); @@ -1422,9 +1505,9 @@ void GrGpuGL::flushStencil() { } if (settings->isDisabled()) { - GR_GL(Disable(GL_STENCIL_TEST)); + GR_GL(Disable(GR_GL_STENCIL_TEST)); } else { - GR_GL(Enable(GL_STENCIL_TEST)); + GR_GL(Enable(GR_GL_STENCIL_TEST)); #if GR_DEBUG if (!fStencilWrapOpsSupport) { GrAssert(settings->fFrontPassOp != kIncWrap_StencilOp); @@ -1441,13 +1524,13 @@ void GrGpuGL::flushStencil() { GrAssert(stencilBits || (GrStencilSettings::gDisabled == fCurrDrawState.fStencilSettings)); - GLuint clipStencilMask = 1 << (stencilBits - 1); - GLuint userStencilMask = clipStencilMask - 1; + GrGLuint clipStencilMask = 1 << (stencilBits - 1); + GrGLuint userStencilMask = clipStencilMask - 1; unsigned int frontRef = settings->fFrontFuncRef; unsigned int frontMask = settings->fFrontFuncMask; unsigned int frontWriteMask = settings->fFrontWriteMask; - GLenum frontFunc; + GrGLenum frontFunc; if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { @@ -1465,15 +1548,15 @@ void GrGpuGL::flushStencil() { frontWriteMask &= userStencilMask; } GrAssert(settings->fFrontFailOp >= 0 && - settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp)); + (unsigned) settings->fFrontFailOp < GR_ARRAY_COUNT(grToGLStencilOp)); GrAssert(settings->fFrontPassOp >= 0 && - settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp)); + (unsigned) settings->fFrontPassOp < GR_ARRAY_COUNT(grToGLStencilOp)); GrAssert(settings->fBackFailOp >= 0 && - settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp)); + (unsigned) settings->fBackFailOp < GR_ARRAY_COUNT(grToGLStencilOp)); GrAssert(settings->fBackPassOp >= 0 && - settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp)); + (unsigned) settings->fBackPassOp < GR_ARRAY_COUNT(grToGLStencilOp)); if (fTwoSidedStencilSupport) { - GLenum backFunc; + GrGLenum backFunc; unsigned int backRef = settings->fBackFuncRef; unsigned int backMask = settings->fBackFuncMask; @@ -1494,15 +1577,15 @@ void GrGpuGL::flushStencil() { backWriteMask &= userStencilMask; } - GR_GL(StencilFuncSeparate(GL_FRONT, frontFunc, frontRef, frontMask)); - GR_GL(StencilMaskSeparate(GL_FRONT, frontWriteMask)); - GR_GL(StencilFuncSeparate(GL_BACK, backFunc, backRef, backMask)); - GR_GL(StencilMaskSeparate(GL_BACK, backWriteMask)); - GR_GL(StencilOpSeparate(GL_FRONT, grToGLStencilOp[settings->fFrontFailOp], + GR_GL(StencilFuncSeparate(GR_GL_FRONT, frontFunc, frontRef, frontMask)); + GR_GL(StencilMaskSeparate(GR_GL_FRONT, frontWriteMask)); + GR_GL(StencilFuncSeparate(GR_GL_BACK, backFunc, backRef, backMask)); + GR_GL(StencilMaskSeparate(GR_GL_BACK, backWriteMask)); + GR_GL(StencilOpSeparate(GR_GL_FRONT, grToGLStencilOp[settings->fFrontFailOp], grToGLStencilOp[settings->fFrontPassOp], grToGLStencilOp[settings->fFrontPassOp])); - GR_GL(StencilOpSeparate(GL_BACK, grToGLStencilOp[settings->fBackFailOp], + GR_GL(StencilOpSeparate(GR_GL_BACK, grToGLStencilOp[settings->fBackFailOp], grToGLStencilOp[settings->fBackPassOp], grToGLStencilOp[settings->fBackPassOp])); } else { @@ -1518,6 +1601,101 @@ void GrGpuGL::flushStencil() { } } +bool GrGpuGL::useSmoothLines() { + // there is a conflict between using smooth lines and our use of + // premultiplied alpha. Smooth lines tweak the incoming alpha value + // but not in a premul-alpha way. So we only use them when our alpha + // is 0xff. + + // TODO: write a smarter line frag shader. + + return (kAntialias_StateBit & fCurrDrawState.fFlagBits) && + canDisableBlend(); +} + +void GrGpuGL::flushAAState(GrPrimitiveType type) { + if (GR_GL_SUPPORT_DESKTOP) { + // ES doesn't support toggling GL_MULTISAMPLE and doesn't have + // smooth lines. + + // we prefer smooth lines over multisampled lines + // msaa should be disabled if drawing smooth lines. + if (GrIsPrimTypeLines(type)) { + bool smooth = useSmoothLines(); + if (!fHWAAState.fSmoothLineEnabled && smooth) { + GR_GL(Enable(GR_GL_LINE_SMOOTH)); + fHWAAState.fSmoothLineEnabled = true; + } else if (fHWAAState.fSmoothLineEnabled && !smooth) { + GR_GL(Disable(GR_GL_LINE_SMOOTH)); + fHWAAState.fSmoothLineEnabled = false; + } + if (fCurrDrawState.fRenderTarget->isMultisampled() && + fHWAAState.fMSAAEnabled) { + GR_GL(Disable(GR_GL_MULTISAMPLE)); + fHWAAState.fMSAAEnabled = false; + } + } else if (fCurrDrawState.fRenderTarget->isMultisampled() && + !!(kAntialias_StateBit & fCurrDrawState.fFlagBits) != + fHWAAState.fMSAAEnabled) { + if (fHWAAState.fMSAAEnabled) { + GR_GL(Disable(GR_GL_MULTISAMPLE)); + fHWAAState.fMSAAEnabled = false; + } else { + GR_GL(Enable(GR_GL_MULTISAMPLE)); + fHWAAState.fMSAAEnabled = true; + } + } + } +} + +void GrGpuGL::flushBlend(GrPrimitiveType type) { + if (GrIsPrimTypeLines(type) && useSmoothLines()) { + if (fHWBlendDisabled) { + GR_GL(Enable(GR_GL_BLEND)); + fHWBlendDisabled = false; + } + if (kSA_BlendCoeff != fHWDrawState.fSrcBlend || + kISA_BlendCoeff != fHWDrawState.fDstBlend) { + GR_GL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff], + gXfermodeCoeff2Blend[kISA_BlendCoeff])); + fHWDrawState.fSrcBlend = kSA_BlendCoeff; + fHWDrawState.fDstBlend = kISA_BlendCoeff; + } + } else { + bool blendOff = canDisableBlend(); + if (fHWBlendDisabled != blendOff) { + if (blendOff) { + GR_GL(Disable(GR_GL_BLEND)); + } else { + GR_GL(Enable(GR_GL_BLEND)); + } + fHWBlendDisabled = blendOff; + } + if (!blendOff) { + if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend || + fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) { + GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend], + gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend])); + fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend; + fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend; + } + if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) || + BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) && + fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) { + + float c[] = { + GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f, + GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f, + GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f, + GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f + }; + GR_GL(BlendColor(c[0], c[1], c[2], c[3])); + fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant; + } + } + } +} + bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // GrGpu::setupClipAndFlushState should have already checked this @@ -1536,11 +1714,15 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // texture and now we're texuring from the rt it will still be // the last bound texture, but it needs resolving. So keep this // out of the "last != next" check. - resolveTextureRenderTarget(nextTexture); + GrGLRenderTarget* texRT = + static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget()); + if (NULL != texRT) { + resolveRenderTarget(texRT); + } if (fHWDrawState.fTextures[s] != nextTexture) { setTextureUnit(s); - GR_GL(BindTexture(GL_TEXTURE_2D, nextTexture->textureID())); + GR_GL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); #if GR_COLLECT_STATS ++fStats.fTextureChngCnt; #endif @@ -1553,32 +1735,32 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { nextTexture->getTexParams(); GrGLTexture::TexParams newTexParams; - newTexParams.fFilter = sampler.isFilter() ? GL_LINEAR : - GL_NEAREST; + newTexParams.fFilter = sampler.isFilter() ? GR_GL_LINEAR : + GR_GL_NEAREST; newTexParams.fWrapS = - GrGLTexture::gWrapMode2GLWrap[sampler.getWrapX()]; + GrGLTexture::WrapMode2GLWrap()[sampler.getWrapX()]; newTexParams.fWrapT = - GrGLTexture::gWrapMode2GLWrap[sampler.getWrapY()]; + GrGLTexture::WrapMode2GLWrap()[sampler.getWrapY()]; if (newTexParams.fFilter != oldTexParams.fFilter) { setTextureUnit(s); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_MAG_FILTER, newTexParams.fFilter)); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_MIN_FILTER, newTexParams.fFilter)); } if (newTexParams.fWrapS != oldTexParams.fWrapS) { setTextureUnit(s); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_S, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS)); } if (newTexParams.fWrapT != oldTexParams.fWrapT) { setTextureUnit(s); - GR_GL(TexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_WRAP_T, + GR_GL(TexParameteri(GR_GL_TEXTURE_2D, + GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT)); } nextTexture->setTexParams(newTexParams); @@ -1594,100 +1776,41 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { } flushRenderTarget(); - + flushAAState(type); + flushBlend(type); + if ((fCurrDrawState.fFlagBits & kDither_StateBit) != (fHWDrawState.fFlagBits & kDither_StateBit)) { if (fCurrDrawState.fFlagBits & kDither_StateBit) { - GR_GL(Enable(GL_DITHER)); + GR_GL(Enable(GR_GL_DITHER)); } else { - GR_GL(Disable(GL_DITHER)); + GR_GL(Disable(GR_GL_DITHER)); } } if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) != (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) { - GLenum mask; + GrGLenum mask; if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) { - mask = GL_FALSE; + mask = GR_GL_FALSE; } else { - mask = GL_TRUE; + mask = GR_GL_TRUE; } GR_GL(ColorMask(mask, mask, mask, mask)); } -#if GR_SUPPORT_GLDESKTOP - // ES doesn't support toggling GL_MULTISAMPLE and doesn't have - // smooth lines. - if (fDirtyFlags.fRenderTargetChanged || - (fCurrDrawState.fFlagBits & kAntialias_StateBit) != - (fHWDrawState.fFlagBits & kAntialias_StateBit)) { - GLint msaa = 0; - // only perform query if we know MSAA is supported. - // calling on non-MSAA target caused a crash in one environment, - // though I don't think it should. - if (fAASamples[kHigh_AALevel]) { - GR_GL_GetIntegerv(GL_SAMPLE_BUFFERS, &msaa); - } - if (fCurrDrawState.fFlagBits & kAntialias_StateBit) { - if (msaa) { - GR_GL(Enable(GL_MULTISAMPLE)); - } else { - GR_GL(Enable(GL_LINE_SMOOTH)); - } - } else { - if (msaa) { - GR_GL(Disable(GL_MULTISAMPLE)); - } - GR_GL(Disable(GL_LINE_SMOOTH)); - } - } -#endif - - bool blendOff = canDisableBlend(); - if (fHWBlendDisabled != blendOff) { - if (blendOff) { - GR_GL(Disable(GL_BLEND)); - } else { - GR_GL(Enable(GL_BLEND)); - } - fHWBlendDisabled = blendOff; - } - - if (!blendOff) { - if (fHWDrawState.fSrcBlend != fCurrDrawState.fSrcBlend || - fHWDrawState.fDstBlend != fCurrDrawState.fDstBlend) { - GR_GL(BlendFunc(gXfermodeCoeff2Blend[fCurrDrawState.fSrcBlend], - gXfermodeCoeff2Blend[fCurrDrawState.fDstBlend])); - fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend; - fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend; - } - if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) || - BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) && - fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) { - - float c[] = { - GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f - }; - GR_GL(BlendColor(c[0], c[1], c[2], c[3])); - fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant; - } - } - if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) { switch (fCurrDrawState.fDrawFace) { case kCCW_DrawFace: - glEnable(GL_CULL_FACE); - GR_GL(CullFace(GL_BACK)); + GR_GL(Enable(GR_GL_CULL_FACE)); + GR_GL(CullFace(GR_GL_BACK)); break; case kCW_DrawFace: - GR_GL(Enable(GL_CULL_FACE)); - GR_GL(CullFace(GL_FRONT)); + GR_GL(Enable(GR_GL_CULL_FACE)); + GR_GL(CullFace(GR_GL_FRONT)); break; case kBoth_DrawFace: - GR_GL(Disable(GL_CULL_FACE)); + GR_GL(Disable(GR_GL_CULL_FACE)); break; default: GrCrash("Unknown draw face."); @@ -1721,9 +1844,6 @@ void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) { } void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) { - GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc && - buffer == fGeometrySrc.fVertexBuffer)); - if (fHWGeometryState.fVertexBuffer == buffer) { // deleting bound buffer does implied bind to 0 fHWGeometryState.fVertexBuffer = NULL; @@ -1736,9 +1856,6 @@ void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) { } void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { - GrAssert(!(kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc && - buffer == fGeometrySrc.fIndexBuffer)); - if (fHWGeometryState.fIndexBuffer == buffer) { // deleting bound buffer does implied bind to 0 fHWGeometryState.fIndexBuffer = NULL; @@ -1767,46 +1884,46 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { } } -bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config, - GLenum* internalFormat, - GLenum* format, - GLenum* type) { +bool GrGpuGL::canBeTexture(GrPixelConfig config, + GrGLenum* internalFormat, + GrGLenum* format, + GrGLenum* type) { switch (config) { - case GrTexture::kRGBA_8888_PixelConfig: - case GrTexture::kRGBX_8888_PixelConfig: // todo: can we tell it our X? + case kRGBA_8888_GrPixelConfig: + case kRGBX_8888_GrPixelConfig: // todo: can we tell it our X? *format = GR_GL_32BPP_COLOR_FORMAT; -#if GR_SUPPORT_GLES - // according to GL_EXT_texture_format_BGRA8888 the *internal* - // format for a BGRA is BGRA not RGBA (as on desktop) - *internalFormat = GR_GL_32BPP_COLOR_FORMAT; -#else - *internalFormat = GL_RGBA; -#endif - *type = GL_UNSIGNED_BYTE; + if (GR_GL_SUPPORT_ES) { + // according to GL_EXT_texture_format_BGRA8888 the *internal* + // format for a BGRA is BGRA not RGBA (as on desktop) + *internalFormat = GR_GL_32BPP_COLOR_FORMAT; + } else { + *internalFormat = GR_GL_RGBA; + } + *type = GR_GL_UNSIGNED_BYTE; break; - case GrTexture::kRGB_565_PixelConfig: - *format = GL_RGB; - *internalFormat = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; + case kRGB_565_GrPixelConfig: + *format = GR_GL_RGB; + *internalFormat = GR_GL_RGB; + *type = GR_GL_UNSIGNED_SHORT_5_6_5; break; - case GrTexture::kRGBA_4444_PixelConfig: - *format = GL_RGBA; - *internalFormat = GL_RGBA; - *type = GL_UNSIGNED_SHORT_4_4_4_4; + case kRGBA_4444_GrPixelConfig: + *format = GR_GL_RGBA; + *internalFormat = GR_GL_RGBA; + *type = GR_GL_UNSIGNED_SHORT_4_4_4_4; break; - case GrTexture::kIndex_8_PixelConfig: + case kIndex_8_GrPixelConfig: if (this->supports8BitPalette()) { - *format = GR_PALETTE8_RGBA8; - *internalFormat = GR_PALETTE8_RGBA8; - *type = GL_UNSIGNED_BYTE; // unused I think + *format = GR_GL_PALETTE8_RGBA8; + *internalFormat = GR_GL_PALETTE8_RGBA8; + *type = GR_GL_UNSIGNED_BYTE; // unused I think } else { return false; } break; - case GrTexture::kAlpha_8_PixelConfig: - *format = GL_ALPHA; - *internalFormat = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; + case kAlpha_8_GrPixelConfig: + *format = GR_GL_ALPHA; + *internalFormat = GR_GL_ALPHA; + *type = GR_GL_UNSIGNED_BYTE; break; default: return false; @@ -1817,14 +1934,14 @@ bool GrGpuGL::canBeTexture(GrTexture::PixelConfig config, void GrGpuGL::setTextureUnit(int unit) { GrAssert(unit >= 0 && unit < kNumStages); if (fActiveTextureUnitIdx != unit) { - GR_GL(ActiveTexture(GL_TEXTURE0 + unit)); + GR_GL(ActiveTexture(GR_GL_TEXTURE0 + unit)); fActiveTextureUnitIdx = unit; } } void GrGpuGL::setSpareTextureUnit() { - if (fActiveTextureUnitIdx != (GL_TEXTURE0 + SPARE_TEX_UNIT)) { - GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT)); + if (fActiveTextureUnitIdx != (GR_GL_TEXTURE0 + SPARE_TEX_UNIT)) { + GR_GL(ActiveTexture(GR_GL_TEXTURE0 + SPARE_TEX_UNIT)); fActiveTextureUnitIdx = SPARE_TEX_UNIT; } } @@ -1835,24 +1952,24 @@ void GrGpuGL::setSpareTextureUnit() { RenderBufferStorage* has to be a specific format (not a base format like GL_RGBA). */ -bool GrGpuGL::fboInternalFormat(GrTexture::PixelConfig config, GLenum* format) { +bool GrGpuGL::fboInternalFormat(GrPixelConfig config, GrGLenum* format) { switch (config) { - case GrTexture::kRGBA_8888_PixelConfig: - case GrTexture::kRGBX_8888_PixelConfig: + case kRGBA_8888_GrPixelConfig: + case kRGBX_8888_GrPixelConfig: if (fRGBA8Renderbuffer) { - *format = GR_RGBA8; + *format = GR_GL_RGBA8; return true; } else { return false; } -#if GR_SUPPORT_GLES // ES2 supports 565. ES1 supports it with FBO extension - // desktop GL has no such internal format - case GrTexture::kRGB_565_PixelConfig: - *format = GR_RGB565; + case kRGB_565_GrPixelConfig: + GrAssert(GR_GL_SUPPORT_ES); // ES2 supports 565. ES1 supports it + // with FBO extension desktop GL has + // no such internal format + *format = GR_GL_RGB565; return true; -#endif - case GrTexture::kRGBA_4444_PixelConfig: - *format = GL_RGBA4; + case kRGBA_4444_GrPixelConfig: + *format = GR_GL_RGBA4; return true; default: return false; @@ -1889,7 +2006,7 @@ void GrGpuGL::setBuffers(bool indexed, GrAssert(NULL != vbuf); GrAssert(!vbuf->isLocked()); if (fHWGeometryState.fVertexBuffer != vbuf) { - GR_GL(BindBuffer(GL_ARRAY_BUFFER, vbuf->bufferID())); + GR_GL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID())); fHWGeometryState.fArrayPtrsDirty = true; fHWGeometryState.fVertexBuffer = vbuf; } @@ -1917,7 +2034,7 @@ void GrGpuGL::setBuffers(bool indexed, GrAssert(NULL != ibuf); GrAssert(!ibuf->isLocked()); if (fHWGeometryState.fIndexBuffer != ibuf) { - GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID())); + GR_GL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID())); fHWGeometryState.fIndexBuffer = ibuf; } } diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h index ea0c081..eaeec5e 100644 --- a/gpu/src/GrGpuGL.h +++ b/gpu/src/GrGpuGL.h @@ -19,7 +19,6 @@ #define GrGpuGL_DEFINED #include "GrGpu.h" -#include "GrGLConfig.h" #include "GrGLIRect.h" #include "GrGLTexture.h" @@ -40,6 +39,11 @@ protected: bool fArrayPtrsDirty; } fHWGeometryState; + struct AAState { + bool fMSAAEnabled; + bool fSmoothLineEnabled; + } fHWAAState; + DrState fHWDrawState; bool fHWStencilClip; @@ -68,34 +72,35 @@ protected: // overrides from GrGpu virtual void resetContext(); - virtual GrTexture* createTextureHelper(const TextureDesc& desc, - const void* srcData, - size_t rowBytes); - virtual GrVertexBuffer* createVertexBufferHelper(uint32_t size, - bool dynamic); - virtual GrIndexBuffer* createIndexBufferHelper(uint32_t size, - bool dynamic); - - virtual GrRenderTarget* createPlatformRenderTargetHelper( + virtual GrTexture* onCreateTexture(const TextureDesc& desc, + const void* srcData, + size_t rowBytes); + virtual GrVertexBuffer* onCreateVertexBuffer(uint32_t size, + bool dynamic); + virtual GrIndexBuffer* onCreateIndexBuffer(uint32_t size, + bool dynamic); + virtual GrResource* onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc); + virtual GrRenderTarget* onCreatePlatformRenderTarget( intptr_t platformRenderTarget, int stencilBits, + bool isMultisampled, int width, int height); + virtual GrRenderTarget* onCreateRenderTargetFrom3DApiState(); - virtual GrRenderTarget* createRenderTargetFrom3DApiStateHelper(); - - virtual void eraseColorHelper(GrColor color); + virtual void onEraseColor(GrColor color); - virtual void forceRenderTargetFlushHelper(); + virtual void onForceRenderTargetFlush(); - virtual bool readPixelsHelper(int left, int top, int width, int height, - GrTexture::PixelConfig, void* buffer); + virtual bool onReadPixels(GrRenderTarget* target, + int left, int top, int width, int height, + GrPixelConfig, void* buffer); - virtual void drawIndexedHelper(GrPrimitiveType type, + virtual void onDrawIndexed(GrPrimitiveType type, uint32_t startVertex, uint32_t startIndex, uint32_t vertexCount, uint32_t indexCount); - virtual void drawNonIndexedHelper(GrPrimitiveType type, + virtual void onDrawNonIndexed(GrPrimitiveType type, uint32_t vertexCount, uint32_t numVertices); virtual void flushScissor(const GrIRect* rect); @@ -146,15 +151,21 @@ private: void setSpareTextureUnit(); + bool useSmoothLines(); + void flushRenderTarget(); void flushStencil(); - void resolveTextureRenderTarget(GrGLTexture* texture); + void flushAAState(GrPrimitiveType type); + void flushBlend(GrPrimitiveType type); + + void resolveRenderTarget(GrGLRenderTarget* texture); + + bool canBeTexture(GrPixelConfig config, + GrGLenum* internalFormat, + GrGLenum* format, + GrGLenum* type); - bool canBeTexture(GrTexture::PixelConfig config, - GLenum* internalFormat, - GLenum* format, - GLenum* type); - bool fboInternalFormat(GrTexture::PixelConfig config, GLenum* format); + bool fboInternalFormat(GrPixelConfig config, GrGLenum* format); friend class GrGLVertexBuffer; friend class GrGLIndexBuffer; @@ -163,12 +174,12 @@ private: bool fHWBlendDisabled; - GLuint fAASamples[4]; + GrGLuint fAASamples[4]; enum { - kNone_MSFBO = 0, - kDesktop_MSFBO, - kApple_MSFBO, - kIMG_MSFBO + kNone_MSFBO = 0, //<! no support for MSAA FBOs + kDesktopARB_MSFBO,//<! GL3.0-style MSAA FBO (GL_ARB_framebuffer_object) + kDesktopEXT_MSFBO,//<! earlier GL_EXT_framebuffer* extensions + kAppleES_MSFBO, //<! GL_APPLE_framebuffer_multisample ES extension } fMSFBOType; // Do we have stencil wrap ops. diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp index afd9bb6..446949f 100644 --- a/gpu/src/GrGpuGLFixed.cpp +++ b/gpu/src/GrGpuGLFixed.cpp @@ -17,15 +17,13 @@ #include "GrGLConfig.h" -#if GR_SUPPORT_GLES1 || GR_SUPPORT_GLDESKTOP - #include "GrGpuGLFixed.h" #include "GrGpuVertex.h" #define SKIP_CACHE_CHECK true struct GrGpuMatrix { - GLfloat fMat[16]; + GrGLfloat fMat[16]; void reset() { Gr_bzero(fMat, sizeof(fMat)); @@ -51,8 +49,8 @@ struct GrGpuMatrix { }; // these must match the order in the corresponding enum in GrGpu.h -static const GLenum gMatrixMode2Enum[] = { - GL_MODELVIEW, GL_TEXTURE +static const GrGLenum gMatrixMode2Enum[] = { + GR_GL_MODELVIEW, GR_GL_TEXTURE }; /////////////////////////////////////////////////////////////////////////////// @@ -66,22 +64,22 @@ GrGpuGLFixed::~GrGpuGLFixed() { void GrGpuGLFixed::resetContext() { INHERITED::resetContext(); - GR_GL(Disable(GL_TEXTURE_2D)); + GR_GL(Disable(GR_GL_TEXTURE_2D)); for (int s = 0; s < kNumStages; ++s) { setTextureUnit(s); - GR_GL(EnableClientState(GL_VERTEX_ARRAY)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0+s)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR)); - - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0+s)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS)); - GR_GL(TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA)); + GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_TEXTURE_ENV_MODE, GR_GL_COMBINE)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_RGB, GR_GL_MODULATE)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_RGB, GR_GL_TEXTURE0+s)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_RGB, GR_GL_PREVIOUS)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_RGB, GR_GL_SRC_COLOR)); + + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_ALPHA, GR_GL_MODULATE)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_ALPHA, GR_GL_TEXTURE0+s)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND0_ALPHA, GR_GL_SRC_ALPHA)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_ALPHA, GR_GL_PREVIOUS)); + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_ALPHA, GR_GL_SRC_ALPHA)); // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending // upon whether we have a (premultiplied) RGBA texture or just an ALPHA @@ -92,10 +90,10 @@ void GrGpuGLFixed::resetContext() { fHWGeometryState.fVertexLayout = 0; fHWGeometryState.fVertexOffset = ~0; - GR_GL(EnableClientState(GL_VERTEX_ARRAY)); - GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY)); - GR_GL(ShadeModel(GL_FLAT)); - GR_GL(DisableClientState(GL_COLOR_ARRAY)); + GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); + GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); + GR_GL(ShadeModel(GR_GL_FLAT)); + GR_GL(DisableClientState(GR_GL_COLOR_ARRAY)); GR_GL(PointSize(1.f)); @@ -120,7 +118,7 @@ void GrGpuGLFixed::flushProjectionMatrix() { mat[12] = -1.f; mat[13] = 1.f; - GR_GL(MatrixMode(GL_PROJECTION)); + GR_GL(MatrixMode(GR_GL_PROJECTION)); GR_GL(LoadMatrixf(mat)); } @@ -137,13 +135,13 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { } } -#if GR_SUPPORT_GLES1 - if (BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) || - BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) { - uimpl("ES1 doesn't support blend constant"); - return false; + if (GR_GL_SUPPORT_ES1) { + if (BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) || + BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) { + unimpl("ES1 doesn't support blend constant"); + return false; + } } -#endif if (!flushGLStateCommon(type)) { return false; @@ -158,9 +156,9 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { if (usingTextures[s] != wasUsingTexture) { setTextureUnit(s); if (usingTextures[s]) { - GR_GL(Enable(GL_TEXTURE_2D)); + GR_GL(Enable(GR_GL_TEXTURE_2D)); } else { - GR_GL(Disable(GL_TEXTURE_2D)); + GR_GL(Disable(GR_GL_TEXTURE_2D)); } } } @@ -171,11 +169,11 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { if (vertColor != prevVertColor) { if (vertColor) { - GR_GL(ShadeModel(GL_SMOOTH)); + GR_GL(ShadeModel(GR_GL_SMOOTH)); // invalidate the immediate mode color fHWDrawState.fColor = GrColor_ILLEGAL; } else { - GR_GL(ShadeModel(GL_FLAT)); + GR_GL(ShadeModel(GR_GL_FLAT)); } } @@ -194,16 +192,16 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { GrGLTexture* texture = (GrGLTexture*)fCurrDrawState.fTextures[s]; if (NULL != texture) { TextureEnvRGBOperands nextRGBOperand0 = - (texture->config() == GrTexture::kAlpha_8_PixelConfig) ? + (GrPixelConfigIsAlphaOnly(texture->config())) ? kAlpha_TextureEnvRGBOperand : kColor_TextureEnvRGBOperand; if (fHWRGBOperand0[s] != nextRGBOperand0) { setTextureUnit(s); - GR_GL(TexEnvi(GL_TEXTURE_ENV, - GL_OPERAND0_RGB, + GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, + GR_GL_OPERAND0_RGB, (nextRGBOperand0==kAlpha_TextureEnvRGBOperand) ? - GL_SRC_ALPHA : - GL_SRC_COLOR)); + GR_GL_SRC_ALPHA : + GR_GL_SRC_COLOR)); fHWRGBOperand0[s] = nextRGBOperand0; } @@ -218,7 +216,7 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { GrGpuMatrix glm; glm.set(texMat); setTextureUnit(s); - GR_GL(MatrixMode(GL_TEXTURE)); + GR_GL(MatrixMode(GR_GL_TEXTURE)); GR_GL(LoadMatrixf(glm.fMat)); recordHWSamplerMatrix(s, getSamplerMatrix(s)); } @@ -232,7 +230,7 @@ bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) { if (fHWDrawState.fViewMatrix != fCurrDrawState.fViewMatrix) { GrGpuMatrix glm; glm.set(fCurrDrawState.fViewMatrix); - GR_GL(MatrixMode(GL_MODELVIEW)); + GR_GL(MatrixMode(GR_GL_MODELVIEW)); GR_GL(LoadMatrixf(glm.fMat)); fHWDrawState.fViewMatrix = fCurrDrawState.fViewMatrix; @@ -249,14 +247,14 @@ void GrGpuGLFixed::setupGeometry(int* startVertex, int newColorOffset; int newTexCoordOffsets[kNumStages]; - GLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout, - newTexCoordOffsets, - &newColorOffset); + GrGLsizei newStride = VertexSizeAndOffsetsByStage(fGeometrySrc.fVertexLayout, + newTexCoordOffsets, + &newColorOffset); int oldColorOffset; int oldTexCoordOffsets[kNumStages]; - GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout, - oldTexCoordOffsets, - &oldColorOffset); + GrGLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout, + oldTexCoordOffsets, + &oldColorOffset); bool indexed = NULL != startIndex; @@ -264,7 +262,7 @@ void GrGpuGLFixed::setupGeometry(int* startVertex, int extraIndexOffset; setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); - GLenum scalarType; + GrGLenum scalarType; if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { scalarType = GrGLTextType; } else { @@ -291,7 +289,7 @@ void GrGpuGLFixed::setupGeometry(int* startVertex, fGeometrySrc.fVertexLayout))); if (posAndTexChange) { - GR_GL(VertexPointer(2, scalarType, newStride, (GLvoid*)vertexOffset)); + GR_GL(VertexPointer(2, scalarType, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } @@ -299,37 +297,34 @@ void GrGpuGLFixed::setupGeometry(int* startVertex, // need to enable array if tex coord offset is 0 // (using positions as coords) if (newTexCoordOffsets[s] >= 0) { - GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[s]); + GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[s]); if (oldTexCoordOffsets[s] < 0) { - GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); - GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY)); + GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); + GR_GL(EnableClientState(GR_GL_TEXTURE_COORD_ARRAY)); GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset)); } else if (posAndTexChange || newTexCoordOffsets[s] != oldTexCoordOffsets[s]) { - GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); + GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[s] >= 0) { - GR_GL(ClientActiveTexture(GL_TEXTURE0+s)); - GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY)); + GR_GL(ClientActiveTexture(GR_GL_TEXTURE0+s)); + GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); } } if (newColorOffset > 0) { - GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset); + GrGLvoid* colorOffset = (GrGLvoid*)(vertexOffset + newColorOffset); if (oldColorOffset <= 0) { - GR_GL(EnableClientState(GL_COLOR_ARRAY)); - GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset)); + GR_GL(EnableClientState(GR_GL_COLOR_ARRAY)); + GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { - GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset)); + GR_GL(ColorPointer(4, GR_GL_UNSIGNED_BYTE, newStride, colorOffset)); } } else if (oldColorOffset > 0) { - GR_GL(DisableClientState(GL_COLOR_ARRAY)); + GR_GL(DisableClientState(GR_GL_COLOR_ARRAY)); } fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; fHWGeometryState.fArrayPtrsDirty = false; } - -#endif - diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp new file mode 100644 index 0000000..b34fc33 --- /dev/null +++ b/gpu/src/GrGpuGLShaders.cpp @@ -0,0 +1,530 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrBinHashKey.h" +#include "GrGLEffect.h" +#include "GrGLProgram.h" +#include "GrGpuGLShaders.h" +#include "GrGpuVertex.h" +#include "GrMemory.h" +#include "GrNoncopyable.h" +#include "GrStringBuilder.h" + +#define ATTRIBUTE_MATRIX 0 +#define PRINT_SHADERS 0 +#define SKIP_CACHE_CHECK true +#define GR_UINT32_MAX static_cast<uint32_t>(-1) + +#if ATTRIBUTE_MATRIX +#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords) +#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X)) +#define BOGUS_MATRIX_UNI_LOCATION 1000 +#endif + +#include "GrTHashCache.h" + +class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable { +private: + class Entry; + +#if GR_DEBUG + typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug +#else + typedef GrBinHashKey<Entry, 32> ProgramHashKey; +#endif + + class Entry : public ::GrNoncopyable { + public: + Entry() {} + private: + void copyAndTakeOwnership(Entry& entry) { + fProgramData.copyAndTakeOwnership(entry.fProgramData); + fKey.copyAndTakeOwnership(entry.fKey); // ownership transfer + fLRUStamp = entry.fLRUStamp; + } + + public: + int compare(const ProgramHashKey& key) const { return fKey.compare(key); } + + public: + GrGLProgram::CachedData fProgramData; + ProgramHashKey fKey; + unsigned int fLRUStamp; + }; + + GrTHashTable<Entry, ProgramHashKey, 8> fHashCache; + + enum { + kMaxEntries = 32 + }; + Entry fEntries[kMaxEntries]; + int fCount; + unsigned int fCurrLRUStamp; + +public: + ProgramCache() + : fCount(0) + , fCurrLRUStamp(0) { + } + + ~ProgramCache() { + for (int i = 0; i < fCount; ++i) { + GrGpuGLShaders::DeleteProgram(&fEntries[i].fProgramData); + } + } + + void abandon() { + fCount = 0; + } + + void invalidateViewMatrices() { + for (int i = 0; i < fCount; ++i) { + // set to illegal matrix + fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix(); + } + } + + GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc, + const GrDrawTarget* target) { + ProgramHashKey key; + while (key.doPass()) { + desc.buildKey(key); + } + Entry* entry = fHashCache.find(key); + if (NULL == entry) { + if (fCount < kMaxEntries) { + entry = fEntries + fCount; + ++fCount; + } else { + GrAssert(kMaxEntries == fCount); + entry = fEntries; + for (int i = 1; i < kMaxEntries; ++i) { + if (fEntries[i].fLRUStamp < entry->fLRUStamp) { + entry = fEntries + i; + } + } + fHashCache.remove(entry->fKey, entry); + GrGpuGLShaders::DeleteProgram(&entry->fProgramData); + } + entry->fKey.copyAndTakeOwnership(key); + desc.genProgram(&entry->fProgramData, target); + fHashCache.insert(entry->fKey, entry); + } + + entry->fLRUStamp = fCurrLRUStamp; + if (GR_UINT32_MAX == fCurrLRUStamp) { + // wrap around! just trash our LRU, one time hit. + for (int i = 0; i < fCount; ++i) { + fEntries[i].fLRUStamp = 0; + } + } + ++fCurrLRUStamp; + return &entry->fProgramData; + } +}; + +void GrGpuGLShaders::DeleteProgram(GrGLProgram::CachedData* programData) { + GR_GL(DeleteShader(programData->fVShaderID)); + GR_GL(DeleteShader(programData->fFShaderID)); + GR_GL(DeleteProgram(programData->fProgramID)); + GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));) +} + + +GrGpuGLShaders::GrGpuGLShaders() { + + resetContext(); + + fProgramData = NULL; + fProgramCache = new ProgramCache(); +} + +GrGpuGLShaders::~GrGpuGLShaders() { + delete fProgramCache; +} + +const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { +#if ATTRIBUTE_MATRIX + return fHWDrawState.fSamplerStates[stage].getMatrix(); +#else + GrAssert(fProgramData); + return fProgramData->fTextureMatrices[stage]; +#endif +} + +void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { +#if ATTRIBUTE_MATRIX + fHWDrawState.fSamplerStates[stage].setMatrix(matrix); +#else + GrAssert(fProgramData); + fProgramData->fTextureMatrices[stage] = matrix; +#endif +} + +void GrGpuGLShaders::resetContext() { + INHERITED::resetContext(); + + fHWGeometryState.fVertexLayout = 0; + fHWGeometryState.fVertexOffset = ~0; + GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION)); + for (int t = 0; t < kMaxTexCoords; ++t) { + GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t))); + } + GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION)); + + fHWProgramID = 0; +} + +void GrGpuGLShaders::flushViewMatrix() { + GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrMatrix m ( + GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1, + 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1, + 0, 0, GrMatrix::I()[8]); + m.setConcat(m, fCurrDrawState.fViewMatrix); + + // ES doesn't allow you to pass true to the transpose param, + // so do our own transpose + GrScalar mt[] = { + m[GrMatrix::kScaleX], + m[GrMatrix::kSkewY], + m[GrMatrix::kPersp0], + m[GrMatrix::kSkewX], + m[GrMatrix::kScaleY], + m[GrMatrix::kPersp1], + m[GrMatrix::kTransX], + m[GrMatrix::kTransY], + m[GrMatrix::kPersp2] + }; +#if ATTRIBUTE_MATRIX + GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0)); + GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3)); + GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6)); +#else + GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,1,false,mt)); +#endif +} + +void GrGpuGLShaders::flushTextureMatrix(int stage) { + GrAssert(NULL != fCurrDrawState.fTextures[stage]); + + GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[stage]; + + GrMatrix m = getSamplerMatrix(stage); + GrSamplerState::SampleMode mode = + fCurrDrawState.fSamplerStates[0].getSampleMode(); + AdjustTextureMatrix(texture, mode, &m); + + // ES doesn't allow you to pass true to the transpose param, + // so do our own transpose + GrScalar mt[] = { + m[GrMatrix::kScaleX], + m[GrMatrix::kSkewY], + m[GrMatrix::kPersp0], + m[GrMatrix::kSkewX], + m[GrMatrix::kScaleY], + m[GrMatrix::kPersp1], + m[GrMatrix::kTransX], + m[GrMatrix::kTransY], + m[GrMatrix::kPersp2] + }; +#if ATTRIBUTE_MATRIX + GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0)); + GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3)); + GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6)); +#else + GR_GL(UniformMatrix3fv(fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni, + 1, false, mt)); +#endif +} + +void GrGpuGLShaders::flushRadial2(int stage) { + + const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[stage]; + + GrScalar centerX1 = sampler.getRadial2CenterX1(); + GrScalar radius0 = sampler.getRadial2Radius0(); + + GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1; + + float unis[6] = { + GrScalarToFloat(a), + 1 / (2.f * unis[0]), + GrScalarToFloat(centerX1), + GrScalarToFloat(radius0), + GrScalarToFloat(GrMul(radius0, radius0)), + sampler.isRadial2PosRoot() ? 1.f : -1.f + }; + GR_GL(Uniform1fv(fProgramData->fUniLocations.fStages[stage].fRadial2Uni, + 6, + unis)); +} + +bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { + if (!flushGLStateCommon(type)) { + return false; + } + + if (fDirtyFlags.fRenderTargetChanged) { + // our coords are in pixel space and the GL matrices map to NDC + // so if the viewport changed, our matrix is now wrong. +#if ATTRIBUTE_MATRIX + fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix(); +#else + // we assume all shader matrices may be wrong after viewport changes + fProgramCache->invalidateViewMatrices(); +#endif + } + + if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) { + // invalidate the immediate mode color + fHWDrawState.fColor = GrColor_ILLEGAL; + } else { + if (fHWDrawState.fColor != fCurrDrawState.fColor) { + // OpenGL ES only supports the float varities of glVertexAttrib + float c[] = { + GrColorUnpackR(fCurrDrawState.fColor) / 255.f, + GrColorUnpackG(fCurrDrawState.fColor) / 255.f, + GrColorUnpackB(fCurrDrawState.fColor) / 255.f, + GrColorUnpackA(fCurrDrawState.fColor) / 255.f + }; + GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c)); + fHWDrawState.fColor = fCurrDrawState.fColor; + } + } + + buildProgram(type); + fProgramData = fProgramCache->getProgramData(fCurrentProgram, this); + + if (fHWProgramID != fProgramData->fProgramID) { + GR_GL(UseProgram(fProgramData->fProgramID)); + fHWProgramID = fProgramData->fProgramID; + } + + if (!fCurrentProgram.doGLSetup(type, fProgramData)) { + return false; + } + +#if ATTRIBUTE_MATRIX + GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix; +#else + GrMatrix& currViewMatrix = fProgramData->fViewMatrix; +#endif + + if (currViewMatrix != fCurrDrawState.fViewMatrix) { + flushViewMatrix(); + currViewMatrix = fCurrDrawState.fViewMatrix; + } + + for (int s = 0; s < kNumStages; ++s) { + GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + if (NULL != texture) { + if (-1 != fProgramData->fUniLocations.fStages[s].fTextureMatrixUni && + (((1 << s) & fDirtyFlags.fTextureChangedMask) || + getHWSamplerMatrix(s) != getSamplerMatrix(s))) { + flushTextureMatrix(s); + recordHWSamplerMatrix(s, getSamplerMatrix(s)); + } + } + + const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + if (-1 != fProgramData->fUniLocations.fStages[s].fRadial2Uni && + (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || + fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || + fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) { + + flushRadial2(s); + + fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1(); + fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0(); + fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot(); + } + } + resetDirtyFlags(); + return true; +} + +void GrGpuGLShaders::postDraw() { + fCurrentProgram.doGLPost(); +} + +void GrGpuGLShaders::setupGeometry(int* startVertex, + int* startIndex, + int vertexCount, + int indexCount) { + + int newColorOffset; + int newTexCoordOffsets[kMaxTexCoords]; + + GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout, + newTexCoordOffsets, + &newColorOffset); + int oldColorOffset; + int oldTexCoordOffsets[kMaxTexCoords]; + GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, + oldTexCoordOffsets, + &oldColorOffset); + bool indexed = NULL != startIndex; + + int extraVertexOffset; + int extraIndexOffset; + setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); + + GrGLenum scalarType; + bool texCoordNorm; + if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { + scalarType = GrGLTextType; + texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; + } else { + scalarType = GrGLType; + texCoordNorm = false; + } + + size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; + *startVertex = 0; + if (indexed) { + *startIndex += extraIndexOffset; + } + + // all the Pointers must be set if any of these are true + bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || + vertexOffset != fHWGeometryState.fVertexOffset || + newStride != oldStride; + + // position and tex coord offsets change if above conditions are true + // or the type/normalization changed based on text vs nontext type coords. + bool posAndTexChange = allOffsetsChange || + (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && + (kTextFormat_VertexLayoutBit & + (fHWGeometryState.fVertexLayout ^ + fGeometrySrc.fVertexLayout))); + + if (posAndTexChange) { + GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType, + false, newStride, (GrGLvoid*)vertexOffset)); + fHWGeometryState.fVertexOffset = vertexOffset; + } + + for (int t = 0; t < kMaxTexCoords; ++t) { + if (newTexCoordOffsets[t] > 0) { + GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); + if (oldTexCoordOffsets[t] <= 0) { + GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t))); + GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType, + texCoordNorm, newStride, texCoordOffset)); + } else if (posAndTexChange || + newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { + GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType, + texCoordNorm, newStride, texCoordOffset)); + } + } else if (oldTexCoordOffsets[t] > 0) { + GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t))); + } + } + + if (newColorOffset > 0) { + GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); + if (oldColorOffset <= 0) { + GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION)); + GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, + GR_GL_UNSIGNED_BYTE, + true, newStride, colorOffset)); + } else if (allOffsetsChange || newColorOffset != oldColorOffset) { + GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, + GR_GL_UNSIGNED_BYTE, + true, newStride, colorOffset)); + } + } else if (oldColorOffset > 0) { + GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION)); + } + + fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; + fHWGeometryState.fArrayPtrsDirty = false; +} + +void GrGpuGLShaders::buildProgram(GrPrimitiveType type) { + // Must initialize all fields or cache will have false negatives! + fCurrentProgram.fProgramDesc.fVertexLayout = fGeometrySrc.fVertexLayout; + + fCurrentProgram.fProgramDesc.fOptFlags = 0; + if (kPoints_PrimitiveType != type) { + fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kNotPoints_OptFlagBit; + } +#if GR_AGGRESSIVE_SHADER_OPTS + if (!(fCurrentProgram.fProgramDesc.fVertexLayout & kColor_VertexLayoutBit) && + (0xffffffff == fCurrDrawState.fColor)) { + fCurrentProgram.fProgramDesc.fOptFlags |= GrGLProgram::ProgramDesc::kVertexColorAllOnes_OptFlagBit; + } +#endif + + for (int s = 0; s < kNumStages; ++s) { + GrGLProgram::ProgramDesc::StageDesc& stage = fCurrentProgram.fProgramDesc.fStages[s]; + + stage.fEnabled = VertexUsesStage(s, fGeometrySrc.fVertexLayout); + + if (stage.fEnabled) { + GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrAssert(NULL != texture); + // we matrix to invert when orientation is TopDown, so make sure + // we aren't in that case before flagging as identity. + if (TextureMatrixIsIdentity(texture, fCurrDrawState.fSamplerStates[s])) { + stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kIdentityMatrix_OptFlagBit; + } else if (!getSamplerMatrix(s).hasPerspective()) { + stage.fOptFlags = GrGLProgram::ProgramDesc::StageDesc::kNoPerspective_OptFlagBit; + } else { + stage.fOptFlags = 0; + } + switch (fCurrDrawState.fSamplerStates[s].getSampleMode()) { + case GrSamplerState::kNormal_SampleMode: + stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kIdentity_CoordMapping; + break; + case GrSamplerState::kRadial_SampleMode: + stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadialGradient_CoordMapping; + break; + case GrSamplerState::kRadial2_SampleMode: + stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kRadial2Gradient_CoordMapping; + break; + case GrSamplerState::kSweep_SampleMode: + stage.fCoordMapping = GrGLProgram::ProgramDesc::StageDesc::kSweepGradient_CoordMapping; + break; + default: + GrAssert(!"Unexpected sample mode!"); + break; + } + + if (GrPixelConfigIsAlphaOnly(texture->config())) { + stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kAlpha_Modulation; + } else { + stage.fModulation = GrGLProgram::ProgramDesc::StageDesc::kColor_Modulation; + } + + if (fCurrDrawState.fEffects[s]) { + fCurrentProgram.fStageEffects[s] = GrGLEffect::Create(fCurrDrawState.fEffects[s]); + } else { + delete fCurrentProgram.fStageEffects[s]; + fCurrentProgram.fStageEffects[s] = NULL; + } + } else { + stage.fOptFlags = 0; + stage.fCoordMapping = (GrGLProgram::ProgramDesc::StageDesc::CoordMapping)0; + stage.fModulation = (GrGLProgram::ProgramDesc::StageDesc::Modulation)0; + fCurrentProgram.fStageEffects[s] = NULL; + } + } +} + + + diff --git a/gpu/src/GrGpuGLShaders.h b/gpu/src/GrGpuGLShaders.h new file mode 100644 index 0000000..ee29533 --- /dev/null +++ b/gpu/src/GrGpuGLShaders.h @@ -0,0 +1,75 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef GrGpuGLShaders_DEFINED +#define GrGpuGLShaders_DEFINED + +#include "GrGpuGL.h" +#include "GrGLProgram.h" + +class GrGpuGLProgram; + +// Programmable OpenGL or OpenGL ES 2.0 +class GrGpuGLShaders : public GrGpuGL { +public: + GrGpuGLShaders(); + virtual ~GrGpuGLShaders(); + + virtual void resetContext(); + +protected: + // overrides from GrGpu + virtual bool flushGraphicsState(GrPrimitiveType type); + virtual void setupGeometry(int* startVertex, + int* startIndex, + int vertexCount, + int indexCount); + virtual void postDraw(); + +private: + + class ProgramCache; + + // Helpers to make code more readable + const GrMatrix& getHWSamplerMatrix(int stage); + void recordHWSamplerMatrix(int stage, const GrMatrix& matrix); + + // sets the texture matrix uniform for currently bound program + void flushTextureMatrix(int stage); + + // sets the MVP matrix uniform for currently bound program + void flushViewMatrix(); + + // flushes the parameters to two point radial gradient + void flushRadial2(int stage); + + static void DeleteProgram(GrGLProgram::CachedData* programData); + + void ProgramUnitTest(); + + void buildProgram(GrPrimitiveType type); + + ProgramCache* fProgramCache; + GrGLProgram::CachedData* fProgramData; + GrGLuint fHWProgramID; + GrGLProgram fCurrentProgram; + + typedef GrGpuGL INHERITED; +}; + +#endif + diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp index f79e9c8..4deecd4 100644 --- a/gpu/src/GrGpuGLShaders2.cpp +++ b/gpu/src/GrGpuGLShaders2.cpp @@ -1,5 +1,5 @@ /* - Copyright 2010 Google Inc. + Copyright 2011 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,8 +17,6 @@ #include "GrGLConfig.h" -#if GR_SUPPORT_GLES2 || GR_SUPPORT_GLDESKTOP - #include "GrGpuGLShaders2.h" #include "GrGpuVertex.h" #include "GrMemory.h" @@ -31,15 +29,6 @@ #define SKIP_CACHE_CHECK true -#if GR_SUPPORT_GLES2 - #define GR_PRECISION "mediump" - const char GR_SHADER_PRECISION[] = "precision mediump float;\n"; -#else - #define GR_PRECISION "" - const char GR_SHADER_PRECISION[] = ""; -#endif - - #define POS_ATTR_LOCATION 0 #define TEX_ATTR_LOCATION(X) (1 + X) #define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords) @@ -51,14 +40,34 @@ #define GR_UINT32_MAX static_cast<uint32_t>(-1) +namespace { + +const char* GrPrecision() { + if (GR_GL_SUPPORT_ES2) { + return "mediump"; + } else { + return ""; + } +} + +const char* GrShaderPrecision() { + if (GR_GL_SUPPORT_ES2) { + return "precision mediump float;\n"; + } else { + return ""; + } +} + +} // namespace + struct GrGpuGLShaders2::StageUniLocations { - GLint fTextureMatrixUni; - GLint fSamplerUni; - GLint fRadial2Uni; + GrGLint fTextureMatrixUni; + GrGLint fSamplerUni; + GrGLint fRadial2Uni; }; struct GrGpuGLShaders2::UniLocations { - GLint fViewMatrixUni; + GrGLint fViewMatrixUni; StageUniLocations fStages[kNumStages]; }; @@ -71,9 +80,9 @@ struct GrGpuGLShaders2::UniLocations { // previous uniform state after a program change. struct GrGpuGLShaders2::Program { // IDs - GLuint fVShaderID; - GLuint fFShaderID; - GLuint fProgramID; + GrGLuint fVShaderID; + GrGLuint fFShaderID; + GrGLuint fProgramID; // shader uniform locations (-1 if shader doesn't use them) UniLocations fUniLocations; @@ -501,11 +510,15 @@ void GrGpuGLShaders2::GenStageCode(int stageNum, if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping) { - segments->fVSUnis += "uniform " GR_PRECISION " float "; + segments->fVSUnis += "uniform "; + segments->fVSUnis += GrPrecision(); + segments->fVSUnis += " float "; segments->fVSUnis += radial2ParamsName; segments->fVSUnis += "[6];\n"; - segments->fFSUnis += "uniform " GR_PRECISION " float "; + segments->fFSUnis += "uniform "; + segments->fFSUnis += GrPrecision(); + segments->fFSUnis += " float "; segments->fFSUnis += radial2ParamsName; segments->fFSUnis += "[6];\n"; locations->fRadial2Uni = 1; @@ -814,16 +827,16 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc, segments.fVaryings.cstr(), segments.fVSCode.cstr()); #endif - program->fVShaderID = CompileShader(GL_VERTEX_SHADER, + program->fVShaderID = CompileShader(GR_GL_VERTEX_SHADER, stringCnt, strings, lengths); stringCnt = 0; - if (GR_ARRAY_COUNT(GR_SHADER_PRECISION) > 1) { - strings[stringCnt] = GR_SHADER_PRECISION; - lengths[stringCnt] = GR_ARRAY_COUNT(GR_SHADER_PRECISION) - 1; + if (strlen(GrShaderPrecision()) > 1) { + strings[stringCnt] = GrShaderPrecision(); + lengths[stringCnt] = strlen(GrShaderPrecision()); ++stringCnt; } if (segments.fFSUnis.length()) { @@ -844,18 +857,18 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc, #if PRINT_SHADERS GrPrintf("%s%s%s%s\n", - GR_SHADER_PRECISION, + GrShaderPrecision(), segments.fFSUnis.cstr(), segments.fVaryings.cstr(), segments.fFSCode.cstr()); #endif - program->fFShaderID = CompileShader(GL_FRAGMENT_SHADER, + program->fFShaderID = CompileShader(GR_GL_FRAGMENT_SHADER, stringCnt, strings, lengths); program->fProgramID = GR_GL(CreateProgram()); - const GLint& progID = program->fProgramID; + const GrGLint& progID = program->fProgramID; GR_GL(AttachShader(progID, program->fVShaderID)); GR_GL(AttachShader(progID, program->fFShaderID)); @@ -896,11 +909,11 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc, GR_GL(LinkProgram(progID)); - GLint linked = GR_GL_INIT_ZERO; - GR_GL(GetProgramiv(progID, GL_LINK_STATUS, &linked)); + GrGLint linked = GR_GL_INIT_ZERO; + GR_GL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked)); if (!linked) { - GLint infoLen = GR_GL_INIT_ZERO; - GR_GL(GetProgramiv(progID, GL_INFO_LOG_LENGTH, &infoLen)); + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetProgramInfoLog(progID, @@ -1029,7 +1042,7 @@ void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc GrAssert(!"Unexpected sample mode!"); break; } - if (GrTexture::kAlpha_8_PixelConfig == texture->config()) { + if (GrPixelConfigIsAlphaOnly(texture->config())) { stage.fModulation = StageDesc::kAlpha_Modulation; } else { stage.fModulation = StageDesc::kColor_Modulation; @@ -1042,23 +1055,23 @@ void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc } } -GLuint GrGpuGLShaders2::CompileShader(GLenum type, - int stringCnt, - const char** strings, - int* stringLengths) { - GLuint shader = GR_GL(CreateShader(type)); +GrGLuint GrGpuGLShaders2::CompileShader(GrGLenum type, + int stringCnt, + const char** strings, + int* stringLengths) { + GrGLuint shader = GR_GL(CreateShader(type)); if (0 == shader) { return 0; } - GLint compiled = GR_GL_INIT_ZERO; + GrGLint compiled = GR_GL_INIT_ZERO; GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths)); GR_GL(CompileShader(shader)); - GR_GL(GetShaderiv(shader, GL_COMPILE_STATUS, &compiled)); + GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { - GLint infoLen = GR_GL_INIT_ZERO; - GR_GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen)); + GrGLint infoLen = GR_GL_INIT_ZERO; + GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get())); @@ -1316,21 +1329,21 @@ void GrGpuGLShaders2::setupGeometry(int* startVertex, int newColorOffset; int newTexCoordOffsets[kMaxTexCoords]; - GLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout, - newTexCoordOffsets, - &newColorOffset); + GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout, + newTexCoordOffsets, + &newColorOffset); int oldColorOffset; int oldTexCoordOffsets[kMaxTexCoords]; - GLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, - oldTexCoordOffsets, - &oldColorOffset); + GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, + oldTexCoordOffsets, + &oldColorOffset); bool indexed = NULL != startIndex; int extraVertexOffset; int extraIndexOffset; setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); - GLenum scalarType; + GrGLenum scalarType; bool texCoordNorm; if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { scalarType = GrGLTextType; @@ -1361,13 +1374,13 @@ void GrGpuGLShaders2::setupGeometry(int* startVertex, if (posAndTexChange) { GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType, - false, newStride, (GLvoid*)vertexOffset)); + false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } for (int t = 0; t < kMaxTexCoords; ++t) { if (newTexCoordOffsets[t] > 0) { - GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[t]); + GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); if (oldTexCoordOffsets[t] <= 0) { GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t))); GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType, @@ -1383,15 +1396,15 @@ void GrGpuGLShaders2::setupGeometry(int* startVertex, } if (newColorOffset > 0) { - GLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); + GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); if (oldColorOffset <= 0) { GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION)); GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, - GL_UNSIGNED_BYTE, + GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, - GL_UNSIGNED_BYTE, + GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { @@ -1401,6 +1414,3 @@ void GrGpuGLShaders2::setupGeometry(int* startVertex, fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; fHWGeometryState.fArrayPtrsDirty = false; } -#endif - - diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h index 4c501be..b9a019b 100644 --- a/gpu/src/GrGpuGLShaders2.h +++ b/gpu/src/GrGpuGLShaders2.h @@ -1,5 +1,5 @@ /* - Copyright 2010 Google Inc. + Copyright 2011 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -84,16 +84,16 @@ private: // Compiles a GL shader, returns shader ID or 0 if failed // params have same meaning as glShaderSource - static GLuint CompileShader(GLenum type, int stringCnt, - const char** strings, - int* stringLengths); + static GrGLuint CompileShader(GrGLenum type, int stringCnt, + const char** strings, + int* stringLengths); static void DeleteProgram(Program* program); void ProgramUnitTest(); ProgramCache* fProgramCache; Program* fProgram; - GLuint fHWProgramID; + GrGLuint fHWProgramID; typedef GrGpuGL INHERITED; }; diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp index 8225425..be4db99 100644 --- a/gpu/src/GrInOrderDrawBuffer.cpp +++ b/gpu/src/GrInOrderDrawBuffer.cpp @@ -316,6 +316,7 @@ void GrInOrderDrawBuffer::reset() { } void GrInOrderDrawBuffer::playback(GrDrawTarget* target) { + GrAssert(!fReservedGeometry.fLocked); GrAssert(NULL != target); GrAssert(target != this); // not considered and why? @@ -346,8 +347,6 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) { ++currClip; target->setClip(fClips[currClip]); } - uint32_t vertexReserveCount = 0; - uint32_t indexReserveCount = 0; target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer); @@ -366,9 +365,6 @@ void GrInOrderDrawBuffer::playback(GrDrawTarget* target) { draw.fStartVertex, draw.fVertexCount); } - if (vertexReserveCount || indexReserveCount) { - target->releaseReservedGeometry(); - } } } @@ -402,9 +398,9 @@ bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout, return flush; } -bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout, - void** vertices, - void** indices) { +bool GrInOrderDrawBuffer::onAcquireGeometry(GrVertexLayout vertexLayout, + void** vertices, + void** indices) { GrAssert(!fReservedGeometry.fLocked); if (fReservedGeometry.fVertexCount) { GrAssert(NULL != vertices); @@ -439,7 +435,7 @@ bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout, return true; } -void GrInOrderDrawBuffer::releaseGeometryHelper() { +void GrInOrderDrawBuffer::onReleaseGeometry() { GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes); GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes); @@ -458,8 +454,8 @@ void GrInOrderDrawBuffer::releaseGeometryHelper() { } -void GrInOrderDrawBuffer::setVertexSourceToArrayHelper(const void* vertexArray, - int vertexCount) { +void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray, + int vertexCount) { GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount); #if GR_DEBUG bool success = @@ -472,8 +468,8 @@ void GrInOrderDrawBuffer::setVertexSourceToArrayHelper(const void* vertexArray, GR_DEBUGASSERT(success); } -void GrInOrderDrawBuffer::setIndexSourceToArrayHelper(const void* indexArray, - int indexCount) { +void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray, + int indexCount) { GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount); #if GR_DEBUG bool success = diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp index 6d7aabb..317b7d3 100644 --- a/gpu/src/GrPathRenderer.cpp +++ b/gpu/src/GrPathRenderer.cpp @@ -3,6 +3,7 @@ #include "GrPoint.h" #include "GrDrawTarget.h" #include "GrPathIter.h" +#include "GrPathUtils.h" #include "GrMemory.h" #include "GrTexture.h" @@ -147,127 +148,6 @@ static const GrStencilSettings gDirectToStencil = { // Helpers for drawPath #define STENCIL_OFF 0 // Always disable stencil (even when needed) -static const GrScalar gTolerance = GR_Scalar1; - -static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10; - -static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) { - GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]); - if (d < tol) { - return 1; - } else { - // Each time we subdivide, d should be cut in 4. So we need to - // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x) - // points. - // 2^(log4(x)) = sqrt(x); - d = ceilf(sqrtf(d/tol)); - return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE); - } -} - -static uint32_t generate_quadratic_points(const GrPoint& p0, - const GrPoint& p1, - const GrPoint& p2, - GrScalar tolSqd, - GrPoint** points, - uint32_t pointsLeft) { - if (pointsLeft < 2 || - (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) { - (*points)[0] = p2; - *points += 1; - return 1; - } - - GrPoint q[] = { - GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)), - GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)), - }; - GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)); - - pointsLeft >>= 1; - uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft); - uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft); - return a + b; -} - -static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) { - GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]), - points[2].distanceToLineSegmentBetweenSqd(points[0], points[3])); - d = sqrtf(d); - if (d < tol) { - return 1; - } else { - d = ceilf(sqrtf(d/tol)); - return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE); - } -} - -static uint32_t generate_cubic_points(const GrPoint& p0, - const GrPoint& p1, - const GrPoint& p2, - const GrPoint& p3, - GrScalar tolSqd, - GrPoint** points, - uint32_t pointsLeft) { - if (pointsLeft < 2 || - (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd && - p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) { - (*points)[0] = p3; - *points += 1; - return 1; - } - GrPoint q[] = { - GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)), - GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)), - GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY)) - }; - GrPoint r[] = { - GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)), - GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY)) - }; - GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY)); - pointsLeft >>= 1; - uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft); - uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft); - return a + b; -} - -static int worst_case_point_count(GrPathIter* path, - int* subpaths, - GrScalar tol) { - int pointCount = 0; - *subpaths = 1; - - bool first = true; - - GrPathCmd cmd; - - GrPoint pts[4]; - while ((cmd = path->next(pts)) != kEnd_PathCmd) { - - switch (cmd) { - case kLine_PathCmd: - pointCount += 1; - break; - case kQuadratic_PathCmd: - pointCount += quadratic_point_count(pts, tol); - break; - case kCubic_PathCmd: - pointCount += cubic_point_count(pts, tol); - break; - case kMove_PathCmd: - pointCount += 1; - if (!first) { - ++(*subpaths); - } - break; - default: - break; - } - first = false; - } - return pointCount; -} static inline bool single_pass_path(const GrDrawTarget& target, const GrPathIter& path, @@ -294,15 +174,15 @@ static inline bool single_pass_path(const GrDrawTarget& target, bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target, GrPathIter* path, GrPathFill fill) const { - return single_pass_path(*target, *path, fill); + return !single_pass_path(*target, *path, fill); } -void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target, - GrDrawTarget::StageBitfield stages, - GrPathIter* path, - GrPathFill fill, - const GrPoint* translate, - bool stencilOnly) { +void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate, + bool stencilOnly) { GrDrawTarget::AutoStateRestore asr(target); bool colorWritesWereDisabled = target->isColorWriteDisabled(); @@ -314,7 +194,7 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target, // stretch when mapping to screen coordinates. GrScalar stretch = viewM.getMaxStretch(); bool useStretch = stretch > 0; - GrScalar tol = gTolerance; + GrScalar tol = GrPathUtils::gTolerance; if (!useStretch) { // TODO: deal with perspective in some better way. @@ -328,9 +208,7 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target, path->rewind(); int subpathCnt; - int maxPts = worst_case_point_count(path, - &subpathCnt, - tol); + int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol); GrVertexLayout layout = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { @@ -468,15 +346,15 @@ void GrDefaultPathRenderer::drawPathHelper(GrDrawTarget* target, vert++; break; case kQuadratic_PathCmd: { - generate_quadratic_points(pts[0], pts[1], pts[2], - tolSqd, &vert, - quadratic_point_count(pts, tol)); + GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], + tolSqd, &vert, + GrPathUtils::quadraticPointCount(pts, tol)); break; } case kCubic_PathCmd: { - generate_cubic_points(pts[0], pts[1], pts[2], pts[3], - tolSqd, &vert, - cubic_point_count(pts, tol)); + GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], + tolSqd, &vert, + GrPathUtils::cubicPointCount(pts, tol)); break; } case kClose_PathCmd: @@ -556,14 +434,14 @@ void GrDefaultPathRenderer::drawPath(GrDrawTarget* target, GrPathIter* path, GrPathFill fill, const GrPoint* translate) { - this->drawPathHelper(target, stages, path, fill, translate, false); + this->onDrawPath(target, stages, path, fill, translate, false); } void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target, GrPathIter* path, GrPathFill fill, const GrPoint* translate) { - GrAssert(kInverseEvenOdd_PathFill != fill); - GrAssert(kInverseWinding_PathFill != fill); - this->drawPathHelper(target, 0, path, fill, translate, true); - } + GrAssert(kInverseEvenOdd_PathFill != fill); + GrAssert(kInverseWinding_PathFill != fill); + this->onDrawPath(target, 0, path, fill, translate, true); +} diff --git a/gpu/src/GrPathUtils.cpp b/gpu/src/GrPathUtils.cpp new file mode 100644 index 0000000..274dc49 --- /dev/null +++ b/gpu/src/GrPathUtils.cpp @@ -0,0 +1,144 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrPathUtils.h" + +#include "GrPathIter.h" +#include "GrPoint.h" + +const GrScalar GrPathUtils::gTolerance = GR_Scalar1; + +static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10; + +uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[], + GrScalar tol) { + GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]); + if (d < tol) { + return 1; + } else { + // Each time we subdivide, d should be cut in 4. So we need to + // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x) + // points. + // 2^(log4(x)) = sqrt(x); + d = ceilf(sqrtf(d/tol)); + return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE); + } +} + +uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0, + const GrPoint& p1, + const GrPoint& p2, + GrScalar tolSqd, + GrPoint** points, + uint32_t pointsLeft) { + if (pointsLeft < 2 || + (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) { + (*points)[0] = p2; + *points += 1; + return 1; + } + + GrPoint q[] = { + GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)), + GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)), + }; + GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)); + + pointsLeft >>= 1; + uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft); + uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft); + return a + b; +} + +uint32_t GrPathUtils::cubicPointCount(const GrPoint points[], + GrScalar tol) { + GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]), + points[2].distanceToLineSegmentBetweenSqd(points[0], points[3])); + d = sqrtf(d); + if (d < tol) { + return 1; + } else { + d = ceilf(sqrtf(d/tol)); + return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE); + } +} + +uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0, + const GrPoint& p1, + const GrPoint& p2, + const GrPoint& p3, + GrScalar tolSqd, + GrPoint** points, + uint32_t pointsLeft) { + if (pointsLeft < 2 || + (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd && + p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) { + (*points)[0] = p3; + *points += 1; + return 1; + } + GrPoint q[] = { + GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)), + GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)), + GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY)) + }; + GrPoint r[] = { + GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)), + GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY)) + }; + GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY)); + pointsLeft >>= 1; + uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft); + uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft); + return a + b; +} + +int GrPathUtils::worstCasePointCount(GrPathIter* path, + int* subpaths, + GrScalar tol) { + int pointCount = 0; + *subpaths = 1; + + bool first = true; + + GrPathCmd cmd; + + GrPoint pts[4]; + while ((cmd = path->next(pts)) != kEnd_PathCmd) { + + switch (cmd) { + case kLine_PathCmd: + pointCount += 1; + break; + case kQuadratic_PathCmd: + pointCount += quadraticPointCount(pts, tol); + break; + case kCubic_PathCmd: + pointCount += cubicPointCount(pts, tol); + break; + case kMove_PathCmd: + pointCount += 1; + if (!first) { + ++(*subpaths); + } + break; + default: + break; + } + first = false; + } + return pointCount; +} diff --git a/gpu/src/GrPathUtils.h b/gpu/src/GrPathUtils.h new file mode 100644 index 0000000..97841dd --- /dev/null +++ b/gpu/src/GrPathUtils.h @@ -0,0 +1,52 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef GrPathUtils_DEFINED +#define GrPathUtils_DEFINED + +#include "GrNoncopyable.h" +#include "GrScalar.h" + +class GrPathIter; +struct GrPoint; + +/** + * Utilities for evaluating paths. + */ +class GrPathUtils : public GrNoncopyable { +public: + static int worstCasePointCount(GrPathIter* path, + int* subpaths, + GrScalar tol); + static uint32_t quadraticPointCount(const GrPoint points[], GrScalar tol); + static uint32_t generateQuadraticPoints(const GrPoint& p0, + const GrPoint& p1, + const GrPoint& p2, + GrScalar tolSqd, + GrPoint** points, + uint32_t pointsLeft); + static uint32_t cubicPointCount(const GrPoint points[], GrScalar tol); + static uint32_t generateCubicPoints(const GrPoint& p0, + const GrPoint& p1, + const GrPoint& p2, + const GrPoint& p3, + GrScalar tolSqd, + GrPoint** points, + uint32_t pointsLeft); + + static const GrScalar gTolerance; +}; +#endif diff --git a/gpu/src/GrRedBlackTree.h b/gpu/src/GrRedBlackTree.h index 7ba326f..b57ce9e 100644 --- a/gpu/src/GrRedBlackTree.h +++ b/gpu/src/GrRedBlackTree.h @@ -163,7 +163,7 @@ private: void deleteAtNode(Node* x); static void RecursiveDelete(Node* x); - int countOfHelper(const Node* n, const T& t) const; + int onCountOf(const Node* n, const T& t) const; #if GR_DEBUG void validate() const; @@ -312,11 +312,11 @@ typename GrRedBlackTree<T,C>::Iter GrRedBlackTree<T,C>::findLast(const T& t) { template <typename T, typename C> int GrRedBlackTree<T,C>::countOf(const T& t) const { - return countOfHelper(fRoot, t); + return onCountOf(fRoot, t); } template <typename T, typename C> -int GrRedBlackTree<T,C>::countOfHelper(const Node* n, const T& t) const { +int GrRedBlackTree<T,C>::onCountOf(const Node* n, const T& t) const { // this is count*log(n) :( while (NULL != n) { if (fComp(t, n->fItem)) { @@ -324,8 +324,8 @@ int GrRedBlackTree<T,C>::countOfHelper(const Node* n, const T& t) const { } else { if (!fComp(n->fItem, t)) { int count = 1; - count += countOfHelper(n->fChildren[kLeft_Child], t); - count += countOfHelper(n->fChildren[kRight_Child], t); + count += onCountOf(n->fChildren[kLeft_Child], t); + count += onCountOf(n->fChildren[kRight_Child], t); return count; } n = n->fChildren[kRight_Child]; diff --git a/gpu/src/GrResource.cpp b/gpu/src/GrResource.cpp new file mode 100644 index 0000000..70e87d5 --- /dev/null +++ b/gpu/src/GrResource.cpp @@ -0,0 +1,41 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrResource.h" +#include "GrGpu.h" + +GrResource::GrResource(GrGpu* gpu) { + fGpu = gpu; + fNext = NULL; + fPrevious = NULL; + fGpu->insertResource(this); +} + +void GrResource::release() { + if (NULL != fGpu) { + this->onRelease(); + fGpu->removeResource(this); + fGpu = NULL; + } +} + +void GrResource::abandon() { + if (NULL != fGpu) { + this->onAbandon(); + fGpu->removeResource(this); + fGpu = NULL; + } +} diff --git a/gpu/src/GrStencil.cpp b/gpu/src/GrStencil.cpp index a1c8c09..c366f61 100644 --- a/gpu/src/GrStencil.cpp +++ b/gpu/src/GrStencil.cpp @@ -249,7 +249,7 @@ bool GrStencilSettings::GetClipPasses(GrSetOp op, bool invertedFill, int* numPasses, GrStencilSettings settings[kMaxStencilClipPasses]) { - if (canBeDirect) { + if (canBeDirect && !invertedFill) { *numPasses = 0; switch (op) { case kReplace_SetOp: diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp new file mode 100644 index 0000000..8ed2c22 --- /dev/null +++ b/gpu/src/GrTesselatedPathRenderer.cpp @@ -0,0 +1,277 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrTesselatedPathRenderer.h" + +#include "GrMemory.h" +#include "GrPathUtils.h" + +#include <internal_glu.h> + +struct PolygonData { + PolygonData(GrTDArray<GrPoint>* vertices, GrTDArray<short>* indices) + : fVertices(vertices) + , fIndices(indices) + { + } + GrTDArray<GrPoint>* fVertices; + GrTDArray<short>* fIndices; +}; + +static void beginData(GLenum type, void* data) +{ + GR_DEBUGASSERT(type == GL_TRIANGLES); +} + +static void edgeFlagData(GLboolean flag, void* data) +{ +} + +static void vertexData(void* vertexData, void* data) +{ + short* end = static_cast<PolygonData*>(data)->fIndices->append(); + *end = reinterpret_cast<long>(vertexData); +} + +static void endData(void* data) +{ +} + +static void combineData(GLdouble coords[3], void* vertexData[4], + GLfloat weight[4], void **outData, void* data) +{ + PolygonData* polygonData = static_cast<PolygonData*>(data); + int index = polygonData->fVertices->count(); + *polygonData->fVertices->append() = GrPoint(static_cast<float>(coords[0]), + static_cast<float>(coords[1])); + *outData = reinterpret_cast<void*>(index); +} + +typedef void (*TESSCB)(); + +static unsigned fill_type_to_glu_winding_rule(GrPathFill fill) { + switch (fill) { + case kWinding_PathFill: + return GLU_TESS_WINDING_NONZERO; + case kEvenOdd_PathFill: + return GLU_TESS_WINDING_ODD; + case kInverseWinding_PathFill: + return GLU_TESS_WINDING_POSITIVE; + case kInverseEvenOdd_PathFill: + return GLU_TESS_WINDING_ODD; + case kHairLine_PathFill: + return GLU_TESS_WINDING_NONZERO; // FIXME: handle this + default: + GrAssert(!"Unknown path fill!"); + return 0; + } +} + +GrTesselatedPathRenderer::GrTesselatedPathRenderer() { +} + +void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target, + GrDrawTarget::StageBitfield stages, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate) { + GrDrawTarget::AutoStateRestore asr(target); + bool colorWritesWereDisabled = target->isColorWriteDisabled(); + // face culling doesn't make sense here + GrAssert(GrDrawTarget::kBoth_DrawFace == target->getDrawFace()); + + GrMatrix viewM = target->getViewMatrix(); + // In order to tesselate the path we get a bound on how much the matrix can + // stretch when mapping to screen coordinates. + GrScalar stretch = viewM.getMaxStretch(); + bool useStretch = stretch > 0; + GrScalar tol = GrPathUtils::gTolerance; + + if (!useStretch) { + // TODO: deal with perspective in some better way. + tol /= 10; + } else { + GrScalar sinv = GR_Scalar1 / stretch; + tol = GrMul(tol, sinv); + } + GrScalar tolSqd = GrMul(tol, tol); + + path->rewind(); + + int subpathCnt; + int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol); + + GrVertexLayout layout = 0; + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if ((1 << s) & stages) { + layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); + } + } + + bool inverted = IsFillInverted(fill); + if (inverted) { + maxPts += 4; + subpathCnt++; + } + GrPoint* base = new GrPoint[maxPts]; + GrPoint* vert = base; + GrPoint* subpathBase = base; + + GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt); + + path->rewind(); + + GrPoint pts[4]; + + bool first = true; + int subpath = 0; + + for (;;) { + GrPathCmd cmd = path->next(pts); + switch (cmd) { + case kMove_PathCmd: + if (!first) { + subpathVertCount[subpath] = vert-subpathBase; + subpathBase = vert; + ++subpath; + } + *vert = pts[0]; + vert++; + break; + case kLine_PathCmd: + *vert = pts[1]; + vert++; + break; + case kQuadratic_PathCmd: { + GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], + tolSqd, &vert, + GrPathUtils::quadraticPointCount(pts, tol)); + break; + } + case kCubic_PathCmd: { + GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], + tolSqd, &vert, + GrPathUtils::cubicPointCount(pts, tol)); + break; + } + case kClose_PathCmd: + break; + case kEnd_PathCmd: + subpathVertCount[subpath] = vert-subpathBase; + ++subpath; // this could be only in debug + goto FINISHED; + } + first = false; + } +FINISHED: + if (translate) { + for (int i = 0; i < vert - base; i++) { + base[i].offset(translate->fX, translate->fY); + } + } + + if (inverted) { + GrRect bounds; + GrAssert(NULL != target->getRenderTarget()); + bounds.setLTRB(0, 0, + GrIntToScalar(target->getRenderTarget()->width()), + GrIntToScalar(target->getRenderTarget()->height())); + GrMatrix vmi; + if (target->getViewInverse(&vmi)) { + vmi.mapRect(&bounds); + } + *vert++ = GrPoint(bounds.fLeft, bounds.fTop); + *vert++ = GrPoint(bounds.fLeft, bounds.fBottom); + *vert++ = GrPoint(bounds.fRight, bounds.fBottom); + *vert++ = GrPoint(bounds.fRight, bounds.fTop); + subpathVertCount[subpath++] = 4; + } + + GrAssert(subpath == subpathCnt); + GrAssert((vert - base) <= maxPts); + + size_t count = vert - base; + + if (subpathCnt == 1 && !inverted && path->convexHint() == kConvex_ConvexHint) { + target->setVertexSourceToArray(layout, base, count); + target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); + delete[] base; + return; + } + + // FIXME: This copy could be removed if we had (templated?) versions of + // generate_*_point above that wrote directly into doubles. + double* inVertices = new double[count * 3]; + for (size_t i = 0; i < count; ++i) { + inVertices[i * 3] = base[i].fX; + inVertices[i * 3 + 1] = base[i].fY; + inVertices[i * 3 + 2] = 1.0; + } + + GLUtesselator* tess = internal_gluNewTess(); + unsigned windingRule = fill_type_to_glu_winding_rule(fill); + internal_gluTessProperty(tess, GLU_TESS_WINDING_RULE, windingRule); + internal_gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TESSCB) &beginData); + internal_gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (TESSCB) &vertexData); + internal_gluTessCallback(tess, GLU_TESS_END_DATA, (TESSCB) &endData); + internal_gluTessCallback(tess, GLU_TESS_EDGE_FLAG_DATA, (TESSCB) &edgeFlagData); + internal_gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (TESSCB) &combineData); + GrTDArray<short> indices; + GrTDArray<GrPoint> vertices; + PolygonData data(&vertices, &indices); + + internal_gluTessBeginPolygon(tess, &data); + size_t i = 0; + for (int sp = 0; sp < subpathCnt; ++sp) { + internal_gluTessBeginContour(tess); + int start = i; + int end = start + subpathVertCount[sp]; + for (; i < end; ++i) { + double* inVertex = &inVertices[i * 3]; + *vertices.append() = GrPoint(inVertex[0], inVertex[1]); + internal_gluTessVertex(tess, inVertex, reinterpret_cast<void*>(i)); + } + internal_gluTessEndContour(tess); + } + + internal_gluTessEndPolygon(tess); + internal_gluDeleteTess(tess); + + if (indices.count() > 0) { + target->setVertexSourceToArray(layout, vertices.begin(), vertices.count()); + target->setIndexSourceToArray(indices.begin(), indices.count()); + target->drawIndexed(kTriangles_PrimitiveType, + 0, + 0, + vertices.count(), + indices.count()); + } + delete[] inVertices; + delete[] base; +} + +bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill) const { + return kHairLine_PathFill != fill; +} + +void GrTesselatedPathRenderer::drawPathToStencil(GrDrawTarget* target, + GrPathIter* path, + GrPathFill fill, + const GrPoint* translate) { + GrAlwaysAssert(!"multipass stencil should not be needed"); +} diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp index 2230af2..09113e0 100644 --- a/gpu/src/GrTextContext.cpp +++ b/gpu/src/GrTextContext.cpp @@ -47,7 +47,7 @@ void GrTextContext::flushGlyphs() { GrAssert(fCurrTexture); fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture); - if (!GrTexture::PixelConfigIsAlphaOnly(fCurrTexture->config())) { + if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff || kISA_BlendCoeff != fPaint.fDstBlendCoeff || NULL != fPaint.getTexture()) { @@ -176,7 +176,9 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, if (fStrike->getGlyphAtlas(glyph, scaler)) { goto HAS_ATLAS; } - // must do this to flush inorder buffering before we purge + + // before we purge the cache, we must flush any accumulated draws + this->flushGlyphs(); fContext->flushText(); // try to purge @@ -185,11 +187,7 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, goto HAS_ATLAS; } - // Draw as a path, so we flush any accumulated glyphs first - this->flushGlyphs(); - if (NULL == glyph->fPath) { - GrPath* path = new GrPath; if (!scaler->getGlyphPath(glyph->glyphID(), path)) { // flag the glyph as being dead? diff --git a/gpu/src/GrTextStrike.cpp b/gpu/src/GrTextStrike.cpp index 6cdb61c..7aae757 100644 --- a/gpu/src/GrTextStrike.cpp +++ b/gpu/src/GrTextStrike.cpp @@ -58,19 +58,12 @@ GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler, return strike; } -void GrFontCache::abandonAll() { - fCache.deleteAll(); - if (fAtlasMgr) { - fAtlasMgr->abandonAll(); - delete fAtlasMgr; - fAtlasMgr = NULL; - } -} - void GrFontCache::freeAll() { fCache.deleteAll(); delete fAtlasMgr; fAtlasMgr = NULL; + fHead = NULL; + fTail = NULL; } void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { @@ -176,6 +169,11 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, } bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { +#if 0 // testing hack to force us to flush our cache often + static int gCounter; + if ((++gCounter % 10) == 0) return false; +#endif + GrAssert(glyph); GrAssert(scaler); GrAssert(fCache.contains(glyph)); diff --git a/gpu/src/GrTexture.cpp b/gpu/src/GrTexture.cpp new file mode 100644 index 0000000..1ea02a7 --- /dev/null +++ b/gpu/src/GrTexture.cpp @@ -0,0 +1,40 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrTexture.h" +#include "GrContext.h" + +bool GrRenderTarget::readPixels(int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + // go through context so that all necessary flushing occurs + GrContext* context = this->getGpu()->getContext(); + GrAssert(NULL != context); + return context->readRenderTargetPixels(this, + left, top, + width, height, + config, buffer); +} + +bool GrTexture::readPixels(int left, int top, int width, int height, + GrPixelConfig config, void* buffer) { + // go through context so that all necessary flushing occurs + GrContext* context = this->getGpu()->getContext(); + GrAssert(NULL != context); + return context->readTexturePixels(this, + left, top, + width, height, + config, buffer); +} diff --git a/gpu/src/GrTextureCache.cpp b/gpu/src/GrTextureCache.cpp index fe3ff68..c3a61ac 100644 --- a/gpu/src/GrTextureCache.cpp +++ b/gpu/src/GrTextureCache.cpp @@ -55,7 +55,7 @@ GrTextureCache::GrTextureCache(int maxCount, size_t maxBytes) : GrTextureCache::~GrTextureCache() { GrAutoTextureCacheValidate atcv(this); - this->deleteAll(kFreeTexture_DeleteMode); + this->removeAll(); } void GrTextureCache::getLimits(int* maxTextures, size_t* maxTextureBytes) const{ @@ -237,7 +237,7 @@ void GrTextureCache::purgeAsNeeded() { } } -void GrTextureCache::deleteAll(DeleteMode mode) { +void GrTextureCache::removeAll() { GrAssert(!fClientDetachedCount); GrAssert(!fClientDetachedBytes); @@ -246,9 +246,6 @@ void GrTextureCache::deleteAll(DeleteMode mode) { GrAssert(!entry->isLocked()); GrTextureEntry* next = entry->fNext; - if (kAbandonTexture_DeleteMode == mode) { - entry->texture()->abandon(); - } delete entry; entry = next; } diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk index 8aeddc9..a40d7bd 100644 --- a/gpu/src/gr_files.mk +++ b/gpu/src/gr_files.mk @@ -3,9 +3,11 @@ SOURCE := \ GrAtlas.cpp \ GrClip.cpp \ GrContext.cpp \ + GrCreatePathRenderer_none.cpp \ GrDrawTarget.cpp \ GrGLIndexBuffer.cpp \ GrGLInterface.cpp \ + GrGLProgram.cpp \ GrGLTexture.cpp \ GrGLVertexBuffer.cpp \ GrGpu.cpp \ @@ -14,11 +16,15 @@ SOURCE := \ GrGpuFactory.cpp \ GrGLUtil.cpp \ GrGpuGL.cpp \ + GrGpuGLShaders.cpp \ GrInOrderDrawBuffer.cpp \ GrMatrix.cpp \ GrMemory.cpp \ GrPath.cpp \ + GrPathUtils.cpp \ GrRectanizer_fifo.cpp \ + GrResource.cpp \ + GrTexture.cpp \ GrTextureCache.cpp \ GrTextContext.cpp \ GrTextStrike.cpp \ diff --git a/gpu/src/gr_unittests.cpp b/gpu/src/gr_unittests.cpp index 16fd9dc..fd27f19 100644 --- a/gpu/src/gr_unittests.cpp +++ b/gpu/src/gr_unittests.cpp @@ -21,6 +21,7 @@ #include "GrMatrix.h" #include "GrRedBlackTree.h" #include "GrPath.h" +#include "GrBinHashKey.h" static void dump(const GrTDArray<int>& array) { #if 0 @@ -74,9 +75,83 @@ static void test_bsearch() { } } +// bogus empty class for GrBinHashKey +class BogusEntry {}; + +static void test_binHashKey() +{ + const char* testStringA = "abcdA"; + const char* testStringB = "abcdB"; + enum { + kDataLenUsedForKey = 5 + }; + + typedef GrBinHashKey<BogusEntry, kDataLenUsedForKey> KeyType; + + KeyType keyA; + int passCnt = 0; + while (keyA.doPass()) { + ++passCnt; + keyA.keyData(reinterpret_cast<const uint8_t*>(testStringA), kDataLenUsedForKey); + } + GrAssert(passCnt == 1); //We expect the static allocation to suffice + GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust; + passCnt = 0; + while (keyBust.doPass()) { + ++passCnt; + // Exceed static storage by 1 + keyBust.keyData(reinterpret_cast<const uint8_t*>(testStringA), kDataLenUsedForKey); + } + GrAssert(passCnt == 2); //We expect dynamic allocation to be necessary + GrAssert(keyA.getHash() == keyBust.getHash()); + + // Test that adding keyData in chunks gives + // the same hash as with one chunk + KeyType keyA2; + while (keyA2.doPass()) { + keyA2.keyData(reinterpret_cast<const uint8_t*>(testStringA), 2); + keyA2.keyData(&reinterpret_cast<const uint8_t*>(testStringA)[2], kDataLenUsedForKey-2); + } + GrAssert(keyA.getHash() == keyA2.getHash()); + + KeyType keyB; + while (keyB.doPass()){ + keyB.keyData(reinterpret_cast<const uint8_t*>(testStringB), kDataLenUsedForKey); + } + GrAssert(keyA.compare(keyB) < 0); + GrAssert(keyA.compare(keyA2) == 0); + + //Test ownership tranfer and copying + keyB.copyAndTakeOwnership(keyA); + GrAssert(keyA.fIsValid == false); + GrAssert(keyB.fIsValid); + GrAssert(keyB.getHash() == keyA2.getHash()); + GrAssert(keyB.compare(keyA2) == 0); + keyA.deepCopyFrom(keyB); + GrAssert(keyA.fIsValid); + GrAssert(keyB.fIsValid); + GrAssert(keyA.getHash() == keyA2.getHash()); + GrAssert(keyA.compare(keyA2) == 0); + + //Test ownership tranfer and copying with key on heap + GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust2; + keyBust2.deepCopyFrom(keyBust); + GrAssert(keyBust.fIsValid); + GrAssert(keyBust2.fIsValid); + GrAssert(keyBust.getHash() == keyBust2.getHash()); + GrAssert(keyBust.compare(keyBust2) == 0); + GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust3; + keyBust3.deepCopyFrom(keyBust); + GrAssert(keyBust.fIsValid == false); + GrAssert(keyBust3.fIsValid); + GrAssert(keyBust3.getHash() == keyBust2.getHash()); + GrAssert(keyBust3.compare(keyBust2) == 0); +} + void gr_run_unittests() { test_tdarray(); test_bsearch(); + test_binHashKey(); GrMatrix::UnitTest(); GrRedBlackTree<int>::UnitTest(); GrPath::ConvexUnitTest(); diff --git a/gpu/src/mac/GrGLDefaultInterface_mac.cpp b/gpu/src/mac/GrGLDefaultInterface_mac.cpp new file mode 100644 index 0000000..802d717 --- /dev/null +++ b/gpu/src/mac/GrGLDefaultInterface_mac.cpp @@ -0,0 +1,148 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrGLInterface.h" + +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> + +void GrGLSetDefaultGLInterface() { + static GrGLInterface gDefaultInterface; + static bool gDefaultInterfaceInit; + if (!gDefaultInterfaceInit) { + gDefaultInterface.fActiveTexture = glActiveTexture; + gDefaultInterface.fAttachShader = glAttachShader; + gDefaultInterface.fBindAttribLocation = glBindAttribLocation; + gDefaultInterface.fBindBuffer = glBindBuffer; + gDefaultInterface.fBindTexture = glBindTexture; + gDefaultInterface.fBlendColor = glBlendColor; + gDefaultInterface.fBlendFunc = glBlendFunc; + gDefaultInterface.fBufferData = glBufferData; + gDefaultInterface.fBufferSubData = glBufferSubData; + gDefaultInterface.fClear = glClear; + gDefaultInterface.fClearColor = glClearColor; + gDefaultInterface.fClearStencil = glClearStencil; + gDefaultInterface.fClientActiveTexture = glClientActiveTexture; + gDefaultInterface.fColorMask = glColorMask; + gDefaultInterface.fColorPointer = glColorPointer; + gDefaultInterface.fColor4ub = glColor4ub; + gDefaultInterface.fCompileShader = glCompileShader; + gDefaultInterface.fCompressedTexImage2D = glCompressedTexImage2D; + gDefaultInterface.fCreateProgram = glCreateProgram; + gDefaultInterface.fCreateShader = glCreateShader; + gDefaultInterface.fCullFace = glCullFace; + gDefaultInterface.fDeleteBuffers = glDeleteBuffers; + gDefaultInterface.fDeleteProgram = glDeleteProgram; + gDefaultInterface.fDeleteShader = glDeleteShader; + gDefaultInterface.fDeleteTextures = glDeleteTextures; + gDefaultInterface.fDepthMask = glDepthMask; + gDefaultInterface.fDisable = glDisable; + gDefaultInterface.fDisableClientState = glDisableClientState; + gDefaultInterface.fDisableVertexAttribArray = + glDisableVertexAttribArray; + gDefaultInterface.fDrawArrays = glDrawArrays; + gDefaultInterface.fDrawElements = glDrawElements; + gDefaultInterface.fEnable = glEnable; + gDefaultInterface.fEnableClientState = glEnableClientState; + gDefaultInterface.fEnableVertexAttribArray = glEnableVertexAttribArray; + gDefaultInterface.fFrontFace = glFrontFace; + gDefaultInterface.fGenBuffers = glGenBuffers; + gDefaultInterface.fGetBufferParameteriv = glGetBufferParameteriv; + gDefaultInterface.fGetError = glGetError; + gDefaultInterface.fGetIntegerv = glGetIntegerv; + gDefaultInterface.fGetProgramInfoLog = glGetProgramInfoLog; + gDefaultInterface.fGetProgramiv = glGetProgramiv; + gDefaultInterface.fGetShaderInfoLog = glGetShaderInfoLog; + gDefaultInterface.fGetShaderiv = glGetShaderiv; + gDefaultInterface.fGetString = glGetString; + gDefaultInterface.fGenTextures = glGenTextures; + gDefaultInterface.fGetUniformLocation = glGetUniformLocation; + gDefaultInterface.fLineWidth = glLineWidth; + gDefaultInterface.fLinkProgram = glLinkProgram; + gDefaultInterface.fLoadMatrixf = glLoadMatrixf; + gDefaultInterface.fMapBuffer = glMapBuffer; + gDefaultInterface.fMatrixMode = glMatrixMode; + gDefaultInterface.fPointSize = glPointSize; + gDefaultInterface.fPixelStorei = glPixelStorei; + gDefaultInterface.fReadPixels = glReadPixels; + gDefaultInterface.fScissor = glScissor; + gDefaultInterface.fShadeModel = glShadeModel; + gDefaultInterface.fShaderSource = glShaderSource; + gDefaultInterface.fStencilFunc = glStencilFunc; + gDefaultInterface.fStencilFuncSeparate = glStencilFuncSeparate; + gDefaultInterface.fStencilMask = glStencilMask; + gDefaultInterface.fStencilMaskSeparate = glStencilMaskSeparate; + gDefaultInterface.fStencilOp = glStencilOp; + gDefaultInterface.fStencilOpSeparate = glStencilOpSeparate; + gDefaultInterface.fTexCoordPointer = glTexCoordPointer; + gDefaultInterface.fTexEnvi = glTexEnvi; + // mac uses GLenum for internalFormat param (non-standard) + // amounts to int vs. uint. + gDefaultInterface.fTexImage2D = + (GrGLInterface::GrGLTexImage2DProc)glTexImage2D; + gDefaultInterface.fTexParameteri = glTexParameteri; + gDefaultInterface.fTexSubImage2D = glTexSubImage2D; + gDefaultInterface.fUniform1fv = glUniform1fv; + gDefaultInterface.fUniform1i = glUniform1i; + gDefaultInterface.fUniform4fv = glUniform4fv; + gDefaultInterface.fUniformMatrix3fv = glUniformMatrix3fv; + gDefaultInterface.fUnmapBuffer = glUnmapBuffer; + gDefaultInterface.fUseProgram = glUseProgram; + gDefaultInterface.fVertexAttrib4fv = glVertexAttrib4fv; + gDefaultInterface.fVertexAttribPointer = glVertexAttribPointer; + gDefaultInterface.fVertexPointer = glVertexPointer; + gDefaultInterface.fViewport = glViewport; + +#if GL_ARB_framebuffer_object + gDefaultInterface.fGenFramebuffers = glGenFramebuffers; + gDefaultInterface.fBindFramebuffer = glBindFramebuffer; + gDefaultInterface.fFramebufferTexture2D = glFramebufferTexture2D; + gDefaultInterface.fCheckFramebufferStatus = glCheckFramebufferStatus; + gDefaultInterface.fDeleteFramebuffers = glDeleteFramebuffers; + gDefaultInterface.fRenderbufferStorage = glRenderbufferStorage; + gDefaultInterface.fGenRenderbuffers = glGenRenderbuffers; + gDefaultInterface.fDeleteRenderbuffers = glDeleteRenderbuffers; + gDefaultInterface.fFramebufferRenderbuffer = glFramebufferRenderbuffer; + gDefaultInterface.fBindRenderbuffer = glBindRenderbuffer; + gDefaultInterface.fRenderbufferStorageMultisample = + glRenderbufferStorageMultisample; + gDefaultInterface.fBlitFramebuffer = glBlitFramebuffer; +#elif GL_EXT_framebuffer_object + gDefaultInterface.fGenFramebuffers = glGenFramebuffersEXT; + gDefaultInterface.fBindFramebuffer = glBindFramebufferEXT; + gDefaultInterface.fFramebufferTexture2D = glFramebufferTexture2DEXT; + gDefaultInterface.fCheckFramebufferStatus = glCheckFramebufferStatusEXT; + gDefaultInterface.fDeleteFramebuffers = glDeleteFramebuffersEXT; + gDefaultInterface.fRenderbufferStorage = glRenderbufferStorageEXT; + gDefaultInterface.fGenRenderbuffers = glGenRenderbuffersEXT; + gDefaultInterface.fDeleteRenderbuffers = glDeleteRenderbuffers; + gDefaultInterface.fFramebufferRenderbuffer = + glFramebufferRenderbufferEXT; + gDefaultInterface.fBindRenderbuffer = glBindRenderbufferEXT; + #if GL_EXT_framebuffer_multisample + gDefaultInterface.fRenderbufferStorageMultisample = + glRenderbufferStorageMultisampleEXT; + #endif + #if GL_EXT_framebuffer_blit + gDefaultInterface.fBlitFramebuffer = glBlitFramebufferEXT; + #endif +#endif + gDefaultInterface.fBindingsExported = kDesktop_GrGLBinding; + + gDefaultInterfaceInit = true; + } + GrGLSetGLInterface(&gDefaultInterface); +} diff --git a/gpu/src/win/GrGLDefaultInterface_win.cpp b/gpu/src/win/GrGLDefaultInterface_win.cpp new file mode 100644 index 0000000..6227015 --- /dev/null +++ b/gpu/src/win/GrGLDefaultInterface_win.cpp @@ -0,0 +1,175 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "GrGLInterface.h" + +#include <Windows.h> +#include <GL/GL.h> + +/* + * Windows makes the GL funcs all be __stdcall instead of __cdecl :( + * This implementation will only work if GR_GL_FUNCTION_TYPE is __stdcall. + * Otherwise, a springboard would be needed that hides the calling convention. + */ + +#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) wglGetProcAddress("gl" #F); +#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) wglGetProcAddress("gl" #F #S); + +void GrGLSetDefaultGLInterface() { + static GrGLInterface gDefaultInterface; + static bool gDefaultInterfaceInit; + if (!gDefaultInterfaceInit) { + + // wglGetProcAddress requires a context. + if (NULL != wglGetCurrentContext()) { + int major, minor; + const char* versionString = (const char*) glGetString(GL_VERSION); + const char* extString = (const char*) glGetString(GL_EXTENSIONS); + gl_version_from_string(&major, &minor, versionString); + + if (major == 1 && minor < 5) { + // We must have array and element_array buffer objects. + return; + } + + // Functions that are part of GL 1.1 will return NULL in + // wglGetProcAddress + gDefaultInterface.fBlendFunc = glBlendFunc; + gDefaultInterface.fClear = glClear; + gDefaultInterface.fClearColor = glClearColor; + gDefaultInterface.fClearStencil = glClearStencil; + gDefaultInterface.fColor4ub = glColor4ub; + gDefaultInterface.fColorMask = glColorMask; + gDefaultInterface.fColorPointer = glColorPointer; + gDefaultInterface.fCullFace = glCullFace; + gDefaultInterface.fDeleteTextures = glDeleteTextures; + gDefaultInterface.fDepthMask = glDepthMask; + gDefaultInterface.fDisable = glDisable; + gDefaultInterface.fDisableClientState = glDisableClientState; + gDefaultInterface.fDrawArrays = glDrawArrays; + gDefaultInterface.fDrawElements = glDrawElements; + gDefaultInterface.fEnable = glEnable; + gDefaultInterface.fEnableClientState = glEnableClientState; + gDefaultInterface.fFrontFace = glFrontFace; + gDefaultInterface.fGenTextures = glGenTextures; + gDefaultInterface.fGetError = glGetError; + gDefaultInterface.fGetIntegerv = glGetIntegerv; + gDefaultInterface.fGetString = glGetString; + gDefaultInterface.fLineWidth = glLineWidth; + gDefaultInterface.fLoadMatrixf = glLoadMatrixf; + gDefaultInterface.fMatrixMode = glMatrixMode; + gDefaultInterface.fPixelStorei = glPixelStorei; + gDefaultInterface.fPointSize = glPointSize; + gDefaultInterface.fReadPixels = glReadPixels; + gDefaultInterface.fScissor = glScissor; + gDefaultInterface.fShadeModel = glShadeModel; + gDefaultInterface.fStencilFunc = glStencilFunc; + gDefaultInterface.fStencilMask = glStencilMask; + gDefaultInterface.fStencilOp = glStencilOp; + gDefaultInterface.fTexImage2D = glTexImage2D; + gDefaultInterface.fTexParameteri = glTexParameteri; + gDefaultInterface.fTexCoordPointer = glTexCoordPointer; + gDefaultInterface.fTexEnvi = glTexEnvi; + gDefaultInterface.fTexSubImage2D = glTexSubImage2D; + gDefaultInterface.fViewport = glViewport; + gDefaultInterface.fVertexPointer = glVertexPointer; + + GR_GL_GET_PROC(ActiveTexture); + GR_GL_GET_PROC(AttachShader); + GR_GL_GET_PROC(BindAttribLocation); + GR_GL_GET_PROC(BindBuffer); + GR_GL_GET_PROC(BindTexture); + GR_GL_GET_PROC(BlendColor); + GR_GL_GET_PROC(BufferData); + GR_GL_GET_PROC(BufferSubData); + GR_GL_GET_PROC(ClientActiveTexture); + GR_GL_GET_PROC(CompileShader); + GR_GL_GET_PROC(CompressedTexImage2D); + GR_GL_GET_PROC(CreateProgram); + GR_GL_GET_PROC(CreateShader); + GR_GL_GET_PROC(DeleteBuffers); + GR_GL_GET_PROC(DeleteProgram); + GR_GL_GET_PROC(DeleteShader); + GR_GL_GET_PROC(DisableVertexAttribArray); + GR_GL_GET_PROC(EnableVertexAttribArray); + GR_GL_GET_PROC(GenBuffers); + GR_GL_GET_PROC(GetBufferParameteriv); + GR_GL_GET_PROC(GetProgramInfoLog); + GR_GL_GET_PROC(GetProgramiv); + GR_GL_GET_PROC(GetShaderInfoLog); + GR_GL_GET_PROC(GetShaderiv); + GR_GL_GET_PROC(GetUniformLocation); + GR_GL_GET_PROC(LinkProgram); + GR_GL_GET_PROC(ShaderSource); + GR_GL_GET_PROC(StencilFuncSeparate); + GR_GL_GET_PROC(StencilMaskSeparate); + GR_GL_GET_PROC(StencilOpSeparate); + GR_GL_GET_PROC(Uniform1fv); + GR_GL_GET_PROC(Uniform1i); + GR_GL_GET_PROC(Uniform4fv); + GR_GL_GET_PROC(UniformMatrix3fv); + GR_GL_GET_PROC(UseProgram); + GR_GL_GET_PROC(VertexAttrib4fv); + GR_GL_GET_PROC(VertexAttribPointer); + + // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since + // GL_ARB_framebuffer_object doesn't use ARB suffix.) + if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object", extString)) { + GR_GL_GET_PROC(GenFramebuffers); + GR_GL_GET_PROC(BindFramebuffer); + GR_GL_GET_PROC(FramebufferTexture2D); + GR_GL_GET_PROC(CheckFramebufferStatus); + GR_GL_GET_PROC(DeleteFramebuffers); + GR_GL_GET_PROC(RenderbufferStorage); + GR_GL_GET_PROC(GenRenderbuffers); + GR_GL_GET_PROC(DeleteRenderbuffers); + GR_GL_GET_PROC(FramebufferRenderbuffer); + GR_GL_GET_PROC(BindRenderbuffer); + GR_GL_GET_PROC(RenderbufferStorageMultisample); + GR_GL_GET_PROC(BlitFramebuffer); + } else if (has_gl_extension_from_string("GL_EXT_framebuffer_object", extString)) { + GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT); + GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT); + GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT); + GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT); + GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT); + GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT); + GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT); + GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT); + GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT); + GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT); + if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", extString)) { + GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT); + } + if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", extString)) { + GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT); + } + } else { + // we must have FBOs + return; + } + GR_GL_GET_PROC(MapBuffer); + GR_GL_GET_PROC(UnmapBuffer); + + gDefaultInterface.fBindingsExported = kDesktop_GrGLBinding; + + gDefaultInterfaceInit = true; + } + } + if (gDefaultInterfaceInit) { + GrGLSetGLInterface(&gDefaultInterface); + } +} diff --git a/gyp/common.gypi b/gyp/common.gypi new file mode 100644 index 0000000..aadaffb --- /dev/null +++ b/gyp/common.gypi @@ -0,0 +1,94 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +{ + 'conditions' : [ + ['OS == "win"', + { + 'target_defaults': { + 'msvs_cygwin_shell': 0, + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarningLevel': '1', + 'WarnAsError': 'false', + 'DebugInformationFormat': '3', + 'AdditionalOptions': '/MP', + }, + }, + 'configurations': { + 'Debug': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '0', # 0 = /Od + 'PreprocessorDefinitions': ['_DEBUG'], + 'RuntimeLibrary': '3', # 3 = /MDd (debug DLL) + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + }, + }, + 'Release': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'Optimization': '2', # 2 = /Os + 'PreprocessorDefinitions': ['NDEBUG'], + 'RuntimeLibrary': '2', # 2 = /MD (nondebug DLL) + }, + 'VCLinkerTool': { + 'GenerateDebugInformation': 'false', + }, + }, + }, + }, + }, + }, + ], + ['OS == "linux"', + { + 'target_defaults': { + 'configurations': { + 'Debug': { + 'cflags': ['-g'] + }, + 'Release': { + 'cflags': ['-O2'] + }, + }, + }, + }, + ], + ['OS == "mac"', + { + 'target_defaults': { + 'configurations': { + 'Debug': { + 'cflags': ['-g'] + }, + 'Release': { + 'cflags': ['-O2'] + }, + }, + }, + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/xcodebuild', + }, + }, + ], + ], +} +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/gyp/gyp_skia b/gyp/gyp_skia new file mode 100755 index 0000000..72b4879 --- /dev/null +++ b/gyp/gyp_skia @@ -0,0 +1,77 @@ +#!/usr/bin/python +# +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is a wrapper which invokes gyp with the correct --depth argument, +# and supports the automatic regeneration of build files if skia.gyp is +# changed (Linux-only). + +import glob +import os +import shlex +import sys + +script_dir = os.path.dirname(__file__) + +gyp_dir = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party')) + +sys.path.append(os.path.join(gyp_dir, 'gyp', 'pylib')) +import gyp + +def additional_include_files(args=[]): + # Determine the include files specified on the command line. + # This doesn't cover all the different option formats you can use, + # but it's mainly intended to avoid duplicating flags on the automatic + # makefile regeneration which only uses this format. + specified_includes = set() + for arg in args: + if arg.startswith('-I') and len(arg) > 2: + specified_includes.add(os.path.realpath(arg[2:])) + + result = [] + def AddInclude(path): + if os.path.realpath(path) not in specified_includes: + result.append(path) + + # Always include common.gypi + AddInclude(os.path.join(script_dir, 'common.gypi')) + + return result + +if __name__ == '__main__': + args = sys.argv[1:] + + # This could give false positives since it doesn't actually do real option + # parsing. Oh well. + gyp_file_specified = False + for arg in args: + if arg.endswith('.gyp'): + gyp_file_specified = True + break + + # If we didn't get a file, then fall back to assuming 'skia.gyp' from the + # same directory as the script. + if not gyp_file_specified: + args.append(os.path.join(script_dir, 'skia.gyp')) + + args.extend(['-I' + i for i in additional_include_files(args)]) + + args.extend(['--depth']) + args.extend([os.path.abspath(script_dir)]) + print 'Updating projects from gyp files...' + sys.stdout.flush() + + # Off we go... + sys.exit(gyp.main(args)) diff --git a/gyp/skia.gyp b/gyp/skia.gyp new file mode 100644 index 0000000..bd19c04 --- /dev/null +++ b/gyp/skia.gyp @@ -0,0 +1,1555 @@ +{ + 'target_defaults': { + 'msvs_settings': { + #really need to figure out how to generate debug and release + 'VCLinkerTool': { + 'GenerateDebugInformation': 'true', + }, + 'VCCLCompilerTool': { + 'DebugInformationFormat': '4', + 'Optimization': '0', + }, + }, + 'conditions': [ + [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { + 'include_dirs' : [ + '/usr/include/freetype2', + ], + }], + [ 'OS == "mac"', { + 'defines': [ + 'SK_BUILD_FOR_MAC', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'SK_BUILD_FOR_WIN32', + 'SK_IGNORE_STDINT_DOT_H', + ], + },], + ], + 'direct_dependent_settings': { + 'conditions': [ + [ 'OS == "mac"', { + 'defines': [ + 'SK_BUILD_FOR_MAC', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'SK_BUILD_FOR_WIN32', + ], + },], + ], + }, + }, + 'targets': [ + { + 'target_name': 'skia', + 'type': 'static_library', + 'msvs_guid': 'B7760B5E-BFA8-486B-ACFD-49E3A6DE8E76', + 'sources': [ + '../src/core/ARGB32_Clamp_Bilinear_BitmapShader.h', + '../src/core/Sk64.cpp', + '../src/core/SkAdvancedTypefaceMetrics.cpp', + '../src/core/SkAlphaRuns.cpp', + '../src/core/SkAntiRun.h', + '../src/core/SkBitmap.cpp', + '../src/core/SkBitmapProcShader.cpp', + '../src/core/SkBitmapProcShader.h', + '../src/core/SkBitmapProcState.cpp', + '../src/core/SkBitmapProcState.h', + '../src/core/SkBitmapProcState_matrix.h', + '../src/core/SkBitmapProcState_matrixProcs.cpp', + '../src/core/SkBitmapProcState_sample.h', + '../src/core/SkBitmapSampler.cpp', + '../src/core/SkBitmapSampler.h', + '../src/core/SkBitmapSamplerTemplate.h', + '../src/core/SkBitmapShader16BilerpTemplate.h', + '../src/core/SkBitmapShaderTemplate.h', + '../src/core/SkBitmap_scroll.cpp', + '../src/core/SkBlitBWMaskTemplate.h', + '../src/core/SkBlitRow_D16.cpp', + '../src/core/SkBlitRow_D32.cpp', + '../src/core/SkBlitRow_D4444.cpp', + '../src/core/SkBlitter.cpp', + '../src/core/SkBlitter_4444.cpp', + '../src/core/SkBlitter_A1.cpp', + '../src/core/SkBlitter_A8.cpp', + '../src/core/SkBlitter_ARGB32.cpp', + '../src/core/SkBlitter_RGB16.cpp', + '../src/core/SkBlitter_Sprite.cpp', + '../src/core/SkBuffer.cpp', + '../src/core/SkCanvas.cpp', + '../src/core/SkChunkAlloc.cpp', + '../src/core/SkClipStack.cpp', + '../src/core/SkColor.cpp', + '../src/core/SkColorFilter.cpp', + '../src/core/SkColorTable.cpp', + '../src/core/SkComposeShader.cpp', + '../src/core/SkConcaveToTriangles.cpp', + '../src/core/SkConcaveToTriangles.h', + '../src/core/SkCordic.cpp', + '../src/core/SkCordic.h', + '../src/core/SkCoreBlitters.h', + '../src/core/SkCubicClipper.cpp', + '../src/core/SkCubicClipper.h', + '../src/core/SkDebug.cpp', + '../src/core/SkDeque.cpp', + '../src/core/SkDevice.cpp', + '../src/core/SkDither.cpp', + '../src/core/SkDraw.cpp', + '../src/core/SkDrawProcs.h', + '../src/core/SkEdgeBuilder.cpp', + '../src/core/SkEdgeClipper.cpp', + '../src/core/SkEdge.cpp', + '../src/core/SkEdge.h', + '../src/core/SkFP.h', + '../src/core/SkFilterProc.cpp', + '../src/core/SkFilterProc.h', + '../src/core/SkFlattenable.cpp', + '../src/core/SkFloat.cpp', + '../src/core/SkFloat.h', + '../src/core/SkFloatBits.cpp', + '../src/core/SkGeometry.cpp', + '../src/core/SkGlobals.cpp', + '../src/core/SkGlyphCache.cpp', + '../src/core/SkGlyphCache.h', + '../src/core/SkGraphics.cpp', + '../src/core/SkLineClipper.cpp', + '../src/core/SkMallocPixelRef.cpp', + '../src/core/SkMask.cpp', + '../src/core/SkMaskFilter.cpp', + '../src/core/SkMath.cpp', + '../src/core/SkMatrix.cpp', + '../src/core/SkMetaData.cpp', + '../src/core/SkPackBits.cpp', + '../src/core/SkPaint.cpp', + '../src/core/SkPath.cpp', + '../src/core/SkPathEffect.cpp', + '../src/core/SkPathHeap.cpp', + '../src/core/SkPathHeap.h', + '../src/core/SkPathMeasure.cpp', + '../src/core/SkPicture.cpp', + '../src/core/SkPictureFlat.cpp', + '../src/core/SkPictureFlat.h', + '../src/core/SkPicturePlayback.cpp', + '../src/core/SkPicturePlayback.h', + '../src/core/SkPictureRecord.cpp', + '../src/core/SkPictureRecord.h', + '../src/core/SkPixelRef.cpp', + '../src/core/SkPoint.cpp', + '../src/core/SkProcSpriteBlitter.cpp', + '../src/core/SkPtrRecorder.cpp', + '../src/core/SkQuadClipper.cpp', + '../src/core/SkQuadClipper.h', + '../src/core/SkRasterizer.cpp', + '../src/core/SkRect.cpp', + '../src/core/SkRefDict.cpp', + '../src/core/SkRegion.cpp', + '../src/core/SkRegionPriv.h', + '../src/core/SkRegion_path.cpp', + '../src/core/SkScalar.cpp', + '../src/core/SkScalerContext.cpp', + '../src/core/SkScan.cpp', + '../src/core/SkScanPriv.h', + '../src/core/SkScan_AntiPath.cpp', + '../src/core/SkScan_Antihair.cpp', + '../src/core/SkScan_Hairline.cpp', + '../src/core/SkScan_Path.cpp', + '../src/core/SkShader.cpp', + '../src/core/SkShape.cpp', + '../src/core/SkSpriteBlitter_ARGB32.cpp', + '../src/core/SkSpriteBlitter_RGB16.cpp', + '../src/core/SkSinTable.h', + '../src/core/SkSpriteBlitter.h', + '../src/core/SkSpriteBlitterTemplate.h', + '../src/core/SkStream.cpp', + '../src/core/SkString.cpp', + '../src/core/SkStroke.cpp', + '../src/core/SkStrokerPriv.cpp', + '../src/core/SkStrokerPriv.h', + '../src/core/SkTextFormatParams.h', + '../src/core/SkTSearch.cpp', + '../src/core/SkTSort.h', + '../src/core/SkTemplatesPriv.h', + '../src/core/SkTypeface.cpp', + '../src/core/SkUnPreMultiply.cpp', + '../src/core/SkUtils.cpp', + '../src/core/SkWriter32.cpp', + '../src/core/SkXfermode.cpp', + + '../src/opts/opts_check_SSE2.cpp', + + '../src/ports/SkDebug_stdio.cpp', + '../src/ports/SkFontHost_tables.cpp', + '../src/ports/SkGlobals_global.cpp', + '../src/ports/SkMemory_malloc.cpp', + '../src/ports/SkOSFile_stdio.cpp', + '../src/ports/SkTime_Unix.cpp', + '../src/ports/SkXMLParser_empty.cpp', + '../src/ports/sk_predefined_gamma.h', + + '../include/core/Sk64.h', + '../include/core/SkAdvancedTypefaceMetrics.h', + '../include/core/SkAutoKern.h', + '../include/core/SkBitmap.h', + '../include/core/SkBlitRow.h', + '../include/core/SkBlitter.h', + '../include/core/SkBounder.h', + '../include/core/SkBuffer.h', + '../include/core/SkCanvas.h', + '../include/core/SkChunkAlloc.h', + '../include/core/SkClipStack.h', + '../include/core/SkColor.h', + '../include/core/SkColorFilter.h', + '../include/core/SkColorPriv.h', + '../include/core/SkColorShader.h', + '../include/core/SkComposeShader.h', + '../include/core/SkDeque.h', + '../include/core/SkDescriptor.h', + '../include/core/SkDevice.h', + '../include/core/SkDither.h', + '../include/core/SkDraw.h', + '../include/core/SkDrawFilter.h', + '../include/core/SkDrawLooper.h', + '../include/core/SkEndian.h', + '../include/core/SkFDot6.h', + '../include/core/SkFixed.h', + '../include/core/SkFlattenable.h', + '../include/core/SkFloatBits.h', + '../include/core/SkFloatingPoint.h', + '../include/core/SkFontHost.h', + '../include/core/SkGeometry.h', + '../include/core/SkGlobals.h', + '../include/core/SkGraphics.h', + '../include/core/SkMallocPixelRef.h', + '../include/core/SkMask.h', + '../include/core/SkMaskFilter.h', + '../include/core/SkMath.h', + '../include/core/SkMatrix.h', + '../include/core/SkMetaData.h', + '../include/core/SkOSFile.h', + '../include/core/SkPackBits.h', + '../include/core/SkPaint.h', + '../include/core/SkPath.h', + '../include/core/SkPathEffect.h', + '../include/core/SkPathMeasure.h', + '../include/core/SkPerspIter.h', + '../include/core/SkPicture.h', + '../include/core/SkPixelRef.h', + '../include/core/SkPoint.h', + '../include/core/SkPtrRecorder.h', + '../include/core/SkRandom.h', + '../include/core/SkRasterizer.h', + '../include/core/SkReader32.h', + '../include/core/SkRect.h', + '../include/core/SkRefCnt.h', + '../include/core/SkRefDict.h', + '../include/core/SkRegion.h', + '../include/core/SkScalar.h', + '../include/core/SkScalarCompare.h', + '../include/core/SkScalerContext.h', + '../include/core/SkScan.h', + '../include/core/SkShader.h', + '../include/core/SkStream.h', + '../include/core/SkString.h', + '../include/core/SkStroke.h', + '../include/core/SkTDArray.h', + '../include/core/SkTDStack.h', + '../include/core/SkTDict.h', + '../include/core/SkTRegistry.h', + '../include/core/SkTScopedPtr.h', + '../include/core/SkTSearch.h', + '../include/core/SkTemplates.h', + '../include/core/SkThread.h', + '../include/core/SkThread_platform.h', + '../include/core/SkTime.h', + '../include/core/SkTypeface.h', + '../include/core/SkTypes.h', + '../include/core/SkUnPreMultiply.h', + '../include/core/SkUnitMapper.h', + '../include/core/SkUtils.h', + '../include/core/SkWriter32.h', + '../include/core/SkXfermode.h', + ], + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/ports', + '../include/xml', + '../src/core', + ], + 'msvs_disabled_warnings': [4244, 4267,4345, 4390, 4554, 4800], + 'conditions': [ + [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { + 'cflags': [ + '-Wno-unused', + '-Wno-unused-function', + ], + 'sources': [ + '../include/core/SkMMapStream.h', + '../src/core/SkMMapStream.cpp', + '../src/core/SkBlitter_ARGB32_Subpixel.cpp', + '../src/core/SkFontHost.cpp', + '../src/ports/SkThread_pthread.cpp', + '../src/ports/SkTime_Unix.cpp', + '../src/ports/SkFontHost_FreeType_Subpixel.cpp', + '../src/ports/SkFontHost_FreeType.cpp', + '../src/ports/SkFontHost_gamma_none.cpp', + '../src/ports/SkFontHost_linux.cpp', + ], + 'link_settings': { + 'libraries': [ + '-lfreetype', + '-lpthread', + ], + }, + }], + [ 'OS == "mac"', { + 'include_dirs': [ + '../include/utils/mac', + ], + 'sources': [ + '../include/core/SkMMapStream.h', + '../include/utils/mac/SkCGUtils.h', + + '../src/core/SkMMapStream.cpp', + '../src/ports/SkFontHost_mac_coretext.cpp', + + '../src/ports/SkThread_pthread.cpp', + '../src/ports/SkTime_Unix.cpp', + + '../src/utils/mac/SkCreateCGImageRef.cpp', + ], + }], + [ 'OS == "win"', { + 'include_dirs': [ + 'config/win', + ], + 'sources': [ + '../src/ports/SkFontHost_win.cpp', + '../src/ports/SkThread_win.cpp', + ], + },], + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'config', + '../include/config', + '../include/core', + 'ext', + ], + }, + 'dependencies': [ + 'skia_opts' + ], + }, + + # Due to an unfortunate intersection of lameness between gcc and gyp, + # we have to build the *_SSE2.cpp files in a separate target. The + # gcc lameness is that, in order to compile SSE2 intrinsics code, it + # must be passed the -msse2 flag. However, with this flag, it may + # emit SSE2 instructions even for scalar code, such as the CPUID + # test used to test for the presence of SSE2. So that, and all other + # code must be compiled *without* -msse2. The gyp lameness is that it + # does not allow file-specific CFLAGS, so we must create this extra + # target for those files to be compiled with -msse2. + # + # This is actually only a problem on 32-bit Linux (all Intel Macs have + # SSE2, Linux x86_64 has SSE2 by definition, and MSC will happily emit + # SSE2 from instrinsics, while generating plain ol' 386 for everything + # else). However, to keep the .gyp file simple and avoid platform-specific + # build breakage, we do this on all platforms. + + # For about the same reason, we need to compile the ARM opts files + # separately as well. + { + 'target_name': 'skia_opts', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../src/core', + ], + 'conditions': [ + [ '(OS == "linux" or OS == "freebsd" or OS == "openbsd")', { + 'cflags': [ + '-msse2', + ], + }], + ], + 'sources': [ + '../src/opts/SkBitmapProcState_opts_SSE2.cpp', + '../src/opts/SkBlitRow_opts_SSE2.cpp', + '../src/opts/SkUtils_opts_SSE2.cpp', + ], + }, + { + 'target_name': 'effects', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/effects', + ], + 'sources': [ + '../include/effects/Sk1DPathEffect.h', + '../include/effects/Sk2DPathEffect.h', + '../include/effects/SkAvoidXfermode.h', + '../include/effects/SkBlurDrawLooper.h', + '../include/effects/SkBlurMaskFilter.h', + '../include/effects/SkColorMatrix.h', + '../include/effects/SkColorMatrixFilter.h', + '../include/effects/SkCornerPathEffect.h', + '../include/effects/SkDashPathEffect.h', + '../include/effects/SkDiscretePathEffect.h', + '../include/effects/SkDrawExtraPathEffect.h', + '../include/effects/SkEmbossMaskFilter.h', + '../include/effects/SkGradientShader.h', + '../include/effects/SkGroupShape.h', + '../include/effects/SkKernel33MaskFilter.h', + '../include/effects/SkLayerDrawLooper.h', + '../include/effects/SkLayerRasterizer.h', + '../include/effects/SkPaintFlagsDrawFilter.h', + '../include/effects/SkPixelXorXfermode.h', + '../include/effects/SkPorterDuff.h', + '../include/effects/SkRectShape.h', + '../include/effects/SkTableMaskFilter.h', + '../include/effects/SkTransparentShader.h', + + '../src/effects/Sk1DPathEffect.cpp', + '../src/effects/Sk2DPathEffect.cpp', + '../src/effects/SkAvoidXfermode.cpp', + '../src/effects/SkBitmapCache.cpp', + '../src/effects/SkBitmapCache.h', + '../src/effects/SkBlurDrawLooper.cpp', + '../src/effects/SkBlurMask.cpp', + '../src/effects/SkBlurMask.h', + '../src/effects/SkBlurMaskFilter.cpp', + '../src/effects/SkColorFilters.cpp', + '../src/effects/SkColorMatrixFilter.cpp', + '../src/effects/SkCornerPathEffect.cpp', + '../src/effects/SkDashPathEffect.cpp', + '../src/effects/SkDiscretePathEffect.cpp', + '../src/effects/SkEmbossMask.cpp', + '../src/effects/SkEmbossMask.h', + '../src/effects/SkEmbossMask_Table.h', + '../src/effects/SkEmbossMaskFilter.cpp', + '../src/effects/SkGradientShader.cpp', + '../src/effects/SkGroupShape.cpp', + '../src/effects/SkKernel33MaskFilter.cpp', + '../src/effects/SkLayerDrawLooper.cpp', + '../src/effects/SkLayerRasterizer.cpp', + '../src/effects/SkPaintFlagsDrawFilter.cpp', + '../src/effects/SkPixelXorXfermode.cpp', + '../src/effects/SkPorterDuff.cpp', + '../src/effects/SkRadialGradient_Table.h', + '../src/effects/SkRectShape.cpp', + '../src/effects/SkTableMaskFilter.cpp', + '../src/effects/SkTransparentShader.cpp', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/effects', + ], + }, + }, + { + 'target_name': 'images', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/images', + ], + 'sources': [ + '../include/images/SkFlipPixelRef.h', + '../include/images/SkImageDecoder.h', + '../include/images/SkImageEncoder.h', + '../include/images/SkImageRef.h', + '../include/images/SkImageRef_GlobalPool.h', + '../include/images/SkJpegUtility.h', + '../include/images/SkMovie.h', + '../include/images/SkPageFlipper.h', + + '../src/images/bmpdecoderhelper.cpp', + '../src/images/bmpdecoderhelper.h', + '../src/images/SkBitmap_RLEPixels.h', + '../src/images/SkCreateRLEPixelRef.cpp', + '../src/images/SkFDStream.cpp', + '../src/images/SkFlipPixelRef.cpp', + '../src/images/SkImageDecoder.cpp', + '../src/images/SkImageDecoder_Factory.cpp', + '../src/images/SkImageDecoder_libbmp.cpp', + '../src/images/SkImageDecoder_libgif.cpp', + '../src/images/SkImageDecoder_libico.cpp', + '../src/images/SkImageDecoder_libjpeg.cpp', + '../src/images/SkImageDecoder_libpng.cpp', + '../src/images/SkImageDecoder_libpvjpeg.c', + '../src/images/SkImageDecoder_wbmp.cpp', + '../src/images/SkImageEncoder.cpp', + '../src/images/SkImageEncoder_Factory.cpp', + '../src/images/SkImageRef.cpp', + '../src/images/SkImageRefPool.cpp', + '../src/images/SkImageRefPool.h', + '../src/images/SkImageRef_GlobalPool.cpp', + '../src/images/SkJpegUtility.cpp', + '../src/images/SkMovie.cpp', + '../src/images/SkMovie_gif.cpp', + '../src/images/SkPageFlipper.cpp', + '../src/images/SkScaledBitmapSampler.cpp', + '../src/images/SkScaledBitmapSampler.h', + ], + 'conditions': [ + [ 'OS == "win"', { + 'sources!': [ + '../include/images/SkJpegUtility.h', + + '../src/images/SkFDStream.cpp', + '../src/images/SkImageDecoder_libgif.cpp', + '../src/images/SkImageDecoder_libjpeg.cpp', + '../src/images/SkImageDecoder_libpng.cpp', + '../src/images/SkImageDecoder_libpvjpeg.c', + '../src/images/SkJpegUtility.cpp', + '../src/images/SkMovie_gif.cpp', + ], + },], + [ 'OS == "mac"', { + 'sources!': [ + '../include/images/SkJpegUtility.h', + + '../src/images/SkImageDecoder_libgif.cpp', + '../src/images/SkImageDecoder_libjpeg.cpp', + '../src/images/SkImageDecoder_libpng.cpp', + '../src/images/SkImageDecoder_libpvjpeg.c', + '../src/images/SkJpegUtility.cpp', + '../src/images/SkMovie_gif.cpp', + ], + },], + [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { + 'sources!': [ + '../include/images/SkJpegUtility.h', + + '../src/images/SkImageDecoder_libjpeg.cpp', + '../src/images/SkImageDecoder_libgif.cpp', + '../src/images/SkImageDecoder_libpvjpeg.c', + '../src/images/SkJpegUtility.cpp', + '../src/images/SkMovie_gif.cpp', + ], + }], + + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/images', + ], + }, + }, + { + 'target_name': 'xml', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/xml', + '../include/utils', + ], + 'sources': [ + '../include/xml/SkBML_WXMLParser.h', + '../include/xml/SkBML_XMLParser.h', + '../include/xml/SkDOM.h', + '../include/xml/SkJS.h', + '../include/xml/SkXMLParser.h', + '../include/xml/SkXMLWriter.h', + + '../src/xml/SkBML_Verbs.h', + '../src/xml/SkBML_XMLParser.cpp', + '../src/xml/SkDOM.cpp', + '../src/xml/SkJS.cpp', + '../src/xml/SkJSDisplayable.cpp', + '../src/xml/SkXMLParser.cpp', + '../src/xml/SkXMLPullParser.cpp', + '../src/xml/SkXMLWriter.cpp', + ], + 'sources!': [ + '../src/xml/SkXMLPullParser.cpp', #if 0 around class decl in header + ], + 'conditions': [ + [ 'OS == "win" or OS == "mac" or OS == "linux" or OS == "openbsd" or OS == "solaris"', { + 'sources!': [ + # no jsapi.h by default on system + '../include/xml/SkJS.h', + '../src/xml/SkJS.cpp', + '../src/xml/SkJSDisplayable.cpp', + ], + },], + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/xml', + ], + }, + }, + { + 'target_name': 'pdf', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/pdf', + '../src/core', # needed to get SkGlyphCache.h and SkTextFormatParams.h + ], + 'sources': [ + '../include/pdf/SkPDFCatalog.h', + '../include/pdf/SkPDFDevice.h', + '../include/pdf/SkPDFDocument.h', + '../include/pdf/SkPDFFont.h', + '../include/pdf/SkPDFFormXObject.h', + '../include/pdf/SkPDFGraphicState.h', + '../include/pdf/SkPDFImage.h', + '../include/pdf/SkPDFPage.h', + '../include/pdf/SkPDFShader.h', + '../include/pdf/SkPDFStream.h', + '../include/pdf/SkPDFTypes.h', + '../include/pdf/SkPDFUtils.h', + + '../src/pdf/SkPDFCatalog.cpp', + '../src/pdf/SkPDFDevice.cpp', + '../src/pdf/SkPDFDocument.cpp', + '../src/pdf/SkPDFFont.cpp', + '../src/pdf/SkPDFFormXObject.cpp', + '../src/pdf/SkPDFGraphicState.cpp', + '../src/pdf/SkPDFImage.cpp', + '../src/pdf/SkPDFPage.cpp', + '../src/pdf/SkPDFShader.cpp', + '../src/pdf/SkPDFStream.cpp', + '../src/pdf/SkPDFTypes.cpp', + '../src/pdf/SkPDFUtils.cpp', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/pdf', + ], + }, + }, + { + 'target_name': 'utils', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/utils', + '../include/views', + '../include/effects', + '../include/xml', + ], + 'sources': [ + '../include/utils/SkBoundaryPatch.h', + '../include/utils/SkCamera.h', + '../include/utils/SkCubicInterval.h', + '../include/utils/SkCullPoints.h', + '../include/utils/SkDumpCanvas.h', + '../include/utils/SkEGLContext.h', + '../include/utils/SkGLCanvas.h', + '../include/utils/SkInterpolator.h', + '../include/utils/SkLayer.h', + '../include/utils/SkMeshUtils.h', + '../include/utils/SkNinePatch.h', + '../include/utils/SkNWayCanvas.h', + '../include/utils/SkParse.h', + '../include/utils/SkParsePaint.h', + '../include/utils/SkParsePath.h', + '../include/utils/SkProxyCanvas.h', + '../include/utils/SkSfntUtils.h', + '../include/utils/SkTextBox.h', + '../include/utils/SkUnitMappers.h', + + '../src/utils/SkBoundaryPatch.cpp', + '../src/utils/SkCamera.cpp', + '../src/utils/SkColorMatrix.cpp', + '../src/utils/SkCubicInterval.cpp', + '../src/utils/SkCullPoints.cpp', + '../src/utils/SkDumpCanvas.cpp', + '../src/utils/SkEGLContext_none.cpp', + '../src/utils/SkInterpolator.cpp', + '../src/utils/SkLayer.cpp', + '../src/utils/SkMeshUtils.cpp', + '../src/utils/SkNinePatch.cpp', + '../src/utils/SkNWayCanvas.cpp', + '../src/utils/SkOSFile.cpp', + '../src/utils/SkParse.cpp', + '../src/utils/SkParseColor.cpp', + '../src/utils/SkParsePath.cpp', + '../src/utils/SkProxyCanvas.cpp', + '../src/utils/SkSfntUtils.cpp', + '../src/utils/SkUnitMappers.cpp', + ], + 'conditions': [ + [ 'OS == "mac"', { + 'sources': [ + '../include/utils/SkCGUtils.h', + '../src/utils/mac/SkCreateCGImageRef.cpp', + '../src/utils/mac/SkEGLContext_mac.cpp', + ], + },], + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/utils', + ], + }, + }, + { + 'target_name': 'views', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/views', + '../include/xml', + '../include/utils', + '../include/images', + '../include/animator', + '../include/effects', + ], + 'sources': [ + '../include/views/SkApplication.h', + '../include/views/SkBGViewArtist.h', + '../include/views/SkBorderView.h', + '../include/views/SkEvent.h', + '../include/views/SkEventSink.h', + '../include/views/SkImageView.h', + '../include/views/SkKey.h', + '../include/views/SkOSMenu.h', + '../include/views/SkOSWindow_Mac.h', + '../include/views/SkOSWindow_SDL.h', + '../include/views/SkOSWindow_Unix.h', + '../include/views/SkOSWindow_Win.h', + #'../include/views/SkOSWindow_wxwidgets.h', + '../include/views/SkProgressBarView.h', + '../include/views/SkScrollBarView.h', + '../include/views/SkStackViewLayout.h', + '../include/views/SkSystemEventTypes.h', + '../include/views/SkTouchGesture.h', + '../include/views/SkView.h', + '../include/views/SkViewInflate.h', + '../include/views/SkWidget.h', + '../include/views/SkWidgetViews.h', + '../include/views/SkWindow.h', + + '../src/views/SkBGViewArtist.cpp', + '../src/views/SkBorderView.cpp', + '../src/views/SkEvent.cpp', + '../src/views/SkEventSink.cpp', + '../src/views/SkImageView.cpp', + '../src/views/SkListView.cpp', + '../src/views/SkListWidget.cpp', + '../src/views/SkOSMenu.cpp', + '../src/views/SkParsePaint.cpp', + '../src/views/SkProgressBarView.cpp', + '../src/views/SkProgressView.cpp', + '../src/views/SkScrollBarView.cpp', + '../src/views/SkStackViewLayout.cpp', + '../src/views/SkStaticTextView.cpp', + '../src/views/SkTagList.cpp', + '../src/views/SkTagList.h', + '../src/views/SkTextBox.cpp', + '../src/views/SkTouchGesture.cpp', + '../src/views/SkView.cpp', + '../src/views/SkViewInflate.cpp', + '../src/views/SkViewPriv.cpp', + '../src/views/SkViewPriv.h', + '../src/views/SkWidget.cpp', + '../src/views/SkWidgets.cpp', + '../src/views/SkWidgetViews.cpp', + '../src/views/SkWindow.cpp', + ], + 'sources!' : [ + '../src/views/SkListView.cpp', #depends on missing SkListSource implementation + '../src/views/SkListWidget.cpp', #depends on missing SkListSource implementation + ], + 'conditions': [ + [ 'OS == "win"', { + 'sources': [ + '../src/utils/win/SkOSWindow_Win.cpp', + '../src/utils/win/skia_win.cpp', + ], + },], + [ 'OS == "mac"', { + 'sources': [ + '../include/utils/SkCGUtils.h', + #'../src/utils/mac/SkBitmap_Mac.cpp', + '../src/utils/mac/SkCreateCGImageRef.cpp', + '../src/utils/mac/SkEGLContext_mac.cpp', + '../src/utils/mac/skia_mac.cpp', + '../src/utils/mac/SkOSWindow_Mac.cpp', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Carbon.framework', + '$(SDKROOT)/System/Library/Frameworks/AGL.framework', + ], + }, + },], + [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { + 'include_dirs' : [ + '../include/utils/unix', + ], + 'sources': [ + '../src/utils/unix/keysym2ucs.c', + '../src/utils/unix/SkOSWindow_Unix.cpp', + '../unix_test_app/main.cpp', + ], + }], + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/views', + ], + }, + }, + { + 'target_name': 'skgr', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../src/core', + '../include/gpu', + '../gpu/include', + ], + 'sources': [ + '../include/gpu/SkGpuCanvas.h', + '../include/gpu/SkGpuDevice.h', + '../include/gpu/SkGpuDeviceFactory.h', + '../include/gpu/SkGr.h', + '../include/gpu/SkGrTexturePixelRef.h', + + '../src/gpu/GrPrintf_skia.cpp', + '../src/gpu/SkGpuCanvas.cpp', + '../src/gpu/SkGpuDevice.cpp', + '../src/gpu/SkGr.cpp', + '../src/gpu/SkGrFontScaler.cpp', + '../src/gpu/SkGrTexturePixelRef.cpp', + ], + 'conditions': [ + [ 'OS == "linux"', { + 'defines': [ + 'GR_LINUX_BUILD=1', + ], + }], + [ 'OS == "mac"', { + 'defines': [ + 'GR_MAC_BUILD=1', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'GR_WIN32_BUILD=1', + ], + },], + ], + 'direct_dependent_settings': { + 'conditions': [ + [ 'OS == "linux"', { + 'defines': [ + 'GR_LINUX_BUILD=1', + ], + }], + [ 'OS == "mac"', { + 'defines': [ + 'GR_MAC_BUILD=1', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'GR_WIN32_BUILD=1', + ], + },], + ], + 'include_dirs': [ + '../include/gpu', + ], + }, + }, + { + 'target_name': 'gr', + 'type': 'static_library', + 'include_dirs': [ + '../gpu/include', + ], + #'dependencies': [ + # 'libtess', + #], + 'sources': [ + '../gpu/include/GrAllocator.h', + '../gpu/include/GrAllocPool.h', + '../gpu/include/GrAtlas.h', + '../gpu/include/GrClip.h', + '../gpu/include/GrClipIterator.h', + '../gpu/include/GrColor.h', + '../gpu/include/GrConfig.h', + '../gpu/include/GrContext.h', + '../gpu/include/GrContext_impl.h', + '../gpu/include/GrDrawTarget.h', + '../gpu/include/GrFontScaler.h', + '../gpu/include/GrGeometryBuffer.h', + '../gpu/include/GrGLConfig.h', + '../gpu/include/GrGLConfig_chrome.h', + '../gpu/include/GrGLIndexBuffer.h', + '../gpu/include/GrGLInterface.h', + '../gpu/include/GrGLIRect.h', + '../gpu/include/GrGLTexture.h', + '../gpu/include/GrGLVertexBuffer.h', + '../gpu/include/GrGlyph.h', + '../gpu/include/GrGpu.h', + '../gpu/include/GrGpuVertex.h', + '../gpu/include/GrIndexBuffer.h', + '../gpu/include/GrInOrderDrawBuffer.h', + '../gpu/include/GrInstanceCounter.h', + '../gpu/include/GrIPoint.h', + '../gpu/include/GrKey.h', + '../gpu/include/GrMatrix.h', + '../gpu/include/GrMemory.h', + '../gpu/include/GrMesh.h', + '../gpu/include/GrNoncopyable.h', + '../gpu/include/GrPaint.h', + '../gpu/include/GrPath.h', + '../gpu/include/GrPathIter.h', + '../gpu/include/GrPathRenderer.h', + '../gpu/include/GrPathSink.h', + '../gpu/include/GrPlotMgr.h', + '../gpu/include/GrPoint.h', + '../gpu/include/GrRandom.h', + '../gpu/include/GrRect.h', + '../gpu/include/GrRectanizer.h', + '../gpu/include/GrRefCnt.h', + '../gpu/include/GrResource.h', + '../gpu/include/GrSamplerState.h', + '../gpu/include/GrScalar.h', + '../gpu/include/GrStencil.h', + '../gpu/include/GrStopwatch.h', + '../gpu/include/GrStringBuilder.h', + '../gpu/include/GrTArray.h', + '../gpu/include/GrTBSearch.h', + '../gpu/include/GrTDArray.h', + #'../gpu/include/GrTesselatedPathRenderer.h', + '../gpu/include/GrTextContext.h', + '../gpu/include/GrTextStrike.h', + '../gpu/include/GrTexture.h', + '../gpu/include/GrTextureCache.h', + '../gpu/include/GrTHashCache.h', + '../gpu/include/GrTLList.h', + '../gpu/include/GrTouchGesture.h', + '../gpu/include/GrTypes.h', + '../gpu/include/GrUserConfig.h', + '../gpu/include/GrVertexBuffer.h', + + '../gpu/src/GrAllocPool.cpp', + '../gpu/src/GrAtlas.cpp', + '../gpu/src/GrBinHashKey.h', + '../gpu/src/GrBufferAllocPool.cpp', + '../gpu/src/GrBufferAllocPool.h', + '../gpu/src/GrClip.cpp', + '../gpu/src/GrContext.cpp', + '../gpu/src/GrCreatePathRenderer_none.cpp', + '../gpu/src/GrDrawTarget.cpp', + '../gpu/src/GrGLEffect.h', + '../gpu/src/GrGLDefaultInterface_none.cpp', + '../gpu/src/GrGLIndexBuffer.cpp', + '../gpu/src/GrGLInterface.cpp', + '../gpu/src/GrGLProgram.cpp', + '../gpu/src/GrGLProgram.h', + '../gpu/src/GrGLTexture.cpp', + '../gpu/src/GrGLUtil.cpp', + '../gpu/src/GrGLVertexBuffer.cpp', + '../gpu/src/GrGpu.cpp', + '../gpu/src/GrGpuFactory.cpp', + '../gpu/src/GrGpuGL.cpp', + '../gpu/src/GrGpuGL.h', + '../gpu/src/GrGpuGLFixed.cpp', + '../gpu/src/GrGpuGLFixed.h', + '../gpu/src/GrGpuGLShaders.cpp', + '../gpu/src/GrGpuGLShaders.h', + '../gpu/src/GrGpuGLShaders2.cpp', + '../gpu/src/GrGpuGLShaders2.h', + '../gpu/src/GrInOrderDrawBuffer.cpp', + '../gpu/src/GrMatrix.cpp', + '../gpu/src/GrMemory.cpp', + '../gpu/src/GrPath.cpp', + '../gpu/src/GrPathRenderer.cpp', + '../gpu/src/GrPathUtils.cpp', + '../gpu/src/GrPathUtils.h', + '../gpu/src/GrPrintf_printf.cpp', + '../gpu/src/GrRectanizer.cpp', + '../gpu/src/GrRedBlackTree.h', + '../gpu/src/GrResource.cpp', + '../gpu/src/GrStencil.cpp', + #'../gpu/src/GrTesselatedPathRenderer.cpp', + '../gpu/src/GrTextContext.cpp', + '../gpu/src/GrTextStrike.cpp', + '../gpu/src/GrTextStrike_impl.h', + '../gpu/src/GrTexture.cpp', + '../gpu/src/GrTextureCache.cpp', + '../gpu/src/gr_unittests.cpp', + + '../gpu/src/mac/GrGLDefaultInterface_mac.cpp', + + '../gpu/src/win/GrGLDefaultInterface_win.cpp', + ], + 'defines': [ + 'GR_IMPLEMENTATION=1', + ], + 'conditions': [ + [ 'OS == "linux"', { + 'defines': [ + 'GR_LINUX_BUILD=1', + ], + 'link_settings': { + 'libraries': [ + '-lGL', + '-lX11', + ], + }, + }], + [ 'OS == "mac"', { + 'defines': [ + 'GR_MAC_BUILD=1', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', + ], + }, + 'sources!': [ + '../gpu/src/GrGLDefaultInterface_none.cpp', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'GR_WIN32_BUILD=1', + 'GR_GL_FUNCTION_TYPE=__stdcall', + ], + 'sources!': [ + '../gpu/src/GrGLDefaultInterface_none.cpp', + ], + },], + [ 'OS != "win"', { + 'sources!': [ + '../gpu/src/win/GrGLDefaultInterface_win.cpp', + ], + }], + [ 'OS != "mac"', { + 'sources!': [ + '../gpu/src/mac/GrGLDefaultInterface_mac.cpp', + ], + }], + ], + 'direct_dependent_settings': { + 'conditions': [ + [ 'OS == "linux"', { + 'defines': [ + 'GR_LINUX_BUILD=1', + ], + }], + [ 'OS == "mac"', { + 'defines': [ + 'GR_MAC_BUILD=1', + ], + }], + [ 'OS == "win"', { + 'defines': [ + 'GR_WIN32_BUILD=1', + 'GR_GL_FUNCTION_TYPE=__stdcall', + ], + },], + ], + 'include_dirs': [ + '../gpu/include', + ], + }, + }, + { + 'target_name': 'animator', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/effects', + '../include/animator', + '../include/views', + '../include/xml', + '../include/utils', + '../include/images', + ], + 'sources': [ + '../include/animator/SkAnimator.h', + '../include/animator/SkAnimatorView.h', + + '../src/animator/SkAnimate.h', + '../src/animator/SkAnimateActive.cpp', + '../src/animator/SkAnimateActive.h', + '../src/animator/SkAnimateBase.cpp', + '../src/animator/SkAnimateBase.h', + '../src/animator/SkAnimateField.cpp', + '../src/animator/SkAnimateMaker.cpp', + '../src/animator/SkAnimateMaker.h', + '../src/animator/SkAnimateProperties.h', + '../src/animator/SkAnimateSet.cpp', + '../src/animator/SkAnimateSet.h', + '../src/animator/SkAnimator.cpp', + '../src/animator/SkAnimatorScript.cpp', + '../src/animator/SkAnimatorScript.h', + #'../src/animator/SkAnimatorScript2.cpp', fails on windows + #'../src/animator/SkAnimatorScript2.h', + '../src/animator/SkBase64.cpp', + '../src/animator/SkBase64.h', + '../src/animator/SkBoundable.cpp', + '../src/animator/SkBoundable.h', + '../src/animator/SkBuildCondensedInfo.cpp', + #'../src/animator/SkCondensedDebug.cpp', fails on windows + '../src/animator/SkCondensedRelease.cpp', + '../src/animator/SkDisplayable.cpp', + '../src/animator/SkDisplayable.h', + '../src/animator/SkDisplayAdd.cpp', + '../src/animator/SkDisplayAdd.h', + '../src/animator/SkDisplayApply.cpp', + '../src/animator/SkDisplayApply.h', + '../src/animator/SkDisplayBounds.cpp', + '../src/animator/SkDisplayBounds.h', + '../src/animator/SkDisplayEvent.cpp', + '../src/animator/SkDisplayEvent.h', + '../src/animator/SkDisplayEvents.cpp', + '../src/animator/SkDisplayEvents.h', + '../src/animator/SkDisplayInclude.cpp', + '../src/animator/SkDisplayInclude.h', + '../src/animator/SkDisplayInput.cpp', + '../src/animator/SkDisplayInput.h', + '../src/animator/SkDisplayList.cpp', + '../src/animator/SkDisplayList.h', + '../src/animator/SkDisplayMath.cpp', + '../src/animator/SkDisplayMath.h', + '../src/animator/SkDisplayMovie.cpp', + '../src/animator/SkDisplayMovie.h', + '../src/animator/SkDisplayNumber.cpp', + '../src/animator/SkDisplayNumber.h', + '../src/animator/SkDisplayPost.cpp', + '../src/animator/SkDisplayPost.h', + '../src/animator/SkDisplayRandom.cpp', + '../src/animator/SkDisplayRandom.h', + '../src/animator/SkDisplayScreenplay.cpp', + '../src/animator/SkDisplayScreenplay.h', + '../src/animator/SkDisplayType.cpp', + '../src/animator/SkDisplayType.h', + '../src/animator/SkDisplayTypes.cpp', + '../src/animator/SkDisplayTypes.h', + '../src/animator/SkDisplayXMLParser.cpp', + '../src/animator/SkDisplayXMLParser.h', + '../src/animator/SkDraw3D.cpp', + '../src/animator/SkDraw3D.h', + '../src/animator/SkDrawable.cpp', + '../src/animator/SkDrawable.h', + '../src/animator/SkDrawBitmap.cpp', + '../src/animator/SkDrawBitmap.h', + '../src/animator/SkDrawBlur.cpp', + '../src/animator/SkDrawBlur.h', + '../src/animator/SkDrawClip.cpp', + '../src/animator/SkDrawClip.h', + '../src/animator/SkDrawColor.cpp', + '../src/animator/SkDrawColor.h', + '../src/animator/SkDrawDash.cpp', + '../src/animator/SkDrawDash.h', + '../src/animator/SkDrawDiscrete.cpp', + '../src/animator/SkDrawDiscrete.h', + '../src/animator/SkDrawEmboss.cpp', + '../src/animator/SkDrawEmboss.h', + '../src/animator/SkDrawExtraPathEffect.cpp', + '../src/animator/SkDrawFull.cpp', + '../src/animator/SkDrawFull.h', + '../src/animator/SkDrawGradient.cpp', + '../src/animator/SkDrawGradient.h', + '../src/animator/SkDrawGroup.cpp', + '../src/animator/SkDrawGroup.h', + '../src/animator/SkDrawLine.cpp', + '../src/animator/SkDrawLine.h', + '../src/animator/SkDrawMatrix.cpp', + '../src/animator/SkDrawMatrix.h', + '../src/animator/SkDrawOval.cpp', + '../src/animator/SkDrawOval.h', + '../src/animator/SkDrawPaint.cpp', + '../src/animator/SkDrawPaint.h', + '../src/animator/SkDrawPath.cpp', + '../src/animator/SkDrawPath.h', + '../src/animator/SkDrawPoint.cpp', + '../src/animator/SkDrawPoint.h', + '../src/animator/SkDrawRectangle.cpp', + '../src/animator/SkDrawRectangle.h', + '../src/animator/SkDrawSaveLayer.cpp', + '../src/animator/SkDrawSaveLayer.h', + '../src/animator/SkDrawShader.cpp', + '../src/animator/SkDrawShader.h', + '../src/animator/SkDrawText.cpp', + '../src/animator/SkDrawText.h', + '../src/animator/SkDrawTextBox.cpp', + '../src/animator/SkDrawTextBox.h', + '../src/animator/SkDrawTo.cpp', + '../src/animator/SkDrawTo.h', + '../src/animator/SkDrawTransparentShader.cpp', + '../src/animator/SkDrawTransparentShader.h', + '../src/animator/SkDump.cpp', + '../src/animator/SkDump.h', + '../src/animator/SkExtras.h', + '../src/animator/SkGetCondensedInfo.cpp', + '../src/animator/SkHitClear.cpp', + '../src/animator/SkHitClear.h', + '../src/animator/SkHitTest.cpp', + '../src/animator/SkHitTest.h', + '../src/animator/SkIntArray.h', + '../src/animator/SkMatrixParts.cpp', + '../src/animator/SkMatrixParts.h', + '../src/animator/SkMemberInfo.cpp', + '../src/animator/SkMemberInfo.h', + '../src/animator/SkOpArray.cpp', + '../src/animator/SkOpArray.h', + '../src/animator/SkOperand.h', + '../src/animator/SkOperand2.h', + '../src/animator/SkOperandInterpolator.h', + '../src/animator/SkOperandIterpolator.cpp', + '../src/animator/SkPaintParts.cpp', + '../src/animator/SkPaintParts.h', + '../src/animator/SkParseSVGPath.cpp', + '../src/animator/SkPathParts.cpp', + '../src/animator/SkPathParts.h', + '../src/animator/SkPostParts.cpp', + '../src/animator/SkPostParts.h', + '../src/animator/SkScript.cpp', + '../src/animator/SkScript.h', + '../src/animator/SkScript2.h', + '../src/animator/SkScriptCallBack.h', + '../src/animator/SkScriptDecompile.cpp', + '../src/animator/SkScriptRuntime.cpp', + '../src/animator/SkScriptRuntime.h', + '../src/animator/SkScriptTokenizer.cpp', + '../src/animator/SkSnapshot.cpp', + '../src/animator/SkSnapshot.h', + '../src/animator/SkTDArray_Experimental.h', + '../src/animator/SkTextOnPath.cpp', + '../src/animator/SkTextOnPath.h', + '../src/animator/SkTextToPath.cpp', + '../src/animator/SkTextToPath.h', + '../src/animator/SkTime.cpp', + '../src/animator/SkTypedArray.cpp', + '../src/animator/SkTypedArray.h', + '../src/animator/SkXMLAnimatorWriter.cpp', + '../src/animator/SkXMLAnimatorWriter.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/animator', + ], + }, + }, + + { + 'target_name': 'svg', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + '../include/xml', + '../include/utils', + '../include/svg', + ], + 'sources': [ + '../include/svg/SkSVGAttribute.h', + '../include/svg/SkSVGBase.h', + '../include/svg/SkSVGPaintState.h', + '../include/svg/SkSVGParser.h', + '../include/svg/SkSVGTypes.h', + + '../src/svg/SkSVGCircle.cpp', + '../src/svg/SkSVGCircle.h', + '../src/svg/SkSVGClipPath.cpp', + '../src/svg/SkSVGClipPath.h', + '../src/svg/SkSVGDefs.cpp', + '../src/svg/SkSVGDefs.h', + '../src/svg/SkSVGElements.cpp', + '../src/svg/SkSVGElements.h', + '../src/svg/SkSVGEllipse.cpp', + '../src/svg/SkSVGEllipse.h', + '../src/svg/SkSVGFeColorMatrix.cpp', + '../src/svg/SkSVGFeColorMatrix.h', + '../src/svg/SkSVGFilter.cpp', + '../src/svg/SkSVGFilter.h', + '../src/svg/SkSVGG.cpp', + '../src/svg/SkSVGG.h', + '../src/svg/SkSVGGradient.cpp', + '../src/svg/SkSVGGradient.h', + '../src/svg/SkSVGGroup.cpp', + '../src/svg/SkSVGGroup.h', + '../src/svg/SkSVGImage.cpp', + '../src/svg/SkSVGImage.h', + '../src/svg/SkSVGLine.cpp', + '../src/svg/SkSVGLine.h', + '../src/svg/SkSVGLinearGradient.cpp', + '../src/svg/SkSVGLinearGradient.h', + '../src/svg/SkSVGMask.cpp', + '../src/svg/SkSVGMask.h', + '../src/svg/SkSVGMetadata.cpp', + '../src/svg/SkSVGMetadata.h', + '../src/svg/SkSVGPaintState.cpp', + '../src/svg/SkSVGParser.cpp', + '../src/svg/SkSVGPath.cpp', + '../src/svg/SkSVGPath.h', + '../src/svg/SkSVGPolygon.cpp', + '../src/svg/SkSVGPolygon.h', + '../src/svg/SkSVGPolyline.cpp', + '../src/svg/SkSVGPolyline.h', + '../src/svg/SkSVGRadialGradient.cpp', + '../src/svg/SkSVGRadialGradient.h', + '../src/svg/SkSVGRect.cpp', + '../src/svg/SkSVGRect.h', + '../src/svg/SkSVGStop.cpp', + '../src/svg/SkSVGStop.h', + '../src/svg/SkSVGSVG.cpp', + '../src/svg/SkSVGSVG.h', + '../src/svg/SkSVGSymbol.cpp', + '../src/svg/SkSVGSymbol.h', + '../src/svg/SkSVGText.cpp', + '../src/svg/SkSVGText.h', + '../src/svg/SkSVGUse.cpp', + ], + 'sources!' : [ + '../src/svg/SkSVG.cpp', # doesn't compile, maybe this is test code? + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../include/svg', + ], + }, + }, + + { + 'target_name': 'experimental', + 'type': 'static_library', + 'include_dirs': [ + '../include/config', + '../include/core', + ], + 'sources': [ + '../experimental/SkMatrix44.cpp', + '../experimental/SkMatrix44.h', + '../experimental/SkSetPoly3To3.cpp', + '../experimental/SkSetPoly3To3_A.cpp', + '../experimental/SkSetPoly3To3_D.cpp', + ], + 'sources!': [ + '../experimental/SkMatrix44.cpp', #doesn't compile + '../experimental/SkMatrix44.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../experimental', + ], + }, + }, + + { + 'target_name': 'SampleApp', + 'type': 'executable', + 'mac_bundle' : 1, + 'include_dirs' : [ + '../src/core', # needed to get SkConcaveToTriangle, maybe this should be moved to include dir? + '../gm', # SampleGM.cpp pulls gm.h + ], + 'sources': [ + # gm files needed for SampleGM.cpp + '../gm/bitmapfilters.cpp', + '../gm/blurs.cpp', + '../gm/complexclip.cpp', + '../gm/filltypes.cpp', + '../gm/gm.h', + '../gm/gradients.cpp', + '../gm/points.cpp', + '../gm/poly2poly.cpp', + '../gm/shadertext.cpp', + '../gm/shadows.cpp', + '../gm/shapes.cpp', + '../gm/tilemodes.cpp', + '../gm/xfermodes.cpp', + + '../samplecode/ClockFaceView.cpp', + '../samplecode/OverView.cpp', + '../samplecode/SampleAll.cpp', + '../samplecode/SampleAnimator.cpp', + '../samplecode/SampleApp.cpp', + '../samplecode/SampleArc.cpp', + '../samplecode/SampleAvoid.cpp', + '../samplecode/SampleBigGradient.cpp', + '../samplecode/SampleBitmapRect.cpp', + '../samplecode/SampleBlur.cpp', + '../samplecode/SampleCamera.cpp', + '../samplecode/SampleCircle.cpp', + '../samplecode/SampleCode.h', + '../samplecode/SampleComplexClip.cpp', + '../samplecode/SampleCull.cpp', + '../samplecode/SampleDecode.cpp', + '../samplecode/SampleDither.cpp', + '../samplecode/SampleDitherBitmap.cpp', + '../samplecode/SampleDrawLooper.cpp', + '../samplecode/SampleEffects.cpp', + '../samplecode/SampleEmboss.cpp', + '../samplecode/SampleEncode.cpp', + '../samplecode/SampleExtractAlpha.cpp', + '../samplecode/SampleFillType.cpp', + '../samplecode/SampleFilter.cpp', + '../samplecode/SampleFilter2.cpp', + '../samplecode/SampleFontCache.cpp', + '../samplecode/SampleFontScalerTest.cpp', + '../samplecode/SampleFuzz.cpp', + '../samplecode/SampleGM.cpp', + '../samplecode/SampleGradients.cpp', + '../samplecode/SampleHairline.cpp', + '../samplecode/SampleImage.cpp', + '../samplecode/SampleImageDir.cpp', + '../samplecode/SampleLayerMask.cpp', + '../samplecode/SampleLayers.cpp', + '../samplecode/SampleLCD.cpp', + '../samplecode/SampleLineClipper.cpp', + '../samplecode/SampleLines.cpp', + '../samplecode/SampleMeasure.cpp', + '../samplecode/SampleMipMap.cpp', + '../samplecode/SampleMovie.cpp', + '../samplecode/SampleNinePatch.cpp', + '../samplecode/SampleOvalTest.cpp', + '../samplecode/SampleOverflow.cpp', + '../samplecode/SamplePageFlip.cpp', + '../samplecode/SamplePatch.cpp', + '../samplecode/SamplePath.cpp', + '../samplecode/SamplePathClip.cpp', + '../samplecode/SamplePathEffects.cpp', + '../samplecode/SamplePicture.cpp', + '../samplecode/SamplePoints.cpp', + '../samplecode/SamplePolyToPoly.cpp', + '../samplecode/SampleRegion.cpp', + '../samplecode/SampleRepeatTile.cpp', + '../samplecode/SampleShaders.cpp', + '../samplecode/SampleShaderText.cpp', + '../samplecode/SampleShapes.cpp', + '../samplecode/SampleSkLayer.cpp', + '../samplecode/SampleSlides.cpp', + '../samplecode/SampleStrokePath.cpp', + '../samplecode/SampleStrokeText.cpp', + '../samplecode/SampleSVG.cpp', + '../samplecode/SampleTests.cpp', + '../samplecode/SampleText.cpp', + '../samplecode/SampleTextAlpha.cpp', + '../samplecode/SampleTextBox.cpp', + '../samplecode/SampleTextEffects.cpp', + '../samplecode/SampleTextOnPath.cpp', + '../samplecode/SampleTiling.cpp', + '../samplecode/SampleTinyBitmap.cpp', + '../samplecode/SampleTriangles.cpp', + '../samplecode/SampleTypeface.cpp', + '../samplecode/SampleUnitMapper.cpp', + '../samplecode/SampleVertices.cpp', + '../samplecode/SampleXfermodes.cpp', + ], + 'sources!': [ + '../samplecode/SampleSkLayer.cpp', #relies on SkMatrix44 which doesn't compile + '../samplecode/SampleTests.cpp', #includes unknown file SkShaderExtras.h + '../samplecode/SampleWarp.cpp', + '../samplecode/SampleFontCache.cpp', + ], + 'dependencies': [ + 'skia', + 'effects', + 'images', + 'views', + 'utils', + 'animator', + 'xml', + 'svg', + 'experimental', + 'gr', + 'skgr', + ], + 'conditions' : [ + [ 'OS == "linux" or OS == "freebsd" or OS == "openbsd" or OS == "solaris"', { + 'sources!': [ + '../samplecode/SampleDecode.cpp', + ], + }], + [ 'OS == "win"', { + 'sources!': [ + # require UNIX functions + '../samplecode/SampleEncode.cpp', + '../samplecode/SamplePageFlip.cpp', + ], + },], + [ 'OS == "mac"', { + 'sources!': [ + '../samplecode/SampleDecode.cpp', + ], + },], + + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', + 'AdditionalDependencies': [ + 'OpenGL32.lib', + 'usp10.lib', + 'd3d9.lib', + ], + }, + }, + }, + { + 'target_name': 'libtess', + 'type': 'static_library', + 'include_dirs': [ + '../third_party/glu', + ], + 'sources': [ + '../third_party/glu/internal_glu.h', + '../third_party/glu/gluos.h', + '../third_party/glu/libtess/dict-list.h', + '../third_party/glu/libtess/dict.c', + '../third_party/glu/libtess/dict.h', + '../third_party/glu/libtess/geom.c', + '../third_party/glu/libtess/geom.h', + '../third_party/glu/libtess/memalloc.c', + '../third_party/glu/libtess/memalloc.h', + '../third_party/glu/libtess/mesh.c', + '../third_party/glu/libtess/mesh.h', + '../third_party/glu/libtess/normal.c', + '../third_party/glu/libtess/normal.h', + '../third_party/glu/libtess/priorityq-heap.h', + '../third_party/glu/libtess/priorityq-sort.h', + '../third_party/glu/libtess/priorityq.c', + '../third_party/glu/libtess/priorityq.h', + '../third_party/glu/libtess/render.c', + '../third_party/glu/libtess/render.h', + '../third_party/glu/libtess/sweep.c', + '../third_party/glu/libtess/sweep.h', + '../third_party/glu/libtess/tess.c', + '../third_party/glu/libtess/tess.h', + '../third_party/glu/libtess/tessmono.c', + '../third_party/glu/libtess/tessmono.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../third_party/glu', + ], + }, + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h index 13169ca..aa2e6cf 100644 --- a/include/config/SkUserConfig.h +++ b/include/config/SkUserConfig.h @@ -141,5 +141,14 @@ //#define SK_SUPPORT_UNITTEST #endif +/* Change the ordering to work in X windows. + */ +#ifdef SK_SAMPLES_FOR_X + #define SK_R32_SHIFT 16 + #define SK_G32_SHIFT 8 + #define SK_B32_SHIFT 0 + #define SK_A32_SHIFT 24 +#endif + #endif diff --git a/include/core/SkAdvancedTypefaceMetrics.h b/include/core/SkAdvancedTypefaceMetrics.h index 033e738..f536a56 100644 --- a/include/core/SkAdvancedTypefaceMetrics.h +++ b/include/core/SkAdvancedTypefaceMetrics.h @@ -76,6 +76,14 @@ public: SkIRect fBBox; // The bounding box of all glyphs (in font units). + // The type of advance data wanted. + enum PerGlyphInfo { + kNo_PerGlyphInfo = 0x0, // Don't populate any per glyph info. + kHAdvance_PerGlyphInfo = 0x1, // Populate horizontal advance data. + kVAdvance_PerGlyphInfo = 0x2, // Populate vertical advance data. + kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only). + }; + template <typename Data> struct AdvanceMetric { enum MetricType { diff --git a/include/core/SkBounder.h b/include/core/SkBounder.h index bda5c97..fa4f7fb 100644 --- a/include/core/SkBounder.h +++ b/include/core/SkBounder.h @@ -36,6 +36,8 @@ class SkRegion; */ class SkBounder : public SkRefCnt { public: + SkBounder(); + /* Call to perform a clip test before calling onIRect. Returns the result from onIRect. */ diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 0a1b393..39fd998 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -78,12 +78,16 @@ public: /** If the Device supports GL viewports, return true and set size (if not null) to the size of the viewport. If it is not supported, ignore size and return false. + + DEPRECATED: the gpu-device backend takes care of managing the viewport */ virtual bool getViewport(SkIPoint* size) const; /** If the Device supports GL viewports, return true and set the viewport to the specified x and y dimensions. If it is not supported, ignore x and y and return false. + + DEPRECATED: the gpu-device backend takes care of managing the viewport */ virtual bool setViewport(int x, int y); @@ -99,6 +103,15 @@ public: */ SkDevice* setDevice(SkDevice* device); + /** + * saveLayer() can create another device (which is later drawn onto + * the previous device). getTopDevice() returns the top-most device current + * installed. Note that this can change on other calls like save/restore, + * so do not access this device after subsequent canvas calls. + * The reference count of the device is not changed. + */ + SkDevice* getTopDevice() const; + /** May be overridden by subclasses. This returns a compatible device for this canvas, with the specified config/width/height. If the device is raster, the pixels will be allocated automatically. diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 2f95015..8889fb4 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -21,13 +21,13 @@ #include "SkBitmap.h" #include "SkCanvas.h" #include "SkColor.h" -#include "SkRefDict.h" class SkClipStack; class SkDevice; class SkDraw; struct SkIRect; class SkMatrix; +class SkMetaData; class SkRegion; /** \class SkDeviceFactory @@ -36,7 +36,7 @@ class SkRegion; to pass into SkCanvas. Doing so will eliminate the need to extend SkCanvas as well. */ -class SkDeviceFactory { +class SK_API SkDeviceFactory { public: virtual ~SkDeviceFactory(); virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width, @@ -63,6 +63,7 @@ public: @param bitmap A copy of this bitmap is made and stored in the device */ SkDevice(SkCanvas*, const SkBitmap& bitmap, bool forOffscreen); + virtual ~SkDevice(); virtual SkDeviceFactory* getDeviceFactory() { return SkNEW(SkRasterDeviceFactory); @@ -180,6 +181,17 @@ public: const SkPoint[], const SkPaint& paint); virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint); + /** + * If pathIsMutable, then the implementation is allowed to cast path to a + * non-const pointer and modify it in place (as an optimization). Canvas + * may do this to implement helpers such as drawOval, by placing a temp + * path on the stack to hold the representation of the oval. + * + * If prePathMatrix is not null, it should logically be applied before any + * stroking or other effects. If there are no effects on the paint that + * affect the geometry/rasterization, then the pre matrix can just be + * pre-concated with the current matrix. + */ virtual void drawPath(const SkDraw&, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix = NULL, @@ -212,7 +224,7 @@ public: /////////////////////////////////////////////////////////////////////////// - SkRefDict& getRefDict() { return fRefDict; } + SkMetaData& getMetaData(); struct TextFlags { uint32_t fFlags; // SkPaint::getFlags() @@ -250,8 +262,8 @@ private: SkCanvas* fCanvas; SkBitmap fBitmap; - SkRefDict fRefDict; SkIPoint fOrigin; + SkMetaData* fMetaData; }; #endif diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h index 99ab342..b751be0 100644 --- a/include/core/SkDraw.h +++ b/include/core/SkDraw.h @@ -41,9 +41,15 @@ public: void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[], const SkPaint&, bool forceUseDevice = false) const; void drawRect(const SkRect&, const SkPaint&) const; - /* To save on mallocs, we allow a flag that tells us that srcPath is - mutable, so that we don't have to make copies of it as we transform it. - */ + /** + * To save on mallocs, we allow a flag that tells us that srcPath is + * mutable, so that we don't have to make copies of it as we transform it. + * + * If prePathMatrix is not null, it should logically be applied before any + * stroking or other effects. If there are no effects on the paint that + * affect the geometry/rasterization, then the pre matrix can just be + * pre-concated with the current matrix. + */ void drawPath(const SkPath& srcPath, const SkPaint&, const SkMatrix* prePathMatrix, bool pathIsMutable) const; void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const; @@ -79,6 +85,24 @@ public: SkMaskFilter* filter, const SkMatrix* filterMatrix, SkMask* mask, SkMask::CreateMode mode); + enum RectType { + kHair_RectType, + kFill_RectType, + kStroke_RectType, + kPath_RectType + }; + + /** + * Based on the paint's style, strokeWidth, and the matrix, classify how + * to draw the rect. If no special-case is available, returns + * kPath_RectType. + * + * Iff RectType == kStroke_RectType, then strokeSize is set to the device + * width and height of the stroke. + */ + static RectType ComputeRectType(const SkPaint&, const SkMatrix&, + SkPoint* strokeSize); + private: void drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y, const SkPaint&) const; diff --git a/include/core/SkDrawFilter.h b/include/core/SkDrawFilter.h index db5a685..c8af187 100644 --- a/include/core/SkDrawFilter.h +++ b/include/core/SkDrawFilter.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,18 +19,15 @@ #include "SkRefCnt.h" -////////////////// EXPERIMENTAL ////////////////////////// - class SkCanvas; class SkPaint; -/** Right before something is being draw, filter() is called with the - current canvas and paint. If it returns true, then drawing proceeds - with the (possibly modified) canvas/paint, and then restore() is called - to restore the canvas/paint to their state before filter() was called. - If filter returns false, canvas/paint should not have been changed, and - restore() will not be called. -*/ +/** + * Right before something is being draw, filter() is called with the + * paint. The filter may modify the paint as it wishes, which will then be + * used for the actual drawing. Note: this modification only lasts for the + * current draw, as a temporary copy of the paint is used. + */ class SkDrawFilter : public SkRefCnt { public: enum Type { @@ -43,14 +40,11 @@ public: kText_Type }; - /** Return true to allow the draw to continue (with possibly modified - canvas/paint). If true is returned, then restore() will be called. - */ - virtual bool filter(SkCanvas*, SkPaint*, Type) = 0; - /** If filter() returned true, then restore() will be called to restore the - canvas/paint to their previous states - */ - virtual void restore(SkCanvas*, SkPaint*, Type) = 0; + /** + * Called with the paint that will be used to draw the specified type. + * The implementation may modify the paint as they wish. + */ + virtual void filter(SkPaint*, Type) = 0; }; #endif diff --git a/include/core/SkDrawLooper.h b/include/core/SkDrawLooper.h index 87eb5cb..270abc2 100644 --- a/include/core/SkDrawLooper.h +++ b/include/core/SkDrawLooper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,8 +19,6 @@ #include "SkFlattenable.h" -////////////////// EXPERIMENTAL ////////////////////////// - class SkCanvas; class SkPaint; @@ -34,24 +32,25 @@ class SkPaint; */ class SK_API SkDrawLooper : public SkFlattenable { public: - /** Called right before something is being drawn to the specified canvas - with the specified paint. Subclass that want to modify either parameter - can do so now. - */ - virtual void init(SkCanvas*, SkPaint*) {} - /** Called in a loop (after init()). Each time true is returned, the object - is drawn (possibly with a modified canvas and/or paint). When false is - finally returned, drawing for the object stops. - */ - virtual bool next() { return false; } - /** Called after the looper has finally returned false from next(), allowing - the looper to restore the canvas/paint to their original states. - is this required, since the subclass knows when it is done??? - should we pass the canvas/paint here, and/or to the next call - so that subclasses don't need to retain pointers to them during the - loop? - */ - virtual void restore() {} + /** + * Called right before something is being drawn. This will be followed by + * calls to next() until next() returns false. + */ + virtual void init(SkCanvas*) = 0; + + /** + * Called in a loop (after init()). Each time true is returned, the object + * is drawn (possibly with a modified canvas and/or paint). When false is + * finally returned, drawing for the object stops. + * + * On each call, the paint will be in its original state, but the canvas + * will be as it was following the previous call to next() or init(). + * + * The implementation must ensure that, when next() finally returns false, + * that the canvas has been restored to the state it was initially, before + * init() was first called. + */ + virtual bool next(SkCanvas*, SkPaint* paint) = 0; protected: SkDrawLooper() {} diff --git a/include/core/SkEndian.h b/include/core/SkEndian.h index f08a9a9..a72dfe3 100644 --- a/include/core/SkEndian.h +++ b/include/core/SkEndian.h @@ -36,8 +36,7 @@ /** Swap the two bytes in the low 16bits of the parameters. e.g. 0x1234 -> 0x3412 */ -inline uint16_t SkEndianSwap16(U16CPU value) -{ +static inline uint16_t SkEndianSwap16(U16CPU value) { SkASSERT(value == (uint16_t)value); return (uint16_t)((value >> 8) | (value << 8)); } @@ -45,12 +44,10 @@ inline uint16_t SkEndianSwap16(U16CPU value) /** Vector version of SkEndianSwap16(), which swaps the low two bytes of each value in the array. */ -inline void SkEndianSwap16s(uint16_t array[], int count) -{ +static inline void SkEndianSwap16s(uint16_t array[], int count) { SkASSERT(count == 0 || array != NULL); - while (--count >= 0) - { + while (--count >= 0) { *array = SkEndianSwap16(*array); array += 1; } @@ -59,8 +56,7 @@ inline void SkEndianSwap16s(uint16_t array[], int count) /** Reverse all 4 bytes in a 32bit value. e.g. 0x12345678 -> 0x78563412 */ -inline uint32_t SkEndianSwap32(uint32_t value) -{ +static inline uint32_t SkEndianSwap32(uint32_t value) { return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | @@ -70,12 +66,10 @@ inline uint32_t SkEndianSwap32(uint32_t value) /** Vector version of SkEndianSwap16(), which swaps the bytes of each value in the array. */ -inline void SkEndianSwap32s(uint32_t array[], int count) -{ +static inline void SkEndianSwap32s(uint32_t array[], int count) { SkASSERT(count == 0 || array != NULL); - while (--count >= 0) - { + while (--count >= 0) { *array = SkEndianSwap32(*array); array += 1; } diff --git a/include/core/SkFDot6.h b/include/core/SkFDot6.h index a4b9cf7..9d56116 100644 --- a/include/core/SkFDot6.h +++ b/include/core/SkFDot6.h @@ -21,12 +21,11 @@ typedef int32_t SkFDot6; -#define SK_FDot61 (64) +#define SK_FDot6One (64) #define SK_FDot6Half (32) #ifdef SK_DEBUG - inline SkFDot6 SkIntToFDot6(S16CPU x) - { + inline SkFDot6 SkIntToFDot6(S16CPU x) { SkASSERT(SkToS16(x) == x); return x << 6; } @@ -40,8 +39,7 @@ typedef int32_t SkFDot6; #define SkFixedToFDot6(x) ((x) >> 10) -inline SkFixed SkFDot6ToFixed(SkFDot6 x) -{ +inline SkFixed SkFDot6ToFixed(SkFDot6 x) { SkASSERT((x << 10 >> 10) == x); return x << 10; @@ -53,14 +51,14 @@ inline SkFixed SkFDot6ToFixed(SkFDot6 x) #define SkScalarToFDot6(x) ((x) >> 10) #endif -inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) -{ +inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) { SkASSERT(b != 0); - if (a == (int16_t)a) + if (a == (int16_t)a) { return (a << 16) / b; - else + } else { return SkFixedDiv(a, b); + } } #endif diff --git a/include/core/SkFlate.h b/include/core/SkFlate.h index c496b6f..b606742 100644 --- a/include/core/SkFlate.h +++ b/include/core/SkFlate.h @@ -40,9 +40,6 @@ public: putting the result into dst. Returns false if an error occurs. */ static bool Inflate(SkStream* src, SkDynamicMemoryWStream* dst); - -private: - static const size_t kBufferSize; }; #endif diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h index 3c69251..72faed7 100644 --- a/include/core/SkFontHost.h +++ b/include/core/SkFontHost.h @@ -177,14 +177,14 @@ public: /////////////////////////////////////////////////////////////////////////// /** Retrieve detailed typeface metrics. Used by the PDF backend. - @param perGlyphInfo Indicate if the glyph specific information. - @param perGlyphInfo Indicate if the glyph specific information (advances - and names) should be populated. + @param perGlyphInfo Indicate what glyph specific information (advances, + names, etc.) should be populated. @return The returned object has already been referenced. NULL is returned if the font is not found. */ static SkAdvancedTypefaceMetrics* GetAdvancedTypefaceMetrics( - SkFontID fontID, bool perGlyphInfo); + SkFontID fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo); /** Return the number of tables in the font */ diff --git a/include/core/SkGeometry.h b/include/core/SkGeometry.h index d4b13fb..000ca73 100644 --- a/include/core/SkGeometry.h +++ b/include/core/SkGeometry.h @@ -32,7 +32,8 @@ typedef SkPoint SkXRay; one of the endpoints' y coordinates, indicating that another query y coordinate is preferred for robustness. */ -bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2], bool* ambiguous = NULL); +bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2], + bool* ambiguous = NULL); /** Given a quadratic equation Ax^2 + Bx + C = 0, return 0, 1, 2 roots for the equation. @@ -44,8 +45,10 @@ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]); /** Set pt to the point on the src quadratic specified by t. t must be 0 <= t <= 1.0 */ -void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tangent = NULL); -void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent = NULL); +void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, + SkVector* tangent = NULL); +void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, + SkVector* tangent = NULL); /** Given a src quadratic bezier, chop it at the specified t value, where 0 < t < 1, and return the two new quadratics in dst: @@ -92,7 +95,7 @@ int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]); */ SK_API void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]); -//////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /** Convert from parametric from (pts) to polynomial coefficients coeff[0]*T^3 + coeff[1]*T^2 + coeff[2]*T + coeff[3] @@ -102,14 +105,16 @@ void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4]); /** Set pt to the point on the src cubic specified by t. t must be 0 <= t <= 1.0 */ -void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* locOrNull, SkVector* tangentOrNull, SkVector* curvatureOrNull); +void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* locOrNull, + SkVector* tangentOrNull, SkVector* curvatureOrNull); /** Given a src cubic bezier, chop it at the specified t value, where 0 < t < 1, and return the two new cubics in dst: dst[0..3] and dst[3..6] */ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t); -void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], const SkScalar t[], int t_count); +void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], const SkScalar t[], + int t_count); /** Given a src cubic bezier, chop it at the specified t == 1/2, The new cubics are returned in dst[0..3] and dst[3..6] @@ -125,7 +130,8 @@ void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7]); 1 0 < tValues[0] < 1 2 0 < tValues[0] < tValues[1] < 1 */ -int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2]); +int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, + SkScalar tValues[2]); /** Given 4 points on a cubic bezier, chop it into 1, 2, 3 beziers such that the resulting beziers are monotonic in Y. This is called by the scan converter. @@ -149,7 +155,8 @@ int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[2]); int SkChopCubicAtInflections(const SkPoint src[4], SkPoint dst[10]); int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]); -int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tValues[3] = NULL); +int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], + SkScalar tValues[3] = NULL); /** Given a monotonic cubic bezier, determine whether an xray intersects the cubic. @@ -163,7 +170,8 @@ int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tV coordinates, indicating that another query y coordinate is preferred for robustness. */ -bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool* ambiguous = NULL); +bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], + bool* ambiguous = NULL); /** Given an arbitrary cubic bezier, return the number of times an xray crosses the cubic. Valid return values are [0..3] @@ -177,9 +185,10 @@ bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool* coordinates or at a tangent point, indicating that another query y coordinate is preferred for robustness. */ -int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], bool* ambiguous = NULL); +int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], + bool* ambiguous = NULL); -/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// enum SkRotationDirection { kCW_SkRotationDirection, @@ -197,7 +206,7 @@ enum SkRotationDirection { matrix, if not null, is appled to the points before they are returned. */ -int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop, SkRotationDirection, - const SkMatrix* matrix, SkPoint quadPoints[]); +int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop, + SkRotationDirection, const SkMatrix*, SkPoint quadPoints[]); #endif diff --git a/include/core/SkMallocPixelRef.h b/include/core/SkMallocPixelRef.h index 7022ba2..edaab94 100644 --- a/include/core/SkMallocPixelRef.h +++ b/include/core/SkMallocPixelRef.h @@ -54,6 +54,7 @@ protected: void* fStorage; private: + size_t fSize; SkColorTable* fCTable; diff --git a/include/core/SkMath.h b/include/core/SkMath.h index af19083..3e72904 100644 --- a/include/core/SkMath.h +++ b/include/core/SkMath.h @@ -77,7 +77,6 @@ static inline int SkClampPos(int value) { /** Given an integer and a positive (max) integer, return the value pinned against 0 and max, inclusive. - Note: only works as long as max - value doesn't wrap around @param value The value we want returned pinned between [0...max] @param max The positive max value @return 0 if value < 0, max if value > max, else value @@ -85,10 +84,6 @@ static inline int SkClampPos(int value) { static inline int SkClampMax(int value, int max) { // ensure that max is positive SkASSERT(max >= 0); - // ensure that if value is negative, max - value doesn't wrap around - SkASSERT(value >= 0 || max - value > 0); - -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR if (value < 0) { value = 0; } @@ -96,15 +91,6 @@ static inline int SkClampMax(int value, int max) { value = max; } return value; -#else - - int diff = max - value; - // clear diff if diff is positive - diff &= diff >> 31; - - // clear the result if value < 0 - return (value + diff) & ~(value >> 31); -#endif } /** Given a positive value and a positive max, return the value diff --git a/include/core/SkMetaData.h b/include/core/SkMetaData.h new file mode 100644 index 0000000..ee2fa2b --- /dev/null +++ b/include/core/SkMetaData.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkMetaData_DEFINED +#define SkMetaData_DEFINED + +#include "SkScalar.h" + +class SkRefCnt; + +class SkMetaData { +public: + /** + * Used to manage the life-cycle of a ptr in the metadata. This is option + * in setPtr, and is only invoked when either copying one metadata to + * another, or when the metadata is destroyed. + * + * setPtr(name, ptr, proc) { + * fPtr = proc(ptr, true); + * } + * + * copy: A = B { + * A.fPtr = B.fProc(B.fPtr, true); + * } + * + * ~SkMetaData { + * fProc(fPtr, false); + * } + */ + typedef void* (*PtrProc)(void* ptr, bool doRef); + + /** + * Implements PtrProc for SkRefCnt pointers + */ + static void* RefCntProc(void* ptr, bool doRef); + + SkMetaData(); + SkMetaData(const SkMetaData& src); + ~SkMetaData(); + + SkMetaData& operator=(const SkMetaData& src); + + void reset(); + + bool findS32(const char name[], int32_t* value = NULL) const; + bool findScalar(const char name[], SkScalar* value = NULL) const; + const SkScalar* findScalars(const char name[], int* count, + SkScalar values[] = NULL) const; + const char* findString(const char name[]) const; + bool findPtr(const char name[], void** value = NULL, PtrProc* = NULL) const; + bool findBool(const char name[], bool* value = NULL) const; + const void* findData(const char name[], size_t* byteCount = NULL) const; + + bool hasS32(const char name[], int32_t value) const { + int32_t v; + return this->findS32(name, &v) && v == value; + } + bool hasScalar(const char name[], SkScalar value) const { + SkScalar v; + return this->findScalar(name, &v) && v == value; + } + bool hasString(const char name[], const char value[]) const { + const char* v = this->findString(name); + return (v == NULL && value == NULL) || + (v != NULL && value != NULL && !strcmp(v, value)); + } + bool hasPtr(const char name[], void* value) const { + void* v; + return this->findPtr(name, &v) && v == value; + } + bool hasBool(const char name[], bool value) const { + bool v; + return this->findBool(name, &v) && v == value; + } + bool hasData(const char name[], const void* data, size_t byteCount) const { + size_t len; + const void* ptr = this->findData(name, &len); + return NULL != ptr && len == byteCount && !memcmp(ptr, data, len); + } + + void setS32(const char name[], int32_t value); + void setScalar(const char name[], SkScalar value); + SkScalar* setScalars(const char name[], int count, const SkScalar values[] = NULL); + void setString(const char name[], const char value[]); + void setPtr(const char name[], void* value, PtrProc proc = NULL); + void setBool(const char name[], bool value); + // the data is copied from the input pointer. + void setData(const char name[], const void* data, size_t byteCount); + + bool removeS32(const char name[]); + bool removeScalar(const char name[]); + bool removeString(const char name[]); + bool removePtr(const char name[]); + bool removeBool(const char name[]); + bool removeData(const char name[]); + + // helpers for SkRefCnt + bool findRefCnt(const char name[], SkRefCnt** ptr = NULL) { + return this->findPtr(name, reinterpret_cast<void**>(ptr)); + } + bool hasRefCnt(const char name[], SkRefCnt* ptr) { + return this->hasPtr(name, ptr); + } + void setRefCnt(const char name[], SkRefCnt* ptr) { + this->setPtr(name, ptr, RefCntProc); + } + bool removeRefCnt(const char name[]) { + return this->removePtr(name); + } + + enum Type { + kS32_Type, + kScalar_Type, + kString_Type, + kPtr_Type, + kBool_Type, + kData_Type, + + kTypeCount + }; + + struct Rec; + class Iter; + friend class Iter; + + class Iter { + public: + Iter() : fRec(NULL) {} + Iter(const SkMetaData&); + + /** Reset the iterator, so that calling next() will return the first + data element. This is done implicitly in the constructor. + */ + void reset(const SkMetaData&); + + /** Each time next is called, it returns the name of the next data element, + or null when there are no more elements. If non-null is returned, then the + element's type is returned (if not null), and the number of data values + is returned in count (if not null). + */ + const char* next(Type*, int* count); + + private: + Rec* fRec; + }; + +public: + struct Rec { + Rec* fNext; + uint16_t fDataCount; // number of elements + uint8_t fDataLen; // sizeof a single element + uint8_t fType; + + const void* data() const { return (this + 1); } + void* data() { return (this + 1); } + const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; } + char* name() { return (char*)this->data() + fDataLen * fDataCount; } + + static Rec* Alloc(size_t); + static void Free(Rec*); + }; + Rec* fRec; + + const Rec* find(const char name[], Type) const; + void* set(const char name[], const void* data, size_t len, Type, int count); + bool remove(const char name[], Type); +}; + +#endif + diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index eec11cf..f4b325f 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -89,12 +89,7 @@ public: return static_cast<Hinting>(fHinting); } - void setHinting(Hinting hintingLevel) { - if ((unsigned) hintingLevel != fHinting) { - fGenerationID++; - fHinting = hintingLevel; - } - } + void setHinting(Hinting hintingLevel); /** Specifies the bit values that are stored in the paint's flags. */ @@ -820,10 +815,12 @@ public: void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y, SkPath* path) const; +#ifdef ANDROID const SkGlyph& getUnicharMetrics(SkUnichar); const void* findImage(const SkGlyph&); uint32_t getGenerationID() const; +#endif private: SkTypeface* fTypeface; @@ -849,7 +846,9 @@ private: unsigned fStyle : 2; unsigned fTextEncoding : 2; // 3 values unsigned fHinting : 2; +#ifdef ANDROID uint32_t fGenerationID; +#endif SkDrawCacheProc getDrawCacheProc() const; SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir, diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 24e260b..d9a7093 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -20,6 +20,14 @@ #include "SkMatrix.h" #include "SkTDArray.h" +#ifdef ANDROID +#define GEN_ID_INC fGenerationID++ +#define GEN_ID_PTR_INC(ptr) ptr->fGenerationID++ +#else +#define GEN_ID_INC +#define GEN_ID_PTR_INC(ptr) +#endif + class SkFlattenableReadBuffer; class SkFlattenableWriteBuffer; class SkAutoPathBoundsUpdate; @@ -74,7 +82,7 @@ public: */ void setFillType(FillType ft) { fFillType = SkToU8(ft); - fGenerationID++; + GEN_ID_INC; } /** Returns true if the filltype is one of the Inverse variants */ @@ -85,7 +93,7 @@ public: */ void toggleInverseFillType() { fFillType ^= 2; - fGenerationID++; + GEN_ID_INC; } /** Returns true if the path is flagged as being convex. This is not a @@ -100,7 +108,7 @@ public: */ void setIsConvex(bool isConvex) { fIsConvex = (isConvex != 0); - fGenerationID++; + GEN_ID_INC; } /** Clear any lines and curves from the path, making it empty. This frees up @@ -580,7 +588,9 @@ public: */ void subdivide(SkScalar dist, bool bendLines, SkPath* dst = NULL) const; +#ifdef ANDROID uint32_t getGenerationID() const; +#endif SkDEBUGCODE(void validate() const;) @@ -591,7 +601,9 @@ private: mutable uint8_t fBoundsIsDirty; uint8_t fFillType; uint8_t fIsConvex; +#ifdef ANDROID uint32_t fGenerationID; +#endif // called, if dirty, by getBounds() void computeBounds() const; diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index 177ecec..8fb368a 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -20,7 +20,9 @@ #include "SkRefCnt.h" #include "SkString.h" +class SkBitmap; class SkColorTable; +struct SkIRect; class SkMutex; class SkFlattenableReadBuffer; class SkFlattenableWriteBuffer; @@ -112,6 +114,8 @@ public: */ virtual SkGpuTexture* getTexture() { return NULL; } + bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL); + // serialization typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&); @@ -157,6 +161,14 @@ protected: */ virtual void onUnlockPixels() = 0; + /** + * For pixelrefs that don't have access to their raw pixels, they may be + * able to make a copy of them (e.g. if the pixels are on the GPU). + * + * The base class implementation returns false; + */ + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull); + /** Return the mutex associated with this pixelref. This value is assigned in the constructor, and cannot change during the lifetime of the object. */ diff --git a/include/core/SkPoint.h b/include/core/SkPoint.h index c89f080..52dbd51 100644 --- a/include/core/SkPoint.h +++ b/include/core/SkPoint.h @@ -149,6 +149,9 @@ struct SK_API SkPoint { return pt; } + SkScalar x() const { return fX; } + SkScalar y() const { return fY; } + /** Set the point's X and Y coordinates */ void set(SkScalar x, SkScalar y) { fX = x; fY = y; } diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h index 4cda2cd..1dace59 100644 --- a/include/core/SkRegion.h +++ b/include/core/SkRegion.h @@ -47,118 +47,148 @@ public: ~SkRegion(); SkRegion& operator=(const SkRegion&); - - friend int operator==(const SkRegion& a, const SkRegion& b); - friend int operator!=(const SkRegion& a, const SkRegion& b) { + + /** + * Return true if the two regions are equal. i.e. The enclose exactly + * the same area. + */ + friend bool operator==(const SkRegion& a, const SkRegion& b); + + /** + * Return true if the two regions are not equal. + */ + friend bool operator!=(const SkRegion& a, const SkRegion& b) { return !(a == b); } - /** Replace this region with the specified region, and return true if the - resulting region is non-empty. - */ + /** + * Replace this region with the specified region, and return true if the + * resulting region is non-empty. + */ bool set(const SkRegion& src) { SkASSERT(&src); *this = src; return !this->isEmpty(); } - /** Swap the contents of this and the specified region. This operation - is gauarenteed to never fail. - */ - void swap(SkRegion&); + /** + * Swap the contents of this and the specified region. This operation + * is gauarenteed to never fail. + */ + void swap(SkRegion&); /** Return true if this region is empty */ - bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; } + bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; } + /** Return true if this region is a single, non-empty rectangle */ - bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; } + bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; } + /** Return true if this region consists of more than 1 rectangular area */ - bool isComplex() const { return !this->isEmpty() && !this->isRect(); } - /** Return the bounds of this region. If the region is empty, returns an - empty rectangle. - */ + bool isComplex() const { return !this->isEmpty() && !this->isRect(); } + + /** + * Return the bounds of this region. If the region is empty, returns an + * empty rectangle. + */ const SkIRect& getBounds() const { return fBounds; } - /** Returns true if the region is non-empty, and if so, sets the specified - path to the boundary(s) of the region. - */ + /** + * Returns true if the region is non-empty, and if so, sets the specified + * path to the boundary(s) of the region. If the region is empty, then + * this returns false, and path is left unmodified. + */ bool getBoundaryPath(SkPath* path) const; - /** Set the region to be empty, and return false, since the resulting - region is empty - */ - bool setEmpty(); + /** + * Set the region to be empty, and return false, since the resulting + * region is empty + */ + bool setEmpty(); - /** If rect is non-empty, set this region to that rectangle and return true, - otherwise set this region to empty and return false. - */ - bool setRect(const SkIRect&); + /** + * If rect is non-empty, set this region to that rectangle and return true, + * otherwise set this region to empty and return false. + */ + bool setRect(const SkIRect&); - /** If left < right and top < bottom, set this region to that rectangle and - return true, otherwise set this region to empty and return false. - */ - bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom); + /** + * If left < right and top < bottom, set this region to that rectangle and + * return true, otherwise set this region to empty and return false. + */ + bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom); - /** Set this region to the union of an array of rects. This is generally - faster than calling region.op(rect, kUnion_Op) in a loop. If count is - 0, then this region is set to the empty region. - @return true if the resulting region is non-empty + /** + * Set this region to the union of an array of rects. This is generally + * faster than calling region.op(rect, kUnion_Op) in a loop. If count is + * 0, then this region is set to the empty region. + * @return true if the resulting region is non-empty */ bool setRects(const SkIRect rects[], int count); - /** Set this region to the specified region, and return true if it is - non-empty. */ - bool setRegion(const SkRegion&); - - /** Set this region to the area described by the path, clipped. - Return true if the resulting region is non-empty. - This produces a region that is identical to the pixels that would be - drawn by the path (with no antialiasing) with the specified clip. - */ - bool setPath(const SkPath&, const SkRegion& clip); + /** + * Set this region to the specified region, and return true if it is + * non-empty. + */ + bool setRegion(const SkRegion&); + + /** + * Set this region to the area described by the path, clipped. + * Return true if the resulting region is non-empty. + * This produces a region that is identical to the pixels that would be + * drawn by the path (with no antialiasing) with the specified clip. + */ + bool setPath(const SkPath&, const SkRegion& clip); - /** Returns true if the specified rectangle has a non-empty intersection - with this region. - */ - bool intersects(const SkIRect&) const; + /** + * Returns true if the specified rectangle has a non-empty intersection + * with this region. + */ + bool intersects(const SkIRect&) const; - /** Returns true if the specified region has a non-empty intersection - with this region. - */ - bool intersects(const SkRegion&) const; - - /** Return true if the specified x,y coordinate is inside the region. - */ - bool contains(int32_t x, int32_t y) const; - - /** Return true if the specified rectangle is completely inside the region. - This works for simple (rectangular) and complex regions, and always - returns the correct result. Note: if either this region or the rectangle - is empty, contains() returns false. - */ - bool contains(const SkIRect&) const; - - /** Return true if the specified region is completely inside the region. - This works for simple (rectangular) and complex regions, and always - returns the correct result. Note: if either region is empty, contains() - returns false. - */ - bool contains(const SkRegion&) const; - - /** Return true if this region is a single rectangle (not complex) and the - specified rectangle is contained by this region. Returning false is not - a guarantee that the rectangle is not contained by this region, but - return true is a guarantee that the rectangle is contained by this region. - */ + /** + * Returns true if the specified region has a non-empty intersection + * with this region. + */ + bool intersects(const SkRegion&) const; + + /** + * Return true if the specified x,y coordinate is inside the region. + */ + bool contains(int32_t x, int32_t y) const; + + /** + * Return true if the specified rectangle is completely inside the region. + * This works for simple (rectangular) and complex regions, and always + * returns the correct result. Note: if either this region or the rectangle + * is empty, contains() returns false. + */ + bool contains(const SkIRect&) const; + + /** + * Return true if the specified region is completely inside the region. + * This works for simple (rectangular) and complex regions, and always + * returns the correct result. Note: if either region is empty, contains() + * returns false. + */ + bool contains(const SkRegion&) const; + + /** + * Return true if this region is a single rectangle (not complex) and the + * specified rectangle is contained by this region. Returning false is not + * a guarantee that the rectangle is not contained by this region, but + * return true is a guarantee that the rectangle is contained by this region. + */ bool quickContains(const SkIRect& r) const { return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom); } - /** Return true if this region is a single rectangle (not complex) and the - specified rectangle is contained by this region. Returning false is not - a guarantee that the rectangle is not contained by this region, but - return true is a guarantee that the rectangle is contained by this - region. - */ + /** + * Return true if this region is a single rectangle (not complex) and the + * specified rectangle is contained by this region. Returning false is not + * a guarantee that the rectangle is not contained by this region, but + * return true is a guarantee that the rectangle is contained by this + * region. + */ bool quickContains(int32_t left, int32_t top, int32_t right, int32_t bottom) const { SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region @@ -170,38 +200,40 @@ public: fBounds.fRight >= right && fBounds.fBottom >= bottom; } - /** Return true if this region is empty, or if the specified rectangle does - not intersect the region. Returning false is not a guarantee that they - intersect, but returning true is a guarantee that they do not. - */ - bool quickReject(const SkIRect& rect) const - { + /** + * Return true if this region is empty, or if the specified rectangle does + * not intersect the region. Returning false is not a guarantee that they + * intersect, but returning true is a guarantee that they do not. + */ + bool quickReject(const SkIRect& rect) const { return this->isEmpty() || rect.isEmpty() || !SkIRect::Intersects(fBounds, rect); } - /** Return true if this region, or rgn, is empty, or if their bounds do not - intersect. Returning false is not a guarantee that they intersect, but - returning true is a guarantee that they do not. - */ + /** + * Return true if this region, or rgn, is empty, or if their bounds do not + * intersect. Returning false is not a guarantee that they intersect, but + * returning true is a guarantee that they do not. + */ bool quickReject(const SkRegion& rgn) const { return this->isEmpty() || rgn.isEmpty() || !SkIRect::Intersects(fBounds, rgn.fBounds); } - /** Translate the region by the specified (dx, dy) amount. - */ + /** Translate the region by the specified (dx, dy) amount. */ void translate(int dx, int dy) { this->translate(dx, dy, this); } - /** Translate the region by the specified (dx, dy) amount, writing the - resulting region into dst. Note: it is legal to pass this region as the - dst parameter, effectively translating the region in place. If dst is - null, nothing happens. - */ + /** + * Translate the region by the specified (dx, dy) amount, writing the + * resulting region into dst. Note: it is legal to pass this region as the + * dst parameter, effectively translating the region in place. If dst is + * null, nothing happens. + */ void translate(int dx, int dy, SkRegion* dst) const; - /** The logical operations that can be performed when combining two regions. - */ + /** + * The logical operations that can be performed when combining two regions. + */ enum Op { kDifference_Op, //!< subtract the op region from the first region kIntersect_Op, //!< intersect the two regions @@ -212,41 +244,50 @@ public: kReplace_Op //!< replace the dst region with the op region }; - /** Set this region to the result of applying the Op to this region and the - specified rectangle: this = (this op rect). - Return true if the resulting region is non-empty. - */ + /** + * Set this region to the result of applying the Op to this region and the + * specified rectangle: this = (this op rect). + * Return true if the resulting region is non-empty. + */ bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); } - /** Set this region to the result of applying the Op to this region and the - specified rectangle: this = (this op rect). - Return true if the resulting region is non-empty. - */ + /** + * Set this region to the result of applying the Op to this region and the + * specified rectangle: this = (this op rect). + * Return true if the resulting region is non-empty. + */ bool op(int left, int top, int right, int bottom, Op op) { SkIRect rect; rect.set(left, top, right, bottom); return this->op(*this, rect, op); } - /** Set this region to the result of applying the Op to this region and the - specified region: this = (this op rgn). - Return true if the resulting region is non-empty. - */ + /** + * Set this region to the result of applying the Op to this region and the + * specified region: this = (this op rgn). + * Return true if the resulting region is non-empty. + */ bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); } - /** Set this region to the result of applying the Op to the specified - rectangle and region: this = (rect op rgn). - Return true if the resulting region is non-empty. - */ + + /** + * Set this region to the result of applying the Op to the specified + * rectangle and region: this = (rect op rgn). + * Return true if the resulting region is non-empty. + */ bool op(const SkIRect& rect, const SkRegion& rgn, Op); - /** Set this region to the result of applying the Op to the specified - region and rectangle: this = (rgn op rect). - Return true if the resulting region is non-empty. - */ + + /** + * Set this region to the result of applying the Op to the specified + * region and rectangle: this = (rgn op rect). + * Return true if the resulting region is non-empty. + */ bool op(const SkRegion& rgn, const SkIRect& rect, Op); - /** Set this region to the result of applying the Op to the specified - regions: this = (rgna op rgnb). - Return true if the resulting region is non-empty. - */ + + /** + * Set this region to the result of applying the Op to the specified + * regions: this = (rgna op rgnb). + * Return true if the resulting region is non-empty. + */ bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op); #ifdef ANDROID @@ -255,9 +296,10 @@ public: char* toString(); #endif - /** Returns the sequence of rectangles, sorted in Y and X, that make up - this region. - */ + /** + * Returns the sequence of rectangles, sorted in Y and X, that make up + * this region. + */ class SK_API Iterator { public: Iterator() : fRgn(NULL), fDone(true) {} @@ -271,6 +313,7 @@ public: const SkIRect& rect() const { return fRect; } // may return null const SkRegion* rgn() const { return fRgn; } + private: const SkRegion* fRgn; const RunType* fRuns; @@ -278,14 +321,15 @@ public: bool fDone; }; - /** Returns the sequence of rectangles, sorted in Y and X, that make up - this region intersected with the specified clip rectangle. - */ + /** + * Returns the sequence of rectangles, sorted in Y and X, that make up + * this region intersected with the specified clip rectangle. + */ class SK_API Cliperator { public: Cliperator(const SkRegion&, const SkIRect& clip); - bool done() { return fDone; } - void next(); + bool done() { return fDone; } + void next(); const SkIRect& rect() const { return fRect; } private: @@ -295,13 +339,14 @@ public: bool fDone; }; - /** Returns the sequence of runs that make up this region for the specified - Y scanline, clipped to the specified left and right X values. - */ + /** + * Returns the sequence of runs that make up this region for the specified + * Y scanline, clipped to the specified left and right X values. + */ class Spanerator { public: Spanerator(const SkRegion&, int y, int left, int right); - bool next(int* left, int* right); + bool next(int* left, int* right); private: const SkRegion::RunType* fRuns; @@ -309,15 +354,24 @@ public: bool fDone; }; - /** Write the region to the buffer, and return the number of bytes written. - If buffer is NULL, it still returns the number of bytes. - */ + /** + * Write the region to the buffer, and return the number of bytes written. + * If buffer is NULL, it still returns the number of bytes. + */ uint32_t flatten(void* buffer) const; - /** Initialized the region from the buffer, returning the number - of bytes actually read. - */ + + /** + * Initialized the region from the buffer, returning the number + * of bytes actually read. + */ uint32_t unflatten(const void* buffer); - + + /** + * Returns a reference to a global empty region. Just a convenience for + * callers that need a const empty region. + */ + static const SkRegion& GetEmptyRegion(); + SkDEBUGCODE(void dump() const;) SkDEBUGCODE(void validate() const;) SkDEBUGCODE(static void UnitTest();) @@ -361,6 +415,4 @@ private: friend class SkFlatRegion; }; - #endif - diff --git a/include/core/SkRelay.h b/include/core/SkRelay.h new file mode 100644 index 0000000..9361482 --- /dev/null +++ b/include/core/SkRelay.h @@ -0,0 +1,50 @@ +/* + Copyright 2010 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef SkTRelay_DEFINED +#define SkTRelay_DEFINED + +#include "SkRefCnt.h" + +/** + * Similar to a weakptr in java, a Relay allows for a back-ptr to an + * object to be "safe", without using a hard reference-count. + * + * Typically, the target creates a Relay with a pointer to itself. Whenever it + * wants to have another object maintain a safe-ptr to it, it gives them a + * Relay, which they ref()/unref(). Through the Relay each external object can + * retrieve a pointer to the Target. However, when the Target goes away, it + * clears the Relay pointer to it (relay->set(NULL)) and then unref()s the + * Relay. The other objects still have a ref on the Relay, but now when they + * call get() the receive a NULL. + */ +template <template T> class SkTRelay : public SkRefCnt { +public: + SkTRelay(T* ptr) : fPtr(ptr) {} + + // consumers call this + T* get() const { return fPtr; } + + // producer calls this + void set(T* ptr) { fPtr = ptr; } + + void clear() { this->set(NULL); } + +private: + T* fPtr; +}; + +#endif diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h index 09f24b5..4fca656 100644 --- a/include/core/SkScalar.h +++ b/include/core/SkScalar.h @@ -50,10 +50,10 @@ #define SK_ScalarInfinity (*(const float*)&gIEEEInfinity) /** SK_ScalarMax is defined to be the largest value representable as an SkScalar */ - #define SK_ScalarMax (3.4028235e+38f) + #define SK_ScalarMax (3.402823466e+38f) /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar */ - #define SK_ScalarMin (1.1754944e-38f) + #define SK_ScalarMin (1.175494351e-38f) /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar */ #define SK_ScalarNaN (*(const float*)(const void*)&gIEEENotANumber) diff --git a/include/core/SkScan.h b/include/core/SkScan.h index 037dc09..31d4845 100644 --- a/include/core/SkScan.h +++ b/include/core/SkScan.h @@ -1,6 +1,6 @@ /* libs/graphics/sgl/SkScan.h ** -** Copyright 2006, The Android Open Source Project +** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -42,10 +42,9 @@ public: #else static void FillRect(const SkRect&, const SkRegion* clip, SkBlitter*); #endif - - static void FillTriangle(const SkPoint pts[], const SkRegion*, SkBlitter*); static void FillPath(const SkPath&, const SkRegion& clip, SkBlitter*); + static void FillTriangle(const SkPoint pts[], const SkRegion*, SkBlitter*); static void FillTriangle(const SkPoint& a, const SkPoint& b, const SkPoint& c, const SkRegion* clip, SkBlitter* blitter) { @@ -56,12 +55,11 @@ public: FillTriangle(pts, clip, blitter); } - static void HairLine(const SkPoint&, const SkPoint&, const SkRegion* clip, SkBlitter*); + static void HairLine(const SkPoint&, const SkPoint&, const SkRegion*, + SkBlitter*); static void HairRect(const SkRect&, const SkRegion* clip, SkBlitter*); static void HairPath(const SkPath&, const SkRegion* clip, SkBlitter*); - static void FrameRect(const SkRect&, SkScalar width, const SkRegion* clip, SkBlitter*); - static void AntiFillXRect(const SkXRect&, const SkRegion* clip, SkBlitter*); #ifdef SK_SCALAR_IS_FIXED static void AntiFillRect(const SkRect& rect, const SkRegion* clip, @@ -74,9 +72,16 @@ public: static void AntiFillPath(const SkPath&, const SkRegion& clip, SkBlitter*); - static void AntiHairLine(const SkPoint&, const SkPoint&, const SkRegion* clip, SkBlitter*); + static void AntiHairLine(const SkPoint&, const SkPoint&, const SkRegion*, + SkBlitter*); static void AntiHairRect(const SkRect&, const SkRegion* clip, SkBlitter*); static void AntiHairPath(const SkPath&, const SkRegion* clip, SkBlitter*); + + // draws with a miter-join + static void FrameRect(const SkRect&, const SkPoint& strokeSize, + const SkRegion*, SkBlitter*); + static void AntiFrameRect(const SkRect&, const SkPoint& strokeSize, + const SkRegion*, SkBlitter*); }; /** Assign an SkXRect from a SkIRect, by promoting the src rect's coordinates diff --git a/include/core/SkShader.h b/include/core/SkShader.h index d837284..cf1d4e9 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -26,28 +26,33 @@ class SkPath; /** \class SkShader - - SkShader is the based class for objects that return horizontal spans of colors during drawing. - A subclass of SkShader is installed in a SkPaint calling paint.setShader(shader). After that - any object (other than a bitmap) that is drawn with that paint will get its color(s) from the - shader. -*/ + * + * SkShader is the based class for objects that return horizontal spans of + * colors during drawing. A subclass of SkShader is installed in a SkPaint + * calling paint.setShader(shader). After that any object (other than a bitmap) + * that is drawn with that paint will get its color(s) from the shader. + */ class SK_API SkShader : public SkFlattenable { public: SkShader(); virtual ~SkShader(); - /** Return true if the shader has a non-identity local matrix. - @param localM Optional: If not null, return the shader's local matrix - @return true if the shader has a non-identity local matrix. - */ + /** + * Return true if the shader has a non-identity local matrix. + * @param localM Optional: If not null, return the shader's local matrix + * @return true if the shader has a non-identity local matrix. + */ bool getLocalMatrix(SkMatrix* localM) const; - /** Set the shader's local matrix. - @param localM The shader's new local matrix. - */ + + /** + * Set the shader's local matrix. + * @param localM The shader's new local matrix. + */ void setLocalMatrix(const SkMatrix& localM); - /** Reset the shader's local matrix to identity. - */ + + /** + * Reset the shader's local matrix to identity. + */ void resetLocalMatrix(); enum TileMode { @@ -89,59 +94,69 @@ public: kConstInY16_Flag = 0x10 }; - /** Called sometimes before drawing with this shader. - Return the type of alpha your shader will return. - The default implementation returns 0. Your subclass should override if it can - (even sometimes) report a non-zero value, since that will enable various blitters - to perform faster. - */ + /** + * Called sometimes before drawing with this shader. Return the type of + * alpha your shader will return. The default implementation returns 0. + * Your subclass should override if it can (even sometimes) report a + * non-zero value, since that will enable various blitters to perform + * faster. + */ virtual uint32_t getFlags() { return 0; } - /** Return the alpha associated with the data returned by shadeSpan16(). If - kHasSpan16_Flag is not set, this value is meaningless. - */ + /** + * Return the alpha associated with the data returned by shadeSpan16(). If + * kHasSpan16_Flag is not set, this value is meaningless. + */ virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; } - /** Called once before drawing, with the current paint and - device matrix. Return true if your shader supports these - parameters, or false if not. If false is returned, nothing - will be drawn. - */ + /** + * Called once before drawing, with the current paint and device matrix. + * Return true if your shader supports these parameters, or false if not. + * If false is returned, nothing will be drawn. + */ virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); - /** Called for each span of the object being drawn. Your subclass - should set the appropriate colors (with premultiplied alpha) that - correspond to the specified device coordinates. - */ + /** + * Called for each span of the object being drawn. Your subclass should + * set the appropriate colors (with premultiplied alpha) that correspond + * to the specified device coordinates. + */ virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; - /** Called only for 16bit devices when getFlags() returns - kOpaqueAlphaFlag | kHasSpan16_Flag - */ + + /** + * Called only for 16bit devices when getFlags() returns + * kOpaqueAlphaFlag | kHasSpan16_Flag + */ virtual void shadeSpan16(int x, int y, uint16_t[], int count); - /** Similar to shadeSpan, but only returns the alpha-channel for a span. - The default implementation calls shadeSpan() and then extracts the alpha - values from the returned colors. - */ + + /** + * Similar to shadeSpan, but only returns the alpha-channel for a span. + * The default implementation calls shadeSpan() and then extracts the alpha + * values from the returned colors. + */ virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); - /** Helper function that returns true if this shader's shadeSpan16() method can - be called. - */ + /** + * Helper function that returns true if this shader's shadeSpan16() method + * can be called. + */ bool canCallShadeSpan16() { return SkShader::CanCallShadeSpan16(this->getFlags()); } - /** Helper to check the flags to know if it is legal to call shadeSpan16() - */ + /** + * Helper to check the flags to know if it is legal to call shadeSpan16() + */ static bool CanCallShadeSpan16(uint32_t flags) { return (flags & kHasSpan16_Flag) != 0; } - /** Called before a session using the shader begins. Some shaders override - this to defer some of their work (like calling bitmap.lockPixels()). - Must be balanced by a call to endSession. - */ + /** + * Called before a session using the shader begins. Some shaders override + * this to defer some of their work (like calling bitmap.lockPixels()). + * Must be balanced by a call to endSession. + */ virtual void beginSession(); virtual void endSession(); @@ -195,7 +210,7 @@ public: about the first point. */ virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, - TileMode xy[2], SkScalar* twoPointRadialParams) const; + TileMode xy[2], SkScalar* twoPointRadialParams) const; /** * If the shader subclass can be represented as a gradient, asAGradient diff --git a/include/core/SkStream.h b/include/core/SkStream.h index b02d482..3886b09 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -70,7 +70,7 @@ public: size_t readPackedUInt(); }; -class SkWStream : SkNoncopyable { +class SK_API SkWStream : SkNoncopyable { public: virtual ~SkWStream(); @@ -269,7 +269,7 @@ private: size_t fBytesWritten; }; -class SkDynamicMemoryWStream : public SkWStream { +class SK_API SkDynamicMemoryWStream : public SkWStream { public: SkDynamicMemoryWStream(); virtual ~SkDynamicMemoryWStream(); diff --git a/include/core/SkString.h b/include/core/SkString.h index eb25e15..38604dd 100644 --- a/include/core/SkString.h +++ b/include/core/SkString.h @@ -78,25 +78,21 @@ public: const char* c_str() const { return fRec->data(); } char operator[](size_t n) const { return this->c_str()[n]; } - bool equals(const SkString&) const; - bool equals(const char text[]) const; - bool equals(const char text[], size_t len) const; + bool equals(const SkString&) const; + bool equals(const char text[]) const; + bool equals(const char text[], size_t len) const; - bool startsWith(const char prefix[]) const - { + bool startsWith(const char prefix[]) const { return SkStrStartsWith(fRec->data(), prefix); } - bool endsWith(const char suffix[]) const - { + bool endsWith(const char suffix[]) const { return SkStrEndsWith(fRec->data(), suffix); } - friend int operator==(const SkString& a, const SkString& b) - { + friend int operator==(const SkString& a, const SkString& b) { return a.equals(b); } - friend int operator!=(const SkString& a, const SkString& b) - { + friend int operator!=(const SkString& a, const SkString& b) { return !a.equals(b); } @@ -107,51 +103,52 @@ public: char* writable_str(); char& operator[](size_t n) { return this->writable_str()[n]; } - void reset(); - void resize(size_t len) { this->set(NULL, len); } - void set(const SkString& src) { *this = src; } - void set(const char text[]); - void set(const char text[], size_t len); - void setUTF16(const uint16_t[]); - void setUTF16(const uint16_t[], size_t len); - - void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); } - void insert(size_t offset, const char text[]); - void insert(size_t offset, const char text[], size_t len); - void insertUnichar(size_t offset, SkUnichar); - void insertS32(size_t offset, int32_t value); - void insertS64(size_t offset, int64_t value, int minDigits = 0); - void insertHex(size_t offset, uint32_t value, int minDigits = 0); - void insertScalar(size_t offset, SkScalar); - - void append(const SkString& str) { this->insert((size_t)-1, str); } - void append(const char text[]) { this->insert((size_t)-1, text); } - void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); } - void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); } - void appendS32(int32_t value) { this->insertS32((size_t)-1, value); } - void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); } - void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); } - void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } - - void prepend(const SkString& str) { this->insert(0, str); } - void prepend(const char text[]) { this->insert(0, text); } - void prepend(const char text[], size_t len) { this->insert(0, text, len); } - void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); } - void prependS32(int32_t value) { this->insertS32(0, value); } - void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); } - void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); } - void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } - - void printf(const char format[], ...); - void appendf(const char format[], ...); - void prependf(const char format[], ...); - - void remove(size_t offset, size_t length); - - /** Swap contents between this and other. This function is guaranteed - to never fail or throw. - */ - void swap(SkString& other); + void reset(); + void resize(size_t len) { this->set(NULL, len); } + void set(const SkString& src) { *this = src; } + void set(const char text[]); + void set(const char text[], size_t len); + void setUTF16(const uint16_t[]); + void setUTF16(const uint16_t[], size_t len); + + void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); } + void insert(size_t offset, const char text[]); + void insert(size_t offset, const char text[], size_t len); + void insertUnichar(size_t offset, SkUnichar); + void insertS32(size_t offset, int32_t value); + void insertS64(size_t offset, int64_t value, int minDigits = 0); + void insertHex(size_t offset, uint32_t value, int minDigits = 0); + void insertScalar(size_t offset, SkScalar); + + void append(const SkString& str) { this->insert((size_t)-1, str); } + void append(const char text[]) { this->insert((size_t)-1, text); } + void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); } + void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); } + void appendS32(int32_t value) { this->insertS32((size_t)-1, value); } + void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); } + void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); } + void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } + + void prepend(const SkString& str) { this->insert(0, str); } + void prepend(const char text[]) { this->insert(0, text); } + void prepend(const char text[], size_t len) { this->insert(0, text, len); } + void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); } + void prependS32(int32_t value) { this->insertS32(0, value); } + void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); } + void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); } + void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } + + void printf(const char format[], ...); + void appendf(const char format[], ...); + void prependf(const char format[], ...); + + void remove(size_t offset, size_t length); + + /** + * Swap contents between this and other. This function is guaranteed + * to never fail or throw. + */ + void swap(SkString& other); private: struct Rec { @@ -185,6 +182,7 @@ public: /** This returns the number of ucs2 characters */ int count() const { return fCount; } + /** This returns a null terminated ucs2 string */ const uint16_t* getUCS2() const { return fUCS2; } diff --git a/include/core/SkTLazy.h b/include/core/SkTLazy.h new file mode 100644 index 0000000..fecc975 --- /dev/null +++ b/include/core/SkTLazy.h @@ -0,0 +1,91 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkTLazy_DEFINED +#define SkTLazy_DEFINED + +#include "SkTypes.h" + +/** + * Efficient way to defer allocating/initializing a class until it is needed + * (if ever). + */ +template <typename T> class SkTLazy { +public: + SkTLazy() : fPtr(NULL) {} + + explicit SkTLazy(const T* src) : fPtr(NULL) { + if (src) { + fPtr = new (fStorage) T(*src); + } + } + + SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) { + const T* ptr = src.get(); + if (ptr) { + fPtr = new (fStorage) T(*ptr); + } + } + + ~SkTLazy() { + if (fPtr) { + fPtr->~T(); + } + } + + /** + * Return a pointer to a default-initialized instance of the class. If a + * previous instance had been initialzied (either from init() or set()) it + * will first be destroyed, so that a freshly initialized instance is + * always returned. + */ + T* init() { + if (fPtr) { + fPtr->~T(); + } + fPtr = new (fStorage) T; + return fPtr; + } + + /** + * Copy src into this, and return a pointer to a copy of it. Note this + * will always return the same pointer, so if it is called on a lazy that + * has already been initialized, then this will copy over the previous + * contents. + */ + T* set(const T& src) { + if (fPtr) { + *fPtr = src; + } else { + fPtr = new (fStorage) T(src); + } + return fPtr; + } + + /** + * Returns either NULL, or a copy of the object that was passed to + * set() or the constructor. + */ + T* get() const { return fPtr; } + +private: + T* fPtr; // NULL or fStorage + char fStorage[sizeof(T)]; +}; + +#endif + diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index c3b0f50..c415329 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -17,6 +17,7 @@ #ifndef SkTypeface_DEFINED #define SkTypeface_DEFINED +#include "SkAdvancedTypefaceMetrics.h" #include "SkRefCnt.h" class SkStream; @@ -136,12 +137,12 @@ public: static SkTypeface* Deserialize(SkStream*); /** Retrieve detailed typeface metrics. Used by the PDF backend. - @param perGlyphInfo Indicate if the glyph specific information (advances - and names) should be populated. + @param perGlyphInfo Indicate what glyph specific information (advances, + names, etc.) should be populated. @return The returned object has already been referenced. */ SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics( - bool perGlyphInfo) const; + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const; protected: /** uniqueID must be unique (please!) and non-zero diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h index 1290935..1a3a2e5 100644 --- a/include/core/SkTypes.h +++ b/include/core/SkTypes.h @@ -318,6 +318,13 @@ static inline uint32_t SkSetClearMask(uint32_t bits, bool cond, /////////////////////////////////////////////////////////////////////////////// +/** Use to combine multiple bits in a bitmask in a type safe way. + */ +template <typename T> +T SkTBitOr(T a, T b) { + return (T)(a | b); +} + /** * Use to cast a pointer to a different type, and maintaining strict-aliasing */ diff --git a/include/core/SkUserConfig.h b/include/core/SkUserConfig.h index 2140a15..29e64f2 100644 --- a/include/core/SkUserConfig.h +++ b/include/core/SkUserConfig.h @@ -163,5 +163,14 @@ void Android_SkDebugf(const char* file, int line, #define SK_SUPPORT_UNITTEST #endif +/* Change the ordering to work in X windows. + */ +#ifdef SK_SAMPLES_FOR_X + #define SK_R32_SHIFT 16 + #define SK_G32_SHIFT 8 + #define SK_B32_SHIFT 0 + #define SK_A32_SHIFT 24 +#endif + #endif diff --git a/include/core/SkUtils.h b/include/core/SkUtils.h index 7cb2066..a346d48 100644 --- a/include/core/SkUtils.h +++ b/include/core/SkUtils.h @@ -19,7 +19,7 @@ #include "SkTypes.h" -/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /** Similar to memset(), but it assigns a 16bit value into the buffer. @param buffer The memory to have value copied into it @@ -54,7 +54,7 @@ extern SkMemset16Proc sk_memset16; extern SkMemset32Proc sk_memset32; #endif -/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #define kMaxBytesInUTF8Sequence 4 @@ -64,8 +64,7 @@ extern SkMemset32Proc sk_memset32; #define SkUTF8_LeadByteToCount(c) ((((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1) #endif -inline int SkUTF8_CountUTF8Bytes(const char utf8[]) -{ +inline int SkUTF8_CountUTF8Bytes(const char utf8[]) { SkASSERT(utf8); return SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); } diff --git a/include/effects/SkBlurDrawLooper.h b/include/effects/SkBlurDrawLooper.h index 101d24e..846048c 100644 --- a/include/effects/SkBlurDrawLooper.h +++ b/include/effects/SkBlurDrawLooper.h @@ -48,9 +48,8 @@ public: virtual ~SkBlurDrawLooper(); // overrides from SkDrawLooper - virtual void init(SkCanvas*, SkPaint*); - virtual bool next(); - virtual void restore(); + virtual void init(SkCanvas*); + virtual bool next(SkCanvas*, SkPaint* paint); static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { return SkNEW_ARGS(SkBlurDrawLooper, (buffer)); @@ -64,14 +63,10 @@ protected: virtual Factory getFactory() { return CreateProc; } private: - SkCanvas* fCanvas; - SkPaint* fPaint; SkMaskFilter* fBlur; SkColorFilter* fColorFilter; SkScalar fDx, fDy; SkColor fBlurColor; - SkColor fSavedColor; // remember the original - int fSaveCount; uint32_t fBlurFlags; enum State { diff --git a/include/effects/SkLayerDrawLooper.h b/include/effects/SkLayerDrawLooper.h index 670ac23..b487a88 100644 --- a/include/effects/SkLayerDrawLooper.h +++ b/include/effects/SkLayerDrawLooper.h @@ -2,6 +2,7 @@ #define SkLayerDrawLooper_DEFINED #include "SkDrawLooper.h" +#include "SkXfermode.h" struct SkPoint; @@ -9,23 +10,83 @@ class SkLayerDrawLooper : public SkDrawLooper { public: SkLayerDrawLooper(); virtual ~SkLayerDrawLooper(); - - /** Call for each layer you want to add (from top to bottom). - This returns a paint you can modify, but that ptr is only valid until - the next call made to this object. + + /** + * Bits specifies which aspects of the layer's paint should replace the + * corresponding aspects on the draw's paint. + * kEntirePaint_Bits means use the layer's paint completely. + * 0 means ignore the layer's paint. + */ + enum Bits { + kStyle_Bit = 1 << 0, //!< use this layer's Style/stroke settings + kTextSkewX_Bit = 1 << 1, //!< use this layer's textskewx + kPathEffect_Bit = 1 << 2, //!< use this layer's patheffect + kMaskFilter_Bit = 1 << 3, //!< use this layer's maskfilter + kShader_Bit = 1 << 4, //!< use this layer's shader + kColorFilter_Bit = 1 << 5, //!< use this layer's colorfilter + kXfermode_Bit = 1 << 6, //!< use this layer's xfermode + + kEntirePaint_Bits = -1, //!< use this layer's paint entirely + }; + typedef int32_t BitFlags; + + /** + * Info for how to apply the layer's paint and offset. + * + * fColorMode controls how we compute the final color for the layer: + * The layer's paint's color is treated as the SRC + * The draw's paint's color is treated as the DST + * final-color = Mode(layers-color, draws-color); + * Any SkXfermode::Mode will work. Two common choices are: + * kSrc_Mode: to use the layer's color, ignoring the draw's + * kDst_Mode: to just keep the draw's color, ignoring the layer's + */ + struct LayerInfo { + BitFlags fPaintBits; + SkXfermode::Mode fColorMode; + SkVector fOffset; + bool fPostTranslate; //!< applies to fOffset + + /** + * Initial the LayerInfo. Defaults to settings that will draw the + * layer with no changes: e.g. + * fPaintBits == 0 + * fColorMode == kDst_Mode + * fOffset == (0, 0) + */ + LayerInfo(); + }; + + /** + * Call for each layer you want to add (from top to bottom). + * This returns a paint you can modify, but that ptr is only valid until + * the next call made to this object. + */ + SkPaint* addLayer(const LayerInfo&); + + /** + * Call for each layer you want to add (from top to bottom). + * This returns a paint you can modify, but that ptr is only valid until + * the next call made to this object. + * The returned paint will be ignored, and only the offset will be applied + * + * DEPRECATED: call addLayer(const LayerInfo&) */ SkPaint* addLayer(SkScalar dx, SkScalar dy); - /** Helper for addLayer() which passes (0, 0) for the offset parameters + /** + * Helper for addLayer() which passes (0, 0) for the offset parameters. + * This layer will not affect the drawing in any way. + * + * DEPRECATED: call addLayer(const LayerInfo&) */ SkPaint* addLayer() { return this->addLayer(0, 0); } // overrides from SkDrawLooper - virtual void init(SkCanvas*, SkPaint*); - virtual bool next(); - virtual void restore(); + virtual void init(SkCanvas*); + virtual bool next(SkCanvas*, SkPaint* paint); // must be public for Registrar :( static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { @@ -43,21 +104,19 @@ private: struct Rec { Rec* fNext; SkPaint fPaint; - SkPoint fOffset; - + LayerInfo fInfo; + static Rec* Reverse(Rec*); }; Rec* fRecs; int fCount; - - struct Iter { - SkPaint fSavedPaint; - SkPaint* fPaint; - SkCanvas* fCanvas; - Rec* fRec; - }; - Iter fIter; - + + // state-machine during the init/next cycle + Rec* fCurrRec; + + static void ApplyBits(SkPaint* dst, const SkPaint& src, BitFlags, + SkXfermode::Mode); + class MyRegistrar : public SkFlattenable::Registrar { public: MyRegistrar(); diff --git a/include/effects/SkPaintFlagsDrawFilter.h b/include/effects/SkPaintFlagsDrawFilter.h index 941be24..e4ec466 100644 --- a/include/effects/SkPaintFlagsDrawFilter.h +++ b/include/effects/SkPaintFlagsDrawFilter.h @@ -24,8 +24,7 @@ public: SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags); // overrides - virtual bool filter(SkCanvas*, SkPaint*, Type); - virtual void restore(SkCanvas*, SkPaint*, Type); + virtual void filter(SkPaint*, Type); private: uint32_t fPrevFlags; // local cache for filter/restore diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index 8852803..fbe5929 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -30,7 +30,7 @@ class GrTextContext; * Subclass of SkDevice, which directs all drawing to the GrGpu owned by the * canvas. */ -class SkGpuDevice : public SkDevice { +class SK_API SkGpuDevice : public SkDevice { public: /** * The SkGpuDevice will render to the GrRenderTarget, or if the paremeter is diff --git a/include/gpu/SkGpuDeviceFactory.h b/include/gpu/SkGpuDeviceFactory.h index 5dcba6a..6f62ad6 100644 --- a/include/gpu/SkGpuDeviceFactory.h +++ b/include/gpu/SkGpuDeviceFactory.h @@ -21,7 +21,7 @@ class GrContext; -class SkGpuDeviceFactory : public SkDeviceFactory { +class SK_API SkGpuDeviceFactory : public SkDeviceFactory { public: /** * The constructor will ref() the context, passing it to each device @@ -34,6 +34,14 @@ public: * construction. */ SkGpuDeviceFactory(GrContext*, GrRenderTarget* rootRenderTarget); + + /** + * When the root layer is both a GrRenderTarget and a GrTexture it + * is handy to have the factory hang on to a ref to the GrTexture object. + * This is because the GrTexture has a ref to the GrRenderTarget but not + * vice-versa. + */ + SkGpuDeviceFactory(GrContext*, GrTexture* rootRenderTargetTexture); virtual ~SkGpuDeviceFactory(); @@ -43,6 +51,7 @@ public: private: GrContext* fContext; GrRenderTarget* fRootRenderTarget; + GrTexture* fRootTexture; }; #endif diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h index 7221213..10f1bd0 100644 --- a/include/gpu/SkGr.h +++ b/include/gpu/SkGr.h @@ -129,10 +129,10 @@ public: * Convert the SkBitmap::Config to the corresponding PixelConfig, or * kUnknown_PixelConfig if the conversion cannot be done. */ - static GrTexture::PixelConfig BitmapConfig2PixelConfig(SkBitmap::Config, - bool isOpaque); + static GrPixelConfig BitmapConfig2PixelConfig(SkBitmap::Config, + bool isOpaque); - static GrTexture::PixelConfig Bitmap2PixelConfig(const SkBitmap& bm) { + static GrPixelConfig Bitmap2PixelConfig(const SkBitmap& bm) { return BitmapConfig2PixelConfig(bm.config(), bm.isOpaque()); } @@ -156,14 +156,6 @@ public: unsigned a = SkGetPackedA32(pm); return GrColorPackRGBA(r, g, b, a); } - - /** - * This abandons all texture caches (for bitmaps and text) associated with - * the gpu, and frees any associated skia caches. It differs from - * deleteAllTextures in that it assumes that the gpu has lots its context, - * and thus the associated HW textures are no longer valid - */ - static void AbandonAllTextures(GrContext*); }; //////////////////////////////////////////////////////////////////////////////// @@ -207,7 +199,11 @@ public: virtual GrSetOp getOp() const; virtual void getRect(GrRect* rect) const { - *rect = Sk2Gr(*fCurr->fRect); + if (!fCurr->fRect) { + rect->setEmpty(); + } else { + *rect = Sk2Gr(*fCurr->fRect); + } } virtual GrPathIter* getPathIter() { diff --git a/include/gpu/SkGrTexturePixelRef.h b/include/gpu/SkGrTexturePixelRef.h index 1f5133f..5bc64f5 100644 --- a/include/gpu/SkGrTexturePixelRef.h +++ b/include/gpu/SkGrTexturePixelRef.h @@ -40,11 +40,38 @@ protected: // override from SkPixelRef virtual void onUnlockPixels() {} + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset); private: GrTexture* fTexture; typedef SkPixelRef INHERITED; }; +class SkGrRenderTargetPixelRef : public SkPixelRef { +public: + SkGrRenderTargetPixelRef(GrRenderTarget* rt); + virtual ~SkGrRenderTargetPixelRef(); + + // override from SkPixelRef + virtual SkGpuTexture* getTexture(); + +protected: + // override from SkPixelRef + virtual void* onLockPixels(SkColorTable** ptr) { + if (ptr) { + *ptr = NULL; + } + return NULL; + } + + // override from SkPixelRef + virtual void onUnlockPixels() {} + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset); + +private: + GrRenderTarget* fRenderTarget; + typedef SkPixelRef INHERITED; +}; + #endif diff --git a/include/ports/SkTypeface_mac.h b/include/ports/SkTypeface_mac.h new file mode 100644 index 0000000..61b226b --- /dev/null +++ b/include/ports/SkTypeface_mac.h @@ -0,0 +1,32 @@ +/* + Copyright 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + +#ifndef SkTypeface_mac_DEFINED +#define SkTypeface_mac_DEFINED + +#include "SkTypeface.h" +#include <Carbon/Carbon.h> + +/** + * Like the other Typeface create methods, this returns a new reference to the + * corresponding typeface for the specified CTFontRef. The caller must call + * unref() when it is finished. + */ +SK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef); + +#endif + diff --git a/src/animator/SkDisplayXMLParser.cpp b/src/animator/SkDisplayXMLParser.cpp index d2775e8..a94b848 100644 --- a/src/animator/SkDisplayXMLParser.cpp +++ b/src/animator/SkDisplayXMLParser.cpp @@ -164,6 +164,14 @@ bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char att return false; } +#if defined(SK_BUILD_FOR_WIN32) + #define SK_strcasecmp stricmp + #define SK_strncasecmp strnicmp +#else + #define SK_strcasecmp strcasecmp + #define SK_strncasecmp strncasecmp +#endif + bool SkDisplayXMLParser::onEndElement(const char elem[]) { int parentIndex = fParents.count() - 1; @@ -199,7 +207,7 @@ bool SkDisplayXMLParser::onEndElement(const char elem[]) fParents.remove(parentIndex); } fCurrDisplayable = NULL; - if (fInInclude == false && strcasecmp(elem, "screenplay") == 0) { + if (fInInclude == false && SK_strcasecmp(elem, "screenplay") == 0) { if (fMaker.fInMovie == false) { fMaker.fEnableTime = fMaker.getAppTime(); #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING @@ -231,7 +239,7 @@ bool SkDisplayXMLParser::onStartElement(const char name[]) bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) { fCurrDisplayable = NULL; // init so we'll ignore attributes if we exit early - if (strncasecmp(name, "screenplay", len) == 0) { + if (SK_strncasecmp(name, "screenplay", len) == 0) { fInSkia = true; if (fInInclude == false) fMaker.idsSet(name, len, &fMaker.fScreenplay); diff --git a/src/core/Makefile.am b/src/core/Makefile.am new file mode 100644 index 0000000..4adde0a --- /dev/null +++ b/src/core/Makefile.am @@ -0,0 +1,91 @@ +AM_CPPFLAGS = -I$(top_builddir)/include/core + +noinst_LIBRARIES = libskia.a +libskia_a_SOURCES = Sk64.cpp \ +SkAlphaRuns.cpp \ +SkBitmap.cpp \ +SkBitmapProcShader.cpp \ +SkBitmapProcState.cpp \ +SkBitmapProcState_matrixProcs.cpp \ +SkBitmapSampler.cpp \ +SkBitmapShader.cpp \ +SkBitmap_scroll.cpp \ +SkBlitRow_D16.cpp \ +SkBlitRow_D4444.cpp \ +SkBlitter.cpp \ +SkBlitter_4444.cpp \ +SkBlitter_A1.cpp \ +SkBlitter_A8.cpp \ +SkBlitter_ARGB32.cpp \ +SkBlitter_RGB16.cpp \ +SkBlitter_Sprite.cpp \ +SkBuffer.cpp \ +SkCanvas.cpp \ +SkChunkAlloc.cpp \ +SkColor.cpp \ +SkColorFilter.cpp \ +SkColorTable.cpp \ +SkComposeShader.cpp \ +SkConcaveToTriangles.cpp \ +SkCordic.cpp \ +skCubicClipper.cpp \ +SkDebug.cpp \ +SkDebug_stdio.cpp \ +SkDeque.cpp \ +SkDevice.cpp \ +SkDither.cpp \ +SkDraw.cpp \ +SkEdge.cpp \ +SkFilterProc.cpp \ +SkFlattenable.cpp \ +SkFloat.cpp \ +SkFloatBits.cpp \ +SkGeometry.cpp \ +SkGlobals.cpp \ +SkGlyphCache.cpp \ +SkGraphics.cpp \ +SkMMapStream.cpp \ +SkMask.cpp \ +SkMaskFilter.cpp \ +SkMath.cpp \ +SkMatrix.cpp \ +SkMemory_stdlib.cpp \ +SkPackBits.cpp \ +SkPaint.cpp \ +SkPath.cpp \ +SkPathEffect.cpp \ +SkPathHeap.cpp \ +SkPathMeasure.cpp \ +SkPicture.cpp \ +SkPictureFlat.cpp \ +SkPicturePlayback.cpp \ +SkPictureRecord.cpp \ +SkPixelRef.cpp \ +SkPoint.cpp \ +SkProcSpriteBlitter.cpp \ +SkPtrRecorder.cpp \ +SkRasterizer.cpp \ +SkRect.cpp \ +SkRefCnt.cpp \ +SkRegion.cpp \ +SkRegion_path.cpp \ +SkScalar.cpp \ +SkScalerContext.cpp \ +SkScan.cpp \ +SkScan_AntiPath.cpp \ +SkScan_Antihair.cpp \ +SkScan_Hairline.cpp \ +SkScan_Path.cpp \ +SkShader.cpp \ +SkSpriteBlitter_ARGB32.cpp \ +SkSpriteBlitter_RGB16.cpp \ +SkStream.cpp \ +SkString.cpp \ +SkStroke.cpp \ +SkStrokerPriv.cpp \ +SkTSearch.cpp \ +SkTypeface.cpp \ +SkUnPreMultiply.cpp \ +SkUtils.cpp \ +SkWriter32.cpp \ +SkXfermode.cpp diff --git a/src/core/SkAlphaRuns.cpp b/src/core/SkAlphaRuns.cpp index 46b0206..4125b58 100644 --- a/src/core/SkAlphaRuns.cpp +++ b/src/core/SkAlphaRuns.cpp @@ -17,8 +17,7 @@ #include "SkAntiRun.h" -void SkAlphaRuns::reset(int width) -{ +void SkAlphaRuns::reset(int width) { SkASSERT(width > 0); fRuns[0] = SkToS16(width); @@ -29,8 +28,7 @@ void SkAlphaRuns::reset(int width) SkDEBUGCODE(this->validate();) } -void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) -{ +void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) { SkASSERT(count > 0 && x >= 0); // SkAlphaRuns::BreakAt(runs, alpha, x); @@ -39,13 +37,11 @@ void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) int16_t* next_runs = runs + x; uint8_t* next_alpha = alpha + x; - while (x > 0) - { + while (x > 0) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); @@ -60,37 +56,34 @@ void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) alpha = next_alpha; x = count; - for (;;) - { + for (;;) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); break; } x -= n; - if (x <= 0) + if (x <= 0) { break; - + } runs += n; alpha += n; } } -void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue) -{ +void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, + U8CPU maxValue) { SkASSERT(middleCount >= 0); SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); int16_t* runs = fRuns; uint8_t* alpha = fAlpha; - if (startAlpha) - { + if (startAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); /* I should be able to just add alpha[x] + startAlpha. However, if the trailing edge of the previous span and the leading @@ -106,8 +99,8 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, x = 0; SkDEBUGCODE(this->validate();) } - if (middleCount) - { + + if (middleCount) { SkAlphaRuns::Break(runs, alpha, x, middleCount); alpha += x; runs += x; @@ -122,8 +115,8 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, } while (middleCount > 0); SkDEBUGCODE(this->validate();) } - if (stopAlpha) - { + + if (stopAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); alpha[x] = SkToU8(alpha[x] + stopAlpha); SkDEBUGCODE(this->validate();) @@ -131,49 +124,44 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, } #ifdef SK_DEBUG - void SkAlphaRuns::assertValid(int y, int maxStep) const - { + void SkAlphaRuns::assertValid(int y, int maxStep) const { int max = (y + 1) * maxStep - (y == maxStep - 1); const int16_t* runs = fRuns; const uint8_t* alpha = fAlpha; - while (*runs) - { + while (*runs) { SkASSERT(*alpha <= max); alpha += *runs; runs += *runs; } } - void SkAlphaRuns::dump() const - { + void SkAlphaRuns::dump() const { const int16_t* runs = fRuns; const uint8_t* alpha = fAlpha; SkDebugf("Runs"); - while (*runs) - { + while (*runs) { int n = *runs; SkDebugf(" %02x", *alpha); - if (n > 1) + if (n > 1) { SkDebugf(",%d", n); + } alpha += n; runs += n; } SkDebugf("\n"); } - void SkAlphaRuns::validate() const - { + void SkAlphaRuns::validate() const { SkASSERT(fWidth > 0); int count = 0; const int16_t* runs = fRuns; - while (*runs) - { + while (*runs) { SkASSERT(*runs > 0); count += *runs; SkASSERT(count <= fWidth); diff --git a/src/core/SkAntiRun.h b/src/core/SkAntiRun.h index 12930e6..89e5481 100644 --- a/src/core/SkAntiRun.h +++ b/src/core/SkAntiRun.h @@ -20,151 +20,29 @@ #include "SkBlitter.h" -inline int sk_make_nonzero_neg_one(int x) -{ - return (x | -x) >> 31; -} - -#if 0 -template <int kShift> class SkAntiRun { - static uint8_t coverage_to_alpha(int aa) - { - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - return SkToU8(aa); - } -public: - void set(int start, int stop) - { - SkASSERT(start >= 0 && stop > start); - -#if 1 - int fb = start & kMask; - int fe = stop & kMask; - int n = (stop >> kShift) - (start >> kShift) - 1; - - if (n < 0) - { - fb = fe - fb; - n = 0; - fe = 0; - } - else - { - if (fb == 0) - n += 1; - else - fb = (1 << kShift) - fb; - } - - fStartAlpha = coverage_to_alpha(fb); - fMiddleCount = n; - fStopAlpha = coverage_to_alpha(fe); -#else - int x0 = start >> kShift; - int x1 = (stop - 1) >> kShift; - int middle = x1 - x0; - int aa; - - if (middle == 0) - { - aa = stop - start; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa > 0 && aa < kMax); - fStartAlpha = SkToU8(aa); - fMiddleCount = 0; - fStopAlpha = 0; - } - else - { - int aa = start & kMask; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa >= 0 && aa < kMax); - if (aa) - fStartAlpha = SkToU8(kMax - aa); - else - { - fStartAlpha = 0; - middle += 1; - } - aa = stop & kMask; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa >= 0 && aa < kMax); - middle += sk_make_nonzero_neg_one(aa); - - fStopAlpha = SkToU8(aa); - fMiddleCount = middle; - } - SkASSERT(fStartAlpha < kMax); - SkASSERT(fStopAlpha < kMax); -#endif - } - - void blit(int x, int y, SkBlitter* blitter) - { - int16_t runs[2]; - runs[0] = 1; - runs[1] = 0; - - if (fStartAlpha) - { - blitter->blitAntiH(x, y, &fStartAlpha, runs); - x += 1; - } - if (fMiddleCount) - { - blitter->blitH(x, y, fMiddleCount); - x += fMiddleCount; - } - if (fStopAlpha) - blitter->blitAntiH(x, y, &fStopAlpha, runs); - } - - uint8_t getStartAlpha() const { return fStartAlpha; } - int getMiddleCount() const { return fMiddleCount; } - uint8_t getStopAlpha() const { return fStopAlpha; } - -private: - uint8_t fStartAlpha, fStopAlpha; - int fMiddleCount; - - enum { - kMask = (1 << kShift) - 1, - kMax = (1 << (8 - kShift)) - 1 - }; -}; -#endif - -//////////////////////////////////////////////////////////////////////////////////// - class SkAlphaRuns { public: int16_t* fRuns; uint8_t* fAlpha; - bool empty() const - { + bool empty() const { SkASSERT(fRuns[0] > 0); return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0; } + void reset(int width); void add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue); SkDEBUGCODE(void assertValid(int y, int maxStep) const;) SkDEBUGCODE(void dump() const;) static void Break(int16_t runs[], uint8_t alpha[], int x, int count); - static void BreakAt(int16_t runs[], uint8_t alpha[], int x) - { - while (x > 0) - { + + static void BreakAt(int16_t runs[], uint8_t alpha[], int x) { + while (x > 0) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index a5f7d57..c19e84d 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -865,61 +865,79 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { return false; } + // if we have a texture, first get those pixels + SkBitmap tmpSrc; + const SkBitmap* src = this; + + if (fPixelRef && fPixelRef->readPixels(&tmpSrc)) { + SkASSERT(tmpSrc.width() == this->width()); + SkASSERT(tmpSrc.height() == this->height()); + + // did we get lucky and we can just return tmpSrc? + if (tmpSrc.config() == dstConfig && NULL == alloc) { + dst->swap(tmpSrc); + return true; + } + + // fall through to the raster case + src = &tmpSrc; + } + // we lock this now, since we may need its colortable - SkAutoLockPixels srclock(*this); - if (!this->readyToDraw()) { + SkAutoLockPixels srclock(*src); + if (!src->readyToDraw()) { return false; } - - SkBitmap tmp; - tmp.setConfig(dstConfig, this->width(), this->height()); - + + SkBitmap tmpDst; + tmpDst.setConfig(dstConfig, src->width(), src->height()); + // allocate colortable if srcConfig == kIndex8_Config SkColorTable* ctable = (dstConfig == kIndex8_Config) ? - new SkColorTable(*this->getColorTable()) : NULL; + new SkColorTable(*src->getColorTable()) : NULL; SkAutoUnref au(ctable); - if (!tmp.allocPixels(alloc, ctable)) { + if (!tmpDst.allocPixels(alloc, ctable)) { return false; } - - SkAutoLockPixels dstlock(tmp); - if (!tmp.readyToDraw()) { + + SkAutoLockPixels dstlock(tmpDst); + if (!tmpDst.readyToDraw()) { // allocator/lock failed return false; } - + /* do memcpy for the same configs cases, else use drawing */ - if (this->config() == dstConfig) { - if (tmp.getSize() == this->getSize()) { - memcpy(tmp.getPixels(), this->getPixels(), this->getSafeSize()); + if (src->config() == dstConfig) { + if (tmpDst.getSize() == src->getSize()) { + memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); } else { - const char* srcP = reinterpret_cast<const char*>(this->getPixels()); - char* dstP = reinterpret_cast<char*>(tmp.getPixels()); + const char* srcP = reinterpret_cast<const char*>(src->getPixels()); + char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); // to be sure we don't read too much, only copy our logical pixels - size_t bytesToCopy = tmp.width() * tmp.bytesPerPixel(); - for (int y = 0; y < tmp.height(); y++) { + size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); + for (int y = 0; y < tmpDst.height(); y++) { memcpy(dstP, srcP, bytesToCopy); - srcP += this->rowBytes(); - dstP += tmp.rowBytes(); + srcP += src->rowBytes(); + dstP += tmpDst.rowBytes(); } } } else { // if the src has alpha, we have to clear the dst first - if (!this->isOpaque()) { - tmp.eraseColor(0); + if (!src->isOpaque()) { + tmpDst.eraseColor(0); } - SkCanvas canvas(tmp); + SkCanvas canvas(tmpDst); SkPaint paint; paint.setDither(true); - canvas.drawBitmap(*this, 0, 0, &paint); + canvas.drawBitmap(*src, 0, 0, &paint); } - tmp.setIsOpaque(this->isOpaque()); + tmpDst.setIsOpaque(src->isOpaque()); - dst->swap(tmp); + dst->swap(tmpDst); return true; } diff --git a/src/core/SkBlitter_4444.cpp b/src/core/SkBlitter_4444.cpp index e1c519a..d976f2d 100644 --- a/src/core/SkBlitter_4444.cpp +++ b/src/core/SkBlitter_4444.cpp @@ -41,7 +41,8 @@ class SkARGB4444_Blitter : public SkRasterBlitter { public: SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint); virtual void blitH(int x, int y, int width); - virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); + virtual void blitAntiH(int x, int y, const SkAlpha antialias[], + const int16_t runs[]); virtual void blitV(int x, int y, int height, SkAlpha alpha); virtual void blitRect(int x, int y, int width, int height); virtual void blitMask(const SkMask&, const SkIRect&); @@ -60,9 +61,8 @@ private: }; -SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) -{ +SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, + const SkPaint& paint) : INHERITED(device) { // cache premultiplied versions in 4444 SkPMColor c = SkPreMultiplyColor(paint.getColor()); fPMColor16 = SkPixel32ToPixel4444(c); @@ -82,13 +82,6 @@ SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& pa fRawColor16Other = fRawColor16; } -#if 0 /// don't think this assertion is true, but need it be? - - // our dithered color will be the same or more opaque than the original - // so use dithered to compute our scale - SkASSERT(SkGetPackedA4444(fPMColor16Other) >= SkGetPackedA4444(fPMColor16)); -#endif - fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); if (16 == fScale16) { // force the original to also be opaque @@ -96,8 +89,7 @@ SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& pa } } -const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) -{ +const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) { if (16 == fScale16) { *value = fPMColor16; return &fDevice; @@ -106,8 +98,7 @@ const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) } static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, - SkPMColor16 other, unsigned invScale, int count) -{ + SkPMColor16 other, unsigned invScale, int count) { int twice = count >> 1; while (--twice >= 0) { *dst = color + SkAlphaMulQ4(*dst, invScale); @@ -120,15 +111,13 @@ static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, } } -static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) -{ +static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) { uint32_t c32 = SkExpand_4444(c); return c32 | (c32 << 4); } static void src_over_4444x(SkPMColor16 dst[], uint32_t color, - uint32_t other, unsigned invScale, int count) -{ + uint32_t other, unsigned invScale, int count) { int twice = count >> 1; uint32_t tmp; while (--twice >= 0) { @@ -143,8 +132,7 @@ static void src_over_4444x(SkPMColor16 dst[], uint32_t color, } } -void SkARGB4444_Blitter::blitH(int x, int y, int width) -{ +void SkARGB4444_Blitter::blitH(int x, int y, int width) { SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); if (0 == fScale16) { @@ -161,16 +149,14 @@ void SkARGB4444_Blitter::blitH(int x, int y, int width) if (16 == fScale16) { sk_dither_memset16(device, color, other, width); - } - else { + } else { src_over_4444x(device, SkExpand_4444_Replicate(color), SkExpand_4444_Replicate(other), 16 - fScale16, width); } } -void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) -{ +void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { if (0 == alpha || 0 == fScale16) { return; } @@ -208,9 +194,9 @@ void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) } } -void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) -{ - SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); +void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) { + SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && + y + height <= fDevice.height()); if (0 == fScale16) { return; @@ -243,8 +229,8 @@ void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) } } -void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) -{ +void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], + const int16_t runs[]) { if (0 == fScale16) { return; } @@ -295,19 +281,19 @@ void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], cons } } -////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #define solid_8_pixels(mask, dst, color) \ -do { \ -if (mask & 0x80) dst[0] = color; \ -if (mask & 0x40) dst[1] = color; \ -if (mask & 0x20) dst[2] = color; \ -if (mask & 0x10) dst[3] = color; \ -if (mask & 0x08) dst[4] = color; \ -if (mask & 0x04) dst[5] = color; \ -if (mask & 0x02) dst[6] = color; \ -if (mask & 0x01) dst[7] = color; \ -} while (0) + do { \ + if (mask & 0x80) dst[0] = color; \ + if (mask & 0x40) dst[1] = color; \ + if (mask & 0x20) dst[2] = color; \ + if (mask & 0x10) dst[3] = color; \ + if (mask & 0x08) dst[4] = color; \ + if (mask & 0x04) dst[5] = color; \ + if (mask & 0x02) dst[6] = color; \ + if (mask & 0x01) dst[7] = color; \ + } while (0) #define SK_BLITBWMASK_NAME SkARGB4444_BlitBW #define SK_BLITBWMASK_ARGS , SkPMColor16 color @@ -316,17 +302,17 @@ if (mask & 0x01) dst[7] = color; \ #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" -#define blend_8_pixels(mask, dst, sc, dst_scale) \ -do { \ -if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ -if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ -if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ -if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ -if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ -if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ -if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ -if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ -} while (0) +#define blend_8_pixels(mask, dst, sc, dst_scale) \ + do { \ + if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ + if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ + if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ + if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ + if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ + if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ + if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ + if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ + } while (0) #define SK_BLITBWMASK_NAME SkARGB4444_BlendBW #define SK_BLITBWMASK_ARGS , uint16_t sc, unsigned dst_scale @@ -335,8 +321,7 @@ if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" -void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) -{ +void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkASSERT(mask.fBounds.contains(clip)); if (0 == fScale16) { @@ -375,7 +360,7 @@ void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) } while (--height != 0); } -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// class SkARGB4444_Shader_Blitter : public SkShaderBlitter { SkXfermode* fXfermode; @@ -386,8 +371,7 @@ class SkARGB4444_Shader_Blitter : public SkShaderBlitter { public: SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device, paint) -{ + : INHERITED(device, paint) { const int width = device.width(); fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width); fAAExpand = (uint8_t*)(fBuffer + width); diff --git a/src/core/SkBlitter_A1.cpp b/src/core/SkBlitter_A1.cpp index 1a91a26..d1416ff 100644 --- a/src/core/SkBlitter_A1.cpp +++ b/src/core/SkBlitter_A1.cpp @@ -18,18 +18,17 @@ #include "SkCoreBlitters.h" SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) -{ - fSrcA = SkToU8(SkColorGetA(paint.getColor())); + : INHERITED(device) { + fSrcA = paint.getAlpha(); } -void SkA1_Blitter::blitH(int x, int y, int width) -{ - SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.width()); +void SkA1_Blitter::blitH(int x, int y, int width) { + SkASSERT(x >= 0 && y >= 0 && + (unsigned)(x + width) <= (unsigned)fDevice.width()); - if (fSrcA <= 0x7F) + if (fSrcA <= 0x7F) { return; - + } uint8_t* dst = fDevice.getAddr1(x, y); int right = x + width; @@ -37,23 +36,20 @@ void SkA1_Blitter::blitH(int x, int y, int width) int rite_mask = 0xFF << (8 - (right & 7)); int full_runs = (right >> 3) - ((x + 7) >> 3); - // check for empty right mask, so we don't read off the end (or go slower than we need to) - if (rite_mask == 0) - { + // check for empty right mask, so we don't read off the end + // (or go slower than we need to) + if (rite_mask == 0) { SkASSERT(full_runs >= 0); full_runs -= 1; rite_mask = 0xFF; } - if (left_mask == 0xFF) + if (left_mask == 0xFF) { full_runs -= 1; - - if (full_runs < 0) - { + } + if (full_runs < 0) { SkASSERT((left_mask & rite_mask) != 0); *dst |= (left_mask & rite_mask); - } - else - { + } else { *dst++ |= left_mask; memset(dst, 0xFF, full_runs); dst += full_runs; diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp index f74fbe3..2eb762f 100644 --- a/src/core/SkBlitter_A8.cpp +++ b/src/core/SkBlitter_A8.cpp @@ -21,8 +21,8 @@ #include "SkXfermode.h" SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) { - fSrcA = SkColorGetA(paint.getColor()); + : INHERITED(device) { + fSrcA = paint.getAlpha(); } const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a31623e..16cfc4b 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -24,6 +24,7 @@ #include "SkScalarCompare.h" #include "SkShape.h" #include "SkTemplates.h" +#include "SkTLazy.h" #include "SkUtils.h" #include <new> @@ -50,6 +51,8 @@ #define dec_canvas() #endif +typedef SkTLazy<SkPaint> SkLazyPaint; + /////////////////////////////////////////////////////////////////////////////// // Helpers for computing fast bounds for quickReject tests @@ -279,65 +282,69 @@ private: class AutoDrawLooper { public: - AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t) - : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) { - if ((fLooper = paint.getLooper()) != NULL) { - fLooper->init(canvas, (SkPaint*)&paint); - } else { - fOnce = true; - } + AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) { + fCanvas = canvas; + fLooper = paint.getLooper(); fFilter = canvas->getDrawFilter(); - fNeedFilterRestore = false; - } + fPaint = NULL; + fSaveCount = canvas->getSaveCount(); + fDone = false; - ~AutoDrawLooper() { - if (fNeedFilterRestore) { - SkASSERT(fFilter); - fFilter->restore(fCanvas, fPaint, fType); - } - if (NULL != fLooper) { - fLooper->restore(); + if (fLooper) { + fLooper->init(canvas); } } - - bool next() { - SkDrawFilter* filter = fFilter; - - // if we drew earlier with a filter, then we need to restore first - if (fNeedFilterRestore) { - SkASSERT(filter); - filter->restore(fCanvas, fPaint, fType); - fNeedFilterRestore = false; - } - - bool result; - - if (NULL != fLooper) { - result = fLooper->next(); - } else { - result = fOnce; - fOnce = false; - } - - // if we're gonna draw, give the filter a chance to do its work - if (result && NULL != filter) { - fNeedFilterRestore = result = filter->filter(fCanvas, fPaint, - fType); - } - return result; + + ~AutoDrawLooper() { + SkASSERT(fCanvas->getSaveCount() == fSaveCount); } - + + const SkPaint& paint() const { + SkASSERT(fPaint); + return *fPaint; + } + + bool next(SkDrawFilter::Type drawType); + private: + SkLazyPaint fLazyPaint; + SkCanvas* fCanvas; + const SkPaint& fOrigPaint; SkDrawLooper* fLooper; SkDrawFilter* fFilter; - SkCanvas* fCanvas; - SkPaint* fPaint; - SkDrawFilter::Type fType; - bool fOnce; - bool fNeedFilterRestore; - + const SkPaint* fPaint; + int fSaveCount; + bool fDone; }; +bool AutoDrawLooper::next(SkDrawFilter::Type drawType) { + if (fDone) { + fPaint = NULL; + return false; + } + if (!fLooper && !fFilter) { + fDone = true; + fPaint = &fOrigPaint; + return true; + } + + SkPaint* paint = fLazyPaint.set(fOrigPaint); + if (fLooper && !fLooper->next(fCanvas, paint)) { + fDone = true; + fPaint = NULL; + return false; + } + if (fFilter) { + fFilter->filter(paint, drawType); + if (NULL == fLooper) { + // no looper means we only draw once + fDone = true; + } + } + fPaint = paint; + return true; +} + /* Stack helper for managing a SkBounder. In the destructor, if we were given a bounder, we call its commit() method, signifying that we are done accumulating bounds for that draw. @@ -379,14 +386,14 @@ private: ////////// macros to place around the internal draw calls ////////////////// -#define ITER_BEGIN(paint, type) \ +#define LOOPER_BEGIN(paint, type) \ /* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ - AutoDrawLooper looper(this, paint, type); \ - while (looper.next()) { \ + AutoDrawLooper looper(this, paint); \ + while (looper.next(type)) { \ SkAutoBounderCommit ac(fBounder); \ SkDrawIter iter(this); -#define ITER_END } +#define LOOPER_END } //////////////////////////////////////////////////////////////////////////// @@ -472,6 +479,10 @@ SkDevice* SkCanvas::getDevice() const { return rec->fLayer->fDevice; } +SkDevice* SkCanvas::getTopDevice() const { + return fMCRec->fTopLayer->fDevice; +} + SkDevice* SkCanvas::setDevice(SkDevice* device) { // return root device SkDeque::F2BIter iter(fMCStack); @@ -832,12 +843,11 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect return; } + SkLazyPaint lazy; if (NULL == paint) { - SkPaint tmpPaint; - this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint); - } else { - this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); + paint = lazy.init(); } + this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); } void SkCanvas::drawDevice(SkDevice* device, int x, int y, @@ -848,12 +858,12 @@ void SkCanvas::drawDevice(SkDevice* device, int x, int y, paint = &tmp; } - ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), - *paint); + looper.paint()); } - ITER_END + LOOPER_END } ///////////////////////////////////////////////////////////////////////////// @@ -1185,13 +1195,13 @@ SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, ////////////////////////////////////////////////////////////////////////////// void SkCanvas::drawPaint(const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kPaint_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) while (iter.next()) { - iter.fDevice->drawPaint(iter, paint); + iter.fDevice->drawPaint(iter, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], @@ -1202,13 +1212,13 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], SkASSERT(pts != NULL); - ITER_BEGIN(paint, SkDrawFilter::kPoint_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) while (iter.next()) { - iter.fDevice->drawPoints(iter, mode, count, pts, paint); + iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { @@ -1220,13 +1230,13 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { } } - ITER_BEGIN(paint, SkDrawFilter::kRect_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) while (iter.next()) { - iter.fDevice->drawRect(iter, r, paint); + iter.fDevice->drawRect(iter, r, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { @@ -1239,13 +1249,13 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { } } - ITER_BEGIN(paint, SkDrawFilter::kPath_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) while (iter.next()) { - iter.fDevice->drawPath(iter, path, paint); + iter.fDevice->drawPath(iter, path, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, @@ -1305,7 +1315,9 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, SkIRect tmpISrc; if (src) { tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); - tmpISrc.intersect(*src); + if (!tmpISrc.intersect(*src)) { + return; + } src = &tmpISrc; } this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); @@ -1321,13 +1333,13 @@ void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { SkDEBUGCODE(bitmap.validate();) - ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { - iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint); + iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, @@ -1343,13 +1355,13 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, paint = &tmp; } - ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), - *paint); + looper.paint()); } - ITER_END + LOOPER_END } class SkDeviceFilteredPaint { @@ -1357,7 +1369,7 @@ public: SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { SkDevice::TextFlags flags; if (device->filterTextFlags(paint, &flags)) { - SkPaint* newPaint = new (fStorage) SkPaint(paint); + SkPaint* newPaint = fLazy.set(paint); newPaint->setFlags(flags.fFlags); newPaint->setHinting(flags.fHinting); fPaint = newPaint; @@ -1366,71 +1378,63 @@ public: } } - ~SkDeviceFilteredPaint() { - if (reinterpret_cast<SkPaint*>(fStorage) == fPaint) { - fPaint->~SkPaint(); - } - } - const SkPaint& paint() const { return *fPaint; } private: - // points to either fStorage or the caller's paint const SkPaint* fPaint; - // we rely on the fPaint above to ensure proper alignment of fStorage - char fStorage[sizeof(SkPaint)]; + SkLazyPaint fLazy; }; void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { iter.fDevice->drawTextOnPath(iter, text, byteLength, path, - matrix, paint); + matrix, looper.paint()); } - ITER_END + LOOPER_END } #ifdef ANDROID @@ -1438,14 +1442,14 @@ void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint, const SkPath& path, const SkMatrix* matrix) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, - paint, path, matrix); + looper.paint(), path, matrix); } - ITER_END + LOOPER_END } #endif @@ -1454,14 +1458,15 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kPath_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) while (iter.next()) { iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, - colors, xmode, indices, indexCount, paint); + colors, xmode, indices, indexCount, + looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawData(const void* data, size_t length) { diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 8231848..69d0c1c 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -1,15 +1,16 @@ #include "SkDevice.h" #include "SkDraw.h" +#include "SkMetaData.h" #include "SkRect.h" SkDeviceFactory::~SkDeviceFactory() {} -SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) { +SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas), fMetaData(NULL) { fOrigin.setZero(); } SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer) - : fCanvas(canvas), fBitmap(bitmap) { + : fCanvas(canvas), fBitmap(bitmap), fMetaData(NULL) { fOrigin.setZero(); // auto-allocate if we're for offscreen drawing if (isForLayer) { @@ -22,6 +23,19 @@ SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer) } } +SkDevice::~SkDevice() { + delete fMetaData; +} + +SkMetaData& SkDevice::getMetaData() { + // metadata users are rare, so we lazily allocate it. If that changes we + // can decide to just make it a field in the device (rather than a ptr) + if (NULL == fMetaData) { + fMetaData = new SkMetaData; + } + return *fMetaData; +} + void SkDevice::lockPixels() { fBitmap.lockPixels(); } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index ce0fa9b..14e5a80 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -679,6 +679,49 @@ static inline SkPoint* as_rightbottom(SkRect* r) { return ((SkPoint*)(void*)r) + 1; } +static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, + SkPoint* strokeSize) { + if (SkPaint::kMiter_Join != paint.getStrokeJoin() || + paint.getStrokeMiter() < SK_ScalarSqrt2) { + return false; + } + + SkASSERT(matrix.rectStaysRect()); + SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; + matrix.mapVectors(strokeSize, &pt, 1); + strokeSize->fX = SkScalarAbs(strokeSize->fX); + strokeSize->fY = SkScalarAbs(strokeSize->fY); + return true; +} + +SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, + const SkMatrix& matrix, + SkPoint* strokeSize) { + RectType rtype; + const SkScalar width = paint.getStrokeWidth(); + const bool zeroWidth = (0 == width); + SkPaint::Style style = paint.getStyle(); + + if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { + style = SkPaint::kFill_Style; + } + + if (paint.getPathEffect() || paint.getMaskFilter() || + paint.getRasterizer() || !matrix.rectStaysRect() || + SkPaint::kStrokeAndFill_Style == style) { + rtype = kPath_RectType; + } else if (SkPaint::kFill_Style == style) { + rtype = kFill_RectType; + } else if (zeroWidth) { + rtype = kHair_RectType; + } else if (easy_rect_join(paint, matrix, strokeSize)) { + rtype = kStroke_RectType; + } else { + rtype = kPath_RectType; + } + return rtype; +} + void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { SkDEBUGCODE(this->validate();) @@ -688,11 +731,16 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { return; } - // complex enough to draw as a path - if (paint.getPathEffect() || paint.getMaskFilter() || - paint.getRasterizer() || !fMatrix->rectStaysRect() || - (paint.getStyle() != SkPaint::kFill_Style && - SkScalarHalf(paint.getStrokeWidth()) > 0)) { + SkPoint strokeSize; + RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); + +#ifdef SK_DISABLE_FAST_AA_STROKE_RECT + if (kStroke_RectType == rtype && paint.isAntiAlias()) { + rtype = kPath_RectType; + } +#endif + + if (kPath_RectType == rtype) { SkPath tmp; tmp.addRect(rect); tmp.setFillType(SkPath::kWinding_FillType); @@ -733,18 +781,30 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter // case we are also hairline (if we've gotten to here), which devolves to // effectively just kFill - if (paint.getStyle() != SkPaint::kStroke_Style) { - if (paint.isAntiAlias()) { - SkScan::AntiFillRect(devRect, clip, blitter); - } else { - SkScan::FillRect(devRect, clip, blitter); - } - } else { - if (paint.isAntiAlias()) { - SkScan::AntiHairRect(devRect, clip, blitter); - } else { - SkScan::HairRect(devRect, clip, blitter); - } + switch (rtype) { + case kFill_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFillRect(devRect, clip, blitter); + } else { + SkScan::FillRect(devRect, clip, blitter); + } + break; + case kStroke_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter); + } else { + SkScan::FrameRect(devRect, strokeSize, clip, blitter); + } + break; + case kHair_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiHairRect(devRect, clip, blitter); + } else { + SkScan::HairRect(devRect, clip, blitter); + } + break; + default: + SkASSERT(!"bad rtype"); } } @@ -1568,7 +1628,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, // apply the bias here, so we don't have to add 1/2 in the loop fx += SK_FixedHalf; fy += SK_FixedHalf; - fy &= finalFYMask; + fyMask &= finalFYMask; SkAutoKern autokern; SkDraw1Glyph d1g; @@ -2364,8 +2424,8 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, } } -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG @@ -2386,7 +2446,12 @@ void SkDraw::validate() const { #endif -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +SkBounder::SkBounder() { + // initialize up front. This gets reset by SkCanvas before each draw call. + fClip = &SkRegion::GetEmptyRegion(); +} bool SkBounder::doIRect(const SkIRect& r) { SkIRect rr; diff --git a/src/core/SkFlate.cpp b/src/core/SkFlate.cpp index ade1658..99b331e 100644 --- a/src/core/SkFlate.cpp +++ b/src/core/SkFlate.cpp @@ -24,19 +24,22 @@ bool SkFlate::Inflate(SkStream*, SkDynamicMemoryWStream*) { return false; } #else // static -const size_t SkFlate::kBufferSize = 1024; - -// static bool SkFlate::HaveFlate() { +#ifdef SK_DEBUG + return false; +#else return true; +#endif } namespace { #include SK_ZLIB_INCLUDE -bool doFlate(bool compress, const size_t kBufferSize, SkStream* src, - SkDynamicMemoryWStream* dst) { +// static +const size_t kBufferSize = 1024; + +bool doFlate(bool compress, SkStream* src, SkDynamicMemoryWStream* dst) { uint8_t inputBuffer[kBufferSize]; uint8_t outputBuffer[kBufferSize]; z_stream flateData; @@ -117,12 +120,12 @@ bool doFlate(bool compress, const size_t kBufferSize, SkStream* src, // static bool SkFlate::Deflate(SkStream* src, SkDynamicMemoryWStream* dst) { - return doFlate(true, kBufferSize, src, dst); + return doFlate(true, src, dst); } // static bool SkFlate::Inflate(SkStream* src, SkDynamicMemoryWStream* dst) { - return doFlate(false, kBufferSize, src, dst); + return doFlate(false, src, dst); } #endif diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index 92e3795..adf0466 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -280,30 +280,27 @@ private: class SkAutoGlyphCache { public: SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {} - SkAutoGlyphCache(const SkDescriptor* desc) - { + SkAutoGlyphCache(const SkDescriptor* desc) { fCache = SkGlyphCache::DetachCache(desc); } - SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix) - { + SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix) { fCache = paint.detachCache(matrix); } - ~SkAutoGlyphCache() - { - if (fCache) + ~SkAutoGlyphCache() { + if (fCache) { SkGlyphCache::AttachCache(fCache); + } } - SkGlyphCache* getCache() const { return fCache; } + SkGlyphCache* getCache() const { return fCache; } - void release() - { - if (fCache) - { + void release() { + if (fCache) { SkGlyphCache::AttachCache(fCache); fCache = NULL; } } + private: SkGlyphCache* fCache; diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index 40f0ea3..8638504 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -37,48 +37,8 @@ #include "SkUtils.h" #include "SkXfermode.h" -#if 0 - -#define SK_SORT_TEMPLATE_TYPE int -#define SK_SORT_TEMPLATE_NAME sort_int -#define SK_SORT_TEMPLATE_CMP(a, b) ((a) - (b)) -#include "SkSortTemplate.h" - -#define SK_SORT_TEMPLATE_TYPE int* -#define SK_SORT_TEMPLATE_NAME sort_intptr -#define SK_SORT_TEMPLATE_CMP(a, b) (*(a) - *(b)) -#include "SkSortTemplate.h" - -static void test_sort() -{ - int array[] = { 4, 3, 7, 5, 2, 5, 1, 2, 9, 6, 7, 4, 5, 3, 1, 0 }; - int* ptr[SK_ARRAY_COUNT(array)]; - int i, N = SK_ARRAY_COUNT(array) - 1; - - for (i = 0; i < N; i++) - printf(" %d", array[i]); - printf("\n"); - - for (i = 0; i < N; i++) - ptr[i] = &array[i]; - sort_intptr(ptr, N); - for (i = 0; i < N; i++) - printf(" %d", *ptr[i]); - printf("\n"); - - sort_int(array, N); - for (i = 0; i < N; i++) - printf(" %d", array[i]); - printf("\n"); - -} -#endif - -#define SPEED_TESTx - #define typesizeline(type) { #type , sizeof(type) } - #ifdef BUILD_EMBOSS_TABLE extern void SkEmbossMask_BuildTable(); #endif @@ -87,65 +47,6 @@ static void test_sort() extern void SkRadialGradient_BuildTable(); #endif -#define BIG_LOOP_COUNT 1000000 -#define TEXT_LOOP_COUNT 1000 - -#ifdef SPEED_TEST -static int test_s64(int i) -{ - Sk64 a, b, c; - - c.set(0); - a.set(i); - b.setMul(i, i); - a.add(b); - a.add(c); - return c.getFixed(); -} - -static int test_native_64(int i) -{ - int16_t a, b, c; - - c = 0; - a = i; - b = (int64_t)i * i; - a += b; - a += c; - return (int)(c >> 16); -} - -static void test_drawText(SkBitmap::Config config, SkColor color) -{ - SkBitmap bm; - - bm.setConfig(config, 320, 240); - bm.allocPixels(); - - SkCanvas canvas(bm); - SkPaint paint; - - paint.setAntiAlias(true); - paint.setTextSize(SkIntToScalar(12)); - paint.setColor(color); - - SkScalar x = SkIntToScalar(20); - SkScalar y = SkIntToScalar(100); - const char* text = "Hamburgefons"; - size_t len = strlen(text); - - // draw once to populate the cache - canvas.drawText(text, len, x, y, paint); - - SkMSec now = SkTime::GetMSecs(); - for (int i = 0; i < TEXT_LOOP_COUNT; i++) - canvas.drawText(text, len, x, y, paint); - printf("----------- Config: %d, Color=%x, CPS = %g\n", config, color, - len * TEXT_LOOP_COUNT * 1000.0 / (SkTime::GetMSecs() - now)); -} - -#endif - void SkGraphics::Init() { SkGlobals::Init(); @@ -210,154 +111,9 @@ void SkGraphics::Init() { } #endif - - if (false) // test asm fixmul - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFixedMul_portable(0x8000, 0x150000); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkFixedMul_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFixedMul(0x8000, 0x150000); - } - printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - SkFixed a = rand.nextS() >> 8; - SkFixed b = rand.nextS() >> 8; - SkFixed c1 = SkFixedMul_portable(a, b); - SkFixed c2 = SkFixedMul(a, b); - if (SkAbs32(c1 - c2) > 1) - printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2); - } - } - - if (false) // test asm fractmul - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFractMul_portable(0x800000, 0x1500000); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkFractMul_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFractMul(0x800000, 0x1500000); - } - printf("-------- SkFractMul = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - SkFixed a = rand.nextS() >> 1; - SkFixed b = rand.nextS() >> 1; - SkFixed c1 = SkFractMul_portable(a, b); - SkFixed c2 = SkFractMul(a, b); - if (SkAbs32(c1 - c2) > 1) - printf("------ FractMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2); - } - } - - if (false) // test asm clz - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkCLZ_portable(now); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkCLZ_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkCLZ(now); - } - printf("-------- SkCLZ = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - uint32_t a = rand.nextU(); - int c1 = SkCLZ_portable(a); - int c2 = SkCLZ(a); - if (c1 != c2) - printf("------ CLZ disagreement: (%x) slow=%x fast=%x\n", a, c1, c2); - } - } - -#ifdef SPEED_TEST - if (false) { - int i; - int (*proc)(int); - - static const struct { - int (*proc)(int); - const char* name; - } gList[] = { - { test_s64, "Sk64" }, - { test_native_64, "native" } - }; - - for (size_t j = 0; j < SK_ARRAY_COUNT(gList); j++) { - SkMSec now = SkTime::GetMSecs(); - proc = gList[j].proc; - for (i = 0; i < BIG_LOOP_COUNT; i++) { - proc(i); - } - printf("-------- %s = %d\n", gList[j].name, SkTime::GetMSecs() - now); - } - } -#endif - - if (false) { - size_t i, size = 480; - char* buffer = (char*)sk_malloc_throw(size); - uint16_t* buffer16 = (uint16_t*)buffer; - uint32_t* buffer32 = (uint32_t*)buffer; - - SkMSec now = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset16(buffer16, (uint16_t)i, size >> 1); - } - SkMSec now2 = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset16_portable(buffer16, (uint16_t)i, size >> 1); - } - SkMSec now3 = SkTime::GetMSecs(); - printf("----------- memset16: native %d, portable %d\n", now2 - now, now3 - now2); - - now = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset32(buffer32, i, size >> 2); - } - now2 = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset32_portable(buffer32, i, size >> 2); - } - now3 = SkTime::GetMSecs(); - printf("----------- memset32: native %d, portable %d\n", now2 - now, now3 - now2); - - sk_free(buffer); - } - -#ifdef SPEED_TEST - if (false) { - test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorBLACK); - test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorRED); - test_drawText(SkBitmap::kRGB_565_Config, SK_ColorBLACK); - test_drawText(SkBitmap::kRGB_565_Config, SK_ColorRED); - } -#endif - -// if (true) { -// test_sort(); -// } } -//////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #include "SkGlyphCache.h" diff --git a/src/core/SkLineClipper.cpp b/src/core/SkLineClipper.cpp index 057f546..ab49773 100644 --- a/src/core/SkLineClipper.cpp +++ b/src/core/SkLineClipper.cpp @@ -6,8 +6,19 @@ static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) { if (SkScalarNearlyZero(dy)) { return SkScalarAve(src[0].fX, src[1].fX); } else { +#ifdef SK_SCALAR_IS_FLOAT + // need the extra precision so we don't compute a value that exceeds + // our original limits + double X0 = src[0].fX; + double Y0 = src[0].fY; + double X1 = src[1].fX; + double Y1 = src[1].fY; + double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0); + return (float)result; +#else return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX, dy); +#endif } } @@ -17,8 +28,19 @@ static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) { if (SkScalarNearlyZero(dx)) { return SkScalarAve(src[0].fY, src[1].fY); } else { +#ifdef SK_SCALAR_IS_FLOAT + // need the extra precision so we don't compute a value that exceeds + // our original limits + double X0 = src[0].fX; + double Y0 = src[0].fY; + double X1 = src[1].fX; + double Y1 = src[1].fY; + double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0); + return (float)result; +#else return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY, dx); +#endif } } @@ -106,6 +128,19 @@ bool SkLineClipper::IntersectLine(const SkPoint src[2], const SkRect& clip, return true; } +#ifdef SK_DEBUG +// return value between the two limits, where the limits are either ascending +// or descending. +static bool is_between_unsorted(SkScalar value, + SkScalar limit0, SkScalar limit1) { + if (limit0 < limit1) { + return limit0 <= value && value <= limit1; + } else { + return limit1 <= value && value <= limit0; + } +} +#endif + int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, SkPoint lines[]) { int index0, index1; @@ -135,9 +170,11 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, // now compute intersections if (pts[index0].fY < clip.fTop) { tmp[index0].set(sect_with_horizontal(pts, clip.fTop), clip.fTop); + SkASSERT(is_between_unsorted(tmp[index0].fX, pts[0].fX, pts[1].fX)); } if (tmp[index1].fY > clip.fBottom) { tmp[index1].set(sect_with_horizontal(pts, clip.fBottom), clip.fBottom); + SkASSERT(is_between_unsorted(tmp[index1].fX, pts[0].fX, pts[1].fX)); } // Chop it into 1..3 segments that are wholly within the clip in X. @@ -173,14 +210,16 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, if (tmp[index0].fX < clip.fLeft) { r->set(clip.fLeft, tmp[index0].fY); r += 1; - r->set(clip.fLeft, sect_with_vertical(pts, clip.fLeft)); + r->set(clip.fLeft, sect_with_vertical(tmp, clip.fLeft)); + SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); } else { *r = tmp[index0]; } r += 1; if (tmp[index1].fX > clip.fRight) { - r->set(clip.fRight, sect_with_vertical(pts, clip.fRight)); + r->set(clip.fRight, sect_with_vertical(tmp, clip.fRight)); + SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); r += 1; r->set(clip.fRight, tmp[index1].fY); } else { diff --git a/src/core/SkMask.cpp b/src/core/SkMask.cpp index 337204b..34f122b 100644 --- a/src/core/SkMask.cpp +++ b/src/core/SkMask.cpp @@ -45,16 +45,14 @@ size_t SkMask::computeTotalImageSize() const { /** We explicitly use this allocator for SkBimap pixels, so that we can freely assign memory allocated by one class to the other. */ -uint8_t* SkMask::AllocImage(size_t size) -{ +uint8_t* SkMask::AllocImage(size_t size) { return (uint8_t*)sk_malloc_throw(SkAlign4(size)); } /** We explicitly use this allocator for SkBimap pixels, so that we can freely assign memory allocated by one class to the other. */ -void SkMask::FreeImage(void* image) -{ +void SkMask::FreeImage(void* image) { sk_free(image); } diff --git a/src/core/SkMetaData.cpp b/src/core/SkMetaData.cpp new file mode 100644 index 0000000..b1901dc --- /dev/null +++ b/src/core/SkMetaData.cpp @@ -0,0 +1,345 @@ +/* libs/graphics/views/SkMetaData.cpp +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkMetaData.h" +#include "SkRefCnt.h" + +struct PtrPair { + void* fPtr; + SkMetaData::PtrProc fProc; +}; + +void* SkMetaData::RefCntProc(void* ptr, bool doRef) { + SkASSERT(ptr); + SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr); + + if (doRef) { + refcnt->ref(); + } else { + refcnt->unref(); + } + return ptr; +} + +SkMetaData::SkMetaData() : fRec(NULL) +{ +} + +SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL) +{ + *this = src; +} + +SkMetaData::~SkMetaData() +{ + this->reset(); +} + +void SkMetaData::reset() +{ + Rec* rec = fRec; + while (rec) { + if (kPtr_Type == rec->fType) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + pair->fPtr = pair->fProc(pair->fPtr, false); + } + } + Rec* next = rec->fNext; + Rec::Free(rec); + rec = next; + } + fRec = NULL; +} + +SkMetaData& SkMetaData::operator=(const SkMetaData& src) +{ + this->reset(); + + const Rec* rec = src.fRec; + while (rec) + { + this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount); + rec = rec->fNext; + } + return *this; +} + +void SkMetaData::setS32(const char name[], int32_t value) +{ + (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1); +} + +void SkMetaData::setScalar(const char name[], SkScalar value) +{ + (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); +} + +SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[]) +{ + SkASSERT(count > 0); + if (count > 0) + return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count); + return NULL; +} + +void SkMetaData::setString(const char name[], const char value[]) +{ + (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); +} + +void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) { + PtrPair pair = { ptr, proc }; + (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1); +} + +void SkMetaData::setBool(const char name[], bool value) +{ + (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); +} + +void SkMetaData::setData(const char name[], const void* data, size_t byteCount) { + (void)this->set(name, data, sizeof(char), kData_Type, byteCount); +} + +void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count) +{ + SkASSERT(name); + SkASSERT(dataSize); + SkASSERT(count > 0); + + (void)this->remove(name, type); + + size_t len = strlen(name); + Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1); + +#ifndef SK_DEBUG + rec->fType = SkToU8(type); +#else + rec->fType = type; +#endif + rec->fDataLen = SkToU8(dataSize); + rec->fDataCount = SkToU16(count); + if (data) + memcpy(rec->data(), data, dataSize * count); + memcpy(rec->name(), name, len + 1); + + if (kPtr_Type == type) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + pair->fPtr = pair->fProc(pair->fPtr, true); + } + } + + rec->fNext = fRec; + fRec = rec; + return rec->data(); +} + +bool SkMetaData::findS32(const char name[], int32_t* value) const +{ + const Rec* rec = this->find(name, kS32_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const int32_t*)rec->data(); + return true; + } + return false; +} + +bool SkMetaData::findScalar(const char name[], SkScalar* value) const +{ + const Rec* rec = this->find(name, kScalar_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const SkScalar*)rec->data(); + return true; + } + return false; +} + +const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const +{ + const Rec* rec = this->find(name, kScalar_Type); + if (rec) + { + if (count) + *count = rec->fDataCount; + if (values) + memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen); + return (const SkScalar*)rec->data(); + } + return NULL; +} + +bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const { + const Rec* rec = this->find(name, kPtr_Type); + if (rec) { + SkASSERT(rec->fDataCount == 1); + const PtrPair* pair = (const PtrPair*)rec->data(); + if (ptr) { + *ptr = pair->fPtr; + } + if (proc) { + *proc = pair->fProc; + } + return true; + } + return false; +} + +const char* SkMetaData::findString(const char name[]) const +{ + const Rec* rec = this->find(name, kString_Type); + SkASSERT(rec == NULL || rec->fDataLen == sizeof(char)); + return rec ? (const char*)rec->data() : NULL; +} + +bool SkMetaData::findBool(const char name[], bool* value) const +{ + const Rec* rec = this->find(name, kBool_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const bool*)rec->data(); + return true; + } + return false; +} + +const void* SkMetaData::findData(const char name[], size_t* length) const { + const Rec* rec = this->find(name, kData_Type); + if (rec) { + SkASSERT(rec->fDataLen == sizeof(char)); + if (length) { + *length = rec->fDataCount; + } + return rec->data(); + } + return NULL; +} + +const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const +{ + const Rec* rec = fRec; + while (rec) + { + if (rec->fType == type && !strcmp(rec->name(), name)) + return rec; + rec = rec->fNext; + } + return NULL; +} + +bool SkMetaData::remove(const char name[], Type type) { + Rec* rec = fRec; + Rec* prev = NULL; + while (rec) { + Rec* next = rec->fNext; + if (rec->fType == type && !strcmp(rec->name(), name)) { + if (prev) { + prev->fNext = next; + } else { + fRec = next; + } + + if (kPtr_Type == type) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + (void)pair->fProc(pair->fPtr, false); + } + } + Rec::Free(rec); + return true; + } + prev = rec; + rec = next; + } + return false; +} + +bool SkMetaData::removeS32(const char name[]) +{ + return this->remove(name, kS32_Type); +} + +bool SkMetaData::removeScalar(const char name[]) +{ + return this->remove(name, kScalar_Type); +} + +bool SkMetaData::removeString(const char name[]) +{ + return this->remove(name, kString_Type); +} + +bool SkMetaData::removePtr(const char name[]) +{ + return this->remove(name, kPtr_Type); +} + +bool SkMetaData::removeBool(const char name[]) +{ + return this->remove(name, kBool_Type); +} + +bool SkMetaData::removeData(const char name[]) { + return this->remove(name, kData_Type); +} + +/////////////////////////////////////////////////////////////////////////////// + +SkMetaData::Iter::Iter(const SkMetaData& metadata) { + fRec = metadata.fRec; +} + +void SkMetaData::Iter::reset(const SkMetaData& metadata) { + fRec = metadata.fRec; +} + +const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) { + const char* name = NULL; + + if (fRec) { + if (t) { + *t = (SkMetaData::Type)fRec->fType; + } + if (count) { + *count = fRec->fDataCount; + } + name = fRec->name(); + + fRec = fRec->fNext; + } + return name; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) { + return (Rec*)sk_malloc_throw(size); +} + +void SkMetaData::Rec::Free(Rec* rec) { + sk_free(rec); +} + diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 5c0f922..95b8ed3 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -35,6 +35,14 @@ #define SK_DefaultFlags 0 //(kNativeHintsText_Flag) +#ifdef ANDROID +#define GEN_ID_INC fGenerationID++ +#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; } +#else +#define GEN_ID_INC +#define GEN_ID_INC_EVAL(expression) +#endif + SkPaint::SkPaint() { // since we may have padding, we zero everything so that our memcmp() call // in operator== will work correctly. @@ -65,7 +73,9 @@ SkPaint::SkPaint() { fStyle = kFill_Style; fTextEncoding = kUTF8_TextEncoding; fHinting = kNormal_Hinting; +#ifdef ANDROID fGenerationID = 0; +#endif } SkPaint::SkPaint(const SkPaint& src) { @@ -113,9 +123,13 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { SkSafeUnref(fRasterizer); SkSafeUnref(fLooper); +#ifdef ANDROID uint32_t oldGenerationID = fGenerationID; +#endif memcpy(this, &src, sizeof(src)); +#ifdef ANDROID fGenerationID = oldGenerationID + 1; +#endif return *this; } @@ -127,293 +141,206 @@ int operator==(const SkPaint& a, const SkPaint& b) { void SkPaint::reset() { SkPaint init; +#ifdef ANDROID uint32_t oldGenerationID = fGenerationID; +#endif *this = init; +#ifdef ANDROID fGenerationID = oldGenerationID + 1; +#endif } +#ifdef ANDROID uint32_t SkPaint::getGenerationID() const { return fGenerationID; } +#endif -void SkPaint::setFlags(uint32_t flags) -{ - if (fFlags != flags) { - fFlags = flags; - fGenerationID++; - } +void SkPaint::setHinting(Hinting hintingLevel) { + GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting); + fHinting = hintingLevel; } -void SkPaint::setAntiAlias(bool doAA) -{ - if (doAA != isAntiAlias()) { - this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); - fGenerationID++; - } +void SkPaint::setFlags(uint32_t flags) { + GEN_ID_INC_EVAL(fFlags != flags); + fFlags = flags; } -void SkPaint::setDither(bool doDither) -{ - if (doDither != isDither()) { - this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); - fGenerationID++; - } +void SkPaint::setAntiAlias(bool doAA) { + GEN_ID_INC_EVAL(doAA != isAntiAlias()); + this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); } -void SkPaint::setSubpixelText(bool doSubpixel) -{ - if (doSubpixel != isSubpixelText()) { - this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); - fGenerationID++; - } +void SkPaint::setDither(bool doDither) { + GEN_ID_INC_EVAL(doDither != isDither()); + this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); } -void SkPaint::setLCDRenderText(bool doLCDRender) -{ - if (doLCDRender != isLCDRenderText()) { - this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); - fGenerationID++; - } +void SkPaint::setSubpixelText(bool doSubpixel) { + GEN_ID_INC_EVAL(doSubpixel != isSubpixelText()); + this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); } -void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) -{ - if (doEmbeddedBitmapText != isEmbeddedBitmapText()) { - this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); - fGenerationID++; - } +void SkPaint::setLCDRenderText(bool doLCDRender) { + GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText()); + this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); +} + +void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) { + GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText()); + this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); } -void SkPaint::setAutohinted(bool useAutohinter) -{ +void SkPaint::setAutohinted(bool useAutohinter) { + GEN_ID_INC_EVAL(useAutohinter != isAutohinted()); this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag)); } -void SkPaint::setLinearText(bool doLinearText) -{ - if (doLinearText != isLinearText()) { - this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); - fGenerationID++; - } +void SkPaint::setLinearText(bool doLinearText) { + GEN_ID_INC_EVAL(doLinearText != isLinearText()); + this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); } -void SkPaint::setUnderlineText(bool doUnderline) -{ - if (doUnderline != isUnderlineText()) { - this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); - fGenerationID++; - } +void SkPaint::setUnderlineText(bool doUnderline) { + GEN_ID_INC_EVAL(doUnderline != isUnderlineText()); + this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); } -void SkPaint::setStrikeThruText(bool doStrikeThru) -{ - if (doStrikeThru != isStrikeThruText()) { - this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); - fGenerationID++; - } +void SkPaint::setStrikeThruText(bool doStrikeThru) { + GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText()); + this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); } -void SkPaint::setFakeBoldText(bool doFakeBold) -{ - if (doFakeBold != isFakeBoldText()) { - this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); - fGenerationID++; - } +void SkPaint::setFakeBoldText(bool doFakeBold) { + GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText()); + this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); } -void SkPaint::setDevKernText(bool doDevKern) -{ - if (doDevKern != isDevKernText()) { - this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); - fGenerationID++; - } +void SkPaint::setDevKernText(bool doDevKern) { + GEN_ID_INC_EVAL(doDevKern != isDevKernText()); + this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); } -void SkPaint::setFilterBitmap(bool doFilter) -{ - if (doFilter != isFilterBitmap()) { - this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); - fGenerationID++; - } +void SkPaint::setFilterBitmap(bool doFilter) { + GEN_ID_INC_EVAL(doFilter != isFilterBitmap()); + this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); } -void SkPaint::setStyle(Style style) -{ +void SkPaint::setStyle(Style style) { if ((unsigned)style < kStyleCount) { - if ((unsigned)style != fStyle) { - fStyle = style; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStyle(%d) out of range\n", style); + GEN_ID_INC_EVAL((unsigned)style != fStyle); + fStyle = style; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStyle(%d) out of range\n", style);) } -#endif } -void SkPaint::setColor(SkColor color) -{ - if (color != fColor) { - fColor = color; - fGenerationID++; - } +void SkPaint::setColor(SkColor color) { + GEN_ID_INC_EVAL(color != fColor); + fColor = color; } -void SkPaint::setAlpha(U8CPU a) -{ - U8CPU oldA = SkColorGetA(fColor); - if (a != oldA) { - fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor)); - fGenerationID++; - } +void SkPaint::setAlpha(U8CPU a) { + this->setColor(SkColorSetARGB(a, SkColorGetR(fColor), + SkColorGetG(fColor), SkColorGetB(fColor))); } -void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) -{ - SkColor oldColor = fColor; - fColor = SkColorSetARGB(a, r, g, b); - if (oldColor != fColor) { - fGenerationID++; - } +void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { + this->setColor(SkColorSetARGB(a, r, g, b)); } -void SkPaint::setStrokeWidth(SkScalar width) -{ +void SkPaint::setStrokeWidth(SkScalar width) { if (width >= 0) { - if (width != fWidth) { - fWidth = width; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); + GEN_ID_INC_EVAL(width != fWidth); + fWidth = width; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");) } -#endif } -void SkPaint::setStrokeMiter(SkScalar limit) -{ +void SkPaint::setStrokeMiter(SkScalar limit) { if (limit >= 0) { - if (limit != fMiterLimit) { - fMiterLimit = limit; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); + GEN_ID_INC_EVAL(limit != fMiterLimit); + fMiterLimit = limit; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");) } -#endif } -void SkPaint::setStrokeCap(Cap ct) -{ +void SkPaint::setStrokeCap(Cap ct) { if ((unsigned)ct < kCapCount) { - if ((unsigned)ct != fCapType) { - fCapType = SkToU8(ct); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)ct != fCapType); + fCapType = SkToU8(ct); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); -#endif } -void SkPaint::setStrokeJoin(Join jt) -{ +void SkPaint::setStrokeJoin(Join jt) { if ((unsigned)jt < kJoinCount) { - if ((unsigned)jt != fJoinType) { - fJoinType = SkToU8(jt); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)jt != fJoinType); + fJoinType = SkToU8(jt); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); -#endif } -////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkPaint::setTextAlign(Align align) -{ +void SkPaint::setTextAlign(Align align) { if ((unsigned)align < kAlignCount) { - if ((unsigned)align != fTextAlign) { - fTextAlign = SkToU8(align); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)align != fTextAlign); + fTextAlign = SkToU8(align); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); -#endif } -void SkPaint::setTextSize(SkScalar ts) -{ +void SkPaint::setTextSize(SkScalar ts) { if (ts > 0) { - if (ts != fTextSize) { - fTextSize = ts; - fGenerationID++; - } + GEN_ID_INC_EVAL(ts != fTextSize); + fTextSize = ts; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextSize() called with negative value\n");) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextSize() called with negative value\n"); -#endif } -void SkPaint::setTextScaleX(SkScalar scaleX) -{ - if (scaleX != fTextScaleX) { - fTextScaleX = scaleX; - fGenerationID++; - } +void SkPaint::setTextScaleX(SkScalar scaleX) { + GEN_ID_INC_EVAL(scaleX != fTextScaleX); + fTextScaleX = scaleX; } -void SkPaint::setTextSkewX(SkScalar skewX) -{ - if (skewX != fTextSkewX) { - fTextSkewX = skewX; - fGenerationID++; - } +void SkPaint::setTextSkewX(SkScalar skewX) { + GEN_ID_INC_EVAL(skewX != fTextSkewX); + fTextSkewX = skewX; } -void SkPaint::setTextEncoding(TextEncoding encoding) -{ +void SkPaint::setTextEncoding(TextEncoding encoding) { if ((unsigned)encoding <= kGlyphID_TextEncoding) { - if ((unsigned)encoding != fTextEncoding) { - fTextEncoding = encoding; - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding); + fTextEncoding = encoding; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding); -#endif } -/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkTypeface* SkPaint::setTypeface(SkTypeface* font) -{ +SkTypeface* SkPaint::setTypeface(SkTypeface* font) { SkRefCnt_SafeAssign(fTypeface, font); - fGenerationID++; + GEN_ID_INC; return font; } SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) { SkRefCnt_SafeAssign(fRasterizer, r); - fGenerationID++; + GEN_ID_INC; return r; } SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { SkRefCnt_SafeAssign(fLooper, looper); - fGenerationID++; + GEN_ID_INC; return looper; } @@ -426,6 +353,7 @@ static void DetachDescProc(const SkDescriptor* desc, void* context) { *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); } +#ifdef ANDROID const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) { SkGlyphCache* cache; descriptorProc(NULL, DetachDescProc, &cache, true); @@ -446,6 +374,7 @@ const void* SkPaint::findImage(const SkGlyph& glyph) { SkGlyphCache::AttachCache(cache); return image; } +#endif int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const { @@ -1601,29 +1530,20 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { /////////////////////////////////////////////////////////////////////////////// -SkShader* SkPaint::setShader(SkShader* shader) -{ - if (shader != fShader) { - fGenerationID++; - } +SkShader* SkPaint::setShader(SkShader* shader) { + GEN_ID_INC_EVAL(shader != fShader); SkRefCnt_SafeAssign(fShader, shader); return shader; } -SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) -{ - if (filter != fColorFilter) { - fGenerationID++; - } +SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) { + GEN_ID_INC_EVAL(filter != fColorFilter); SkRefCnt_SafeAssign(fColorFilter, filter); return filter; } -SkXfermode* SkPaint::setXfermode(SkXfermode* mode) -{ - if (mode != fXfermode) { - fGenerationID++; - } +SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { + GEN_ID_INC_EVAL(mode != fXfermode); SkRefCnt_SafeAssign(fXfermode, mode); return mode; } @@ -1631,24 +1551,18 @@ SkXfermode* SkPaint::setXfermode(SkXfermode* mode) SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { SkSafeUnref(fXfermode); fXfermode = SkXfermode::Create(mode); - fGenerationID++; + GEN_ID_INC; return fXfermode; } -SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) -{ - if (effect != fPathEffect) { - fGenerationID++; - } +SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) { + GEN_ID_INC_EVAL(effect != fPathEffect); SkRefCnt_SafeAssign(fPathEffect, effect); return effect; } -SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) -{ - if (filter != fMaskFilter) { - fGenerationID++; - } +SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { + GEN_ID_INC_EVAL(filter != fMaskFilter); SkRefCnt_SafeAssign(fMaskFilter, filter); return filter; } diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index a01d8e1..5ddc31d 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -96,15 +96,19 @@ static void compute_pt_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) { //////////////////////////////////////////////////////////////////////////// SkPath::SkPath() : fBoundsIsDirty(true), fFillType(kWinding_FillType) { - fIsConvex = false; + fIsConvex = false; // really should be kUnknown +#ifdef ANDROID fGenerationID = 0; +#endif } SkPath::SkPath(const SkPath& src) { SkDEBUGCODE(src.validate();) - uint32_t currentGenID = fGenerationID; *this = src; - fGenerationID = currentGenID; +#ifdef ANDROID + // the assignment operator above increments the ID so correct for that here + fGenerationID--; +#endif } SkPath::~SkPath() { @@ -121,7 +125,7 @@ SkPath& SkPath::operator=(const SkPath& src) { fFillType = src.fFillType; fBoundsIsDirty = src.fBoundsIsDirty; fIsConvex = src.fIsConvex; - fGenerationID++; + GEN_ID_INC; } SkDEBUGCODE(this->validate();) return *this; @@ -144,20 +148,22 @@ void SkPath::swap(SkPath& other) { SkTSwap<uint8_t>(fFillType, other.fFillType); SkTSwap<uint8_t>(fBoundsIsDirty, other.fBoundsIsDirty); SkTSwap<uint8_t>(fIsConvex, other.fIsConvex); - fGenerationID++; + GEN_ID_INC; } } +#ifdef ANDROID uint32_t SkPath::getGenerationID() const { return fGenerationID; } +#endif void SkPath::reset() { SkDEBUGCODE(this->validate();) fPts.reset(); fVerbs.reset(); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -167,7 +173,7 @@ void SkPath::rewind() { fPts.rewind(); fVerbs.rewind(); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -225,7 +231,7 @@ void SkPath::setLastPt(SkScalar x, SkScalar y) { this->moveTo(x, y); } else { fPts[count - 1].set(x, y); - fGenerationID++; + GEN_ID_INC; } } @@ -263,7 +269,7 @@ void SkPath::moveTo(SkScalar x, SkScalar y) { } pt->set(x, y); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -283,7 +289,7 @@ void SkPath::lineTo(SkScalar x, SkScalar y) { fPts.append()->set(x, y); *fVerbs.append() = kLine_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -306,7 +312,7 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { pts[1].set(x2, y2); *fVerbs.append() = kQuad_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -330,7 +336,7 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, pts[2].set(x3, y3); *fVerbs.append() = kCubic_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -352,7 +358,7 @@ void SkPath::close() { case kQuad_Verb: case kCubic_Verb: *fVerbs.append() = kClose_Verb; - fGenerationID++; + GEN_ID_INC; break; default: // don't add a close if the prev wasn't a primitive @@ -970,7 +976,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { matrix.mapRect(&dst->fBounds, fBounds); dst->fBoundsIsDirty = false; } else { - dst->fGenerationID++; + GEN_ID_PTR_INC(dst); dst->fBoundsIsDirty = true; } @@ -1277,8 +1283,8 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) { fFillType = buffer.readS32(); buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count()); buffer.read(fVerbs.begin(), fVerbs.count()); - - fGenerationID++; + + GEN_ID_INC; fBoundsIsDirty = true; SkDEBUGCODE(this->validate();) diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 4a4c7f8..d17599d 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -528,7 +528,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { SkipClipRec skipRect, skipRegion, skipPath; #endif +#ifdef ANDROID SkAutoMutexAcquire autoMutex(fDrawMutex); +#endif TextContainer text; fReader.rewind(); diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h index f5bf038..350df78 100644 --- a/src/core/SkPicturePlayback.h +++ b/src/core/SkPicturePlayback.h @@ -12,7 +12,10 @@ #include "SkRegion.h" #include "SkPictureFlat.h" #include "SkShape.h" + +#ifdef ANDROID #include "SkThread.h" +#endif class SkPictureRecord; class SkStream; @@ -173,7 +176,9 @@ private: SkRefCntPlayback fRCPlayback; SkTypefacePlayback fTFPlayback; SkFactoryPlayback* fFactoryPlayback; +#ifdef ANDROID SkMutex fDrawMutex; +#endif }; #endif diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp index f558f52..9b12226 100644 --- a/src/core/SkPixelRef.cpp +++ b/src/core/SkPixelRef.cpp @@ -79,6 +79,14 @@ void SkPixelRef::setImmutable() { fIsImmutable = true; } +bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { + return this->onReadPixels(dst, subset); +} + +bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + return false; +} + /////////////////////////////////////////////////////////////////////////////// #define MAX_PAIR_COUNT 16 diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index 18dafb0..e08d2f8 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -85,36 +85,29 @@ bool SkRegion::ComputeRunBounds(const SkRegion::RunType runs[], int count, SkIRe ////////////////////////////////////////////////////////////////////////// -SkRegion::SkRegion() -{ +SkRegion::SkRegion() { fBounds.set(0, 0, 0, 0); fRunHead = SkRegion_gEmptyRunHeadPtr; } -SkRegion::SkRegion(const SkRegion& src) -{ +SkRegion::SkRegion(const SkRegion& src) { fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) this->setRegion(src); } -SkRegion::SkRegion(const SkIRect& rect) -{ +SkRegion::SkRegion(const SkIRect& rect) { fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) this->setRect(rect); } -SkRegion::~SkRegion() -{ +SkRegion::~SkRegion() { this->freeRuns(); } -void SkRegion::freeRuns() -{ - if (fRunHead->isComplex()) - { +void SkRegion::freeRuns() { + if (fRunHead->isComplex()) { SkASSERT(fRunHead->fRefCnt >= 1); - if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) - { + if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) { //SkASSERT(gRgnAllocCounter > 0); //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter)); //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter)); @@ -123,76 +116,68 @@ void SkRegion::freeRuns() } } -void SkRegion::allocateRuns(int count) -{ +void SkRegion::allocateRuns(int count) { fRunHead = RunHead::Alloc(count); } -SkRegion& SkRegion::operator=(const SkRegion& src) -{ +SkRegion& SkRegion::operator=(const SkRegion& src) { (void)this->setRegion(src); return *this; } -void SkRegion::swap(SkRegion& other) -{ +void SkRegion::swap(SkRegion& other) { SkTSwap<SkIRect>(fBounds, other.fBounds); SkTSwap<RunHead*>(fRunHead, other.fRunHead); } -bool SkRegion::setEmpty() -{ +bool SkRegion::setEmpty() { this->freeRuns(); fBounds.set(0, 0, 0, 0); fRunHead = SkRegion_gEmptyRunHeadPtr; return false; } -bool SkRegion::setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) -{ - if (left >= right || top >= bottom) +bool SkRegion::setRect(int32_t left, int32_t top, + int32_t right, int32_t bottom) { + if (left >= right || top >= bottom) { return this->setEmpty(); - + } this->freeRuns(); fBounds.set(left, top, right, bottom); fRunHead = SkRegion_gRectRunHeadPtr; return true; } -bool SkRegion::setRect(const SkIRect& r) -{ +bool SkRegion::setRect(const SkIRect& r) { return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom); } -bool SkRegion::setRegion(const SkRegion& src) -{ - if (this != &src) - { +bool SkRegion::setRegion(const SkRegion& src) { + if (this != &src) { this->freeRuns(); fBounds = src.fBounds; fRunHead = src.fRunHead; - if (fRunHead->isComplex()) + if (fRunHead->isComplex()) { sk_atomic_inc(&fRunHead->fRefCnt); + } } return fRunHead != SkRegion_gEmptyRunHeadPtr; } -bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) -{ +bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) { SkRegion tmp(rect); return this->op(tmp, rgn, op); } -bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) -{ +bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) { SkRegion tmp(rect); return this->op(rgn, tmp, op); } -////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #ifdef ANDROID char* SkRegion::toString() @@ -482,52 +467,48 @@ bool SkRegion::intersects(const SkRegion& rgn) const { ///////////////////////////////////////////////////////////////////////////////////// -int operator==(const SkRegion& a, const SkRegion& b) -{ +bool operator==(const SkRegion& a, const SkRegion& b) { SkDEBUGCODE(a.validate();) SkDEBUGCODE(b.validate();) - if (&a == &b) + if (&a == &b) { return true; - if (a.fBounds != b.fBounds) + } + if (a.fBounds != b.fBounds) { return false; + } const SkRegion::RunHead* ah = a.fRunHead; const SkRegion::RunHead* bh = b.fRunHead; // this catches empties and rects being equal - if (ah == bh) + if (ah == bh) { return true; - + } // now we insist that both are complex (but different ptrs) - if (!ah->isComplex() || !bh->isComplex()) + if (!ah->isComplex() || !bh->isComplex()) { return false; - + } return ah->fRunCount == bh->fRunCount && !memcmp(ah->readonly_runs(), bh->readonly_runs(), ah->fRunCount * sizeof(SkRegion::RunType)); } -void SkRegion::translate(int dx, int dy, SkRegion* dst) const -{ +void SkRegion::translate(int dx, int dy, SkRegion* dst) const { SkDEBUGCODE(this->validate();) - if (NULL == dst) + if (NULL == dst) { return; - - if (this->isEmpty()) + } + if (this->isEmpty()) { dst->setEmpty(); - else if (this->isRect()) + } else if (this->isRect()) { dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, fBounds.fRight + dx, fBounds.fBottom + dy); - else - { - if (this == dst) - { + } else { + if (this == dst) { dst->fRunHead = dst->fRunHead->ensureWritable(); - } - else - { + } else { SkRegion tmp; tmp.allocateRuns(fRunHead->fRunCount); tmp.fBounds = fBounds; @@ -540,17 +521,17 @@ void SkRegion::translate(int dx, int dy, SkRegion* dst) const RunType* druns = dst->fRunHead->writable_runs(); *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top - for (;;) - { + for (;;) { int bottom = *sruns++; - if (bottom == kRunTypeSentinel) + if (bottom == kRunTypeSentinel) { break; + } *druns++ = (SkRegion::RunType)(bottom + dy); // bottom; - for (;;) - { + for (;;) { int x = *sruns++; - if (x == kRunTypeSentinel) + if (x == kRunTypeSentinel) { break; + } *druns++ = (SkRegion::RunType)(x + dx); *druns++ = (SkRegion::RunType)(*sruns++ + dx); } @@ -1086,7 +1067,14 @@ uint32_t SkRegion::unflatten(const void* storage) { return buffer.pos(); } -////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +const SkRegion& SkRegion::GetEmptyRegion() { + static SkRegion gEmpty; + return gEmpty; +} + +/////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index ff8e168..6b5f663 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -27,10 +27,6 @@ #include "SkStroke.h" #include "SkThread.h" -#ifdef SK_DEBUG -// #define TRACK_MISSING_CHARS -#endif - #define ComputeBWRowBytes(width) (((unsigned)(width) + 7) >> 3) static const uint8_t* gBlackGammaTable; @@ -49,14 +45,14 @@ size_t SkGlyph::computeImageSize() const { const size_t size = this->rowBytes() * fHeight; switch (fMaskFormat) { - case SkMask::kHorizontalLCD_Format: - return SkAlign4(size) + sizeof(uint32_t) * ((fWidth + 2) * fHeight); - case SkMask::kVerticalLCD_Format: - return SkAlign4(size) + sizeof(uint32_t) * (fWidth * (fHeight + 2)); - case SkMask::k3D_Format: - return 3 * size; - default: - return size; + case SkMask::kHorizontalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * ((fWidth + 2) * fHeight); + case SkMask::kVerticalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * (fWidth * (fHeight + 2)); + case SkMask::k3D_Format: + return 3 * size; + default: + return size; } } @@ -154,14 +150,16 @@ SkScalerContext::SkScalerContext(const SkDescriptor* desc) #ifdef DUMP_REC desc->assertChecksum(); - SkDebugf("SkScalarContext checksum %x count %d length %d\n", desc->getChecksum(), desc->getCount(), desc->getLength()); + SkDebugf("SkScalarContext checksum %x count %d length %d\n", + desc->getChecksum(), desc->getCount(), desc->getLength()); SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n", rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0], rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]); SkDebugf(" frame %g miter %g hints %d framefill %d format %d join %d\n", rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill, rec->fMaskFormat, rec->fStrokeJoin); - SkDebugf(" pathEffect %x maskFilter %x\n", desc->findEntry(kPathEffect_SkDescriptorTag, NULL), + SkDebugf(" pathEffect %x maskFilter %x\n", + desc->findEntry(kPathEffect_SkDescriptorTag, NULL), desc->findEntry(kMaskFilter_SkDescriptorTag, NULL)); #endif @@ -452,8 +450,9 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { draw.drawPath(devPath, paint); } - if (lcdMode) + if (lcdMode) { glyph->expandA8ToLCD(); + } } else { this->getGlyphContext(*glyph)->generateImage(*glyph); } @@ -501,28 +500,26 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { (fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0) { const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable; - if (NULL != table) - { + if (NULL != table) { uint8_t* dst = (uint8_t*)origGlyph.fImage; unsigned rowBytes = origGlyph.rowBytes(); - for (int y = origGlyph.fHeight - 1; y >= 0; --y) - { - for (int x = origGlyph.fWidth - 1; x >= 0; --x) + for (int y = origGlyph.fHeight - 1; y >= 0; --y) { + for (int x = origGlyph.fWidth - 1; x >= 0; --x) { dst[x] = table[dst[x]]; + } dst += rowBytes; } } } } -void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) -{ +void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) { this->internalGetPath(glyph, NULL, path, NULL); } -void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) -{ +void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, + SkPaint::FontMetrics* my) { this->generateFontMetrics(mx, my); } @@ -530,16 +527,15 @@ SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) { return 0; } -/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix) -{ +void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, + SkPath* devPath, SkMatrix* fillToDevMatrix) { SkPath path; this->getGlyphContext(glyph)->generatePath(glyph, &path); - if (fRec.fFrameWidth > 0 || fPathEffect != NULL) - { + if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { // need the path in user-space, with only the point-size applied // so that our stroking and effects will operate the same way they // would if the user had extracted the path themself, and then @@ -554,16 +550,15 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, Sk SkScalar width = fRec.fFrameWidth; - if (fPathEffect) - { + if (fPathEffect) { SkPath effectPath; - if (fPathEffect->filterPath(&effectPath, localPath, &width)) + if (fPathEffect->filterPath(&effectPath, localPath, &width)) { localPath.swap(effectPath); + } } - if (width > 0) - { + if (width > 0) { SkStroke stroker; SkPath outline; @@ -576,41 +571,42 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, Sk } // now return stuff to the caller - if (fillToDevMatrix) + if (fillToDevMatrix) { *fillToDevMatrix = matrix; - - if (devPath) + } + if (devPath) { localPath.transform(matrix, devPath); - - if (fillPath) + } + if (fillPath) { fillPath->swap(localPath); - } - else // nothing tricky to do - { - if (fillToDevMatrix) + } + } else { // nothing tricky to do + if (fillToDevMatrix) { fillToDevMatrix->reset(); - - if (devPath) - { - if (fillPath == NULL) + } + if (devPath) { + if (fillPath == NULL) { devPath->swap(path); - else + } else { *devPath = path; + } } - if (fillPath) + if (fillPath) { fillPath->swap(path); + } } - if (devPath) + if (devPath) { devPath->updateBoundsCache(); - if (fillPath) + } + if (fillPath) { fillPath->updateBoundsCache(); + } } -void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const -{ +void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const { dst->reset(); dst->setScaleX(fPost2x2[0][0]); dst->setSkewX( fPost2x2[0][1]); @@ -618,23 +614,20 @@ void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const dst->setScaleY(fPost2x2[1][1]); } -void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const -{ +void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const { m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize); - if (fPreSkewX) + if (fPreSkewX) { m->postSkew(fPreSkewX, 0); + } } -void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const -{ +void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const { this->getLocalMatrix(m); // now concat the device matrix - { - SkMatrix deviceMatrix; - this->getMatrixFrom2x2(&deviceMatrix); - m->postConcat(deviceMatrix); - } + SkMatrix deviceMatrix; + this->getMatrixFrom2x2(&deviceMatrix); + m->postConcat(deviceMatrix); } /////////////////////////////////////////////////////////////////////////////// @@ -673,8 +666,7 @@ protected: extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc); -SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) -{ +SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) { SkScalerContext* c = NULL; //SkCreateColorScalerContext(desc); if (NULL == c) { c = SkFontHost::CreateScalerContext(desc); diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 90a1f68..5457b59 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -26,7 +26,10 @@ #define SCALE (1 << SHIFT) #define MASK (SCALE - 1) -/////////////////////////////////////////////////////////////////////////////////////////// +//#define FORCE_SUPERMASK +//#define FORCE_RLE + +/////////////////////////////////////////////////////////////////////////////// class BaseSuperBlitter : public SkBlitter { public: @@ -99,12 +102,9 @@ SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, fRuns.reset(width); } -void SuperBlitter::flush() -{ - if (fCurrIY >= 0) - { - if (!fRuns.empty()) - { +void SuperBlitter::flush() { + if (fCurrIY >= 0) { + if (!fRuns.empty()) { // SkDEBUGCODE(fRuns.dump();) fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); fRuns.reset(fWidth); @@ -114,8 +114,7 @@ void SuperBlitter::flush() } } -static inline int coverage_to_alpha(int aa) -{ +static inline int coverage_to_alpha(int aa) { aa <<= 8 - 2*SHIFT; aa -= aa >> (8 - SHIFT - 1); return aa; @@ -123,15 +122,13 @@ static inline int coverage_to_alpha(int aa) #define SUPER_Mask ((1 << SHIFT) - 1) -void SuperBlitter::blitH(int x, int y, int width) -{ +void SuperBlitter::blitH(int x, int y, int width) { int iy = y >> SHIFT; SkASSERT(iy >= fCurrIY); x -= fSuperLeft; // hack, until I figure out why my cubics (I think) go beyond the bounds - if (x < 0) - { + if (x < 0) { width += x; x = 0; } @@ -142,8 +139,7 @@ void SuperBlitter::blitH(int x, int y, int width) fCurrY = y; #endif - if (iy != fCurrIY) // new scanline - { + if (iy != fCurrIY) { // new scanline this->flush(); fCurrIY = iy; } @@ -155,7 +151,8 @@ void SuperBlitter::blitH(int x, int y, int width) #if 0 SkAntiRun<SHIFT> arun; arun.set(x, x + width); - fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), arun.getStopAlpha(), maxValue); + fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), + arun.getStopAlpha(), maxValue); #else { int start = x; @@ -166,18 +163,16 @@ void SuperBlitter::blitH(int x, int y, int width) int fe = stop & SUPER_Mask; int n = (stop >> SHIFT) - (start >> SHIFT) - 1; - if (n < 0) - { + if (n < 0) { fb = fe - fb; n = 0; fe = 0; - } - else - { - if (fb == 0) + } else { + if (fb == 0) { n += 1; - else + } else { fb = (1 << SHIFT) - fb; + } } fRuns.add(x >> SHIFT, coverage_to_alpha(fb), n, coverage_to_alpha(fe), (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); @@ -190,8 +185,7 @@ void SuperBlitter::blitH(int x, int y, int width) #endif } -void SuperBlitter::blitRect(int x, int y, int width, int height) -{ +void SuperBlitter::blitRect(int x, int y, int width, int height) { for (int i = 0; i < height; ++i) { blitH(x, y + i, width); } @@ -211,8 +205,10 @@ public: virtual void blitH(int x, int y, int width); - static bool CanHandleRect(const SkIRect& bounds) - { + static bool CanHandleRect(const SkIRect& bounds) { +#ifdef FORCE_RLE + return false; +#endif int width = bounds.width(); int rb = SkAlign4(width); @@ -222,8 +218,13 @@ public: private: enum { +#ifdef FORCE_SUPERMASK + kMAX_WIDTH = 2048, + kMAX_STORAGE = 1024 * 1024 * 2 +#else kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster kMAX_STORAGE = 1024 +#endif }; SkMask fMask; @@ -251,8 +252,7 @@ MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1); } -static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) -{ +static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) { /* I should be able to just add alpha[x] + startAlpha. However, if the trailing edge of the previous span and the leading edge of the current span round to the same super-sampled x value, @@ -263,8 +263,16 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) *alpha = SkToU8(tmp - (tmp >> 8)); } -static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue) -{ +static inline uint32_t quadplicate_byte(U8CPU value) { + uint32_t pair = (value << 8) | value; + return (pair << 16) | pair; +} + +// minimum count before we want to setup an inner loop, adding 4-at-a-time +#define MIN_COUNT_FOR_QUAD_LOOP 16 + +static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, + U8CPU stopAlpha, U8CPU maxValue) { SkASSERT(middleCount >= 0); /* I should be able to just add alpha[x] + startAlpha. @@ -276,8 +284,27 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU SkASSERT(tmp <= 256); *alpha++ = SkToU8(tmp - (tmp >> 8)); - while (--middleCount >= 0) - { + if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) { + // loop until we're quad-byte aligned + while (SkTCast<intptr_t>(alpha) & 0x3) { + alpha[0] = SkToU8(alpha[0] + maxValue); + alpha += 1; + middleCount -= 1; + } + + int bigCount = middleCount >> 2; + uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha); + uint32_t qval = quadplicate_byte(maxValue); + do { + *qptr++ += qval; + } while (--bigCount > 0); + + middleCount &= 3; + alpha = reinterpret_cast<uint8_t*> (qptr); + // fall through to the following while-loop + } + + while (--middleCount >= 0) { alpha[0] = SkToU8(alpha[0] + maxValue); alpha += 1; } @@ -289,8 +316,7 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU *alpha = SkToU8(*alpha + stopAlpha); } -void MaskSuperBlitter::blitH(int x, int y, int width) -{ +void MaskSuperBlitter::blitH(int x, int y, int width) { int iy = (y >> SHIFT); SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom); @@ -313,8 +339,7 @@ void MaskSuperBlitter::blitH(int x, int y, int width) x -= (fMask.fBounds.fLeft << SHIFT); // hack, until I figure out why my cubics (I think) go beyond the bounds - if (x < 0) - { + if (x < 0) { width += x; x = 0; } @@ -334,14 +359,11 @@ void MaskSuperBlitter::blitH(int x, int y, int width) int n = (stop >> SHIFT) - (start >> SHIFT) - 1; - if (n < 0) - { + if (n < 0) { SkASSERT(row >= fMask.fImage); SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1); add_aa_span(row, coverage_to_alpha(fe - fb)); - } - else - { + } else { fb = (1 << SHIFT) - fb; SkASSERT(row >= fMask.fImage); SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1); @@ -407,8 +429,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, SkIRect superRect, *superClipRect = NULL; - if (clipRect) - { + if (clipRect) { superRect.set( clipRect->fLeft << SHIFT, clipRect->fTop << SHIFT, clipRect->fRight << SHIFT, clipRect->fBottom << SHIFT); superClipRect = &superRect; @@ -418,14 +439,11 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it // if we're an inverse filltype - if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir)) - { + if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir)) { MaskSuperBlitter superBlit(blitter, ir, clip); SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); - } - else - { + } else { SuperBlitter superBlit(blitter, ir, clip); sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); } diff --git a/src/core/SkScan_Antihair.cpp b/src/core/SkScan_Antihair.cpp index 0003298..99bd2c8 100644 --- a/src/core/SkScan_Antihair.cpp +++ b/src/core/SkScan_Antihair.cpp @@ -1,6 +1,6 @@ /* libs/graphics/sgl/SkScan_Antihair.cpp ** -** Copyright 2006, The Android Open Source Project +** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -51,14 +51,11 @@ static inline int SmallDot6Scale(int value, int dot6) { static uint8_t gGammaTable[256]; #define ApplyGamma(table, alpha) (table)[alpha] - static void build_gamma_table() - { + static void build_gamma_table() { static bool gInit = false; - if (gInit == false) - { - for (int i = 0; i < 256; i++) - { + if (gInit == false) { + for (int i = 0; i < 256; i++) { SkFixed n = i * 257; n += n >> 15; SkASSERT(n >= 0 && n <= SK_Fixed1); @@ -76,8 +73,8 @@ static inline int SmallDot6Scale(int value, int dot6) { /////////////////////////////////////////////////////////////////////////////// -static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CPU alpha) -{ +static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, + U8CPU alpha) { SkASSERT(count > 0); int16_t runs[HLINE_STACK_BUFFER + 1]; @@ -86,9 +83,9 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP aa[0] = ApplyGamma(gGammaTable, alpha); do { int n = count; - if (n > HLINE_STACK_BUFFER) + if (n > HLINE_STACK_BUFFER) { n = HLINE_STACK_BUFFER; - + } runs[0] = SkToS16(n); runs[n] = 0; blitter->blitAntiH(x, y, aa, runs); @@ -97,8 +94,8 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP } while (count > 0); } -static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* blitter, int mod64) -{ +static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, + SkBlitter* blitter, int mod64) { SkASSERT(x < stopx); int count = stopx - x; fy += SK_Fixed1/2; @@ -121,8 +118,8 @@ static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* return fy - SK_Fixed1/2; } -static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter, int mod64) -{ +static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, + SkBlitter* blitter, int mod64) { SkASSERT(x < stopx); #ifdef TEST_GAMMA @@ -139,8 +136,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt int lower_y = fy >> 16; uint8_t a = (uint8_t)(fy >> 8); unsigned ma = SmallDot6Scale(a, mod64); - if (ma) - { + if (ma) { aa[0] = ApplyGamma(gamma, ma); blitter->blitAntiH(x, lower_y, aa, runs); // the clipping blitters might edit runs, but should not affect us @@ -148,8 +144,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt SkASSERT(runs[1] == 0); } ma = SmallDot6Scale(255 - a, mod64); - if (ma) - { + if (ma) { aa[0] = ApplyGamma(gamma, ma); blitter->blitAntiH(x, lower_y - 1, aa, runs); // the clipping blitters might edit runs, but should not affect us @@ -162,8 +157,8 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt return fy - SK_Fixed1/2; } -static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* blitter, int mod64) -{ +static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, + SkBlitter* blitter, int mod64) { SkASSERT(y < stopy); fx += SK_Fixed1/2; @@ -171,17 +166,19 @@ static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* int a = (uint8_t)(fx >> 8); unsigned ma = SmallDot6Scale(a, mod64); - if (ma) + if (ma) { blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, ma)); + } ma = SmallDot6Scale(255 - a, mod64); - if (ma) + if (ma) { blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, ma)); + } return fx - SK_Fixed1/2; } -static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter, int mod64) -{ +static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, + SkBlitter* blitter, int mod64) { SkASSERT(y < stopy); #ifdef TEST_GAMMA const uint8_t* gamma = gGammaTable; @@ -211,23 +208,21 @@ static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blit return fx - SK_Fixed1/2; } -typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, SkFixed slope, SkBlitter*, int); +typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, + SkFixed slope, SkBlitter*, int); -static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) -{ +static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) { SkASSERT((a << 16 >> 16) == a); SkASSERT(b != 0); return (a << 16) / b; } static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, - const SkIRect* clip, SkBlitter* blitter) -{ + const SkIRect* clip, SkBlitter* blitter) { // check that we're no larger than 511 pixels (so we can do a faster div). // if we are, subdivide and call again - if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) - { + if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) { /* instead of (x0 + x1) >> 1, we shift each separately. This is less precise, but avoids overflowing the intermediate result if the values are huge. A better fix might be to clip the original pts @@ -246,8 +241,7 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, SkFixed fstart, slope; LineProc proc; - if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) // mostly horizontal - { + if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal if (x0 > x1) { // we want to go left-to-right SkTSwap<SkFDot6>(x0, x1); SkTSwap<SkFDot6>(y0, y1); @@ -276,12 +270,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = x1 & 63; } - if (clip) - { - if (istart >= clip->fRight || istop <= clip->fLeft) + if (clip){ + if (istart >= clip->fRight || istop <= clip->fLeft) { return; - if (istart < clip->fLeft) - { + } + if (istart < clip->fLeft) { fstart += slope * (clip->fLeft - istart); istart = clip->fLeft; scaleStart = 64; @@ -291,18 +284,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = 64; } SkASSERT(istart <= istop); - if (istart == istop) + if (istart == istop) { return; - + } // now test if our Y values are completely inside the clip int top, bottom; - if (slope >= 0) // T2B - { + if (slope >= 0) { // T2B top = SkFixedFloor(fstart - SK_FixedHalf); bottom = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf); - } - else // B2T - { + } else { // B2T bottom = SkFixedCeil(fstart + SK_FixedHalf); top = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf); } @@ -310,16 +300,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, top -= 1; bottom += 1; #endif - if (top >= clip->fBottom || bottom <= clip->fTop) + if (top >= clip->fBottom || bottom <= clip->fTop) { return; - if (clip->fTop <= top && clip->fBottom >= bottom) + } + if (clip->fTop <= top && clip->fBottom >= bottom) { clip = NULL; + } } - } - else // mostly vertical - { - if (y0 > y1) // we want to go top-to-bottom - { + } else { // mostly vertical + if (y0 > y1) { // we want to go top-to-bottom SkTSwap<SkFDot6>(x0, x1); SkTSwap<SkFDot6>(y0, y1); } @@ -327,16 +316,13 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, istart = SkFDot6Floor(y0); istop = SkFDot6Ceil(y1); fstart = SkFDot6ToFixed(x0); - if (x0 == x1) - { + if (x0 == x1) { if (y0 == y1) { // are we zero length? return; // nothing to do } slope = 0; proc = vline; - } - else - { + } else { slope = fastfixdiv(x1 - x0, y1 - y0); SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1); fstart += (slope * (32 - (y0 & 63)) + 32) >> 6; @@ -353,12 +339,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = y1 & 63; } - if (clip) - { - if (istart >= clip->fBottom || istop <= clip->fTop) + if (clip) { + if (istart >= clip->fBottom || istop <= clip->fTop) { return; - if (istart < clip->fTop) - { + } + if (istart < clip->fTop) { fstart += slope * (clip->fTop - istart); istart = clip->fTop; scaleStart = 64; @@ -373,13 +358,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, // now test if our X values are completely inside the clip int left, right; - if (slope >= 0) // L2R - { + if (slope >= 0) { // L2R left = SkFixedFloor(fstart - SK_FixedHalf); right = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf); - } - else // R2L - { + } else { // R2L right = SkFixedCeil(fstart + SK_FixedHalf); left = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf); } @@ -387,16 +369,17 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, left -= 1; right += 1; #endif - if (left >= clip->fRight || right <= clip->fLeft) + if (left >= clip->fRight || right <= clip->fLeft) { return; - if (clip->fLeft <= left && clip->fRight >= right) + } + if (clip->fLeft <= left && clip->fRight >= right) { clip = NULL; + } } } SkRectClipBlitter rectClipper; - if (clip) - { + if (clip) { rectClipper.init(blitter, *clip); blitter = &rectClipper; } @@ -413,10 +396,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, } void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1, - const SkRegion* clip, SkBlitter* blitter) -{ - if (clip && clip->isEmpty()) + const SkRegion* clip, SkBlitter* blitter) { + if (clip && clip->isEmpty()) { return; + } SkASSERT(clip == NULL || !clip->getBounds().isEmpty()); @@ -480,8 +463,8 @@ void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1, do_anti_hairline(x0, y0, x1, y1, NULL, blitter); } -void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* blitter) -{ +void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, + SkBlitter* blitter) { SkPoint p0, p1; p0.set(rect.fLeft, rect.fTop); @@ -495,7 +478,7 @@ void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* b SkScan::AntiHairLine(p0, p1, clip, blitter); } -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// typedef int FDot8; // 24.8 integer fixed point @@ -503,77 +486,76 @@ static inline FDot8 SkFixedToFDot8(SkFixed x) { return (x + 0x80) >> 8; } -static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter* blitter) -{ +static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, + SkBlitter* blitter) { SkASSERT(L < R); - if ((L >> 8) == ((R - 1) >> 8)) // 1x1 pixel - { + if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel blitter->blitV(L >> 8, top, 1, SkAlphaMul(alpha, R - L)); return; } int left = L >> 8; - if (L & 0xFF) - { + if (L & 0xFF) { blitter->blitV(left, top, 1, SkAlphaMul(alpha, 256 - (L & 0xFF))); left += 1; } int rite = R >> 8; int width = rite - left; - if (width > 0) + if (width > 0) { call_hline_blitter(blitter, left, top, width, alpha); - - if (R & 0xFF) + } + if (R & 0xFF) { blitter->blitV(rite, top, 1, SkAlphaMul(alpha, R & 0xFF)); + } } -static void antifillrect(const SkXRect& xr, SkBlitter* blitter) -{ - FDot8 L = SkFixedToFDot8(xr.fLeft); - FDot8 T = SkFixedToFDot8(xr.fTop); - FDot8 R = SkFixedToFDot8(xr.fRight); - FDot8 B = SkFixedToFDot8(xr.fBottom); - +static void antifilldot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter* blitter, + bool fillInner) { // check for empty now that we're in our reduced precision space - if (L >= R || T >= B) + if (L >= R || T >= B) { return; - + } int top = T >> 8; - if (top == ((B - 1) >> 8)) // just one scanline high - { + if (top == ((B - 1) >> 8)) { // just one scanline high do_scanline(L, top, R, B - T - 1, blitter); return; } - if (T & 0xFF) - { + if (T & 0xFF) { do_scanline(L, top, R, 256 - (T & 0xFF), blitter); top += 1; } int bot = B >> 8; int height = bot - top; - if (height > 0) - { + if (height > 0) { int left = L >> 8; - if (L & 0xFF) - { + if (L & 0xFF) { blitter->blitV(left, top, height, 256 - (L & 0xFF)); left += 1; } int rite = R >> 8; int width = rite - left; - if (width > 0) + if (width > 0 && fillInner) { blitter->blitRect(left, top, width, height); - if (R & 0xFF) + } + if (R & 0xFF) { blitter->blitV(rite, top, height, R & 0xFF); + } } - if (B & 0xFF) + if (B & 0xFF) { do_scanline(L, bot, R, B & 0xFF, blitter); + } +} + +static void antifillrect(const SkXRect& xr, SkBlitter* blitter) { + antifilldot8(SkFixedToFDot8(xr.fLeft), SkFixedToFDot8(xr.fTop), + SkFixedToFDot8(xr.fRight), SkFixedToFDot8(xr.fBottom), + blitter, true); } /////////////////////////////////////////////////////////////////////////////// @@ -667,6 +649,165 @@ void SkScan::AntiFillRect(const SkRect& origR, const SkRegion* clip, } } +/////////////////////////////////////////////////////////////////////////////// + +#define SkAlphaMulRound(a, b) SkMulDiv255Round(a, b) + +// calls blitRect() if the rectangle is non-empty +static void fillcheckrect(int L, int T, int R, int B, SkBlitter* blitter) { + if (L < R && T < B) { + blitter->blitRect(L, T, R - L, B - T); + } +} + +static inline FDot8 SkScalarToFDot8(SkScalar x) { +#ifdef SK_SCALAR_IS_FLOAT + return (int)(x * 256); +#else + return x >> 8; +#endif +} + +static inline int FDot8Floor(FDot8 x) { + return x >> 8; +} + +static inline int FDot8Ceil(FDot8 x) { + return (x + 0xFF) >> 8; +} + +// 1 - (1 - a)*(1 - b) +static inline U8CPU InvAlphaMul(U8CPU a, U8CPU b) { + // need precise rounding (not just SkAlphaMul) so that values like + // a=228, b=252 don't overflow the result + return SkToU8(a + b - SkAlphaMulRound(a, b)); +} + +static void inner_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, + SkBlitter* blitter) { + SkASSERT(L < R); + + if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel + blitter->blitV(L >> 8, top, 1, InvAlphaMul(alpha, R - L)); + return; + } + + int left = L >> 8; + if (L & 0xFF) { + blitter->blitV(left, top, 1, InvAlphaMul(alpha, L & 0xFF)); + left += 1; + } + + int rite = R >> 8; + int width = rite - left; + if (width > 0) { + call_hline_blitter(blitter, left, top, width, alpha); + } + + if (R & 0xFF) { + blitter->blitV(rite, top, 1, InvAlphaMul(alpha, ~R & 0xFF)); + } +} + +static void innerstrokedot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, + SkBlitter* blitter) { + SkASSERT(L < R && T < B); + + int top = T >> 8; + if (top == ((B - 1) >> 8)) { // just one scanline high + inner_scanline(L, top, R, B - T, blitter); + return; + } + + if (T & 0xFF) { + inner_scanline(L, top, R, T & 0xFF, blitter); + top += 1; + } + + int bot = B >> 8; + int height = bot - top; + if (height > 0) { + if (L & 0xFF) { + blitter->blitV(L >> 8, top, height, L & 0xFF); + } + if (R & 0xFF) { + blitter->blitV(R >> 8, top, height, ~R & 0xFF); + } + } + + if (B & 0xFF) { + inner_scanline(L, bot, R, ~B & 0xFF, blitter); + } +} + +void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, + const SkRegion* clip, SkBlitter* blitter) { + SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); + + SkScalar rx = SkScalarHalf(strokeSize.fX); + SkScalar ry = SkScalarHalf(strokeSize.fY); + + // outset by the radius + FDot8 L = SkScalarToFDot8(r.fLeft - rx); + FDot8 T = SkScalarToFDot8(r.fTop - ry); + FDot8 R = SkScalarToFDot8(r.fRight + rx); + FDot8 B = SkScalarToFDot8(r.fBottom + ry); + + SkIRect outer; + // set outer to the outer rect of the outer section + outer.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); + + SkBlitterClipper clipper; + if (clip) { + if (clip->quickReject(outer)) { + return; + } + if (!clip->contains(outer)) { + blitter = clipper.apply(blitter, clip, &outer); + } + // now we can ignore clip for the rest of the function + } + + // stroke the outer hull + antifilldot8(L, T, R, B, blitter, false); + + // set outer to the outer rect of the middle section + outer.set(FDot8Ceil(L), FDot8Ceil(T), FDot8Floor(R), FDot8Floor(B)); + + // in case we lost a bit with diameter/2 + rx = strokeSize.fX - rx; + ry = strokeSize.fY - ry; + // inset by the radius + L = SkScalarToFDot8(r.fLeft + rx); + T = SkScalarToFDot8(r.fTop + ry); + R = SkScalarToFDot8(r.fRight - rx); + B = SkScalarToFDot8(r.fBottom - ry); + + if (L >= R || T >= B) { + fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, + blitter); + } else { + SkIRect inner; + // set inner to the inner rect of the middle section + inner.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); + + // draw the frame in 4 pieces + fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, + blitter); + fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, + blitter); + fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, + blitter); + fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, + blitter); + + // now stroke the inner rect, which is similar to antifilldot8() except that + // it treats the fractional coordinates with the inverse bias (since its + // inner). + innerstrokedot8(L, T, R, B, blitter); + } +} + #endif diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp index 0dee814..ac2c19c 100644 --- a/src/core/SkScan_Hairline.cpp +++ b/src/core/SkScan_Hairline.cpp @@ -76,8 +76,8 @@ void SkScan::HairLine(const SkPoint& pt0, const SkPoint& pt1, const SkRegion* cl // outset the right and bottom, to account for how hairlines are // actually drawn, which may hit the pixel to the right or below of // the coordinate - ptsR.fRight += SK_FDot61; - ptsR.fBottom += SK_FDot61; + ptsR.fRight += SK_FDot6One; + ptsR.fBottom += SK_FDot6One; if (!SkIRect::Intersects(ptsR, clipR)) { return; @@ -317,36 +317,39 @@ void SkScan::AntiHairPath(const SkPath& path, const SkRegion* clip, SkBlitter* b hair_path(path, clip, blitter, SkScan::AntiHairLine); } -//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkScan::FrameRect(const SkRect& r, SkScalar diameter, const SkRegion* clip, SkBlitter* blitter) -{ - SkASSERT(diameter > 0); +void SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, + const SkRegion* clip, SkBlitter* blitter) { + SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); - if (r.isEmpty()) + if (strokeSize.fX < 0 || strokeSize.fY < 0) { return; + } - SkScalar radius = diameter / 2; + const SkScalar dx = strokeSize.fX; + const SkScalar dy = strokeSize.fY; + SkScalar rx = SkScalarHalf(dx); + SkScalar ry = SkScalarHalf(dy); SkRect outer, tmp; - outer.set( r.fLeft - radius, r.fTop - radius, - r.fRight + radius, r.fBottom + radius); + outer.set(r.fLeft - rx, r.fTop - ry, + r.fRight + rx, r.fBottom + ry); - if (r.width() <= diameter || r.height() <= diameter) - { + if (r.width() <= dx || r.height() <= dx) { SkScan::FillRect(outer, clip, blitter); return; } - tmp.set(outer.fLeft, outer.fTop, outer.fRight, outer.fTop + diameter); + tmp.set(outer.fLeft, outer.fTop, outer.fRight, outer.fTop + dy); SkScan::FillRect(tmp, clip, blitter); - tmp.fTop = outer.fBottom - diameter; + tmp.fTop = outer.fBottom - dy; tmp.fBottom = outer.fBottom; SkScan::FillRect(tmp, clip, blitter); - tmp.set(outer.fLeft, outer.fTop + diameter, outer.fLeft + diameter, outer.fBottom - diameter); + tmp.set(outer.fLeft, outer.fTop + dy, outer.fLeft + dx, outer.fBottom - dy); SkScan::FillRect(tmp, clip, blitter); - tmp.fLeft = outer.fRight - diameter; + tmp.fLeft = outer.fRight - dx; tmp.fRight = outer.fRight; SkScan::FillRect(tmp, clip, blitter); } diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index c5088a1..af5d4b1 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -30,12 +30,10 @@ #define kEDGE_TAIL_Y SK_MaxS32 #ifdef SK_DEBUG - static void validate_sort(const SkEdge* edge) - { + static void validate_sort(const SkEdge* edge) { int y = kEDGE_HEAD_Y; - while (edge->fFirstY != SK_MaxS32) - { + while (edge->fFirstY != SK_MaxS32) { edge->validate(); SkASSERT(y <= edge->fFirstY); @@ -47,14 +45,12 @@ #define validate_sort(edge) #endif -static inline void remove_edge(SkEdge* edge) -{ +static inline void remove_edge(SkEdge* edge) { edge->fPrev->fNext = edge->fNext; edge->fNext->fPrev = edge->fPrev; } -static inline void swap_edges(SkEdge* prev, SkEdge* next) -{ +static inline void swap_edges(SkEdge* prev, SkEdge* next) { SkASSERT(prev->fNext == next && next->fPrev == prev); // remove prev from the list @@ -68,31 +64,27 @@ static inline void swap_edges(SkEdge* prev, SkEdge* next) prev->fPrev = next; } -static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) -{ +static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) { SkFixed x = edge->fX; - for (;;) - { + for (;;) { SkEdge* prev = edge->fPrev; // add 1 to curr_y since we may have added new edges (built from curves) // that start on the next scanline SkASSERT(prev && prev->fFirstY <= curr_y + 1); - if (prev->fX <= x) + if (prev->fX <= x) { break; - + } swap_edges(prev, edge); } } -static void insert_new_edges(SkEdge* newEdge, int curr_y) -{ +static void insert_new_edges(SkEdge* newEdge, int curr_y) { SkASSERT(newEdge->fFirstY >= curr_y); - while (newEdge->fFirstY == curr_y) - { + while (newEdge->fFirstY == curr_y) { SkEdge* next = newEdge->fNext; backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); newEdge = next; @@ -100,10 +92,8 @@ static void insert_new_edges(SkEdge* newEdge, int curr_y) } #ifdef SK_DEBUG -static void validate_edges_for_y(const SkEdge* edge, int curr_y) -{ - while (edge->fFirstY <= curr_y) - { +static void validate_edges_for_y(const SkEdge* edge, int curr_y) { + while (edge->fFirstY <= curr_y) { SkASSERT(edge->fPrev && edge->fNext); SkASSERT(edge->fPrev->fNext == edge); SkASSERT(edge->fNext->fPrev == edge); @@ -128,16 +118,14 @@ typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, SkBlitter* blitter, int start_y, int stop_y, - PrePostProc proc) -{ + PrePostProc proc) { validate_sort(prevHead->fNext); int curr_y = start_y; // returns 1 for evenodd, -1 for winding, regardless of inverse-ness int windingMask = (fillType & 1) ? 1 : -1; - for (;;) - { + for (;;) { int w = 0; int left SK_INIT_TO_AVOID_WARNING; bool in_interval = false; @@ -150,23 +138,19 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, proc(blitter, curr_y, PREPOST_START); // pre-proc } - while (currE->fFirstY <= curr_y) - { + while (currE->fFirstY <= curr_y) { SkASSERT(currE->fLastY >= curr_y); int x = (currE->fX + SK_Fixed1/2) >> 16; w += currE->fWinding; - if ((w & windingMask) == 0) // we finished an interval - { + if ((w & windingMask) == 0) { // we finished an interval SkASSERT(in_interval); int width = x - left; SkASSERT(width >= 0); if (width) blitter->blitH(left, curr_y, width); in_interval = false; - } - else if (!in_interval) - { + } else if (!in_interval) { left = x; in_interval = true; } @@ -174,38 +158,31 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, SkEdge* next = currE->fNext; SkFixed newX; - if (currE->fLastY == curr_y) // are we done with this edge? - { - if (currE->fCurveCount < 0) - { - if (((SkCubicEdge*)currE)->updateCubic()) - { + if (currE->fLastY == curr_y) { // are we done with this edge? + if (currE->fCurveCount < 0) { + if (((SkCubicEdge*)currE)->updateCubic()) { SkASSERT(currE->fFirstY == curr_y + 1); newX = currE->fX; goto NEXT_X; } - } - else if (currE->fCurveCount > 0) - { - if (((SkQuadraticEdge*)currE)->updateQuadratic()) - { + } else if (currE->fCurveCount > 0) { + if (((SkQuadraticEdge*)currE)->updateQuadratic()) { newX = currE->fX; goto NEXT_X; } } remove_edge(currE); - } - else - { + } else { SkASSERT(currE->fLastY > curr_y); newX = currE->fX + currE->fDX; currE->fX = newX; NEXT_X: - if (newX < prevX) // ripple currE backwards until it is x-sorted + if (newX < prevX) { // ripple currE backwards until it is x-sorted backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); - else + } else { prevX = newX; + } } currE = next; SkASSERT(currE); @@ -216,9 +193,9 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, } curr_y += 1; - if (curr_y >= stop_y) + if (curr_y >= stop_y) { break; - + } // now currE points to the first edge with a Yint larger than curr_y insert_new_edges(currE, curr_y); } @@ -291,19 +268,6 @@ static void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) { #pragma warning ( pop ) #endif -/* Our line edge relies on the maximum span being <= 512, so that it can - use FDot6 and keep the dx,dy in 16bits (for much faster slope divide). - This function returns true if the specified line is too big. -*/ -static inline bool line_too_big(const SkPoint pts[2]) -{ - SkScalar dx = pts[1].fX - pts[0].fX; - SkScalar dy = pts[1].fY - pts[0].fY; - - return SkScalarAbs(dx) > SkIntToScalar(511) || - SkScalarAbs(dy) > SkIntToScalar(511); -} - #ifdef USE_NEW_BUILDER #include "SkEdgeBuilder.h" #else @@ -379,31 +343,29 @@ static int build_edges(SkEdge edge[], const SkPath& path, /* 'quick' computation of the max sized needed to allocated for our edgelist. */ -static int worst_case_edge_count(const SkPath& path, size_t* storage) -{ +static int worst_case_edge_count(const SkPath& path, size_t* storage) { size_t size = 0; int edgeCount = 0; SkPath::Iter iter(path, true); SkPath::Verb verb; - while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) - { + while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) { switch (verb) { - case SkPath::kLine_Verb: - edgeCount += 1; - size += sizeof(SkQuadraticEdge); // treat line like Quad (in case its > 512) - break; - case SkPath::kQuad_Verb: - edgeCount += 2; // might need 2 edges when we chop on Y extrema - size += 2 * sizeof(SkQuadraticEdge); - break; - case SkPath::kCubic_Verb: - edgeCount += 3; // might need 3 edges when we chop on Y extrema - size += 3 * sizeof(SkCubicEdge); - break; - default: - break; + case SkPath::kLine_Verb: + edgeCount += 1; + size += sizeof(SkQuadraticEdge); // treat line like Quad (in case its > 512) + break; + case SkPath::kQuad_Verb: + edgeCount += 2; // might need 2 edges when we chop on Y extrema + size += 2 * sizeof(SkQuadraticEdge); + break; + case SkPath::kCubic_Verb: + edgeCount += 3; // might need 3 edges when we chop on Y extrema + size += 3 * sizeof(SkCubicEdge); + break; + default: + break; } } @@ -477,8 +439,8 @@ static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { // clipRect (if no null) has already been shifted up // void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, - int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn) -{ + int start_y, int stop_y, int shiftEdgesUp, + const SkRegion& clipRgn) { SkASSERT(&path && blitter); #ifdef USE_NEW_BUILDER @@ -583,35 +545,30 @@ void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) } } -///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& ir) -{ +SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, + const SkIRect& ir) { fBlitter = NULL; // null means blit nothing fClipRect = NULL; - if (clip) - { + if (clip) { fClipRect = &clip->getBounds(); - if (!SkIRect::Intersects(*fClipRect, ir)) // completely clipped out + if (!SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out return; + } - if (clip->isRect()) - { - if (fClipRect->contains(ir)) + if (clip->isRect()) { + if (fClipRect->contains(ir)) { fClipRect = NULL; - else - { + } else { // only need a wrapper blitter if we're horizontally clipped - if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) - { + if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) { fRectBlitter.init(blitter, *fClipRect); blitter = &fRectBlitter; } } - } - else - { + } else { fRgnBlitter.init(blitter, clip); blitter = &fRgnBlitter; } diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index b8f99c7..49182ea 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -42,15 +42,13 @@ static const size_t kBufferSize = 256; /////////////////////////////////////////////////////////////////////////////// -bool SkStrStartsWith(const char string[], const char prefix[]) -{ +bool SkStrStartsWith(const char string[], const char prefix[]) { SkASSERT(string); SkASSERT(prefix); return !strncmp(string, prefix, strlen(prefix)); } -bool SkStrEndsWith(const char string[], const char suffix[]) -{ +bool SkStrEndsWith(const char string[], const char suffix[]) { SkASSERT(string); SkASSERT(suffix); size_t strLen = strlen(string); @@ -59,50 +57,50 @@ bool SkStrEndsWith(const char string[], const char suffix[]) !strncmp(string + strLen - suffixLen, suffix, suffixLen); } -int SkStrStartsWithOneOf(const char string[], const char prefixes[]) -{ +int SkStrStartsWithOneOf(const char string[], const char prefixes[]) { int index = 0; do { const char* limit = strchr(prefixes, '\0'); - if (!strncmp(string, prefixes, limit - prefixes)) + if (!strncmp(string, prefixes, limit - prefixes)) { return index; + } prefixes = limit + 1; index++; } while (prefixes[0]); return -1; } -char* SkStrAppendS32(char string[], int32_t dec) -{ +char* SkStrAppendS32(char string[], int32_t dec) { SkDEBUGCODE(char* start = string;) char buffer[SkStrAppendS32_MaxSize]; char* p = buffer + sizeof(buffer); bool neg = false; - if (dec < 0) - { + if (dec < 0) { neg = true; dec = -dec; } + do { *--p = SkToU8('0' + dec % 10); dec /= 10; } while (dec != 0); - if (neg) + + if (neg) { *--p = '-'; + } SkASSERT(p >= buffer); char* stop = buffer + sizeof(buffer); - while (p < stop) + while (p < stop) { *string++ = *p++; - + } SkASSERT(string - start <= SkStrAppendS32_MaxSize); return string; } -char* SkStrAppendS64(char string[], int64_t dec, int minDigits) -{ +char* SkStrAppendS64(char string[], int64_t dec, int minDigits) { SkDEBUGCODE(char* start = string;) char buffer[SkStrAppendS64_MaxSize]; @@ -113,18 +111,21 @@ char* SkStrAppendS64(char string[], int64_t dec, int minDigits) neg = true; dec = -dec; } + do { *--p = SkToU8('0' + dec % 10); dec /= 10; minDigits--; } while (dec != 0); + while (minDigits > 0) { *--p = '0'; minDigits--; } - if (neg) - *--p = '-'; + if (neg) { + *--p = '-'; + } SkASSERT(p >= buffer); size_t cp_len = buffer + sizeof(buffer) - p; memcpy(string, p, cp_len); @@ -135,8 +136,7 @@ char* SkStrAppendS64(char string[], int64_t dec, int minDigits) } #ifdef SK_CAN_USE_FLOAT -char* SkStrAppendFloat(char string[], float value) -{ +char* SkStrAppendFloat(char string[], float value) { // since floats have at most 8 significant digits, we limit our %g to that. static const char gFormat[] = "%.8g"; // make it 1 larger for the terminating 0 @@ -148,27 +148,24 @@ char* SkStrAppendFloat(char string[], float value) } #endif -char* SkStrAppendFixed(char string[], SkFixed x) -{ +char* SkStrAppendFixed(char string[], SkFixed x) { SkDEBUGCODE(char* start = string;) - if (x < 0) - { + if (x < 0) { *string++ = '-'; x = -x; } unsigned frac = x & 0xFFFF; x >>= 16; - if (frac == 0xFFFF) // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999 - { + if (frac == 0xFFFF) { + // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999 x += 1; frac = 0; } string = SkStrAppendS32(string, x); // now handle the fractional part (if any) - if (frac) - { + if (frac) { static const uint16_t gTens[] = { 1000, 100, 10, 1 }; const uint16_t* tens = gTens; @@ -189,7 +186,7 @@ char* SkStrAppendFixed(char string[], SkFixed x) return string; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #define kMaxRefCnt_SkString SK_MaxU16 @@ -198,47 +195,43 @@ const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 }; #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec) -SkString::Rec* SkString::AllocRec(const char text[], U16CPU len) -{ +SkString::Rec* SkString::AllocRec(const char text[], U16CPU len) { Rec* rec; - if (len == 0) + if (len == 0) { rec = const_cast<Rec*>(&gEmptyRec); - else - { + } else { // add 1 for terminating 0, then align4 so we can have some slop when growing the string rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1)); rec->fLength = SkToU16(len); rec->fRefCnt = 1; - if (text) + if (text) { memcpy(rec->data(), text, len); + } rec->data()[len] = 0; } return rec; } -SkString::Rec* SkString::RefRec(Rec* src) -{ - if (src != &gEmptyRec) - { +SkString::Rec* SkString::RefRec(Rec* src) { + if (src != &gEmptyRec) { if (src->fRefCnt == kMaxRefCnt_SkString) { src = AllocRec(src->data(), src->fLength); - } else + } else { src->fRefCnt += 1; + } } return src; } #ifdef SK_DEBUG -void SkString::validate() const -{ +void SkString::validate() const { // make sure know one has written over our global SkASSERT(gEmptyRec.fLength == 0); SkASSERT(gEmptyRec.fRefCnt == 0); SkASSERT(gEmptyRec.data()[0] == 0); - if (fRec != &gEmptyRec) - { + if (fRec != &gEmptyRec) { SkASSERT(fRec->fLength > 0); SkASSERT(fRec->fRefCnt > 0); SkASSERT(fRec->data()[fRec->fLength] == 0); @@ -247,7 +240,7 @@ void SkString::validate() const } #endif -/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) { #ifdef SK_DEBUG @@ -255,8 +248,7 @@ SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) { #endif } -SkString::SkString(size_t len) -{ +SkString::SkString(size_t len) { SkASSERT(SkToU16(len) == len); // can't handle larger than 64K fRec = AllocRec(NULL, (U16CPU)len); @@ -265,8 +257,7 @@ SkString::SkString(size_t len) #endif } -SkString::SkString(const char text[]) -{ +SkString::SkString(const char text[]) { size_t len = text ? strlen(text) : 0; fRec = AllocRec(text, (U16CPU)len); @@ -275,16 +266,14 @@ SkString::SkString(const char text[]) #endif } -SkString::SkString(const char text[], size_t len) -{ +SkString::SkString(const char text[], size_t len) { fRec = AllocRec(text, (U16CPU)len); #ifdef SK_DEBUG fStr = fRec->data(); #endif } -SkString::SkString(const SkString& src) -{ +SkString::SkString(const SkString& src) { src.validate(); fRec = RefRec(src.fRec); @@ -293,56 +282,49 @@ SkString::SkString(const SkString& src) #endif } -SkString::~SkString() -{ +SkString::~SkString() { this->validate(); - if (fRec->fLength) - { + if (fRec->fLength) { SkASSERT(fRec->fRefCnt > 0); - if (--fRec->fRefCnt == 0) + if (--fRec->fRefCnt == 0) { sk_free(fRec); + } } } -bool SkString::equals(const SkString& src) const -{ +bool SkString::equals(const SkString& src) const { return fRec == src.fRec || this->equals(src.c_str(), src.size()); } -bool SkString::equals(const char text[]) const -{ +bool SkString::equals(const char text[]) const { return this->equals(text, text ? strlen(text) : 0); } -bool SkString::equals(const char text[], size_t len) const -{ +bool SkString::equals(const char text[], size_t len) const { SkASSERT(len == 0 || text != NULL); return fRec->fLength == len && !memcmp(fRec->data(), text, len); } -SkString& SkString::operator=(const SkString& src) -{ +SkString& SkString::operator=(const SkString& src) { this->validate(); - if (fRec != src.fRec) - { + if (fRec != src.fRec) { SkString tmp(src); this->swap(tmp); } return *this; } -void SkString::reset() -{ +void SkString::reset() { this->validate(); - if (fRec->fLength) - { + if (fRec->fLength) { SkASSERT(fRec->fRefCnt > 0); - if (--fRec->fRefCnt == 0) + if (--fRec->fRefCnt == 0) { sk_free(fRec); + } } fRec = const_cast<Rec*>(&gEmptyRec); @@ -351,14 +333,11 @@ void SkString::reset() #endif } -char* SkString::writable_str() -{ +char* SkString::writable_str() { this->validate(); - if (fRec->fLength) - { - if (fRec->fRefCnt > 1) - { + if (fRec->fLength) { + if (fRec->fRefCnt > 1) { fRec->fRefCnt -= 1; fRec = AllocRec(fRec->data(), fRec->fLength); #ifdef SK_DEBUG @@ -369,86 +348,79 @@ char* SkString::writable_str() return fRec->data(); } -void SkString::set(const char text[]) -{ +void SkString::set(const char text[]) { this->set(text, text ? strlen(text) : 0); } -void SkString::set(const char text[], size_t len) -{ - if (len == 0) +void SkString::set(const char text[], size_t len) { + if (len == 0) { this->reset(); - else if (fRec->fRefCnt == 1 && len <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) - { + } else if (fRec->fRefCnt == 1 && len <= fRec->fLength) { + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))? // just use less of the buffer without allocating a smaller one char* p = this->writable_str(); - if (text) + if (text) { memcpy(p, text, len); + } p[len] = 0; fRec->fLength = SkToU16(len); - } - else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2)) - { + } else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2)) { // we have spare room in the current allocation, so don't alloc a larger one char* p = this->writable_str(); - if (text) + if (text) { memcpy(p, text, len); + } p[len] = 0; fRec->fLength = SkToU16(len); - } - else - { + } else { SkString tmp(text, len); this->swap(tmp); } } -void SkString::setUTF16(const uint16_t src[]) -{ +void SkString::setUTF16(const uint16_t src[]) { int count = 0; - while (src[count]) + while (src[count]) { count += 1; + } setUTF16(src, count); } -void SkString::setUTF16(const uint16_t src[], size_t count) -{ - if (count == 0) +void SkString::setUTF16(const uint16_t src[], size_t count) { + if (count == 0) { this->reset(); - else if (count <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) - { - if (count < fRec->fLength) + } else if (count <= fRec->fLength) { + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) + if (count < fRec->fLength) { this->resize(count); + } char* p = this->writable_str(); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { p[i] = SkToU8(src[i]); + } p[count] = 0; - } - else - { - SkString tmp(count); // puts a null terminator at the end of the string - char* p = tmp.writable_str(); + } else { + SkString tmp(count); // puts a null terminator at the end of the string + char* p = tmp.writable_str(); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { p[i] = SkToU8(src[i]); - + } this->swap(tmp); } } -void SkString::insert(size_t offset, const char text[]) -{ +void SkString::insert(size_t offset, const char text[]) { this->insert(offset, text, text ? strlen(text) : 0); } -void SkString::insert(size_t offset, const char text[], size_t len) -{ - if (len) - { +void SkString::insert(size_t offset, const char text[], size_t len) { + if (len) { size_t length = fRec->fLength; - if (offset > length) + if (offset > length) { offset = length; + } /* If we're the only owner, and we have room in our allocation for the insert, do it in place, rather than allocating a new buffer. @@ -460,61 +432,59 @@ void SkString::insert(size_t offset, const char text[], size_t len) which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 and we can then eliminate the +1+3 since that doesn't affec the answer */ - if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2)) - { + if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2)) { char* dst = this->writable_str(); - if (offset < length) + if (offset < length) { memmove(dst + offset + len, dst + offset, length - offset); + } memcpy(dst + offset, text, len); dst[length + len] = 0; fRec->fLength = SkToU16(length + len); - } - else - { + } else { /* Seems we should use realloc here, since that is safe if it fails (we have the original data), and might be faster than alloc/copy/free. */ SkString tmp(fRec->fLength + len); char* dst = tmp.writable_str(); - if (offset > 0) + if (offset > 0) { memcpy(dst, fRec->data(), offset); + } memcpy(dst + offset, text, len); - if (offset < fRec->fLength) - memcpy(dst + offset + len, fRec->data() + offset, fRec->fLength - offset); + if (offset < fRec->fLength) { + memcpy(dst + offset + len, fRec->data() + offset, + fRec->fLength - offset); + } this->swap(tmp); } } } -void SkString::insertUnichar(size_t offset, SkUnichar uni) -{ +void SkString::insertUnichar(size_t offset, SkUnichar uni) { char buffer[kMaxBytesInUTF8Sequence]; size_t len = SkUTF8_FromUnichar(uni, buffer); - if (len) + if (len) { this->insert(offset, buffer, len); + } } -void SkString::insertS32(size_t offset, int32_t dec) -{ +void SkString::insertS32(size_t offset, int32_t dec) { char buffer[SkStrAppendS32_MaxSize]; char* stop = SkStrAppendS32(buffer, dec); this->insert(offset, buffer, stop - buffer); } -void SkString::insertS64(size_t offset, int64_t dec, int minDigits) -{ +void SkString::insertS64(size_t offset, int64_t dec, int minDigits) { char buffer[SkStrAppendS64_MaxSize]; char* stop = SkStrAppendS64(buffer, dec, minDigits); this->insert(offset, buffer, stop - buffer); } -void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) -{ +void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) { minDigits = SkPin32(minDigits, 0, 8); static const char gHex[] = "0123456789ABCDEF"; @@ -527,15 +497,16 @@ void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) hex >>= 4; minDigits -= 1; } while (hex != 0); - while (--minDigits >= 0) + + while (--minDigits >= 0) { *--p = '0'; + } SkASSERT(p >= buffer); this->insert(offset, p, buffer + sizeof(buffer) - p); } -void SkString::insertScalar(size_t offset, SkScalar value) -{ +void SkString::insertScalar(size_t offset, SkScalar value) { char buffer[SkStrAppendScalar_MaxSize]; char* stop = SkStrAppendScalar(buffer, value); this->insert(offset, buffer, stop - buffer); @@ -566,30 +537,26 @@ void SkString::prependf(const char format[], ...) { /////////////////////////////////////////////////////////////////////////////// -void SkString::remove(size_t offset, size_t length) -{ +void SkString::remove(size_t offset, size_t length) { size_t size = this->size(); - if (offset < size) - { - if (offset + length > size) + if (offset < size) { + if (offset + length > size) { length = size - offset; - if (length > 0) - { + } + if (length > 0) { SkASSERT(size > length); SkString tmp(size - length); char* dst = tmp.writable_str(); const char* src = this->c_str(); - if (offset) - { + if (offset) { SkASSERT(offset <= tmp.size()); memcpy(dst, src, offset); } size_t tail = size - offset - length; SkASSERT((int32_t)tail >= 0); - if (tail) - { + if (tail) { // SkASSERT(offset + length <= tmp.size()); memcpy(dst + offset, src + offset + length, tail); } @@ -599,8 +566,7 @@ void SkString::remove(size_t offset, size_t length) } } -void SkString::swap(SkString& other) -{ +void SkString::swap(SkString& other) { this->validate(); other.validate(); @@ -610,25 +576,23 @@ void SkString::swap(SkString& other) #endif } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkAutoUCS2::SkAutoUCS2(const char utf8[]) -{ +SkAutoUCS2::SkAutoUCS2(const char utf8[]) { size_t len = strlen(utf8); fUCS2 = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t)); uint16_t* dst = fUCS2; - for (;;) - { - SkUnichar uni = SkUTF8_NextUnichar(&utf8); + for (;;) { + SkUnichar uni = SkUTF8_NextUnichar(&utf8); *dst++ = SkToU16(uni); - if (uni == 0) + if (uni == 0) { break; + } } fCount = (int)(dst - fUCS2); } -SkAutoUCS2::~SkAutoUCS2() -{ - delete[] fUCS2; +SkAutoUCS2::~SkAutoUCS2() { + sk_free(fUCS2); } diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 7eeaf19..9a764fc 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "SkAdvancedTypefaceMetrics.h" #include "SkTypeface.h" #include "SkFontHost.h" @@ -76,6 +77,6 @@ SkTypeface* SkTypeface::Deserialize(SkStream* stream) { } SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics( - bool perGlyphInfo) const { + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const { return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID, perGlyphInfo); } diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp index 9fb85c2..6aa57ee 100644 --- a/src/core/SkUtils.cpp +++ b/src/core/SkUtils.cpp @@ -43,18 +43,17 @@ } while (0) #endif -/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) -{ +void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) { SkASSERT(dst != NULL && count >= 0); - if (count <= 0) + if (count <= 0) { return; + } // not sure if this helps to short-circuit on small values of count - if (count < 8) - { + if (count < 8) { do { *dst++ = (uint16_t)value; } while (--count != 0); @@ -62,8 +61,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) } // ensure we're on a long boundary - if ((size_t)dst & 2) - { + if ((size_t)dst & 2) { *dst++ = (uint16_t)value; count -= 1; } @@ -73,8 +71,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) // handle the bulk with our unrolled macro { int sixteenlongs = count >> 5; - if (sixteenlongs) - { + if (sixteenlongs) { uint32_t* dst32 = (uint32_t*)dst; do { assign_16_longs(dst32, value32); @@ -87,8 +84,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) // handle (most) of the rest { int longs = count >> 1; - if (longs) - { + if (longs) { do { *(uint32_t*)dst = value32; dst += 2; @@ -97,27 +93,23 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) } // cleanup a possible trailing short - if (count & 1) + if (count & 1) { *dst = (uint16_t)value; + } } -void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) -{ +void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) { SkASSERT(dst != NULL && count >= 0); - { - int sixteenlongs = count >> 4; - if (sixteenlongs) - { - do { - assign_16_longs(dst, value); - } while (--sixteenlongs != 0); - count &= 15; - } + int sixteenlongs = count >> 4; + if (sixteenlongs) { + do { + assign_16_longs(dst, value); + } while (--sixteenlongs != 0); + count &= 15; } - if (count) - { + if (count) { do { *dst++ = value; } while (--count != 0); @@ -125,8 +117,7 @@ void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) } #if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK) -static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) -{ +static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { SkMemset16Proc proc = SkMemset16GetPlatformProc(); sk_memset16 = proc ? proc : sk_memset16_portable; sk_memset16(dst, value, count); @@ -134,8 +125,7 @@ static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) SkMemset16Proc sk_memset16 = sk_memset16_stub; -static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) -{ +static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) { SkMemset32Proc proc = SkMemset32GetPlatformProc(); sk_memset32 = proc ? proc : sk_memset32_portable; sk_memset32(dst, value, count); @@ -145,7 +135,7 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; #endif -////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /* 0xxxxxxx 1 total 10xxxxxx // never a leading byte @@ -159,14 +149,12 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; */ #ifdef SK_DEBUG - static void assert_utf8_leadingbyte(unsigned c) - { + static void assert_utf8_leadingbyte(unsigned c) { SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes) SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char } - int SkUTF8_LeadByteToCount(unsigned c) - { + int SkUTF8_LeadByteToCount(unsigned c) { assert_utf8_leadingbyte(c); return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1; } @@ -174,41 +162,36 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; #define assert_utf8_leadingbyte(c) #endif -int SkUTF8_CountUnichars(const char utf8[]) -{ +int SkUTF8_CountUnichars(const char utf8[]) { SkASSERT(utf8); int count = 0; - for (;;) - { + for (;;) { int c = *(const uint8_t*)utf8; - if (c == 0) + if (c == 0) { break; - + } utf8 += SkUTF8_LeadByteToCount(c); count += 1; } return count; } -int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) -{ +int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) { SkASSERT(NULL != utf8 || 0 == byteLength); int count = 0; const char* stop = utf8 + byteLength; - while (utf8 < stop) - { + while (utf8 < stop) { utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); count += 1; } return count; } -SkUnichar SkUTF8_ToUnichar(const char utf8[]) -{ +SkUnichar SkUTF8_ToUnichar(const char utf8[]) { SkASSERT(NULL != utf8); const uint8_t* p = (const uint8_t*)utf8; @@ -217,8 +200,7 @@ SkUnichar SkUTF8_ToUnichar(const char utf8[]) assert_utf8_leadingbyte(c); - if (hic < 0) - { + if (hic < 0) { uint32_t mask = (uint32_t)~0x3F; hic <<= 1; do { @@ -230,8 +212,7 @@ SkUnichar SkUTF8_ToUnichar(const char utf8[]) return c; } -SkUnichar SkUTF8_NextUnichar(const char** ptr) -{ +SkUnichar SkUTF8_NextUnichar(const char** ptr) { SkASSERT(NULL != ptr && NULL != *ptr); const uint8_t* p = (const uint8_t*)*ptr; @@ -240,8 +221,7 @@ SkUnichar SkUTF8_NextUnichar(const char** ptr) assert_utf8_leadingbyte(c); - if (hic < 0) - { + if (hic < 0) { uint32_t mask = (uint32_t)~0x3F; hic <<= 1; do { @@ -254,32 +234,31 @@ SkUnichar SkUTF8_NextUnichar(const char** ptr) return c; } -SkUnichar SkUTF8_PrevUnichar(const char** ptr) -{ +SkUnichar SkUTF8_PrevUnichar(const char** ptr) { SkASSERT(NULL != ptr && NULL != *ptr); const char* p = *ptr; - if (*--p & 0x80) - while (*--p & 0x40) + if (*--p & 0x80) { + while (*--p & 0x40) { ; + } + } *ptr = (char*)p; return SkUTF8_NextUnichar(&p); } -size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) -{ - if ((uint32_t)uni > 0x10FFFF) - { +size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) { + if ((uint32_t)uni > 0x10FFFF) { SkASSERT(!"bad unichar"); return 0; } - if (uni <= 127) - { - if (utf8) + if (uni <= 127) { + if (utf8) { *utf8 = (char)uni; + } return 1; } @@ -289,19 +268,18 @@ size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) SkDEBUGCODE(SkUnichar orig = uni;) - while (uni > 0x7F >> count) - { + while (uni > 0x7F >> count) { *p++ = (char)(0x80 | (uni & 0x3F)); uni >>= 6; count += 1; } - if (utf8) - { + if (utf8) { p = tmp; utf8 += count; - while (p < tmp + count - 1) + while (p < tmp + count - 1) { *--utf8 = *p++; + } *--utf8 = (char)(~(0xFF >> count) | uni); } @@ -309,19 +287,16 @@ size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) return count; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -int SkUTF16_CountUnichars(const uint16_t src[]) -{ +int SkUTF16_CountUnichars(const uint16_t src[]) { SkASSERT(src); int count = 0; unsigned c; - while ((c = *src++) != 0) - { + while ((c = *src++) != 0) { SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { c = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c)); } @@ -330,18 +305,15 @@ int SkUTF16_CountUnichars(const uint16_t src[]) return count; } -int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) -{ +int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { SkASSERT(src); const uint16_t* stop = src + numberOf16BitValues; int count = 0; - while (src < stop) - { + while (src < stop) { unsigned c = *src++; SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { SkASSERT(src < stop); c = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c)); @@ -351,16 +323,14 @@ int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) return count; } -SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) -{ +SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { SkASSERT(srcPtr && *srcPtr); const uint16_t* src = *srcPtr; SkUnichar c = *src++; SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { unsigned c2 = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c2)); @@ -372,16 +342,14 @@ SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) return c; } -SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) -{ +SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) { SkASSERT(srcPtr && *srcPtr); const uint16_t* src = *srcPtr; SkUnichar c = *--src; SkASSERT(!SkUTF16_IsHighSurrogate(c)); - if (SkUTF16_IsLowSurrogate(c)) - { + if (SkUTF16_IsLowSurrogate(c)) { unsigned c2 = *--src; SkASSERT(SkUTF16_IsHighSurrogate(c2)); c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00); @@ -390,16 +358,13 @@ SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) return c; } -size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) -{ +size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) { SkASSERT((unsigned)uni <= 0x10FFFF); int extra = (uni > 0xFFFF); - if (dst) - { - if (extra) - { + if (dst) { + if (extra) { // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10)); // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64)); dst[0] = SkToU16((0xD800 - 64) + (uni >> 10)); @@ -407,9 +372,7 @@ size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) SkASSERT(SkUTF16_IsHighSurrogate(dst[0])); SkASSERT(SkUTF16_IsLowSurrogate(dst[1])); - } - else - { + } else { dst[0] = SkToU16(uni); SkASSERT(!SkUTF16_IsHighSurrogate(dst[0])); SkASSERT(!SkUTF16_IsLowSurrogate(dst[0])); @@ -418,46 +381,44 @@ size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) return 1 + extra; } -size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8[]) -{ +size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, + char utf8[]) { SkASSERT(numberOf16BitValues >= 0); - if (numberOf16BitValues <= 0) + if (numberOf16BitValues <= 0) { return 0; + } SkASSERT(utf16 != NULL); const uint16_t* stop = utf16 + numberOf16BitValues; size_t size = 0; - if (utf8 == NULL) // just count - { - while (utf16 < stop) + if (utf8 == NULL) { // just count + while (utf16 < stop) { size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL); - } - else - { + } + } else { char* start = utf8; - while (utf16 < stop) + while (utf16 < stop) { utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8); + } size = utf8 - start; } return size; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #include <stdlib.h> #if 0 -static int round_to_K(size_t bytes) -{ +static int round_to_K(size_t bytes) { return (bytes + 512) >> 10; } #endif SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[]) - : fLabel(label) -{ + : fLabel(label) { #if 0 struct mallinfo mi = mallinfo(); @@ -465,14 +426,14 @@ SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[]) #endif } -SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() -{ +SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() { #if 0 struct mallinfo mi = mallinfo(); printf("SkAutoMemoryUsageProbe "); - if (fLabel) + if (fLabel) { printf("<%s> ", fLabel); + } printf("delta %dK, current total allocated %dK\n", round_to_K(mi.uordblks - fBytesAllocated), round_to_K(mi.uordblks)); diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index a5b9f13..110ccb3 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -448,8 +448,8 @@ static const ProcCoeff gProcCoeffs[] = { { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, - { plus_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, - { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, + { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, diff --git a/src/core/core_files.mk b/src/core/core_files.mk index 252644e..b3427b0 100644 --- a/src/core/core_files.mk +++ b/src/core/core_files.mk @@ -56,6 +56,7 @@ SOURCE := \ SkMath.cpp \ SkMatrix.cpp \ SkMemory_stdlib.cpp \ + SkMetaData.cpp \ SkPackBits.cpp \ SkPaint.cpp \ SkPath.cpp \ diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp index 9585112..bde04ed 100644 --- a/src/effects/SkBlurDrawLooper.cpp +++ b/src/effects/SkBlurDrawLooper.cpp @@ -7,11 +7,10 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags) - : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) -{ + : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) { + SkASSERT(flags <= kAll_BlurFlag); - if (radius > 0) - { + if (radius > 0) { uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ? SkBlurMaskFilter::kIgnoreTransform_BlurFlag : SkBlurMaskFilter::kNone_BlurFlag; @@ -23,28 +22,23 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, fBlur = SkBlurMaskFilter::Create(radius, SkBlurMaskFilter::kNormal_BlurStyle, blurFlags); - } - else - { + } else { fBlur = NULL; } - if (flags & kOverrideColor_BlurFlag) - { + if (flags & kOverrideColor_BlurFlag) { // Set alpha to 1 for the override since transparency will already // be baked into the blurred mask. SkColor opaqueColor = SkColorSetA(color, 255); //The SrcIn xfer mode will multiply 'color' by the incoming alpha - fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode); - } - else - { + fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, + SkXfermode::kSrcIn_Mode); + } else { fColorFilter = NULL; } } -SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) -{ +SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) { fDx = buffer.readScalar(); fDy = buffer.readScalar(); fBlurColor = buffer.readU32(); @@ -53,14 +47,12 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) fBlurFlags = buffer.readU32() & kAll_BlurFlag; } -SkBlurDrawLooper::~SkBlurDrawLooper() -{ +SkBlurDrawLooper::~SkBlurDrawLooper() { SkSafeUnref(fBlur); SkSafeUnref(fColorFilter); } -void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) -{ +void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) { buffer.writeScalar(fDx); buffer.writeScalar(fDy); buffer.write32(fBlurColor); @@ -69,70 +61,47 @@ void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) buffer.write32(fBlurFlags); } -void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint) -{ - // we do nothing if a maskfilter is already installed - if (paint->getMaskFilter() != NULL) - fState = kDone; - else - { - fState = kBeforeEdge; - fPaint = paint; - fCanvas = canvas; - fSaveCount = canvas->getSaveCount(); - } +void SkBlurDrawLooper::init(SkCanvas* canvas) { + fState = kBeforeEdge; } -bool SkBlurDrawLooper::next() -{ - SkColor blurColor; - SkAlpha alpha; +bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { switch (fState) { - case kBeforeEdge: - fSavedColor = fPaint->getColor(); - blurColor = fBlurColor; - alpha = SkColorGetA(blurColor); - if (alpha == 255) { - blurColor = SkColorSetA(blurColor, fPaint->getAlpha()); - } - fPaint->setColor(blurColor); - fPaint->setMaskFilter(fBlur); - fPaint->setColorFilter(fColorFilter); - fCanvas->save(SkCanvas::kMatrix_SaveFlag); - if (fBlurFlags & kIgnoreTransform_BlurFlag) - { - SkMatrix transform(fCanvas->getTotalMatrix()); - transform.postTranslate(fDx, fDy); - fCanvas->setMatrix(transform); - } - else - { - fCanvas->translate(fDx, fDy); - } - fState = kAfterEdge; - return true; - case kAfterEdge: - fPaint->setColor(fSavedColor); - fPaint->setMaskFilter(NULL); - fPaint->setColorFilter(NULL); - fCanvas->restore(); // to remove the translate we did earlier - fState = kDone; - return true; - default: - SkASSERT(kDone == fState); - return false; - } -} - -void SkBlurDrawLooper::restore() -{ - if (kAfterEdge == fState) - { - fPaint->setColor(fSavedColor); - fPaint->setMaskFilter(NULL); - fPaint->setColorFilter(NULL); - fCanvas->restore(); // to remove the translate we did earlier - fState = kDone; + case kBeforeEdge: + // we do nothing if a maskfilter is already installed + if (paint->getMaskFilter()) { + fState = kDone; + return false; + } +#ifdef ANDROID + SkColor blurColor; + blurColor = fBlurColor; + if (SkColorGetA(blurColor) == 255) { + blurColor = SkColorSetA(blurColor, paint->getAlpha()); + } + paint->setColor(blurColor); +#else + paint->setColor(fBlurColor); +#endif + paint->setMaskFilter(fBlur); + paint->setColorFilter(fColorFilter); + canvas->save(SkCanvas::kMatrix_SaveFlag); + if (fBlurFlags & kIgnoreTransform_BlurFlag) { + SkMatrix transform(canvas->getTotalMatrix()); + transform.postTranslate(fDx, fDy); + canvas->setMatrix(transform); + } else { + canvas->translate(fDx, fDy); + } + fState = kAfterEdge; + return true; + case kAfterEdge: + canvas->restore(); + fState = kDone; + return true; + default: + SkASSERT(kDone == fState); + return false; } } diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index 3452212..dca87b0 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -1397,9 +1397,13 @@ public: SkScalarSquare(fDiff.fY)); } if (matrix) { - SkScalar invDiffL = SkScalarInvert(diffL); - matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY), - SkScalarMul(invDiffL, fDiff.fX)); + if (diffL) { + SkScalar invDiffL = SkScalarInvert(diffL); + matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY), + SkScalarMul(invDiffL, fDiff.fX)); + } else { + matrix->reset(); + } matrix->preConcat(fPtsToUnit); } if (xy) { diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp index f2d8ba8..b3f3886 100644 --- a/src/effects/SkLayerDrawLooper.cpp +++ b/src/effects/SkLayerDrawLooper.cpp @@ -1,6 +1,15 @@ #include "SkCanvas.h" +#include "SkColor.h" #include "SkLayerDrawLooper.h" #include "SkPaint.h" +#include "SkUnPreMultiply.h" + +SkLayerDrawLooper::LayerInfo::LayerInfo() { + fPaintBits = 0; // ignore out paint + fColorMode = SkXfermode::kDst_Mode; // ignore our color + fOffset.set(0, 0); + fPostTranslate = false; +} SkLayerDrawLooper::SkLayerDrawLooper() { fRecs = NULL; @@ -15,43 +24,128 @@ SkLayerDrawLooper::~SkLayerDrawLooper() { rec = next; } } - -SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { + +SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) { fCount += 1; Rec* rec = SkNEW(Rec); rec->fNext = fRecs; - rec->fOffset.set(dx, dy); + rec->fInfo = info; fRecs = rec; return &rec->fPaint; } -void SkLayerDrawLooper::init(SkCanvas* canvas, SkPaint* paint) { - fIter.fSavedPaint = *paint; - fIter.fPaint = paint; - fIter.fCanvas = canvas; - fIter.fRec = fRecs; +SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { + LayerInfo info; + + info.fOffset.set(dx, dy); + return this->addLayer(info); +} + +void SkLayerDrawLooper::init(SkCanvas* canvas) { + fCurrRec = fRecs; canvas->save(SkCanvas::kMatrix_SaveFlag); } -bool SkLayerDrawLooper::next() { - Rec* rec = fIter.fRec; - if (rec) { - *fIter.fPaint = rec->fPaint; - fIter.fCanvas->restore(); - fIter.fCanvas->save(SkCanvas::kMatrix_SaveFlag); - fIter.fCanvas->translate(rec->fOffset.fX, rec->fOffset.fY); +static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { + switch (mode) { + case SkXfermode::kSrc_Mode: + return src; + case SkXfermode::kDst_Mode: + return dst; + default: { + SkPMColor pmS = SkPreMultiplyColor(src); + SkPMColor pmD = SkPreMultiplyColor(dst); + SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); + return SkUnPreMultiply::PMColorToColor(result); + } + } +} + +void SkLayerDrawLooper::ApplyBits(SkPaint* dst, const SkPaint& src, + BitFlags bits, SkXfermode::Mode colorMode) { + dst->setColor(xferColor(src.getColor(), dst->getColor(), colorMode)); + + if (0 == bits) { + return; + } + if (kEntirePaint_Bits == bits) { + // we've already compute the color, so save it from the assignment + SkColor c = dst->getColor(); + *dst = src; + dst->setColor(c); + return; + } + + if (bits & kStyle_Bit) { + dst->setStyle(src.getStyle()); + dst->setStrokeWidth(src.getStrokeWidth()); + dst->setStrokeMiter(src.getStrokeMiter()); + dst->setStrokeCap(src.getStrokeCap()); + dst->setStrokeJoin(src.getStrokeJoin()); + } + + if (bits & kTextSkewX_Bit) { + dst->setTextSkewX(src.getTextSkewX()); + } - fIter.fRec = rec->fNext; - return true; + if (bits & kPathEffect_Bit) { + dst->setPathEffect(src.getPathEffect()); + } + if (bits & kMaskFilter_Bit) { + dst->setMaskFilter(src.getMaskFilter()); + } + if (bits & kShader_Bit) { + dst->setShader(src.getShader()); } - return false; + if (bits & kColorFilter_Bit) { + dst->setColorFilter(src.getColorFilter()); + } + if (bits & kXfermode_Bit) { + dst->setXfermode(src.getXfermode()); + } + + // we never copy these +#if 0 + dst->setFlags(src.getFlags()); + dst->setTypeface(src.getTypeface()); + dst->setTextSize(src.getTextSize()); + dst->setTextScaleX(src.getTextScaleX()); + dst->setTextSkewX(src.getTextSkewX()); + dst->setRasterizer(src.getRasterizer()); + dst->setLooper(src.getLooper()); + dst->setTextEncoding(src.getTextEncoding()); + dst->setHinting(src.getHinting()); +#endif } -void SkLayerDrawLooper::restore() { - fIter.fCanvas->restore(); - *fIter.fPaint = fIter.fSavedPaint; +// Should we add this to canvas? +static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { + SkMatrix m = canvas->getTotalMatrix(); + m.postTranslate(dx, dy); + canvas->setMatrix(m); +} + +bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { + canvas->restore(); + if (NULL == fCurrRec) { + return false; + } + + ApplyBits(paint, fCurrRec->fPaint, fCurrRec->fInfo.fPaintBits, + fCurrRec->fInfo.fColorMode); + + canvas->save(SkCanvas::kMatrix_SaveFlag); + if (fCurrRec->fInfo.fPostTranslate) { + postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, + fCurrRec->fInfo.fOffset.fY); + } else { + canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY); + } + fCurrRec = fCurrRec->fNext; + + return true; } SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) { @@ -87,8 +181,11 @@ void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) { Rec* rec = fRecs; for (int i = 0; i < fCount; i++) { - buffer.writeScalar(rec->fOffset.fX); - buffer.writeScalar(rec->fOffset.fY); + buffer.writeInt(rec->fInfo.fPaintBits); + buffer.writeInt(rec->fInfo.fColorMode); + buffer.writeScalar(rec->fInfo.fOffset.fX); + buffer.writeScalar(rec->fInfo.fOffset.fY); + buffer.writeBool(rec->fInfo.fPostTranslate); rec->fPaint.flatten(buffer); rec = rec->fNext; } @@ -102,9 +199,13 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer) int count = buffer.readInt(); for (int i = 0; i < count; i++) { - SkScalar dx = buffer.readScalar(); - SkScalar dy = buffer.readScalar(); - this->addLayer(dx, dy)->unflatten(buffer); + LayerInfo info; + info.fPaintBits = buffer.readInt(); + info.fColorMode = (SkXfermode::Mode)buffer.readInt(); + info.fOffset.fX = buffer.readScalar(); + info.fOffset.fY = buffer.readScalar(); + info.fPostTranslate = buffer.readBool(); + this->addLayer(info)->unflatten(buffer); } SkASSERT(count == fCount); diff --git a/src/effects/SkPaintFlagsDrawFilter.cpp b/src/effects/SkPaintFlagsDrawFilter.cpp index ed2df88..62eb53a 100644 --- a/src/effects/SkPaintFlagsDrawFilter.cpp +++ b/src/effects/SkPaintFlagsDrawFilter.cpp @@ -2,21 +2,12 @@ #include "SkPaint.h" SkPaintFlagsDrawFilter::SkPaintFlagsDrawFilter(uint32_t clearFlags, - uint32_t setFlags) -{ + uint32_t setFlags) { fClearFlags = SkToU16(clearFlags & SkPaint::kAllFlags); fSetFlags = SkToU16(setFlags & SkPaint::kAllFlags); } -bool SkPaintFlagsDrawFilter::filter(SkCanvas*, SkPaint* paint, Type) -{ - fPrevFlags = paint->getFlags(); - paint->setFlags((fPrevFlags & ~fClearFlags) | fSetFlags); - return true; +void SkPaintFlagsDrawFilter::filter(SkPaint* paint, Type) { + paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags); } -void SkPaintFlagsDrawFilter::restore(SkCanvas*, SkPaint* paint, Type) -{ - paint->setFlags(fPrevFlags); -} - diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 3707b67..723c635 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -24,6 +24,7 @@ #include "SkDrawProcs.h" #include "SkGlyphCache.h" +#include "SkUtils.h" #define CACHE_LAYER_TEXTURES 1 @@ -171,11 +172,15 @@ SkGpuDevice::SkGpuDevice(GrContext* context, this->width(), this->height()); GrAssert(false); } - } else if (Current3DApiRenderTarget() == renderTargetOrNull) { - fRenderTarget = fContext->createRenderTargetFrom3DApiState(); } else { - fRenderTarget = renderTargetOrNull; - fRenderTarget->ref(); + if (Current3DApiRenderTarget() == renderTargetOrNull) { + fRenderTarget = fContext->createRenderTargetFrom3DApiState(); + } else { + fRenderTarget = renderTargetOrNull; + fRenderTarget->ref(); + } + SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget); + this->setPixelRef(pr, 0)->unref(); } } @@ -232,16 +237,15 @@ bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { return false; } - SkAutoLockPixels alp(tmp); - fContext->setRenderTarget(fRenderTarget); - // we aren't setting the clip or matrix, so mark as dirty - // we don't need to set them for this call and don't have them anyway - fNeedPrepareRenderTarget = true; + tmp.lockPixels(); - if (!fContext->readPixels(bounds.fLeft, bounds.fTop, - bounds.width(), bounds.height(), - GrTexture::kRGBA_8888_PixelConfig, - tmp.getPixels())) { + bool read = fContext->readRenderTargetPixels(fRenderTarget, + bounds.fLeft, bounds.fTop, + bounds.width(), bounds.height(), + kRGBA_8888_GrPixelConfig, + tmp.getPixels()); + tmp.unlockPixels(); + if (!read) { return false; } @@ -254,8 +258,8 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) { if (!bitmap.readyToDraw()) { return; } - GrTexture::PixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(), - bitmap.isOpaque()); + GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(), + bitmap.isOpaque()); fContext->setRenderTarget(fRenderTarget); // we aren't setting the clip or matrix, so mark as dirty // we don't need to set them for this call and don't have them anyway @@ -305,8 +309,8 @@ void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) { void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip, const SkClipStack& clipStack) { this->INHERITED::setMatrixClip(matrix, clip, clipStack); - - convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin()); + // We don't need to set them now because the context may not reflect this device. + fNeedPrepareRenderTarget = true; } void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix, @@ -643,37 +647,180 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, #endif } +/////////////////////////////////////////////////////////////////////////////// + +static void setInsetFan(GrPoint pts[4], const GrRect& r, + GrScalar dx, GrScalar dy) { + pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy); +} + +static GrColor getColorForMesh(const GrPaint& paint) { + if (NULL == paint.getTexture()) { + return paint.fColor; + } else { + unsigned a = GrColorUnpackA(paint.fColor); + return GrColorPackRGBA(a, a, a, a); + } +} + +static const uint16_t gFillAARectIdx1[] = { + 0, 1, 5, 5, 4, 0, + 1, 2, 6, 6, 5, 1, + 2, 3, 7, 7, 6, 2, + 3, 0, 4, 4, 7, 3, + 4, 5, 6, 6, 7, 4, +}; + +static void fillDevAARect(GrContext* ctx, const GrPaint& paint, + const GrRect& rect) { + if (rect.isEmpty()) { + return; + } + + GrAutoMatrix avm(ctx, GrMatrix::I()); + + GrPoint verts[8]; + GrPoint* texs = NULL; + GrColor colors[8]; + + setInsetFan(&verts[ 0], rect, -0.5f, -0.5f); + setInsetFan(&verts[ 4], rect, 0.5f, 0.5f); + + sk_memset32(&colors[ 0], 0, 4); + sk_memset32(&colors[ 4], getColorForMesh(paint), 4); + + ctx->drawVertices(paint, kTriangles_PrimitiveType, + 8, verts, texs, colors, + gFillAARectIdx1, SK_ARRAY_COUNT(gFillAARectIdx1)); +} + +static const uint16_t gStrokeAARectIdx[] = { + 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, + 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, + 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, + 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, + + 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, + 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, + 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, + 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, + + 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, + 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, + 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, + 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, +}; + +static void strokeDevAARect(GrContext* ctx, const GrPaint& paint, + const GrRect& rect, const SkPoint& strokeSize) { + const GrScalar dx = SkScalarToGrScalar(strokeSize.fX); + const GrScalar dy = SkScalarToGrScalar(strokeSize.fY); + const GrScalar rx = dx * 0.5f; + const GrScalar ry = dy * 0.5f; + + GrScalar spare; + { + GrScalar w = rect.width() - dx; + GrScalar h = rect.height() - dy; + spare = GrMin(w, h); + } + + if (spare <= 0) { + GrRect r(rect); + r.inset(-rx, -ry); + fillDevAARect(ctx, paint, r); + return; + } + + GrAutoMatrix avm(ctx, GrMatrix::I()); + + GrPoint verts[16]; + GrPoint* texs = NULL; + GrColor colors[16]; + + setInsetFan(&verts[ 0], rect, -rx - 0.5f, -ry - 0.5f); + setInsetFan(&verts[ 4], rect, -rx + 0.5f, -ry + 0.5f); + setInsetFan(&verts[ 8], rect, rx - 0.5f, ry - 0.5f); + setInsetFan(&verts[12], rect, rx + 0.5f, ry + 0.5f); + + sk_memset32(&colors[ 0], 0, 4); + sk_memset32(&colors[ 4], getColorForMesh(paint), 8); + sk_memset32(&colors[12], 0, 4); + + ctx->drawVertices(paint, kTriangles_PrimitiveType, + 16, verts, texs, colors, + gStrokeAARectIdx, SK_ARRAY_COUNT(gStrokeAARectIdx)); +} + +/* + * If the paint has a texture, preconcat the ctx's inverse, since when we + * draw verts which are already in device coordinates, we need to "undo" that + * before we run our vertex shaders, which expect the coordinates to be local. + */ +static void preConcatInverseToTextureMatrix(GrContext* ctx, GrPaint* paint) { + if (paint->getTexture()) { + GrMatrix inverse; + if (ctx->getMatrix().invert(&inverse)) { + paint->fSampler.preConcatMatrix(inverse); + } + } +} + void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) { CHECK_SHOULD_DRAW(draw); - bool doStroke = paint.getStyle() == SkPaint::kStroke_Style; - SkScalar width = paint.getStrokeWidth(); + const SkMatrix& matrix = *draw.fMatrix; + SkPoint strokeSize; + SkDraw::RectType type = SkDraw::ComputeRectType(paint, matrix, &strokeSize); - /* - We have special code for hairline strokes, miter-strokes, and fills. - Anything else we just call our path code. - */ - bool usePath = doStroke && width > 0 && - paint.getStrokeJoin() != SkPaint::kMiter_Join; - // another reason we might need to call drawPath... - if (paint.getMaskFilter()) { - usePath = true; - } - - if (usePath) { + if (SkDraw::kPath_RectType == type) { SkPath path; path.addRect(rect); this->drawPath(draw, path, paint, NULL, true); - return; - } + } else { + GrPaint grPaint; + SkAutoCachedTexture act; + if (!this->skPaint2GrPaintShader(paint, &act, matrix, &grPaint)) { + return; + } - GrPaint grPaint; - SkAutoCachedTexture act; - if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) { - return; + bool doAA = paint.isAntiAlias(); + + if (SkDraw::kHair_RectType == type && doAA) { + strokeSize.set(SK_Scalar1, SK_Scalar1); + type = SkDraw::kStroke_RectType; + } + + switch (type) { + case SkDraw::kHair_RectType: + SkASSERT(!doAA); + fContext->drawRect(grPaint, Sk2Gr(rect), 0); + break; + case SkDraw::kFill_RectType: + if (doAA) { + SkRect devRect; + matrix.mapRect(&devRect, rect); + preConcatInverseToTextureMatrix(fContext, &grPaint); + fillDevAARect(fContext, grPaint, Sk2Gr(devRect)); + } else { + fContext->drawRect(grPaint, Sk2Gr(rect), -1); + } + break; + case SkDraw::kStroke_RectType: + if (doAA) { + SkRect devRect; + matrix.mapRect(&devRect, rect); + preConcatInverseToTextureMatrix(fContext, &grPaint); + strokeDevAARect(fContext, grPaint, Sk2Gr(devRect), strokeSize); + } else { + fContext->drawRect(grPaint, Sk2Gr(rect), paint.getStrokeWidth()); + } + break; + default: + SkASSERT(!"bad value for RectType"); + } } - fContext->drawRect(grPaint, Sk2Gr(rect), doStroke ? width : -1); } #include "SkMaskFilter.h" @@ -715,7 +862,7 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path, GrGpu::kNone_AALevel, dstM.fBounds.width(), dstM.fBounds.height(), - GrTexture::kAlpha_8_PixelConfig + kAlpha_8_GrPixelConfig }; GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage, @@ -771,7 +918,22 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) - if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { + // This "if" is not part of the SkDraw::drawPath() lift. + // When we get a 1.0 wide stroke we hairline stroke it instead of creating + // a new stroked-path. This is motivated by canvas2D sites that draw + // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated- + // hairline for width < 1.0 when AA is enabled. + static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask | + SkMatrix::kTranslate_Mask); + if (!paint.getPathEffect() && + SkPaint::kStroke_Style == paint.getStyle() && + !(draw.fMatrix->getType() & gMatrixMask) && + SK_Scalar1 == paint.getStrokeWidth()) { + doFill = false; + } + + if (doFill && (paint.getPathEffect() || + paint.getStyle() != SkPaint::kFill_Style)) { doFill = paint.getFillPath(*pathPtr, &tmpPath); pathPtr = &tmpPath; } @@ -1099,8 +1261,18 @@ static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state, if (NULL == procs->fFontScaler) { procs->fFontScaler = get_gr_font_scaler(state.fCache); } + + /* + * Skia calls us with fx,fy already biased by 1/2. It does this to speed + * up rounding these, so that all of its procs (like us) can just call + * SkFixedFloor and get the "rounded" value. + * + * We take advantage of that for fx, where we pass a rounded value, but + * we want the fractional fy, so we have to unbias it first. + */ procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0), - SkIntToFixed(SkFixedFloor(fx)), fy, + SkIntToFixed(SkFixedFloor(fx)), + fy - SK_FixedHalf, procs->fFontScaler); } @@ -1265,9 +1437,7 @@ void SkGpuDevice::unlockCachedTexture(TexCache* cache) { /////////////////////////////////////////////////////////////////////////////// SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, - GrRenderTarget* rootRenderTarget) - : fContext(context) { - + GrRenderTarget* rootRenderTarget) { GrAssert(NULL != context); GrAssert(NULL != rootRenderTarget); @@ -1280,13 +1450,32 @@ SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, fRootRenderTarget = rootRenderTarget; rootRenderTarget->ref(); } + + fContext = context; context->ref(); + fRootTexture = NULL; +} + +SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) { + GrAssert(NULL != context); + GrAssert(NULL != rootRenderTargetTexture); + GrAssert(NULL != rootRenderTargetTexture->asRenderTarget()); + + fRootTexture = rootRenderTargetTexture; + rootRenderTargetTexture->ref(); + + fRootRenderTarget = rootRenderTargetTexture->asRenderTarget(); + fRootRenderTarget->ref(); + + fContext = context; + context->ref(); } SkGpuDeviceFactory::~SkGpuDeviceFactory() { fContext->unref(); fRootRenderTarget->unref(); + GrSafeUnref(fRootTexture); } SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, @@ -1297,4 +1486,3 @@ SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, bm.setIsOpaque(isOpaque); return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget); } - diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index e57f88a..e7e2365 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -166,10 +166,9 @@ void SkGrClipIterator::reset(const SkClipStack& clipStack) { GrClipType SkGrClipIterator::getType() const { GrAssert(!this->isDone()); - if (NULL != fCurr->fRect) { + if (NULL == fCurr->fPath) { return kRect_ClipType; } else { - GrAssert(NULL != fCurr->fPath); return kPath_ClipType; } } @@ -214,30 +213,25 @@ GrPathFill SkGrClipIterator::getPathFill() const { /////////////////////////////////////////////////////////////////////////////// -GrTexture::PixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, +GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, bool isOpaque) { switch (config) { case SkBitmap::kA8_Config: - return GrTexture::kAlpha_8_PixelConfig; + return kAlpha_8_GrPixelConfig; case SkBitmap::kIndex8_Config: - return GrTexture::kIndex_8_PixelConfig; + return kIndex_8_GrPixelConfig; case SkBitmap::kRGB_565_Config: - return GrTexture::kRGB_565_PixelConfig; + return kRGB_565_GrPixelConfig; case SkBitmap::kARGB_4444_Config: - return GrTexture::kRGBA_4444_PixelConfig; + return kRGBA_4444_GrPixelConfig; case SkBitmap::kARGB_8888_Config: if (isOpaque) { - return GrTexture::kRGBX_8888_PixelConfig; + return kRGBX_8888_GrPixelConfig; } else { - return GrTexture::kRGBA_8888_PixelConfig; + return kRGBA_8888_GrPixelConfig; } default: - return GrTexture::kUnknown_PixelConfig; + return kUnknown_GrPixelConfig; } } -void SkGr::AbandonAllTextures(GrContext* ctx) { - ctx->abandonAllTextures(); -} - - diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp index 16e44b9..e58f035 100644 --- a/src/gpu/SkGrFontScaler.cpp +++ b/src/gpu/SkGrFontScaler.cpp @@ -86,6 +86,8 @@ SkGrFontScaler::~SkGrFontScaler() { GrMaskFormat SkGrFontScaler::getMaskFormat() { SkMask::Format format = fStrike->getMaskFormat(); switch (format) { + case SkMask::kBW_Format: + // fall through to kA8 -- we store BW glyphs in our 8-bit cache case SkMask::kA8_Format: return kA8_GrMaskFormat; case SkMask::kLCD16_Format: @@ -113,6 +115,18 @@ bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, } +static void bits_to_bytes(const uint8_t bits[], uint8_t bytes[], int count) { + while (count > 0) { + unsigned mask = *bits++; + for (int i = 7; i >= 0; --i) { + *bytes++ = (mask & (1 << i)) ? 0xFF : 0; + if (--count == 0) { + return; + } + } + } +} + bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, int width, int height, int dstRB, void* dst) { @@ -127,7 +141,16 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, } int srcRB = glyph.rowBytes(); - if (srcRB == dstRB) { + if (SkMask::kBW_Format == fStrike->getMaskFormat()) { + // expand bits to bytes + const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); + uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); + for (int y = 0; y < height; y++) { + bits_to_bytes(bits, bytes, width); + bits += srcRB; + bytes += dstRB; + } + } else if (srcRB == dstRB) { memcpy(dst, src, dstRB * height); } else { const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index da9ac1a..8becfd4 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -16,8 +16,12 @@ #include "SkGrTexturePixelRef.h" + #include "GrTexture.h" +#include "SkRect.h" +#include "SkBitmap.h" + SkGrTexturePixelRef::SkGrTexturePixelRef(GrTexture* tex) { fTexture = tex; GrSafeRef(tex); @@ -27,4 +31,72 @@ SkGrTexturePixelRef::~SkGrTexturePixelRef() { GrSafeUnref(fTexture); } +bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + if (NULL != fTexture && fTexture->isValid()) { + int left, top, width, height; + if (NULL != subset) { + left = subset->fLeft; + width = subset->width(); + top = subset->fTop; + height = subset->height(); + } else { + left = 0; + width = fTexture->width(); + top = 0; + height = fTexture->height(); + } + dst->setConfig(SkBitmap::kARGB_8888_Config, width, height); + dst->allocPixels(); + SkAutoLockPixels al(*dst); + void* buffer = dst->getPixels(); + return fTexture->readPixels(left, top, width, height, + kRGBA_8888_GrPixelConfig, + buffer); + } else { + return false; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +SkGrRenderTargetPixelRef::SkGrRenderTargetPixelRef(GrRenderTarget* rt) { + fRenderTarget = rt; + GrSafeRef(fRenderTarget); +} +SkGrRenderTargetPixelRef::~SkGrRenderTargetPixelRef() { + GrSafeUnref(fRenderTarget); +} + +SkGpuTexture* SkGrRenderTargetPixelRef::getTexture() { + if (NULL != fRenderTarget) { + return (SkGpuTexture*) fRenderTarget->asTexture(); + } + return NULL; +} + +bool SkGrRenderTargetPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + if (NULL != fRenderTarget && fRenderTarget->isValid()) { + int left, top, width, height; + if (NULL != subset) { + left = subset->fLeft; + width = subset->width(); + top = subset->fTop; + height = subset->height(); + } else { + left = 0; + width = fRenderTarget->width(); + top = 0; + height = fRenderTarget->height(); + } + dst->setConfig(SkBitmap::kARGB_8888_Config, width, height); + dst->allocPixels(); + SkAutoLockPixels al(*dst); + void* buffer = dst->getPixels(); + return fRenderTarget->readPixels(left, top, width, height, + kRGBA_8888_GrPixelConfig, + buffer); + } else { + return false; + } +} diff --git a/src/ports/SkFontHost_FONTPATH.cpp b/src/ports/SkFontHost_FONTPATH.cpp index 98f4ba5..afab874 100644 --- a/src/ports/SkFontHost_FONTPATH.cpp +++ b/src/ports/SkFontHost_FONTPATH.cpp @@ -271,7 +271,8 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { sk_throw(); // not implemented return NULL; } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 7cecb7f..280e0a1 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -98,12 +98,8 @@ InitFreetype() { // Setup LCD filtering. This reduces colour fringes for LCD rendered // glyphs. -//#ifdef ANDROID -// gLCDSupport = false; -//#else err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); gLCDSupport = err == 0; -//#endif gLCDSupportValid = true; return true; @@ -345,7 +341,8 @@ static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { #if defined(SK_BUILD_FOR_MAC) || defined(ANDROID) return NULL; #else @@ -387,12 +384,6 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( } } - SkASSERT(!FT_HAS_VERTICAL(face)); -#ifdef FT_IS_CID_KEYED - SkASSERT(FT_IS_CID_KEYED(face) == - (info->fType == SkAdvancedTypefaceMetrics::kType1CID_Font)); -#endif - info->fStyle = 0; if (FT_IS_FIXED_WIDTH(face)) info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; @@ -464,8 +455,12 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, face->bbox.xMax, face->bbox.yMin); - if (perGlyphInfo && canEmbed(face) && FT_IS_SCALABLE(face) && - info->fType != SkAdvancedTypefaceMetrics::kOther_Font) { + if (!canEmbed(face) || !FT_IS_SCALABLE(face) || + info->fType == SkAdvancedTypefaceMetrics::kOther_Font) { + perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo; + } + + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { if (FT_IS_FIXED_WIDTH(face)) { appendRange(&info->fGlyphWidths, 0); int16_t advance = face->max_advance_width; @@ -493,18 +488,24 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( info->fGlyphWidths.reset( getAdvanceData(face, face->num_glyphs, &getWidthAdvance)); } + } - if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { - // Postscript fonts may contain more than 255 glyphs, so we end up - // using multiple font descriptions with a glyph ordering. Record - // the name of each glyph. - info->fGlyphNames.reset( - new SkAutoTArray<SkString>(face->num_glyphs)); - for (int gID = 0; gID < face->num_glyphs; gID++) { - char glyphName[128]; // PS limit for names is 127 bytes. - FT_Get_Glyph_Name(face, gID, glyphName, 128); - info->fGlyphNames->get()[gID].set(glyphName); - } + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo && + FT_HAS_VERTICAL(face)) { + SkASSERT(false); // Not implemented yet. + } + + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo && + info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { + // Postscript fonts may contain more than 255 glyphs, so we end up + // using multiple font descriptions with a glyph ordering. Record + // the name of each glyph. + info->fGlyphNames.reset( + new SkAutoTArray<SkString>(face->num_glyphs)); + for (int gID = 0; gID < face->num_glyphs; gID++) { + char glyphName[128]; // PS limit for names is 127 bytes. + FT_Get_Glyph_Name(face, gID, glyphName, 128); + info->fGlyphNames->get()[gID].set(glyphName); } } diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp index 1d40a42..5bc438a 100644 --- a/src/ports/SkFontHost_mac_atsui.cpp +++ b/src/ports/SkFontHost_mac_atsui.cpp @@ -481,7 +481,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index ae39361..2def427 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -18,28 +18,18 @@ #include "SkFontHost.h" #include "SkDescriptor.h" -#include "SkString.h" -#include "SkPaint.h" #include "SkFloatingPoint.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkTypeface_mac.h" #include "SkUtils.h" - -//============================================================================ -// Constants -//---------------------------------------------------------------------------- static const SkFontID kSkInvalidFontID = 0; static const size_t FONT_CACHE_MEMORY_BUDGET = 1024 * 1024; static const char FONT_DEFAULT_NAME[] = "Lucida Sans"; -static const float FONT_CANONICAL_POINTSIZE = 1.0f; - - -//============================================================================ -// Types -//---------------------------------------------------------------------------- -// Native font info typedef struct { SkString name; SkTypeface::Style style; @@ -47,13 +37,8 @@ typedef struct { CTFontRef fontRef; } SkNativeFontInfo; -typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList; -typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator; -typedef SkNativeFontInfoList::const_iterator SkNativeFontInfoListConstIterator; - - - - +typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList; +typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator; //============================================================================ // Macros @@ -73,7 +58,21 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont #endif +static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isMonospace) { + unsigned style = SkTypeface::kNormal; + CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); + if (traits & kCTFontBoldTrait) { + style |= SkTypeface::kBold; + } + if (traits & kCTFontItalicTrait) { + style |= SkTypeface::kItalic; + } + if (isMonospace) { + *isMonospace = (traits & kCTFontMonoSpaceTrait) != 0; + } + return (SkTypeface::Style)style; +} //============================================================================ @@ -82,34 +81,24 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont #pragma mark - class SkNativeFontCache { public: - SkNativeFontCache(void); - virtual ~SkNativeFontCache(void); - - - // Is a font ID valid? - bool IsValid(SkFontID fontID); - + SkNativeFontCache(void); + virtual ~SkNativeFontCache(void); - // Get a font - CTFontRef GetFont(SkFontID fontID); - SkNativeFontInfo GetFontInfo(const SkString &theName, SkTypeface::Style theStyle); - - - // Create a font - SkNativeFontInfo CreateFont(const SkString &theName, SkTypeface::Style theStyle); - - - // Get the font table - static SkNativeFontCache *Get(void); + bool IsValid(SkFontID fontID); + CTFontRef GetFont(SkFontID fontID); + SkNativeFontInfo GetFontInfo(const char familyName[], SkTypeface::Style); + SkNativeFontInfo CreateFont(const char familyName[], SkTypeface::Style); + SkNativeFontInfo CreateFromCTFont(CTFontRef); + static SkNativeFontCache* Get(void); private: - CTFontRef CreateNativeFont(const SkString &name, SkTypeface::Style style); + CTFontRef CreateNativeFont(const char familyName[], SkTypeface::Style style); private: - SkNativeFontInfoList mFonts; - SkMutex mMutex; + SkNativeFontInfoList mFonts; + SkMutex mMutex; }; SkNativeFontCache::SkNativeFontCache(void) @@ -168,64 +157,76 @@ CTFontRef SkNativeFontCache::GetFont(SkFontID fontID) return(mFonts.at(fontID).fontRef); } -SkNativeFontInfo SkNativeFontCache::GetFontInfo(const SkString &theName, SkTypeface::Style theStyle) +SkNativeFontInfo SkNativeFontCache::GetFontInfo(const char familyName[], + SkTypeface::Style theStyle) { SkAutoMutexAcquire acquireLock(mMutex); SkNativeFontInfo fontInfo; SkNativeFontInfoListIterator theIter; - // Validate our parameters - SkASSERT(!theName.isEmpty()); - + SkASSERT(familyName && *familyName); // Get the state we need fontInfo.style = SkTypeface::kNormal; fontInfo.fontID = kSkInvalidFontID; fontInfo.fontRef = NULL; - // Get the font - for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) - { - if (theIter->name == theName && theIter->style == theStyle) - return(*theIter); + for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) { + if (theIter->style == theStyle && theIter->name.equals(familyName)) { + return *theIter; } + } - return(fontInfo); + return fontInfo; } -SkNativeFontInfo SkNativeFontCache::CreateFont(const SkString &theName, SkTypeface::Style theStyle) -{ SkAutoMutexAcquire acquireLock(mMutex); +SkNativeFontInfo SkNativeFontCache::CreateFont(const char familyName[], + SkTypeface::Style theStyle) { + SkAutoMutexAcquire acquireLock(mMutex); SkNativeFontInfo fontInfo; - - + + // Validate our parameters - SkASSERT(!theName.isEmpty()); - - + SkASSERT(familyName && *familyName); + + // Create the font - fontInfo.name = theName; - fontInfo.style = theStyle; - fontInfo.fontID = mFonts.size(); - fontInfo.fontRef = CreateNativeFont(theName, theStyle); - + fontInfo.name.set(familyName); + fontInfo.fontID = mFonts.size(); + fontInfo.fontRef = CreateNativeFont(familyName, theStyle); + fontInfo.style = computeStyleBits(fontInfo.fontRef, NULL); + mFonts.push_back(fontInfo); return(fontInfo); } -SkNativeFontCache *SkNativeFontCache::Get(void) -{ static SkNativeFontCache sInstance; - +SkNativeFontInfo SkNativeFontCache::CreateFromCTFont(CTFontRef font) { + SkAutoMutexAcquire acquireLock(mMutex); + SkNativeFontInfo fontInfo; + + // TODO: need to query the font's name +// fontInfo.name.set(familyName); + fontInfo.fontID = mFonts.size(); + fontInfo.fontRef = font; + CFRetain(font); + fontInfo.style = computeStyleBits(font, NULL); + + mFonts.push_back(fontInfo); + return(fontInfo); +} - // Get the instance - // +SkNativeFontCache *SkNativeFontCache::Get(void) { + static SkNativeFontCache sInstance; // We use a local static for well-defined static initialisation order. - return(&sInstance); + return &sInstance; } /////////////////////////////////////////////////////////////////////////// -CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypeface::Style theStyle) -{ CFMutableDictionaryRef cfAttributes, cfTraits; + +CTFontRef SkNativeFontCache::CreateNativeFont(const char familyName[], + SkTypeface::Style theStyle) { + CFMutableDictionaryRef cfAttributes, cfTraits; CFNumberRef cfFontTraits; CTFontSymbolicTraits ctFontTraits; CTFontDescriptorRef ctFontDesc; @@ -246,31 +247,25 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac // Create the font info - cfFontName = CFStringCreateWithCString(NULL, theName.c_str(), kCFStringEncodingUTF8); + cfFontName = CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8); cfFontTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits); cfAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); cfTraits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Create the font - // - // Fonts are scaled using the Sk matrix, so we always request a font - // at a canonical size FONT_CANONICAL_POINTSIZE - if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) - { + if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) { CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); - if (ctFontDesc != NULL) - ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, FONT_CANONICAL_POINTSIZE, NULL); - + if (ctFontDesc != NULL) { + ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); } + } - - // Clean up CFSafeRelease(cfFontName); CFSafeRelease(cfFontTraits); CFSafeRelease(cfAttributes); @@ -280,28 +275,27 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac return(ctFont); } - - - - //============================================================================ // SkTypeface_Mac //---------------------------------------------------------------------------- #pragma mark - class SkTypeface_Mac : public SkTypeface { public: - SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID); + SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID); }; SkTypeface_Mac::SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID) - : SkTypeface(style, fontID) -{ + : SkTypeface(style, fontID) { } - - +SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font) { + SkNativeFontInfo info; + + info = SkNativeFontCache::Get()->CreateFromCTFont(font); + return new SkTypeface_Mac(info.style, info.fontID); +} //============================================================================ // SkScalerContext_Mac @@ -358,15 +352,15 @@ SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) mColorSpaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); mColorSpaceGray = CGColorSpaceCreateDeviceGray(); - const float inv = 1.0f / FONT_CANONICAL_POINTSIZE; - mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]) * inv, - -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]) * inv, - -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMTransX]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMTransY]) * inv); + mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]), + -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]), + -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]), + SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]), + SkScalarToFloat(skMatrix[SkMatrix::kMTransX]), + SkScalarToFloat(skMatrix[SkMatrix::kMTransY])); - mFont = CTFontCreateCopyWithAttributes(ctFont, 0.0, &mTransform, NULL); + // since our matrix includes everything, we pass 1 for pointSize + mFont = CTFontCreateCopyWithAttributes(ctFont, 1, &mTransform, NULL); mGlyphCount = (uint16_t) numGlyphs; } @@ -445,6 +439,19 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) #include "SkColorPriv.h" +static void bytes_to_bits(uint8_t dst[], const uint8_t src[], int count) { + while (count > 0) { + uint8_t mask = 0; + for (int i = 7; i >= 0; --i) { + mask |= (*src++ >> 7) << i; + if (0 == --count) { + break; + } + } + *dst++ = mask; + } +} + static inline uint16_t rgb_to_lcd16(uint32_t rgb) { int r = (rgb >> 16) & 0xFF; int g = (rgb >> 8) & 0xFF; @@ -480,6 +487,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { void* image = glyph.fImage; size_t rowBytes = glyph.rowBytes(); float grayColor = 1; // white + bool doAA = true; /* For LCD16, we first create a temp offscreen cg-context in 32bit, * erase to white, and then draw a black glyph into it. Then we can @@ -496,6 +504,12 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { // we draw black-on-white (and invert in rgb_to_lcd16) sk_memset32((uint32_t*)image, 0xFFFFFFFF, size >> 2); grayColor = 0; // black + } else if (SkMask::kBW_Format == glyph.fMaskFormat) { + rowBytes = SkAlign4(glyph.fWidth); + size_t size = glyph.fHeight * rowBytes; + image = storage.realloc(size); + sk_bzero(image, size); + doAA = false; } cgContext = CGBitmapContextCreate(image, glyph.fWidth, glyph.fHeight, 8, @@ -503,13 +517,15 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { // Draw the glyph if (cgFont != NULL && cgContext != NULL) { +#ifdef WE_ARE_RUNNING_ON_10_6_OR_LATER CGContextSetAllowsFontSubpixelQuantization(cgContext, true); CGContextSetShouldSubpixelQuantizeFonts(cgContext, true); - +#endif + CGContextSetShouldAntialias(cgContext, doAA); CGContextSetGrayFillColor( cgContext, grayColor, 1.0); CGContextSetTextDrawingMode(cgContext, kCGTextFill); CGContextSetFont( cgContext, cgFont); - CGContextSetFontSize( cgContext, FONT_CANONICAL_POINTSIZE); + CGContextSetFontSize( cgContext, 1); // cgFont know's its size CGContextSetTextMatrix( cgContext, mTransform); CGContextShowGlyphsAtPoint( cgContext, -glyph.fLeft, glyph.fTop + glyph.fHeight, &cgGlyph, 1); @@ -526,6 +542,16 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { src = (const uint32_t*)((const char*)src + rowBytes); dst = (uint16_t*)((char*)dst + dstRB); } + } else if (SkMask::kBW_Format == glyph.fMaskFormat) { + // downsample from A8 to A1 + const uint8_t* src = (const uint8_t*)image; + uint8_t* dst = (uint8_t*)glyph.fImage; + size_t dstRB = glyph.rowBytes(); + for (int y = 0; y < glyph.fHeight; y++) { + bytes_to_bits(dst, src, glyph.fWidth); + src += rowBytes; + dst += dstRB; + } } } @@ -616,48 +642,55 @@ void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element } +static const char* map_css_names(const char* name) { + static const struct { + const char* fFrom; + const char* fTo; + } gPairs[] = { + { "sans-serif", "Helvetica" }, + { "serif", "Times" }, + { "monospace", "Courier" } + }; - + for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { + if (strcmp(name, gPairs[i].fFrom) == 0) { + return gPairs[i].fTo; + } + } + return name; // no change +} /////////////////////////////////////////////////////////////////////////// #pragma mark - SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - const void* data, size_t bytelength, - SkTypeface::Style style) -{ SkTypeface *theTypeface; - SkNativeFontCache *fontTable; - SkNativeFontInfo fontInfo; - SkString fontName; - - - // Get the state we need - fontName = SkString(familyName); - fontTable = SkNativeFontCache::Get(); + const char familyName[], + const void* data, size_t bytelength, + SkTypeface::Style style) { + if (familyName) { + familyName = map_css_names(familyName); + } + SkNativeFontCache* fontTable = SkNativeFontCache::Get(); // Clone an existing typeface // TODO: only clone if style matches the familyFace's style... - if (familyName == NULL && familyFace != NULL) - { + if (familyName == NULL && familyFace != NULL) { familyFace->ref(); - return(const_cast<SkTypeface*>(familyFace)); - } - + return const_cast<SkTypeface*>(familyFace); + } - if (fontName.isEmpty()) { - fontName.set(FONT_DEFAULT_NAME); + if (!familyName || !*familyName) { + familyName = FONT_DEFAULT_NAME; } - // Get the native font - fontInfo = fontTable->GetFontInfo(fontName, style); - if (fontInfo.fontID == kSkInvalidFontID) - fontInfo = fontTable->CreateFont(fontName, style); + // Get the native font + SkNativeFontInfo fontInfo = fontTable->GetFontInfo(familyName, style); + if (fontInfo.fontID == kSkInvalidFontID) { + fontInfo = fontTable->CreateFont(familyName, style); + } - // Create the typeface - theTypeface = new SkTypeface_Mac(fontInfo.style, fontInfo.fontID); - return(theTypeface); + return new SkTypeface_Mac(fontInfo.style, fontInfo.fontID); } SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) @@ -674,7 +707,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_none.cpp b/src/ports/SkFontHost_none.cpp index d56c94a..91546f8 100644 --- a/src/ports/SkFontHost_none.cpp +++ b/src/ports/SkFontHost_none.cpp @@ -35,7 +35,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_simple.cpp b/src/ports/SkFontHost_simple.cpp index 60334e7..54d326e 100644 --- a/src/ports/SkFontHost_simple.cpp +++ b/src/ports/SkFontHost_simple.cpp @@ -592,7 +592,8 @@ SkStream* SkFontHost::OpenStream(uint32_t fontID) { #if 0 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index a4f430c..a75b002 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -449,7 +449,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { COLORREF color = SetTextColor(dc, 0); // black SkASSERT(color != CLR_INVALID); uint16_t glyphID = glyph.getGlyphID(); +#if defined(UNICODE) ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCWSTR)&glyphID, 1, NULL); +#else + ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&glyphID, 1, NULL); +#endif GdiFlush(); // downsample from rgba to rgb565 @@ -609,7 +613,8 @@ static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkAutoMutexAcquire ac(gFTMutex); LogFontTypeface* rec = LogFontTypeface::FindById(fontID); LOGFONT lf = rec->logFont(); @@ -717,7 +722,8 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( // If bit 2 is set, the embedding is read-only. if (otm.otmfsType & 0x1) { info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; - } else if (perGlyphInfo) { + } else if (perGlyphInfo & + SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { info->fGlyphWidths.reset( getAdvanceData(hdc, glyphCount, &getWidthAdvance)); } diff --git a/src/ports/ports_files.mk b/src/ports/ports_files.mk new file mode 100644 index 0000000..563f20b --- /dev/null +++ b/src/ports/ports_files.mk @@ -0,0 +1,6 @@ +SOURCE := \ + SkDebug_stdio.cpp \ + SkGlobals_global.cpp \ + SkOSFile_stdio.cpp \ + SkThread_pthread.cpp \ + SkTime_Unix.cpp diff --git a/src/svg/SkSVGPaintState.cpp b/src/svg/SkSVGPaintState.cpp index 7fc90c7..f3c65e7 100644 --- a/src/svg/SkSVGPaintState.cpp +++ b/src/svg/SkSVGPaintState.cpp @@ -321,7 +321,7 @@ fillStrokeAttrCommon: if (strncmp(attrValue, "url(", 4) == 0) { SkASSERT(attrValue[4] == '#'); const char* idStart = attrValue + 5; - char* idEnd = strrchr(attrValue, ')'); + const char* idEnd = strrchr(attrValue, ')'); SkASSERT(idStart < idEnd); SkString id(idStart, idEnd - idStart); SkSVGElement* found; diff --git a/src/utils/SkOSFile.cpp b/src/utils/SkOSFile.cpp index 982bc08..c1b6943 100644 --- a/src/utils/SkOSFile.cpp +++ b/src/utils/SkOSFile.cpp @@ -31,18 +31,19 @@ SkUTF16_Str::SkUTF16_Str(const char src[]) size_t len = strlen(src); fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t)); - for (size_t i = 0; i < len; i++) + size_t i; + for (i = 0; i < len; i++) fStr[i] = src[i]; fStr[i] = 0; } //////////////////////////////////////////////////////////////////////////// -SkOSFile::Iter::Iter() : fHandle(0), fPath16(nil) +SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL) { } -SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(nil) +SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL) { this->reset(path, suffix); } @@ -61,7 +62,7 @@ void SkOSFile::Iter::reset(const char path[], const char suffix[]) ::FindClose(fHandle); fHandle = 0; } - if (path == nil) + if (NULL == path) path = ""; sk_free(fPath16); @@ -78,7 +79,7 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt { WIN32_FIND_DATAW data; - if (dataPtr == nil) + if (NULL == dataPtr) { if (::FindNextFileW(handle, &data)) dataPtr = &data; @@ -90,7 +91,7 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt { if (getDir) { - if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir(dataPtr->cFileName)) + if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName)) break; } else @@ -103,21 +104,21 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt } // if we get here, we've found a file/dir if (name) - name->setUTF16(dataPtr->cFileName); + name->setUTF16((uint16_t*)dataPtr->cFileName); return true; } bool SkOSFile::Iter::next(SkString* name, bool getDir) { WIN32_FIND_DATAW data; - WIN32_FIND_DATAW* dataPtr = nil; + WIN32_FIND_DATAW* dataPtr = NULL; if (fHandle == 0) // our first time { - if (fPath16 == nil || *fPath16 == 0) // check for no path + if (fPath16 == NULL || *fPath16 == 0) // check for no path return false; - fHandle = ::FindFirstFileW(fPath16, &data); + fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data); if (fHandle != 0 && fHandle != (HANDLE)~0) dataPtr = &data; } diff --git a/tests/Android.mk b/tests/Android.mk index a5611ee..a3ea319 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -10,12 +10,14 @@ LOCAL_SRC_FILES:= \ ClipStackTest.cpp \ ClipperTest.cpp \ DequeTest.cpp \ + DrawBitmapRectTest.cpp \ FillPathTest.cpp \ FlateTest.cpp \ GeometryTest.cpp \ InfRectTest.cpp \ MathTest.cpp \ MatrixTest.cpp \ + MetaDataTest.cpp \ PackBitsTest.cpp \ PaintTest.cpp \ ParsePathTest.cpp \ diff --git a/tests/DrawBitmapRectTest.cpp b/tests/DrawBitmapRectTest.cpp new file mode 100644 index 0000000..fc382ce --- /dev/null +++ b/tests/DrawBitmapRectTest.cpp @@ -0,0 +1,47 @@ +#include "Test.h" +#include "SkBitmap.h" +#include "SkCanvas.h" + +static bool check_for_all_zeros(const SkBitmap& bm) { + SkAutoLockPixels alp(bm); + + size_t count = bm.width() * bm.bytesPerPixel(); + for (int y = 0; y < bm.height(); y++) { + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(bm.getAddr(0, y)); + for (size_t i = 0; i < count; i++) { + if (ptr[i]) { + return false; + } + } + } + return true; +} + +static const int gWidth = 256; +static const int gHeight = 256; + +static void create(SkBitmap* bm, SkBitmap::Config config, SkColor color) { + bm->setConfig(config, gWidth, gHeight); + bm->allocPixels(); + bm->eraseColor(color); +} + +static void TestDrawBitmapRect(skiatest::Reporter* reporter) { + SkBitmap src, dst; + + create(&src, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); + create(&dst, SkBitmap::kARGB_8888_Config, 0); + + SkCanvas canvas(dst); + + SkIRect srcR = { gWidth, 0, gWidth + 16, 16 }; + SkRect dstR = { 0, 0, SkIntToScalar(16), SkIntToScalar(16) }; + + canvas.drawBitmapRect(src, &srcR, dstR, NULL); + + // ensure that we draw nothing if srcR does not intersect the bitmap + REPORTER_ASSERT(reporter, check_for_all_zeros(dst)); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("DrawBitmapRect", TestDrawBitmapRectClass, TestDrawBitmapRect) diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp index 493691e..7a9364f 100644 --- a/tests/MathTest.cpp +++ b/tests/MathTest.cpp @@ -3,6 +3,40 @@ #include "SkPoint.h" #include "SkRandom.h" +#if 0 +static U8CPU premul_fast(U8CPU a, U8CPU x) { + return a * x * 32897 >> 23; +} + +static U8CPU premul_trunc(U8CPU a, U8CPU x) { + double result = a * x; + result /= 255.0; + return (unsigned)floor(result + 0.0); +} + +static U8CPU premul_round(U8CPU a, U8CPU x) { + double result = a * x; + result /= 255.0; + return (unsigned)floor(result + 0.5); +} + +static void test_premul(skiatest::Reporter* reporter) { + for (int a = 0; a <= 255; a++) { + for (int x = 0; x <= 255; x++) { + unsigned curr_trunc = SkMulDiv255Trunc(a, x); + unsigned curr_round = SkMulDiv255Round(a, x); + unsigned fast = premul_fast(a, x); + unsigned slow_round = premul_round(a, x); + unsigned slow_trunc = premul_trunc(a, x); + if (fast != slow || curr != fast) { + SkDebugf("---- premul(%d %d) curr=%d fast=%d slow=%d\n", a, x, + curr, fast, slow); + } + } + } +} +#endif + #if defined(SkLONGLONG) static int symmetric_fixmul(int a, int b) { int sa = SkExtractSign(a); @@ -458,6 +492,8 @@ static void TestMath(skiatest::Reporter* reporter) { } SkDebugf("SinCos: maximum error = %d\n", maxDiff); #endif + +// test_premul(reporter); } #include "TestClassDef.h" diff --git a/tests/MetaDataTest.cpp b/tests/MetaDataTest.cpp new file mode 100644 index 0000000..70829d4 --- /dev/null +++ b/tests/MetaDataTest.cpp @@ -0,0 +1,112 @@ +#include "Test.h" +#include "SkMetaData.h" + +static void test_ptrs(skiatest::Reporter* reporter) { + SkRefCnt ref; + REPORTER_ASSERT(reporter, 1 == ref.getRefCnt()); + + { + SkMetaData md0, md1; + const char name[] = "refcnt"; + + md0.setRefCnt(name, &ref); + REPORTER_ASSERT(reporter, md0.findRefCnt(name)); + REPORTER_ASSERT(reporter, md0.hasRefCnt(name, &ref)); + REPORTER_ASSERT(reporter, 2 == ref.getRefCnt()); + + md1 = md0; + REPORTER_ASSERT(reporter, md1.findRefCnt(name)); + REPORTER_ASSERT(reporter, md1.hasRefCnt(name, &ref)); + REPORTER_ASSERT(reporter, 3 == ref.getRefCnt()); + + REPORTER_ASSERT(reporter, md0.removeRefCnt(name)); + REPORTER_ASSERT(reporter, !md0.findRefCnt(name)); + REPORTER_ASSERT(reporter, !md0.hasRefCnt(name, &ref)); + REPORTER_ASSERT(reporter, 2 == ref.getRefCnt()); + } + REPORTER_ASSERT(reporter, 1 == ref.getRefCnt()); +} + +static void TestMetaData(skiatest::Reporter* reporter) { + SkMetaData m1; + + REPORTER_ASSERT(reporter, !m1.findS32("int")); + REPORTER_ASSERT(reporter, !m1.findScalar("scalar")); + REPORTER_ASSERT(reporter, !m1.findString("hello")); + REPORTER_ASSERT(reporter, !m1.removeS32("int")); + REPORTER_ASSERT(reporter, !m1.removeScalar("scalar")); + REPORTER_ASSERT(reporter, !m1.removeString("hello")); + REPORTER_ASSERT(reporter, !m1.removeString("true")); + REPORTER_ASSERT(reporter, !m1.removeString("false")); + + m1.setS32("int", 12345); + m1.setScalar("scalar", SK_Scalar1 * 42); + m1.setString("hello", "world"); + m1.setPtr("ptr", &m1); + m1.setBool("true", true); + m1.setBool("false", false); + + int32_t n; + SkScalar s; + + m1.setScalar("scalar", SK_Scalar1/2); + + REPORTER_ASSERT(reporter, m1.findS32("int", &n) && n == 12345); + REPORTER_ASSERT(reporter, m1.findScalar("scalar", &s) && s == SK_Scalar1/2); + REPORTER_ASSERT(reporter, !strcmp(m1.findString("hello"), "world")); + REPORTER_ASSERT(reporter, m1.hasBool("true", true)); + REPORTER_ASSERT(reporter, m1.hasBool("false", false)); + + SkMetaData::Iter iter(m1); + const char* name; + + static const struct { + const char* fName; + SkMetaData::Type fType; + int fCount; + } gElems[] = { + { "int", SkMetaData::kS32_Type, 1 }, + { "scalar", SkMetaData::kScalar_Type, 1 }, + { "ptr", SkMetaData::kPtr_Type, 1 }, + { "hello", SkMetaData::kString_Type, sizeof("world") }, + { "true", SkMetaData::kBool_Type, 1 }, + { "false", SkMetaData::kBool_Type, 1 } + }; + + int loop = 0; + int count; + SkMetaData::Type t; + while ((name = iter.next(&t, &count)) != NULL) + { + int match = 0; + for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++) + { + if (!strcmp(name, gElems[i].fName)) + { + match += 1; + REPORTER_ASSERT(reporter, gElems[i].fType == t); + REPORTER_ASSERT(reporter, gElems[i].fCount == count); + } + } + REPORTER_ASSERT(reporter, match == 1); + loop += 1; + } + REPORTER_ASSERT(reporter, loop == SK_ARRAY_COUNT(gElems)); + + REPORTER_ASSERT(reporter, m1.removeS32("int")); + REPORTER_ASSERT(reporter, m1.removeScalar("scalar")); + REPORTER_ASSERT(reporter, m1.removeString("hello")); + REPORTER_ASSERT(reporter, m1.removeBool("true")); + REPORTER_ASSERT(reporter, m1.removeBool("false")); + + REPORTER_ASSERT(reporter, !m1.findS32("int")); + REPORTER_ASSERT(reporter, !m1.findScalar("scalar")); + REPORTER_ASSERT(reporter, !m1.findString("hello")); + REPORTER_ASSERT(reporter, !m1.findBool("true")); + REPORTER_ASSERT(reporter, !m1.findBool("false")); + + test_ptrs(reporter); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("MetaData", TestMetaDataClass, TestMetaData) diff --git a/tests/tests_files.mk b/tests/tests_files.mk index 5280502..9f8d6df 100644 --- a/tests/tests_files.mk +++ b/tests/tests_files.mk @@ -6,12 +6,14 @@ SOURCE := \ ClipStackTest.cpp \ ClipperTest.cpp \ DequeTest.cpp \ + DrawBitmapRectTest.cpp \ FillPathTest.cpp \ FlateTest.cpp \ GeometryTest.cpp \ InfRectTest.cpp \ MathTest.cpp \ MatrixTest.cpp \ + MetaDataTest.cpp \ PackBitsTest.cpp \ PaintTest.cpp \ ParsePathTest.cpp \ |