deps = {
# DEPS using https://chromium.googlesource.com are pulled from chromium @ r205199
# (see https://chromium.googlesource.com/chromium/chromium/+/c59bfa8ef877f45bfa859669053859857af1d279)
- # NOTE: Angle has been reverted to http://angleproject.googlecode.com/svn/trunk@1268
- "third_party/externals/angle" : "https://chromium.googlesource.com/external/angleproject.git@e574e26f48223a6718feab841b4a7720785b497a",
+ "third_party/externals/angle" : "https://chromium.googlesource.com/external/angleproject.git",
"third_party/externals/fontconfig" : "https://skia.googlesource.com/third_party/fontconfig.git@2.10.93",
"third_party/externals/freetype" : "https://skia.googlesource.com/third_party/freetype2.git@VER-2-5-0-1",
"third_party/externals/gyp" : "https://chromium.googlesource.com/external/gyp.git@d0176c0a2a9e558662905c328c3aa93fd25bbf12",
#include "SkCommandLineFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
+#include "SkString.h"
#include "gm.h"
#include "DMReporter.h"
__SK_FORCE_IMAGE_DECODER_LINKING;
-// Split str on any characters in delimiters into out. (Think, strtok with a sane API.)
-static void split(const char* str, const char* delimiters, SkTArray<SkString>* out) {
- const char* end = str + strlen(str);
- while (str != end) {
- // Find a token.
- const size_t len = strcspn(str, delimiters);
- out->push_back().set(str, len);
- str += len;
- // Skip any delimiters.
- str += strspn(str, delimiters);
- }
-}
-
// "FooBar" -> "foobar". Obviously, ASCII only.
static SkString lowercase(SkString s) {
for (size_t i = 0; i < s.size(); i++) {
GM::SetResourcePath(FLAGS_resources[0]);
SkTArray<SkString> configs;
for (int i = 0; i < FLAGS_config.count(); i++) {
- split(FLAGS_config[i], ", ", &configs);
+ SkStrSplit(FLAGS_config[i], ", ", &configs);
}
SkTDArray<GMRegistry::Factory> gms;
+++ /dev/null
-#include "DMComparisonTask.h"
-#include "DMUtil.h"
-
-namespace DM {
-
-ComparisonTask::ComparisonTask(const Task& parent,
- skiagm::Expectations expectations,
- SkBitmap bitmap)
- : Task(parent)
- , fName(parent.name()) // Masquerade as parent so failures are attributed to it.
- , fExpectations(expectations)
- , fBitmap(bitmap)
- {}
-
-void ComparisonTask::draw() {
- if (!MeetsExpectations(fExpectations, fBitmap)) {
- this->fail();
- }
-}
-
-} // namespace DM
+++ /dev/null
-#ifndef DMComparisonTask_DEFINED
-#define DMComparisonTask_DEFINED
-
-#include "DMTask.h"
-#include "SkBitmap.h"
-#include "SkString.h"
-#include "gm_expectations.h"
-
-namespace DM {
-
-// We use ComparisonTask to move CPU-bound comparison work of GpuTasks back to
-// the main thread pool, where we probably have more threads available.
-
-class ComparisonTask : public Task {
-public:
- ComparisonTask(const Task& parent, skiagm::Expectations, SkBitmap);
-
- virtual void draw() SK_OVERRIDE;
- virtual bool usesGpu() const SK_OVERRIDE { return false; }
- virtual bool shouldSkip() const SK_OVERRIDE { return false; }
- virtual SkString name() const SK_OVERRIDE { return fName; }
-
-private:
- const SkString fName;
- const skiagm::Expectations fExpectations;
- const SkBitmap fBitmap;
-};
-
-} // namespace DM
-
-#endif // DMComparisonTask_DEFINED
#include "DMCpuTask.h"
+#include "DMChecksumTask.h"
#include "DMPipeTask.h"
#include "DMReplayTask.h"
#include "DMSerializeTask.h"
+#include "DMTileGridTask.h"
#include "DMUtil.h"
#include "DMWriteTask.h"
fGM->draw(&canvas);
canvas.flush();
- if (!MeetsExpectations(fExpectations, bitmap)) {
- this->fail();
- }
-
- this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, false, false)));
- this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, true, false)));
- this->spawnChild(SkNEW_ARGS(PipeTask, (*this, fGMFactory(NULL), bitmap, true, true)));
+#define SPAWN(ChildTask, ...) this->spawnChild(SkNEW_ARGS(ChildTask, (*this, __VA_ARGS__)))
+ SPAWN(ChecksumTask, fExpectations, bitmap);
- this->spawnChild(SkNEW_ARGS(ReplayTask, (*this, fGMFactory(NULL), bitmap, true)));
- this->spawnChild(SkNEW_ARGS(ReplayTask, (*this, fGMFactory(NULL), bitmap, false)));
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, false, false);
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, false);
+ SPAWN(PipeTask, fGMFactory(NULL), bitmap, true, true);
+ SPAWN(ReplayTask, fGMFactory(NULL), bitmap, false);
+ SPAWN(ReplayTask, fGMFactory(NULL), bitmap, true);
+ SPAWN(SerializeTask, fGMFactory(NULL), bitmap);
+ SPAWN(TileGridTask, fGMFactory(NULL), bitmap, SkISize::Make(16,16));
- this->spawnChild(SkNEW_ARGS(SerializeTask, (*this, fGMFactory(NULL), bitmap)));
- this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap)));
+ SPAWN(WriteTask, bitmap);
+#undef SPAWN
}
bool CpuTask::shouldSkip() const {
#include "DMGpuTask.h"
-#include "DMComparisonTask.h"
+#include "DMChecksumTask.h"
#include "DMUtil.h"
#include "DMWriteTask.h"
#include "SkCommandLineFlags.h"
gr->printCacheStats();
#endif
- // We offload checksum comparison to the main CPU threadpool.
- // This cuts run time by about 30%.
- this->spawnChild(SkNEW_ARGS(ComparisonTask, (*this, fExpectations, bitmap)));
+ this->spawnChild(SkNEW_ARGS(ChecksumTask, (*this, fExpectations, bitmap)));
this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap)));
}
#include "SkCommandLineFlags.h"
#include "SkGPipe.h"
-DEFINE_bool(pipe, false, "If true, check several pipe variants against the reference bitmap.");
+DEFINE_bool(pipe, true, "If true, check several pipe variants against the reference bitmap.");
namespace DM {
#include "SkCommandLineFlags.h"
#include "SkPicture.h"
-DEFINE_bool(replay, false, "If true, run picture replay tests.");
-DEFINE_bool(rtree, false, "If true, run picture replay tests with an rtree.");
+DEFINE_bool(replay, true, "If true, run picture replay tests.");
+DEFINE_bool(rtree, true, "If true, run picture replay tests with an rtree.");
namespace DM {
public:
ReplayTask(const Task& parent, // ReplayTask must be a child task. Pass its parent here.
- skiagm::GM*, // GM to run through a pipe. Takes ownership.
- SkBitmap reference, // Bitmap to compare pipe results to.
+ skiagm::GM*, // GM to run through a picture. Takes ownership.
+ SkBitmap reference, // Bitmap to compare picture replay results to.
bool useRTree); // Record with an RTree?
virtual void draw() SK_OVERRIDE;
}
SkString status;
- status.printf("\r\033[K%d / %d", this->finished(), this->started());
+ status.printf("\r\033[K%d tasks left", this->started() - this->finished());
const int failed = this->failed();
if (failed > 0) {
status.appendf(", %d failed", failed);
#include "SkPicture.h"
#include "SkPixelRef.h"
-DEFINE_bool(serialize, false, "If true, run picture serialization tests.");
+DEFINE_bool(serialize, true, "If true, run picture serialization tests.");
namespace DM {
namespace DM {
Task::Task(Reporter* reporter, TaskRunner* taskRunner)
- : fReporter(reporter), fTaskRunner(taskRunner) {
+ : fReporter(reporter), fTaskRunner(taskRunner), fDepth(0) {
fReporter->start();
}
-Task::Task(const Task& that)
- : INHERITED(that)
- , fReporter(that.fReporter)
- , fTaskRunner(that.fTaskRunner) {
+Task::Task(const Task& parent)
+ : INHERITED(parent)
+ , fReporter(parent.fReporter)
+ , fTaskRunner(parent.fTaskRunner)
+ , fDepth(parent.depth()+1) {
fReporter->start();
}
class Task : public SkRunnable {
public:
Task(Reporter* reporter, TaskRunner* taskRunner);
- Task(const Task& that);
+ Task(const Task& parent);
virtual ~Task();
void run() SK_OVERRIDE;
virtual bool shouldSkip() const = 0;
virtual SkString name() const = 0;
+ // Returns the number of parents above this task.
+ // Top-level tasks return 0, their children 1, and so on.
+ int depth() const { return fDepth; }
+
protected:
void spawnChild(Task* task);
void fail();
// Both unowned.
Reporter* fReporter;
TaskRunner* fTaskRunner;
+ int fDepth;
typedef SkRunnable INHERITED;
};
return s;
}
-bool MeetsExpectations(const skiagm::Expectations& expectations, const SkBitmap bitmap) {
- if (expectations.ignoreFailure() || expectations.empty()) {
- return true;
- }
- const skiagm::GmResultDigest digest(bitmap);
- return expectations.match(digest);
-}
-
void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags) {
- SkCanvas* canvas = picture->beginRecording(SkScalarCeilToInt(gm->width()),
- SkScalarCeilToInt(gm->height()),
- recordFlags);
+ const SkISize size = gm->getISize();
+ SkCanvas* canvas = picture->beginRecording(size.width(), size.height(), recordFlags);
canvas->concat(gm->getInitialTransform());
gm->draw(canvas);
canvas->flush();
}
void SetupBitmap(const SkBitmap::Config config, skiagm::GM* gm, SkBitmap* bitmap) {
- bitmap->setConfig(config, SkScalarCeilToInt(gm->width()), SkScalarCeilToInt(gm->height()));
+ const SkISize size = gm->getISize();
+ bitmap->setConfig(config, size.width(), size.height());
bitmap->allocPixels();
bitmap->eraseColor(0x00000000);
}
// Png("a") -> "a.png"
SkString Png(SkString s);
-// Roughly, expectations.match(GmResultDigest(bitmap)), but calculates the digest lazily.
-bool MeetsExpectations(const skiagm::Expectations& expectations, const SkBitmap bitmap);
-
// Draw gm to picture. Passes recordFlags to SkPicture::beginRecording().
void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags = 0);
#include "DMUtil.h"
#include "SkCommandLineFlags.h"
#include "SkImageEncoder.h"
-
-#include <string.h>
+#include "SkString.h"
DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs.");
namespace DM {
-WriteTask::WriteTask(const Task& parent, SkBitmap bitmap)
- : Task(parent)
- , fBitmap(bitmap) {
- // Split parent's name <gmName>_<config> into gmName and config.
- const char* parentName = parent.name().c_str();
- const char* fromLastUnderscore = strrchr(parentName, '_');
- const ptrdiff_t gmNameLength = fromLastUnderscore - parentName;
+WriteTask::WriteTask(const Task& parent, SkBitmap bitmap) : Task(parent), fBitmap(bitmap) {
+ const int suffixes = parent.depth() + 1;
+ const char* name = parent.name().c_str();
+ SkTArray<SkString> split;
+ SkStrSplit(name, "_", &split);
+ int totalSuffixLength = 0;
+ for (int i = 0; i < suffixes; i++) {
+ // We're splitting off suffixes from the back to front.
+ fSuffixes.push_back(split[split.count()-i-1]);
+ totalSuffixLength += fSuffixes.back().size() + 1;
+ }
+ fGmName.set(name, strlen(name)-totalSuffixLength);
+}
- fConfig.set(fromLastUnderscore+1);
- fGmName.set(parentName, gmNameLength);
+void WriteTask::makeDirOrFail(SkString dir) {
+ if (!sk_mkdir(dir.c_str())) {
+ this->fail();
+ }
}
void WriteTask::draw() {
- const char* root = FLAGS_writePath[0];
- const SkString dir = SkOSPath::SkPathJoin(root, fConfig.c_str());
- if (!sk_mkdir(root) ||
- !sk_mkdir(dir.c_str()) ||
- !SkImageEncoder::EncodeFile(Png(SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str())).c_str(),
+ SkString dir(FLAGS_writePath[0]);
+ this->makeDirOrFail(dir);
+ for (int i = 0; i < fSuffixes.count(); i++) {
+ dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str());
+ this->makeDirOrFail(dir);
+ }
+ if (!SkImageEncoder::EncodeFile(Png(SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str())).c_str(),
fBitmap,
SkImageEncoder::kPNG_Type,
- 100/*quality*/))
- {
+ 100/*quality*/)) {
this->fail();
}
}
SkString WriteTask::name() const {
- return SkStringPrintf("writing %s/%s.png", fConfig.c_str(), fGmName.c_str());
+ SkString name("writing ");
+ for (int i = 0; i < fSuffixes.count(); i++) {
+ name.appendf("%s/", fSuffixes[i].c_str());
+ }
+ name.append(fGmName.c_str());
+ return name;
}
bool WriteTask::shouldSkip() const {
#include "DMTask.h"
#include "SkBitmap.h"
#include "SkString.h"
+#include "SkTArray.h"
// Writes a bitmap to a file.
class WriteTask : public Task {
public:
- WriteTask(const Task& parent, SkBitmap bitmap);
+ WriteTask(const Task& parent, // WriteTask must be a child Task. Pass its parent here.
+ SkBitmap bitmap); // Bitmap to write.
virtual void draw() SK_OVERRIDE;
virtual bool usesGpu() const SK_OVERRIDE { return false; }
virtual SkString name() const SK_OVERRIDE;
private:
- SkString fConfig;
+ SkTArray<SkString> fSuffixes;
SkString fGmName;
const SkBitmap fBitmap;
+
+ void makeDirOrFail(SkString dir);
};
} // namespace DM
--writePicturePath
--deferred
- --tiledGrid
DM's design is based around Tasks and a TaskRunner.
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2481797737367594615
+ 7789211976036245847
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 8086938262113983689
+ 12063547141229638542
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10512095643464253945
+ 8512582036956628519
]
],
- "bugs": [
- 1759
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2481797737367594615
+ 7789211976036245847
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 8086938262113983689
+ 12063547141229638542
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10512095643464253945
+ 8512582036956628519
]
],
- "bugs": [
- 1759
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"complexclip2_565.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 12902148816415894358
+ 17182697123061500145
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_msaa4.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 12902148816415894358
+ 17182697123061500145
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 12902148816415894358
+ 17182697123061500145
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_msaa4.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 12902148816415894358
+ 17182697123061500145
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 6811779909537199081
+ 829525110335272310
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2789357359936426897
+ 16101291896048576683
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11420474396559742656
+ 6958362917585628191
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 6811779909537199081
+ 829525110335272310
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2407516010050573816
+ 7322753158848112633
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 5735401648209592903
+ 13587257461703619696
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2407516010050573816
+ 7322753158848112633
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 5735401648209592903
+ 13587257461703619696
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2407516010050573816
+ 7322753158848112633
]
],
- "bugs": [
- 1759
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 5735401648209592903
+ 13587257461703619696
]
],
- "bugs": [
- 1759
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 16722577663537717052
+ 10584626711301986223
]
],
- "bugs": [
- 1759
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2407516010050573816
+ 7322753158848112633
]
],
- "bugs": [
- 1759
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 5735401648209592903
+ 13587257461703619696
]
],
- "bugs": [
- 1759
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 16722577663537717052
+ 10584626711301986223
]
],
- "bugs": [
- 1759
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"complexclip2_565.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10175733445319554072
+ 4055619075226987340
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2036989462359391258
+ 4557992853592297566
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"complexclip2_565.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10175733445319554072
+ 4055619075226987340
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2036989462359391258
+ 4557992853592297566
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 7633944210736451677
+ 4723751871359287410
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2594983628740042115
+ 16275740961157987318
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"complexclip2_565.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 7633944210736451677
+ 4723751871359287410
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2594983628740042115
+ 16275740961157987318
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10175733445319554072
+ 4055619075226987340
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2036989462359391258
+ 4557992853592297566
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10175733445319554072
+ 4055619075226987340
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2036989462359391258
+ 4557992853592297566
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"complexclip2_565.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-mac.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-mac.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-mac.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 3224501961775566147
+ 15826989673456070846
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-mac.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10275865613222220507
+ 16802525720487425080
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10275865613222220507
+ 16802525720487425080
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10275865613222220507
+ 16802525720487425080
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 10275865613222220507
+ 16802525720487425080
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11405847735693538070
+ 14602262721761630857
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_8888.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 4978814888142061167
+ 3481217777013051559
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 1439955102723765584
+ 16802525720487425080
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 8745200028676261652
+ 12587234088162094708
]
- ]
+ ],
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"bleed_gpu.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
12241316569839901585
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_checkerboard_high_512_256_gpu.png": {
"allowed-digests": [
12241316569839901585
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_checkerboard_medium_512_256_gpu.png": {
"allowed-digests": [
13919524755191883787
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_image_high_mandrill_512.png_gpu.png": {
"allowed-digests": [
13919524755191883787
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_image_medium_mandrill_512.png_gpu.png": {
"allowed-digests": [
3631077966779184085
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_text_high_72.00pt_gpu.png": {
"allowed-digests": [
3631077966779184085
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_text_medium_72.00pt_gpu.png": {
"allowed-digests": [
8650483291288564728
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_checkerboard_192_192_gpu.png": {
"allowed-digests": [
7154075947687660440
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_image_mandrill_256.png_gpu.png": {
"allowed-digests": [
14830136006359090292
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_image_mandrill_512.png_gpu.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 2373323581539004655
+ 14984702717513096997
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 8745200028676261652
+ 12587234088162094708
]
- ]
+ ],
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"bleed_gpu.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_gpu.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
12241316569839901585
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_checkerboard_high_512_256_gpu.png": {
"allowed-digests": [
12241316569839901585
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_checkerboard_medium_512_256_gpu.png": {
"allowed-digests": [
13919524755191883787
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_image_high_mandrill_512.png_gpu.png": {
"allowed-digests": [
13919524755191883787
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_image_medium_mandrill_512.png_gpu.png": {
"allowed-digests": [
3631077966779184085
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_text_high_72.00pt_gpu.png": {
"allowed-digests": [
3631077966779184085
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"downsamplebitmap_text_medium_72.00pt_gpu.png": {
"allowed-digests": [
8650483291288564728
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_checkerboard_192_192_gpu.png": {
"allowed-digests": [
7154075947687660440
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_image_mandrill_256.png_gpu.png": {
"allowed-digests": [
14830136006359090292
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "ignore-failure": true,
+ "reviewed-by-human": true
},
"filterbitmap_image_mandrill_512.png_gpu.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 7353287899127074472
+ 13257802686942423930
]
],
- "bugs": [
- 1578
- ],
- "reviewed-by-human": false
+ "reviewed-by-human": true
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
"allowed-digests": [
[
"bitmap-64bitMD5",
- 11235313591528676486
+ 16744651928576717976
]
],
- "bugs": [
- 1578
- ],
"reviewed-by-human": false
},
"colortype_pdf-poppler.png": {
static const char* gConfigNames[] = {
"unknown config",
- "A1",
"A8",
"Index8",
"565",
static const char* gConfigNames[] = {
"unknown config",
- "A1",
"A8",
"Index8",
"565",
import re
import shutil
import socket
+import subprocess
import sys
import thread
+import threading
import time
import urlparse
ACTUALS_SVN_REPO = 'http://skia-autogen.googlecode.com/svn/gm-actual'
PATHSPLIT_RE = re.compile('/([^/]+)/(.+)')
-TRUNK_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.realpath(__file__))))
EXPECTATIONS_DIR = os.path.join(TRUNK_DIRECTORY, 'expectations', 'gm')
GENERATED_IMAGES_ROOT = os.path.join(PARENT_DIRECTORY, 'static',
'generated-images')
_SERVER = None # This gets filled in by main()
+
+def _run_command(args, directory):
+ """Runs a command and returns stdout as a single string.
+
+ Args:
+ args: the command to run, as a list of arguments
+ directory: directory within which to run the command
+
+ Returns: stdout, as a string
+
+ Raises an Exception if the command failed (exited with nonzero return code).
+ """
+ logging.debug('_run_command: %s in directory %s' % (args, directory))
+ proc = subprocess.Popen(args, cwd=directory,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ if proc.returncode is not 0:
+ raise Exception('command "%s" failed in dir "%s": %s' %
+ (args, directory, stderr))
+ return stdout
+
+
def _get_routable_ip_address():
"""Returns routable IP address of this host (the IP address of its network
interface that would be used for most traffic, not its localhost
sock.close()
return host
+
def _create_svn_checkout(dir_path, repo_url):
"""Creates local checkout of an SVN repository at the specified directory
path, returning an svn.Svn object referring to the local checkout.
self._actuals_repo = _create_svn_checkout(
dir_path=actuals_dir, repo_url=ACTUALS_SVN_REPO)
- # We only update the expectations dir if the server was run with a
- # nonzero --reload argument; otherwise, we expect the user to maintain
- # her own expectations as she sees fit.
- #
- # TODO(epoger): Use git instead of svn to update the expectations dir, since
- # the Skia repo is moving to git.
- # When we make that change, we will have to update the entire workspace,
- # not just the expectations dir, because git only operates on the repo
- # as a whole.
- # And since Skia uses depot_tools to manage its dependencies, we will have
- # to run "gclient sync" rather than a raw "git pull".
- if reload_seconds:
- self._expectations_repo = svn.Svn(EXPECTATIONS_DIR)
- else:
- self._expectations_repo = None
+ # Reentrant lock that must be held whenever updating EITHER of:
+ # 1. self._results
+ # 2. the expected or actual results on local disk
+ self.results_rlock = threading.RLock()
+ # self._results will be filled in by calls to update_results()
+ self._results = None
+ @property
+ def results(self):
+ """ Returns the most recently generated results, or None if update_results()
+ has not been called yet. """
+ return self._results
+
+ @property
def is_exported(self):
""" Returns true iff HTTP clients on other hosts are allowed to access
this server. """
return self._export
+ @property
def is_editable(self):
""" Returns true iff HTTP clients are allowed to submit new baselines. """
return self._editable
+ @property
def reload_seconds(self):
""" Returns the result reload period in seconds, or 0 if we don't reload
results. """
return self._reload_seconds
def update_results(self):
- """ Create or update self.results, based on the expectations in
+ """ Create or update self._results, based on the expectations in
EXPECTATIONS_DIR and the latest actuals from skia-autogen.
+
+ We hold self.results_rlock while we do this, to guarantee that no other
+ thread attempts to update either self._results or the underlying files at
+ the same time.
"""
- logging.info('Updating actual GM results in %s from SVN repo %s ...' % (
- self._actuals_dir, ACTUALS_SVN_REPO))
- self._actuals_repo.Update('.')
+ with self.results_rlock:
+ logging.info('Updating actual GM results in %s from SVN repo %s ...' % (
+ self._actuals_dir, ACTUALS_SVN_REPO))
+ self._actuals_repo.Update('.')
+
+ # We only update the expectations dir if the server was run with a
+ # nonzero --reload argument; otherwise, we expect the user to maintain
+ # her own expectations as she sees fit.
+ #
+ # Because the Skia repo is moving from SVN to git, and git does not
+ # support updating a single directory tree, we have to update the entire
+ # repo checkout.
+ #
+ # Because Skia uses depot_tools, we have to update using "gclient sync"
+ # instead of raw git (or SVN) update. Happily, this will work whether
+ # the checkout was created using git or SVN.
+ if self._reload_seconds:
+ logging.info(
+ 'Updating expected GM results in %s by syncing Skia repo ...' %
+ EXPECTATIONS_DIR)
+ _run_command(['gclient', 'sync'], TRUNK_DIRECTORY)
- if self._expectations_repo:
logging.info(
- 'Updating expected GM results in %s ...' % EXPECTATIONS_DIR)
- self._expectations_repo.Update('.')
-
- logging.info(
('Parsing results from actuals in %s and expectations in %s, '
- + 'and generating pixel diffs (may take a while) ...') % (
- self._actuals_dir, EXPECTATIONS_DIR))
- self.results = results.Results(
- actuals_root=self._actuals_dir,
- expected_root=EXPECTATIONS_DIR,
- generated_images_root=GENERATED_IMAGES_ROOT)
+ + 'and generating pixel diffs (may take a while) ...') % (
+ self._actuals_dir, EXPECTATIONS_DIR))
+ self._results = results.Results(
+ actuals_root=self._actuals_dir,
+ expected_root=EXPECTATIONS_DIR,
+ generated_images_root=GENERATED_IMAGES_ROOT)
def _result_reloader(self):
- """ If --reload argument was specified, reload results at the appropriate
- interval.
+ """ Reload results at the appropriate interval. This never exits, so it
+ should be run in its own thread.
"""
- while self._reload_seconds:
+ while True:
time.sleep(self._reload_seconds)
self.update_results()
def run(self):
self.update_results()
- thread.start_new_thread(self._result_reloader, ())
+ if self._reload_seconds:
+ thread.start_new_thread(self._result_reloader, ())
if self._export:
server_address = ('', self._port)
# We only return these timestamps if the --reload argument was passed;
# otherwise, we have no idea when the expectations were last updated
# (we allow the user to maintain her own expectations as she sees fit).
- 'timeUpdated': time_updated if _SERVER.reload_seconds() else None,
+ 'timeUpdated': time_updated if _SERVER.reload_seconds else None,
'timeNextUpdateAvailable': (
- (time_updated+_SERVER.reload_seconds()) if _SERVER.reload_seconds()
+ (time_updated+_SERVER.reload_seconds) if _SERVER.reload_seconds
else None),
# The type we passed to get_results_of_type()
'dataHash': str(hash(repr(response_dict['testData']))),
# Whether the server will accept edits back.
- 'isEditable': _SERVER.is_editable(),
+ 'isEditable': _SERVER.is_editable,
# Whether the service is accessible from other hosts.
- 'isExported': _SERVER.is_exported(),
+ 'isExported': _SERVER.is_exported,
}
self.send_json_dict(response_dict)
except:
Raises an Exception if there were any problems.
"""
- if not _SERVER.is_editable():
+ if not _SERVER.is_editable:
raise Exception('this server is not running in --editable mode')
content_type = self.headers[_HTTP_HEADER_CONTENT_TYPE]
logging.debug('do_POST_edits: received new GM expectations data [%s]' %
data)
- # Since we must make multiple calls to the Results object, grab a
- # reference to it in case it is updated to point at a new Results
- # object within another thread.
- results_obj = _SERVER.results
- oldResultsType = data['oldResultsType']
- oldResults = results_obj.get_results_of_type(oldResultsType)
- oldResultsHash = str(hash(repr(oldResults['testData'])))
- if oldResultsHash != data['oldResultsHash']:
- raise Exception('results of type "%s" changed while the client was '
- 'making modifications. The client should reload the '
- 'results and submit the modifications again.' %
- oldResultsType)
- results_obj.edit_expectations(data['modifications'])
-
- # Now that the edits have been committed, update results to reflect them.
- _SERVER.update_results()
+ # Update the results on disk with the information we received from the
+ # client.
+ # We must hold _SERVER.results_rlock while we do this, to guarantee that
+ # no other thread updates expectations (from the Skia repo) while we are
+ # updating them (using the info we received from the client).
+ with _SERVER.results_rlock:
+ oldResultsType = data['oldResultsType']
+ oldResults = _SERVER.results.get_results_of_type(oldResultsType)
+ oldResultsHash = str(hash(repr(oldResults['testData'])))
+ if oldResultsHash != data['oldResultsHash']:
+ raise Exception('results of type "%s" changed while the client was '
+ 'making modifications. The client should reload the '
+ 'results and submit the modifications again.' %
+ oldResultsType)
+ _SERVER.results.edit_expectations(data['modifications'])
+ # Read the updated results back from disk.
+ _SERVER.update_results()
def redirect_to(self, url):
""" Redirect the HTTP client to a different url.
parser.add_argument('--reload', type=int,
help=('How often (a period in seconds) to update the '
'results. If specified, both expected and actual '
- 'results will be updated. '
+ 'results will be updated by running "gclient sync" '
+ 'on your Skia checkout as a whole. '
'By default, we do not reload at all, and you '
'must restart the server to pick up new data.'),
default=0)
reload_seconds=args.reload)
_SERVER.run()
+
if __name__ == '__main__':
main()
'conditions': [
[ 'skia_angle', {
'target_defaults': {
+ 'include_dirs': [
+ '$(DXSDK_DIR)/Include',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'conditions': [
+ [ 'skia_arch_width == 32 ', {
+ 'AdditionalLibraryDirectories': [
+ '$(DXSDK_DIR)/Lib/x86',
+ ],
+ },{
+ 'AdditionalLibraryDirectories': [
+ '$(DXSDK_DIR)/Lib/x64',
+ ],
+ }],
+ ],
+ },
+ },
'defines': [
'NOMINMAX',
],
+ 'defines/': [
+ ['exclude', 'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES'],
+ ],
},
'variables': {
'component': 'static_library',
'../src/effects',
'../src/utils',
],
- 'includes': [
- 'bench.gypi'
- ],
'dependencies': [
'skia_lib.gyp:skia_lib',
'bench_timer',
'flags.gyp:flags',
],
+ 'sources': [
+ '../bench/AAClipBench.cpp',
+ '../bench/BicubicBench.cpp',
+ '../bench/BitmapBench.cpp',
+ '../bench/BitmapRectBench.cpp',
+ '../bench/BitmapScaleBench.cpp',
+ '../bench/BlurBench.cpp',
+ '../bench/BlurImageFilterBench.cpp',
+ '../bench/BlurRectBench.cpp',
+ '../bench/BlurRoundRectBench.cpp',
+ '../bench/ChartBench.cpp',
+ '../bench/ChecksumBench.cpp',
+ '../bench/ChromeBench.cpp',
+ '../bench/CmapBench.cpp',
+ '../bench/ColorFilterBench.cpp',
+ '../bench/CoverageBench.cpp',
+ '../bench/DashBench.cpp',
+ '../bench/DecodeBench.cpp',
+ '../bench/DeferredCanvasBench.cpp',
+ '../bench/DeferredSurfaceCopyBench.cpp',
+ '../bench/DisplacementBench.cpp',
+ '../bench/FSRectBench.cpp',
+ '../bench/FontCacheBench.cpp',
+ '../bench/FontScalerBench.cpp',
+ '../bench/GameBench.cpp',
+ '../bench/GrMemoryPoolBench.cpp',
+ '../bench/GrResourceCacheBench.cpp',
+ '../bench/GradientBench.cpp',
+ '../bench/HairlinePathBench.cpp',
+ '../bench/ImageCacheBench.cpp',
+ '../bench/ImageDecodeBench.cpp',
+ '../bench/InterpBench.cpp',
+ '../bench/LightingBench.cpp',
+ '../bench/LineBench.cpp',
+ '../bench/MagnifierBench.cpp',
+ '../bench/MathBench.cpp',
+ '../bench/Matrix44Bench.cpp',
+ '../bench/MatrixBench.cpp',
+ '../bench/MatrixConvolutionBench.cpp',
+ '../bench/MemoryBench.cpp',
+ '../bench/MemsetBench.cpp',
+ '../bench/MergeBench.cpp',
+ '../bench/MorphologyBench.cpp',
+ '../bench/MutexBench.cpp',
+ '../bench/PathBench.cpp',
+ '../bench/PathIterBench.cpp',
+ '../bench/PathUtilsBench.cpp',
+ '../bench/PerlinNoiseBench.cpp',
+ '../bench/PicturePlaybackBench.cpp',
+ '../bench/PictureRecordBench.cpp',
+ '../bench/PremulAndUnpremulAlphaOpsBench.cpp',
+ '../bench/RTreeBench.cpp',
+ '../bench/ReadPixBench.cpp',
+ '../bench/RectBench.cpp',
+ '../bench/RectoriBench.cpp',
+ '../bench/RefCntBench.cpp',
+ '../bench/RegionBench.cpp',
+ '../bench/RegionContainBench.cpp',
+ '../bench/RepeatTileBench.cpp',
+ '../bench/ScalarBench.cpp',
+ '../bench/ShaderMaskBench.cpp',
+ '../bench/SkipZeroesBench.cpp',
+ '../bench/SortBench.cpp',
+ '../bench/StrokeBench.cpp',
+ '../bench/TableBench.cpp',
+ '../bench/TextBench.cpp',
+ '../bench/TileBench.cpp',
+ '../bench/VertBench.cpp',
+ '../bench/WritePixelsBench.cpp',
+ '../bench/WriterBench.cpp',
+ '../bench/XfermodeBench.cpp',
+
+ '../bench/SkBenchLogger.cpp',
+ '../bench/SkBenchLogger.h',
+ '../bench/SkBenchmark.cpp',
+ '../bench/SkBenchmark.h',
+ '../bench/benchmain.cpp',
+ ],
'conditions': [
['skia_gpu == 1',
{
+++ /dev/null
-# sources and conditions used in skia's bench.gyp and chromium's skia.gyp
-#
-{
- 'sources': [
- '../bench/benchmain.cpp',
- '../bench/SkBenchmark.h',
- '../bench/SkBenchmark.cpp',
- '../bench/AAClipBench.cpp',
- '../bench/BicubicBench.cpp',
- '../bench/BitmapBench.cpp',
- '../bench/BitmapRectBench.cpp',
- '../bench/BitmapScaleBench.cpp',
- '../bench/BlurBench.cpp',
- '../bench/BlurImageFilterBench.cpp',
- '../bench/BlurRectBench.cpp',
- '../bench/BlurRoundRectBench.cpp',
- '../bench/ChecksumBench.cpp',
- '../bench/ChartBench.cpp',
- '../bench/ChromeBench.cpp',
- '../bench/CmapBench.cpp',
- '../bench/ColorFilterBench.cpp',
- '../bench/CoverageBench.cpp',
- '../bench/DashBench.cpp',
- '../bench/DecodeBench.cpp',
- '../bench/DeferredCanvasBench.cpp',
- '../bench/DeferredSurfaceCopyBench.cpp',
- '../bench/DisplacementBench.cpp',
- '../bench/FontCacheBench.cpp',
- '../bench/FontScalerBench.cpp',
- '../bench/FSRectBench.cpp',
- '../bench/GameBench.cpp',
- '../bench/GradientBench.cpp',
- '../bench/GrMemoryPoolBench.cpp',
- '../bench/GrResourceCacheBench.cpp',
- '../bench/ImageCacheBench.cpp',
- '../bench/ImageDecodeBench.cpp',
- '../bench/InterpBench.cpp',
- '../bench/HairlinePathBench.cpp',
- '../bench/LineBench.cpp',
- '../bench/LightingBench.cpp',
- '../bench/MagnifierBench.cpp',
- '../bench/MathBench.cpp',
- '../bench/Matrix44Bench.cpp',
- '../bench/MatrixBench.cpp',
- '../bench/MatrixConvolutionBench.cpp',
- '../bench/MemoryBench.cpp',
- '../bench/MemsetBench.cpp',
- '../bench/MergeBench.cpp',
- '../bench/MorphologyBench.cpp',
- '../bench/MutexBench.cpp',
- '../bench/PathBench.cpp',
- '../bench/PathIterBench.cpp',
- '../bench/PathUtilsBench.cpp',
- '../bench/PerlinNoiseBench.cpp',
- '../bench/PicturePlaybackBench.cpp',
- '../bench/PictureRecordBench.cpp',
- '../bench/ReadPixBench.cpp',
- '../bench/PremulAndUnpremulAlphaOpsBench.cpp',
- '../bench/RectBench.cpp',
- '../bench/RectoriBench.cpp',
- '../bench/RefCntBench.cpp',
- '../bench/RegionBench.cpp',
- '../bench/RegionContainBench.cpp',
- '../bench/RepeatTileBench.cpp',
- '../bench/RTreeBench.cpp',
- '../bench/ScalarBench.cpp',
- '../bench/ShaderMaskBench.cpp',
- '../bench/SkipZeroesBench.cpp',
- '../bench/SortBench.cpp',
- '../bench/StrokeBench.cpp',
- '../bench/TableBench.cpp',
- '../bench/TextBench.cpp',
- '../bench/TileBench.cpp',
- '../bench/VertBench.cpp',
- '../bench/WriterBench.cpp',
- '../bench/XfermodeBench.cpp',
- '../bench/WritePixelsBench.cpp',
-
- '../bench/SkBenchLogger.h',
- '../bench/SkBenchLogger.cpp',
- ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
'<(skia_src_path)/core/SkBlitRow_D32.cpp',
'<(skia_src_path)/core/SkBlitter.h',
'<(skia_src_path)/core/SkBlitter.cpp',
- '<(skia_src_path)/core/SkBlitter_A1.cpp',
'<(skia_src_path)/core/SkBlitter_A8.cpp',
'<(skia_src_path)/core/SkBlitter_ARGB32.cpp',
'<(skia_src_path)/core/SkBlitter_RGB16.cpp',
'includes': [ 'gmslides.gypi' ],
'sources': [
'../dm/DM.cpp',
- '../dm/DMComparisonTask.cpp',
+ '../dm/DMChecksumTask.cpp',
'../dm/DMCpuTask.cpp',
'../dm/DMGpuTask.cpp',
'../dm/DMPipeTask.cpp',
'../dm/DMSerializeTask.cpp',
'../dm/DMTask.cpp',
'../dm/DMTaskRunner.cpp',
+ '../dm/DMTileGridTask.cpp',
'../dm/DMUtil.cpp',
'../dm/DMWriteTask.cpp',
'../gm/gm.cpp',
'../gm/downsamplebitmap.cpp',
'../gm/drawbitmaprect.cpp',
'../gm/drawlooper.cpp',
+ '../gm/dropshadowimagefilter.cpp',
'../gm/extractbitmap.cpp',
'../gm/emptypath.cpp',
'../gm/fatpathfill.cpp',
'../gm/perlinnoise.cpp',
'../gm/points.cpp',
'../gm/poly2poly.cpp',
+ '../gm/polygons.cpp',
'../gm/quadpaths.cpp',
'../gm/rects.cpp',
'../gm/rrect.cpp',
'<(skia_src_path)/gpu/GrTextureAccess.cpp',
'<(skia_src_path)/gpu/GrTHashTable.h',
'<(skia_src_path)/gpu/GrVertexBuffer.h',
- '<(skia_src_path)/gpu/gr_unittests.cpp',
'<(skia_src_path)/gpu/effects/Gr1DKernelEffect.h',
'<(skia_src_path)/gpu/effects/GrConfigConversionEffect.cpp',
'../src/opts/SkBitmapProcState_matrixProcs_neon.cpp',
'../src/opts/SkBitmapProcState_matrix_clamp_neon.h',
'../src/opts/SkBitmapProcState_matrix_repeat_neon.h',
+ '../src/opts/SkBlitMask_opts_arm_neon.cpp',
'../src/opts/SkBlitRow_opts_arm_neon.cpp',
'../src/opts/SkMorphology_opts_neon.cpp',
'../src/opts/SkXfermode_opts_arm_neon.cpp',
'../tests/GradientTest.cpp',
'../tests/GrMemoryPoolTest.cpp',
'../tests/GrSurfaceTest.cpp',
+ '../tests/GrUnitTests.cpp',
'../tests/HashCacheTest.cpp',
'../tests/ImageCacheTest.cpp',
'../tests/ImageDecodingTest.cpp',
enum Config {
kNo_Config, //!< bitmap has not been configured
- /**
- * 1-bit per pixel, (0 is transparent, 1 is opaque)
- * Valid as a destination (target of a canvas), but not valid as a src.
- * i.e. you can draw into a 1-bit bitmap, but you cannot draw from one.
- */
- kA1_Config,
kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors
kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
*/
inline uint8_t* getAddr8(int x, int y) const;
- /** Returns the address of the byte containing the pixel specified by x,y
- * for 1bit pixels.
- * In debug build, this asserts that the pixels are allocated and locked,
- * and that the config is 1-bit, however none of these checks are performed
- * in the release build.
- */
- inline uint8_t* getAddr1(int x, int y) const;
-
/** Returns the color corresponding to the pixel specified by x,y for
* colortable based bitmaps.
* In debug build, this asserts that the pixels are allocated and locked,
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}
-// returns the address of the byte that contains the x coordinate
-inline uint8_t* SkBitmap::getAddr1(int x, int y) const {
- SkASSERT(fPixels);
- SkASSERT(fConfig == kA1_Config);
- SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
- return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
-}
-
#endif
src: 32/24, no-alpha -> 4
src: 32/24, yes-alpha -> 5
*/
- void setPrefConfigTable(const SkBitmap::Config pref[6]);
+ void setPrefConfigTable(const SkBitmap::Config pref[5]);
/**
* Optional table describing the caller's preferred config based on
// V13: add flag to drawBitmapRectToRect
// parameterize blurs by sigma rather than radius
// V14: Add flags word to PathRef serialization
+ // V15: Remove A1 bitmpa config (and renumber remaining configs)
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V13_AND_ALL_OTHER_INSTANCES_TOO
static const uint32_t PRIOR_PRIOR_PICTURE_VERSION = 12; // TODO: remove when .skps regenerated
#endif
#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TOO
static const uint32_t PRIOR_PICTURE_VERSION2 = 13; // TODO: remove when .skps regenerated
#endif
- static const uint32_t PICTURE_VERSION = 14;
+ static const uint32_t PICTURE_VERSION = 15;
// fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
#define SkString_DEFINED
#include "SkScalar.h"
+#include "SkTArray.h"
#include <stdarg.h>
a.swap(b);
}
+// Split str on any characters in delimiters into out. (Think, strtok with a sane API.)
+void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out);
+
#endif
class SK_API SkDropShadowImageFilter : public SkImageFilter {
public:
SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor, SkImageFilter* input = NULL);
+ SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDropShadowImageFilter)
protected:
virtual bool onFilterImage(Proxy*, const SkBitmap& source, const SkMatrix&, SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
private:
- SkScalar fDx, fDy, fSigma;
+ SkScalar fDx, fDy, fSigmaX, fSigmaY;
SkColor fColor;
typedef SkImageFilter INHERITED;
};
virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) = 0;
virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) = 0;
- // TODO: make this pure-virtual once all ports know about it
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
unsigned styleBits) = 0;
private:
try {
System.loadLibrary("skia_android");
+ } catch (UnsatisfiedLinkError e) {
+ // This might be because skia was linked to SampleApp statically.
+ }
+
+ try {
System.loadLibrary("SampleApp");
LinearLayout holder = (LinearLayout) findViewById(R.id.holder);
fi
adb_push_if_needed "${SKIA_OUT}/${configuration}/skia_launcher" /data/local/tmp
-adb_push_if_needed "${SKIA_OUT}/${configuration}/lib.target/libskia_android.so" /data/local/tmp
+if [ -f "${SKIA_OUT}/${configuration}/lib.target/libskia_android.so" ]; then
+ # Does not exist for builds with static skia.
+ adb_push_if_needed "${SKIA_OUT}/${configuration}/lib.target/libskia_android.so" /data/local/tmp
+fi
adb_push_if_needed "${SKIA_OUT}/${configuration}/lib.target/lib${runVars[0]}.so" /data/local/tmp
STATUS_FILENAME="/data/local/tmp/.skia_tmp_$(date +%s%N)"
DEFINES="${DEFINES} host_os=$(uname -s | sed -e 's/Linux/linux/;s/Darwin/mac/')"
DEFINES="${DEFINES} skia_os=android"
DEFINES="${DEFINES} android_base=${SCRIPT_DIR}/.."
- DEFINES="${DEFINES} skia_shared_lib=1"
+ if [[ "$GYP_DEFINES" != *skia_shared_lib=* ]]; then
+ DEFINES="${DEFINES} skia_shared_lib=1"
+ fi
# Setup the build variation depending on the target device
TARGET_DEVICE="$1"
# still build.
{
'destination': '<(PRODUCT_DIR)/android/libs/<(android_arch)',
- 'files': [
- '<(SHARED_LIB_DIR)/libSampleApp.so',
- '<(SHARED_LIB_DIR)/libskia_android.so',
+ 'conditions': [
+ [ 'skia_shared_lib', {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libSampleApp.so',
+ '<(SHARED_LIB_DIR)/libskia_android.so',
+ ]}, {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libSampleApp.so',
+ ]}
+ ],
],
},
],
return -1;
}
+ void* skiaLibrary;
+
+#if defined(SKIA_DLL)
// load the local skia shared library
- void* skiaLibrary = load_library(appLocation, "skia_android");
+ skiaLibrary = load_library(appLocation, "skia_android");
if (NULL == skiaLibrary)
{
return -1;
}
+#endif
// load the appropriate library
void* appLibrary = load_library(appLocation, argv[1]);
return -1;
}
+#if !defined(SKIA_DLL)
+ skiaLibrary = appLibrary;
+#endif
+
// find the address of the main function
int (*app_main)(int, const char**);
*(void **) (&app_main) = dlsym(appLibrary, "main");
static SkBitmap::Config gConfigCycle[] = {
SkBitmap::kNo_Config, // none -> none
- SkBitmap::kNo_Config, // a1 -> none
SkBitmap::kNo_Config, // a8 -> none
SkBitmap::kNo_Config, // index8 -> none
SkBitmap::kARGB_4444_Config, // 565 -> 4444
static const char* gConfigNames[] = {
"unknown config",
- "A1",
"A8",
"Index8",
"565",
static const char* gConfigNames[] = {
"unknown config",
- "A1",
"A8",
"Index8",
"565",
const char* formatName;
switch (format) {
case 0: formatName = "none"; break;
- case 1: formatName = "A1"; break;
- case 2: formatName = "A8"; break;
- case 3: formatName = "Index8"; break;
- case 4: formatName = "RGB16"; break;
- case 5: formatName = "RGB32"; break;
+ case 1: formatName = "A8"; break;
+ case 2: formatName = "Index8"; break;
+ case 3: formatName = "RGB16"; break;
+ case 4: formatName = "RGB32"; break;
}
SkDebugf("format=\"%s\" />\n", formatName);
}
int bpp;
switch (config) {
case kNo_Config:
- case kA1_Config:
bpp = 0; // not applicable
break;
case kA8_Config:
switch (c) {
case kNo_Config:
break;
- case kA1_Config:
- rowBytes.set(width);
- rowBytes.add(7);
- rowBytes.shiftRight(3);
- break;
case kA8_Config:
case kIndex8_Config:
rowBytes.set(width);
case SkBitmap::kNo_Config:
alphaType = kIgnore_SkAlphaType;
break;
- case SkBitmap::kA1_Config:
case SkBitmap::kA8_Config:
if (kUnpremul_SkAlphaType == alphaType) {
alphaType = kPremul_SkAlphaType;
case SkBitmap::kRGB_565_Config:
alphaType = kOpaque_SkAlphaType;
break;
+ default:
+ return false;
}
if (canonical) {
*canonical = alphaType;
case SkBitmap::kIndex8_Config:
base += x;
break;
- case SkBitmap::kA1_Config:
- base += x >> 3;
break;
default:
SkDEBUGFAIL("Can't return addr for config");
SkASSERT((unsigned)y < (unsigned)this->height());
switch (this->config()) {
- case SkBitmap::kA1_Config: {
- uint8_t* addr = this->getAddr1(x, y);
- uint8_t mask = 1 << (7 - (x % 8));
- if (addr[0] & mask) {
- return SK_ColorBLACK;
- } else {
- return 0;
- }
- }
case SkBitmap::kA8_Config: {
uint8_t* addr = this->getAddr8(x, y);
return SkColorSetA(0, addr[0]);
return SkUnPreMultiply::PMColorToColor(addr[0]);
}
case kNo_Config:
+ default:
SkASSERT(false);
return 0;
}
const int width = bm.width();
switch (bm.config()) {
- case SkBitmap::kA1_Config: {
- // TODO
- } break;
case SkBitmap::kA8_Config: {
unsigned a = 0xFF;
for (int y = 0; y < height; ++y) {
}
switch (fConfig) {
- case kA1_Config: {
- uint8_t* p = this->getAddr1(area.fLeft, area.fTop);
- const int left = area.fLeft >> 3;
- const int right = area.fRight >> 3;
-
- int middle = right - left - 1;
-
- uint8_t leftMask = 0xFF >> (area.fLeft & 7);
- uint8_t rightMask = ~(0xFF >> (area.fRight & 7));
- if (left == right) {
- leftMask &= rightMask;
- rightMask = 0;
- }
-
- a = (a >> 7) ? 0xFF : 0;
- while (--height >= 0) {
- uint8_t* startP = p;
-
- *p = (*p & ~leftMask) | (a & leftMask);
- p++;
- if (middle > 0) {
- memset(p, a, middle);
- p += middle;
- }
- if (rightMask) {
- *p = (*p & ~rightMask) | (a & rightMask);
- }
-
- p = startP + rowBytes;
- }
- break;
- }
case kA8_Config: {
uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
while (--height >= 0) {
break;
case SkBitmap::kNo_Config:
- case SkBitmap::kA1_Config:
default:
return SUB_OFFSET_FAILURE;
}
case SkBitmap::kNo_Config:
// Fall through.
- case SkBitmap::kA1_Config:
- // Fall through.
default:
return false;
}
case kRGB_565_Config:
case kARGB_8888_Config:
break;
- case kA1_Config:
case kIndex8_Config:
if (!sameConfigs) {
return false;
default:
return false;
}
-
- // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config
- if (this->config() == kA1_Config && !sameConfigs) {
- return false;
- }
-
return true;
}
void SkBitmap::toString(SkString* str) const {
static const char* gConfigNames[kConfigCount] = {
- "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888"
+ "NONE", "A8", "INDEX8", "565", "4444", "8888"
};
str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
switch (device.config()) {
- case SkBitmap::kA1_Config:
- SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter,
- storage, storageSize, (device, *paint));
- break;
-
case SkBitmap::kA8_Config:
if (drawCoverage) {
SkASSERT(NULL == shader);
+++ /dev/null
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkCoreBlitters.h"
-
-SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint)
- : 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());
-
- if (fSrcA <= 0x7F) {
- return;
- }
- uint8_t* dst = fDevice.getAddr1(x, y);
- int right = x + width;
-
- int left_mask = 0xFF >> (x & 7);
- 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) {
- SkASSERT(full_runs >= 0);
- full_runs -= 1;
- rite_mask = 0xFF;
- }
- if (left_mask == 0xFF) {
- full_runs -= 1;
- }
- if (full_runs < 0) {
- SkASSERT((left_mask & rite_mask) != 0);
- *dst |= (left_mask & rite_mask);
- } else {
- *dst++ |= left_mask;
- memset(dst, 0xFF, full_runs);
- dst += full_runs;
- *dst |= rite_mask;
- }
-}
///////////////////////////////////////////////////////////////////////////////
-class SkA1_Blitter : public SkRasterBlitter {
-public:
- SkA1_Blitter(const SkBitmap& device, const SkPaint& paint);
- virtual void blitH(int x, int y, int width) SK_OVERRIDE;
-
-private:
- uint8_t fSrcA;
-
- // illegal
- SkA1_Blitter& operator=(const SkA1_Blitter&);
-
- typedef SkRasterBlitter INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
/* These return the correct subclass of blitter for their device config.
Currently, they make the following assumptions about the state of the
fGlyphArray.setReserve(kMinGlyphCount);
- fMetricsCount = 0;
- fAdvanceCount = 0;
fAuxProcList = NULL;
}
if (kJustAdvance_MetricsType == mtype) {
fScalerContext->getAdvance(glyph);
- fAdvanceCount += 1;
} else {
SkASSERT(kFull_MetricsType == mtype);
fScalerContext->getMetrics(glyph);
- fMetricsCount += 1;
}
return glyph;
SkTDArray<SkGlyph*> fGlyphArray;
SkChunkAlloc fGlyphAlloc;
- int fMetricsCount, fAdvanceCount;
-
struct CharGlyphRec {
uint32_t fID; // unichar + subpixel
SkGlyph* fGlyph;
};
// The size of a flat paint's POD fields
-// Include an SkScalar for hinting scale factor whether it is
-// supported or not so that an SKP is valid whether it was
-// created with support or not.
-
-static const uint32_t kPODPaintSize = 6 * sizeof(SkScalar) +
+static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1 * sizeof(SkColor) +
1 * sizeof(uint16_t) +
6 * sizeof(uint8_t);
ptr = write_scalar(ptr, this->getTextSize());
ptr = write_scalar(ptr, this->getTextScaleX());
ptr = write_scalar(ptr, this->getTextSkewX());
- // Dummy value for obsolete hinting scale factor. TODO: remove with next picture version
- ptr = write_scalar(ptr, SK_Scalar1);
ptr = write_scalar(ptr, this->getStrokeWidth());
ptr = write_scalar(ptr, this->getStrokeMiter());
*ptr++ = this->getColor();
buffer.writeScalar(fTextSize);
buffer.writeScalar(fTextScaleX);
buffer.writeScalar(fTextSkewX);
- // Dummy value for obsolete hinting scale factor. TODO: remove with next picture version
- buffer.writeScalar(SK_Scalar1);
buffer.writeScalar(fWidth);
buffer.writeScalar(fMiterLimit);
buffer.writeColor(fColor);
this->setTextSize(read_scalar(pod));
this->setTextScaleX(read_scalar(pod));
this->setTextSkewX(read_scalar(pod));
- // Skip the hinting scalar factor, which is not supported.
- read_scalar(pod);
this->setStrokeWidth(read_scalar(pod));
this->setStrokeMiter(read_scalar(pod));
this->setColor(*pod++);
#include "SkStream.h"
+static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
+
bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
if (NULL == stream) {
return false;
}
+ // Check magic bytes.
+ char magic[sizeof(kMagic)];
+ stream->read(magic, sizeof(kMagic));
+ if (0 != memcmp(magic, kMagic, sizeof(kMagic))) {
+ return false;
+ }
+
SkPictInfo info;
if (!stream->read(&info, sizeof(SkPictInfo))) {
return false;
info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
}
+ // Write 8 magic bytes to ID this file format.
+ SkASSERT(sizeof(kMagic) == 8);
+ stream->write(kMagic, sizeof(kMagic));
+
stream->write(&info, sizeof(info));
if (playback) {
stream->writeBool(true);
return hash;
}
-struct Key {
+struct SkScaledImageCache::Key {
Key(uint32_t genID,
SkScalar scaleX,
SkScalar scaleY,
#include "SkTDynamicHash.h"
namespace { // can't use static functions w/ template parameters
-const Key& key_from_rec(const SkScaledImageCache::Rec& rec) {
+const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec) {
return rec.fKey;
}
-uint32_t hash_from_key(const Key& key) {
+uint32_t hash_from_key(const SkScaledImageCache::Key& key) {
return key.fHash;
}
-bool eq_rec_key(const SkScaledImageCache::Rec& rec, const Key& key) {
+bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Key& key) {
return rec.fKey == key;
}
}
class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec,
- Key, key_from_rec, hash_from_key,
- eq_rec_key> {};
+ SkScaledImageCache::Key,
+ key_from_rec,
+ hash_from_key,
+ eq_rec_key> {};
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-/**
- This private method is the fully general record finder. All other
- record finders should call this funtion. */
+
SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(uint32_t genID,
SkScalar scaleX,
SkScalar scaleY,
const SkIRect& bounds) {
- if (bounds.isEmpty()) {
+ const Key key(genID, scaleX, scaleY, bounds);
+ return this->findAndLock(key);
+}
+
+/**
+ This private method is the fully general record finder. All other
+ record finders should call this function or the one above. */
+SkScaledImageCache::Rec* SkScaledImageCache::findAndLock(const SkScaledImageCache::Key& key) {
+ if (key.fBounds.isEmpty()) {
return NULL;
}
- Key key(genID, scaleX, scaleY, bounds);
#ifdef USE_HASH
Rec* rec = fHash->find(key);
#else
/**
This private method is the fully general record adder. All other
record adders should call this funtion. */
-void SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) {
+SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec* rec) {
SkASSERT(rec);
+ // See if we already have this key (racy inserts, etc.)
+ Rec* existing = this->findAndLock(rec->fKey);
+ if (existing != NULL) {
+ return rec_to_id(existing);
+ }
+
this->addToHead(rec);
SkASSERT(1 == rec->fLockCount);
#ifdef USE_HASH
#endif
// We may (now) be overbudget, so see if we need to purge something.
this->purgeAsNeeded();
+ return rec_to_id(rec);
}
SkScaledImageCache::ID* SkScaledImageCache::addAndLock(uint32_t genID,
const SkBitmap& bitmap) {
Key key(genID, SK_Scalar1, SK_Scalar1, SkIRect::MakeWH(width, height));
Rec* rec = SkNEW_ARGS(Rec, (key, bitmap));
- this->addAndLock(rec);
- return rec_to_id(rec);
+ return this->addAndLock(rec);
}
SkScaledImageCache::ID* SkScaledImageCache::addAndLock(const SkBitmap& orig,
}
Key key(orig.getGenerationID(), scaleX, scaleY, bounds);
Rec* rec = SkNEW_ARGS(Rec, (key, scaled));
- this->addAndLock(rec);
- return rec_to_id(rec);
+ return this->addAndLock(rec);
}
SkScaledImageCache::ID* SkScaledImageCache::addAndLockMip(const SkBitmap& orig,
}
Key key(orig.getGenerationID(), 0, 0, bounds);
Rec* rec = SkNEW_ARGS(Rec, (key, mip));
- this->addAndLock(rec);
- return rec_to_id(rec);
+ return this->addAndLock(rec);
}
void SkScaledImageCache::unlock(SkScaledImageCache::ID* id) {
public:
struct Rec;
+ struct Key;
private:
Rec* fHead;
Rec* fTail;
Rec* findAndLock(uint32_t generationID, SkScalar sx, SkScalar sy,
const SkIRect& bounds);
- void addAndLock(Rec* rec);
+ Rec* findAndLock(const Key& key);
+ ID* addAndLock(Rec* rec);
void purgeAsNeeded();
glyph->fHeight = SkToU16(ir.height());
if (glyph->fWidth > 0) {
- switch (fRec.fMaskFormat) {
- case SkMask::kLCD16_Format:
- case SkMask::kLCD32_Format:
- glyph->fWidth += 2;
- glyph->fLeft -= 1;
- break;
- default:
- break;
+ switch (fRec.fMaskFormat) {
+ case SkMask::kLCD16_Format:
+ case SkMask::kLCD32_Format:
+ glyph->fWidth += 2;
+ glyph->fLeft -= 1;
+ break;
+ default:
+ break;
+ }
}
- }
}
}
}
}
+static inline int convert_8_to_1(unsigned byte) {
+ SkASSERT(byte <= 0xFF);
+ return byte >> 7;
+}
+
+static uint8_t pack_8_to_1(const uint8_t alpha[8]) {
+ unsigned bits = 0;
+ for (int i = 0; i < 8; ++i) {
+ bits <<= 1;
+ bits |= convert_8_to_1(alpha[i]);
+ }
+ return SkToU8(bits);
+}
+
+static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
+ const int height = mask.fBounds.height();
+ const int width = mask.fBounds.width();
+ const int octs = width >> 3;
+ const int leftOverBits = width & 7;
+
+ uint8_t* dst = mask.fImage;
+ const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
+ SkASSERT(dstPad >= 0);
+
+ const int srcPad = srcRB - width;
+ SkASSERT(srcPad >= 0);
+
+ for (int y = 0; y < height; ++y) {
+ for (int i = 0; i < octs; ++i) {
+ *dst++ = pack_8_to_1(src);
+ src += 8;
+ }
+ if (leftOverBits > 0) {
+ unsigned bits = 0;
+ int shift = 7;
+ for (int i = 0; i < leftOverBits; ++i, --shift) {
+ bits |= convert_8_to_1(*src++ >> 7) << shift;
+ }
+ *dst++ = bits;
+ }
+ src += srcPad;
+ dst += dstPad;
+ }
+}
+
static void generateMask(const SkMask& mask, const SkPath& path,
const SkMaskGamma::PreBlend& maskPreBlend) {
- SkBitmap::Config config;
- SkPaint paint;
+ SkPaint paint;
int srcW = mask.fBounds.width();
int srcH = mask.fBounds.height();
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
-SkIntToScalar(mask.fBounds.fTop));
- if (SkMask::kBW_Format == mask.fFormat) {
- config = SkBitmap::kA1_Config;
- paint.setAntiAlias(false);
- } else {
- config = SkBitmap::kA8_Config;
- paint.setAntiAlias(true);
- switch (mask.fFormat) {
- case SkMask::kA8_Format:
- break;
- case SkMask::kLCD16_Format:
- case SkMask::kLCD32_Format:
- // TODO: trigger off LCD orientation
- dstW = 4*dstW - 8;
- matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1),
- -SkIntToScalar(mask.fBounds.fTop));
- matrix.postScale(SkIntToScalar(4), SK_Scalar1);
- dstRB = 0; // signals we need a copy
- break;
- default:
- SkDEBUGFAIL("unexpected mask format");
- }
+ SkBitmap::Config config = SkBitmap::kA8_Config;
+ paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat);
+ switch (mask.fFormat) {
+ case SkMask::kBW_Format:
+ dstRB = 0; // signals we need a copy
+ break;
+ case SkMask::kA8_Format:
+ break;
+ case SkMask::kLCD16_Format:
+ case SkMask::kLCD32_Format:
+ // TODO: trigger off LCD orientation
+ dstW = 4*dstW - 8;
+ matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1),
+ -SkIntToScalar(mask.fBounds.fTop));
+ matrix.postScale(SkIntToScalar(4), SK_Scalar1);
+ dstRB = 0; // signals we need a copy
+ break;
+ default:
+ SkDEBUGFAIL("unexpected mask format");
}
SkRasterClip clip;
draw.drawPath(path, paint);
switch (mask.fFormat) {
+ case SkMask::kBW_Format:
+ packA8ToA1(mask, bm.getAddr8(0, 0), bm.rowBytes());
+ break;
case SkMask::kA8_Format:
if (maskPreBlend.isApplicable()) {
applyLUTToA8Mask(mask, maskPreBlend.fG);
Rec fRec;
unsigned fBaseGlyphCount;
- virtual unsigned generateGlyphCount() = 0;
- virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
- virtual void generateAdvance(SkGlyph*) = 0;
- virtual void generateMetrics(SkGlyph*) = 0;
- virtual void generateImage(const SkGlyph&) = 0;
- virtual void generatePath(const SkGlyph&, SkPath*) = 0;
+ /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY.
+ * May call getMetrics if that would be just as fast.
+ */
+ virtual void generateAdvance(SkGlyph* glyph) = 0;
+
+ /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft,
+ * as well as fAdvanceX and fAdvanceY if not already set.
+ *
+ * TODO: fMaskFormat is set by getMetrics later; cannot be set here.
+ */
+ virtual void generateMetrics(SkGlyph* glyph) = 0;
+
+ /** Generates the contents of glyph.fImage.
+ * When called, glyph.fImage will be pointing to a pre-allocated,
+ * uninitialized region of memory of size glyph.computeImageSize().
+ * This method may change glyph.fMaskFormat if the new image size is
+ * less than or equal to the old image size.
+ *
+ * Because glyph.computeImageSize() will determine the size of fImage,
+ * generateMetrics will be called before generateImage.
+ */
+ virtual void generateImage(const SkGlyph& glyph) = 0;
+
+ /** Sets the passed path to the glyph outline.
+ * If this cannot be done the path is set to empty;
+ * this is indistinguishable from a glyph with an empty path.
+ * This does not set glyph.fPath.
+ *
+ * TODO: path is always glyph.fPath, no reason to pass separately.
+ */
+ virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0;
+
+ /** Retrieves font metrics.
+ * TODO: there is now a vertical bit, no need for two parameters.
+ */
virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
SkPaint::FontMetrics* mY) = 0;
- // default impl returns 0, indicating failure.
- virtual SkUnichar generateGlyphToChar(uint16_t);
+
+ /** Returns the number of glyphs in the font. */
+ virtual unsigned generateGlyphCount() = 0;
+
+ /** Returns the glyph id for the given unichar.
+ * If there is no 1:1 mapping from the unichar to a glyph id, returns 0.
+ */
+ virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0;
+
+ /** Returns the unichar for the given glyph id.
+ * If there is no 1:1 mapping from the glyph id to a unichar, returns 0.
+ * The default implementation always returns 0, indicating failure.
+ */
+ virtual SkUnichar generateGlyphToChar(uint16_t glyphId);
void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
return formattedOutput;
}
+void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
+ const char* end = str + strlen(str);
+ while (str != end) {
+ // Find a token.
+ const size_t len = strcspn(str, delimiters);
+ out->push_back().set(str, len);
+ str += len;
+ // Skip any delimiters.
+ str += strspn(str, delimiters);
+ }
+}
+
#undef VSNPRINTF
#undef SNPRINTF
uint32_t SkValidatingReadBuffer::getArrayCount() {
const size_t inc = sizeof(uint32_t);
fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
- return *(uint32_t*)fReader.peek();
+ return fError ? 0 : *(uint32_t*)fReader.peek();
}
void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) {
#include "SkFlattenableBuffers.h"
SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor color, SkImageFilter* input)
- : SkImageFilter(input)
+ : INHERITED(input)
, fDx(dx)
, fDy(dy)
- , fSigma(sigma)
+ , fSigmaX(sigma)
+ , fSigmaY(sigma)
+ , fColor(color)
+{
+}
+
+SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, SkImageFilter* input, const CropRect* cropRect)
+ : INHERITED(input, cropRect)
+ , fDx(dx)
+ , fDy(dy)
+ , fSigmaX(sigmaX)
+ , fSigmaY(sigmaY)
, fColor(color)
{
}
: INHERITED(1, buffer) {
fDx = buffer.readScalar();
fDy = buffer.readScalar();
- fSigma = buffer.readScalar();
+ fSigmaX = buffer.readScalar();
+ fSigmaY = buffer.readScalar();
fColor = buffer.readColor();
buffer.validate(SkScalarIsFinite(fDx) &&
SkScalarIsFinite(fDy) &&
- SkScalarIsFinite(fSigma));
+ SkScalarIsFinite(fSigmaX) &&
+ SkScalarIsFinite(fSigmaY));
}
void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const
this->INHERITED::flatten(buffer);
buffer.writeScalar(fDx);
buffer.writeScalar(fDy);
- buffer.writeScalar(fSigma);
+ buffer.writeScalar(fSigmaX);
+ buffer.writeScalar(fSigmaY);
buffer.writeColor(fColor);
}
if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc))
return false;
- SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height()));
+ SkIRect bounds;
+ src.getBounds(&bounds);
+ if (!this->applyCropRect(&bounds, matrix)) {
+ return false;
+ }
+
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
SkCanvas canvas(device.get());
- SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigma, fSigma));
+ SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigmaX, fSigmaY));
SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode));
SkPaint paint;
paint.setImageFilter(blurFilter.get());
paint.setColorFilter(colorFilter.get());
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
canvas.drawBitmap(src, fDx, fDy, &paint);
canvas.drawBitmap(src, 0, 0);
*result = device->accessBitmap(false);
+ loc->fX += bounds.fLeft;
+ loc->fY += bounds.fTop;
return true;
}
}
break;
}
- case SkBitmap::kA1_Config:
- SkDEBUGFAIL("kA1_Config umimplemented at this time");
- break;
default: // to avoid warnings
break;
}
void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
fProxy->filterRec(rec);
+ rec->setHinting(SkPaint::kNo_Hinting);
+ rec->fMaskFormat = SkMask::kARGB32_Format;
}
SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
#include "GrTypes.h"
/**
- * Hash function class that can take a data chunk of any predetermined length. The hash function
- * used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html).
- *
- * Keys are computed from ENTRY objects. ENTRY must be fully ordered by a member:
- * int compare(const GrTBinHashKey<ENTRY, ..>& k);
- * which returns negative if the ENTRY < k, 0 if it equals k, and positive if k < the ENTRY.
- * Additionally, ENTRY must be flattenable into the key using setKeyData.
- *
- * This class satisfies the requirements to be a key for a GrTHashTable.
+ * GrBinHashKey is a hash key class that can take a data chunk of any predetermined
+ * length. The hash function used is the One-at-a-Time Hash
+ * (http://burtleburtle.net/bob/hash/doobs.html).
*/
-template<typename ENTRY, size_t KEY_SIZE>
-class GrTBinHashKey {
+template<size_t KEY_SIZE>
+class GrBinHashKey {
public:
enum { kKeySize = KEY_SIZE };
- GrTBinHashKey() {
+ GrBinHashKey() {
this->reset();
}
- GrTBinHashKey(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) {
- *this = other;
- }
-
- GrTBinHashKey<ENTRY, KEY_SIZE>& operator=(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) {
- memcpy(this, &other, sizeof(*this));
- return *this;
- }
-
- ~GrTBinHashKey() {
- }
-
void reset() {
fHash = 0;
#ifdef SK_DEBUG
}
void setKeyData(const uint32_t* SK_RESTRICT data) {
- SkASSERT(GrIsALIGN4(KEY_SIZE));
+ SK_COMPILE_ASSERT(KEY_SIZE % 4 == 0, key_size_mismatch);
memcpy(&fData, data, KEY_SIZE);
uint32_t hash = 0;
size_t len = KEY_SIZE;
while (len >= 4) {
hash += *data++;
- hash += (fHash << 10);
+ hash += (hash << 10);
hash ^= (hash >> 6);
len -= 4;
}
- hash += (fHash << 3);
- hash ^= (fHash >> 11);
- hash += (fHash << 15);
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
#ifdef SK_DEBUG
fIsValid = true;
#endif
fHash = hash;
}
- int compare(const GrTBinHashKey<ENTRY, KEY_SIZE>& key) const {
+ bool operator==(const GrBinHashKey<KEY_SIZE>& key) const {
SkASSERT(fIsValid && key.fIsValid);
- return memcmp(fData, key.fData, KEY_SIZE);
- }
-
- static bool EQ(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) {
- SkASSERT(key.fIsValid);
- return 0 == entry.compare(key);
+ if (fHash != key.fHash) {
+ return false;
+ }
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) {
+ if (fData[i] != key.fData[i]) {
+ return false;
+ }
+ }
+ return true;
}
- static bool LT(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) {
- SkASSERT(key.fIsValid);
- return entry.compare(key) < 0;
+ bool operator<(const GrBinHashKey<KEY_SIZE>& key) const {
+ SkASSERT(fIsValid && key.fIsValid);
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) {
+ if (fData[i] < key.fData[i]) {
+ return true;
+ } else if (fData[i] > key.fData[i]) {
+ return false;
+ }
+ }
+ return false;
}
uint32_t getHash() const {
const uint8_t* getData() const {
SkASSERT(fIsValid);
- return fData;
+ return reinterpret_cast<const uint8_t*>(fData);
}
private:
uint32_t fHash;
- uint8_t fData[KEY_SIZE]; // Buffer for key storage
+ uint32_t fData[KEY_SIZE / sizeof(uint32_t)]; // Buffer for key storage.
#ifdef SK_DEBUG
public:
}
GrResourceKey() {
- fKey.fHashedKey.reset();
+ fKey.reset();
}
void reset(const GrCacheID& id, ResourceType type, ResourceFlags flags) {
//!< returns hash value [0..kHashMask] for the key
int getHash() const {
- return fKey.fHashedKey.getHash() & kHashMask;
+ return fKey.getHash() & kHashMask;
}
bool isScratch() const {
return ScratchDomain() ==
- *reinterpret_cast<const GrCacheID::Domain*>(fKey.fHashedKey.getData() +
+ *reinterpret_cast<const GrCacheID::Domain*>(fKey.getData() +
kCacheIDDomainOffset);
}
ResourceType getResourceType() const {
- return *reinterpret_cast<const ResourceType*>(fKey.fHashedKey.getData() +
+ return *reinterpret_cast<const ResourceType*>(fKey.getData() +
kResourceTypeOffset);
}
ResourceFlags getResourceFlags() const {
- return *reinterpret_cast<const ResourceFlags*>(fKey.fHashedKey.getData() +
+ return *reinterpret_cast<const ResourceFlags*>(fKey.getData() +
kResourceFlagsOffset);
}
- int compare(const GrResourceKey& other) const {
- return fKey.fHashedKey.compare(other.fKey.fHashedKey);
- }
-
- static bool LT(const GrResourceKey& a, const GrResourceKey& b) {
- return a.compare(b) < 0;
- }
-
- static bool EQ(const GrResourceKey& a, const GrResourceKey& b) {
- return 0 == a.compare(b);
- }
+ bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; }
+ bool operator<(const GrResourceKey& other) const { return fKey < other.fKey; }
- inline static bool LT(const GrResourceEntry& entry, const GrResourceKey& key);
- inline static bool EQ(const GrResourceEntry& entry, const GrResourceKey& key);
- inline static bool LT(const GrResourceEntry& a, const GrResourceEntry& b);
- inline static bool EQ(const GrResourceEntry& a, const GrResourceEntry& b);
+ static bool LessThan(const GrResourceEntry& entry, const GrResourceKey& key);
+ static bool Equals(const GrResourceEntry& entry, const GrResourceKey& key);
+#ifdef SK_DEBUG
+ static bool LessThan(const GrResourceEntry& a, const GrResourceEntry& b);
+ static bool Equals(const GrResourceEntry& a, const GrResourceEntry& b);
+#endif
private:
enum {
memcpy(k + kResourceTypeOffset, &type, sizeof(ResourceType));
memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags));
memset(k + kPadOffset, 0, kPadSize);
- fKey.fHashedKey.setKeyData(keyData.fKey32);
+ fKey.setKeyData(keyData.fKey32);
}
-
- struct Key;
- typedef GrTBinHashKey<Key, kKeySize> HashedKey;
-
- struct Key {
- int compare(const HashedKey& hashedKey) const {
- return fHashedKey.compare(hashedKey);
- }
-
- HashedKey fHashedKey;
- };
-
- Key fKey;
+ GrBinHashKey<kKeySize> fKey;
};
// The cache listens for these messages to purge junk resources proactively.
friend class GrDLinkedList;
};
-bool GrResourceKey::LT(const GrResourceEntry& entry, const GrResourceKey& key) {
- return LT(entry.key(), key);
+inline bool GrResourceKey::LessThan(const GrResourceEntry& entry, const GrResourceKey& key) {
+ return entry.key() < key;
}
-bool GrResourceKey::EQ(const GrResourceEntry& entry, const GrResourceKey& key) {
- return EQ(entry.key(), key);
+inline bool GrResourceKey::Equals(const GrResourceEntry& entry, const GrResourceKey& key) {
+ return entry.key() == key;
}
-bool GrResourceKey::LT(const GrResourceEntry& a, const GrResourceEntry& b) {
- return LT(a.key(), b.key());
+#ifdef SK_DEBUG
+inline bool GrResourceKey::LessThan(const GrResourceEntry& a, const GrResourceEntry& b) {
+ return a.key() < b.key();
}
-bool GrResourceKey::EQ(const GrResourceEntry& a, const GrResourceEntry& b) {
- return EQ(a.key(), b.key());
+inline bool GrResourceKey::Equals(const GrResourceEntry& a, const GrResourceEntry& b) {
+ return a.key() == b.key();
}
+#endif
///////////////////////////////////////////////////////////////////////////////
/**
* Key needs
- * static bool EQ(const Entry&, const HashKey&);
- * static bool LT(const Entry&, const HashKey&);
+ * static bool Equals(const Entry&, const Key&);
+ * static bool LessThan(const Entry&, const Key&);
+ * static bool Equals(const Entry&, const Entry&); for SK_DEBUG if GrTHashTable::validate() is called
+ * static bool LessThan(const Entry&, const Entry&); for SK_DEBUG if GrTHashTable::validate() is called
* uint32_t getHash() const;
*
* Allows duplicate key entries but on find you may get
int low = 0;
while (high > low) {
int index = (low + high) >> 1;
- if (Key::LT(*array[index], key)) {
+ if (Key::LessThan(*array[index], key)) {
low = index + 1;
} else {
high = index;
}
// check if we found it
- if (Key::EQ(*array[high], key)) {
+ if (Key::Equals(*array[high], key)) {
// above search should have found the first occurrence if there
// are multiple.
- SkASSERT(0 == high || Key::LT(*array[high - 1], key));
+ SkASSERT(0 == high || Key::LessThan(*array[high - 1], key));
return high;
}
// now return the ~ of where we should insert it
- if (Key::LT(*array[high], key)) {
+ if (Key::LessThan(*array[high], key)) {
high += 1;
}
return ~high;
int hashIndex = hash2Index(key.getHash());
T* elem = fHash[hashIndex];
- if (NULL != elem && Key::EQ(*elem, key) && filter(elem)) {
+ if (NULL != elem && Key::Equals(*elem, key) && filter(elem)) {
return elem;
}
// above search should have found the first occurrence if there
// are multiple.
- SkASSERT(0 == index || Key::LT(*array[index - 1], key));
+ SkASSERT(0 == index || Key::LessThan(*array[index - 1], key));
- for ( ; index < count() && Key::EQ(*array[index], key); ++index) {
+ for ( ; index < count() && Key::Equals(*array[index], key); ++index) {
if (filter(fSorted[index])) {
// update the hash
fHash[hashIndex] = fSorted[index];
void GrTHashTable<T, Key, kHashBits>::validate() const {
int count = fSorted.count();
for (int i = 1; i < count; i++) {
- SkASSERT(Key::LT(*fSorted[i - 1], *fSorted[i]) ||
- Key::EQ(*fSorted[i - 1], *fSorted[i]));
+ SkASSERT(Key::LessThan(*fSorted[i - 1], *fSorted[i]) ||
+ Key::Equals(*fSorted[i - 1], *fSorted[i]));
}
}
intptr_t getHash() const { return fFontScalerKey->getHash(); }
- static bool LT(const GrTextStrike& strike, const Key& key) {
+ static bool LessThan(const GrTextStrike& strike, const Key& key) {
return *strike.getFontScalerKey() < *key.fFontScalerKey;
}
- static bool EQ(const GrTextStrike& strike, const Key& key) {
+ static bool Equals(const GrTextStrike& strike, const Key& key) {
return *strike.getFontScalerKey() == *key.fFontScalerKey;
}
uint32_t getHash() const { return fPackedID; }
- static bool LT(const GrGlyph& glyph, const Key& key) {
+ static bool LessThan(const GrGlyph& glyph, const Key& key) {
return glyph.fPackedID < key.fPackedID;
}
- static bool EQ(const GrGlyph& glyph, const Key& key) {
+ static bool Equals(const GrGlyph& glyph, const Key& key) {
return glyph.fPackedID == key.fPackedID;
}
return kA8_GrMaskFormat;
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
+ // TODO: properly support kARGB32_Format.
+ case SkMask::kARGB32_Format:
case SkMask::kLCD32_Format:
return kA888_GrMaskFormat;
default:
// Hash table entry for atlases
class AtlasEntry;
- typedef GrTBinHashKey<AtlasEntry, sizeof(GrTextureStripAtlas::Desc)> AtlasHashKey;
+ class AtlasHashKey : public GrBinHashKey<sizeof(GrTextureStripAtlas::Desc)> {
+ public:
+ static bool Equals(const AtlasEntry& entry, const AtlasHashKey& key);
+ static bool LessThan(const AtlasEntry& entry, const AtlasHashKey& key);
+ };
class AtlasEntry : public ::SkNoncopyable {
public:
AtlasEntry() : fAtlas(NULL) {}
~AtlasEntry() { SkDELETE(fAtlas); }
- int compare(const AtlasHashKey& key) const { return fKey.compare(key); }
AtlasHashKey fKey;
GrTextureStripAtlas* fAtlas;
};
SkTDArray<AtlasRow*> fKeyTable;
};
+inline bool GrTextureStripAtlas::AtlasHashKey::Equals(const AtlasEntry& entry,
+ const AtlasHashKey& key) {
+ return entry.fKey == key;
+}
+
+inline bool GrTextureStripAtlas::AtlasHashKey::LessThan(const AtlasEntry& entry,
+ const AtlasHashKey& key) {
+ return entry.fKey < key;
+}
+
#endif
return;
}
}
+
this->flushRenderTarget(rect);
GrAutoTRestore<ScissorState> asr(&fScissorState);
fScissorState.fEnabled = (NULL != rect);
if (fHWBoundRenderTarget != rt) {
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
#ifdef SK_DEBUG
- GrGLenum status;
- GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
- if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
- GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
+ // don't do this check in Chromium -- this is causing
+ // lots of repeated command buffer flushes when the compositor is
+ // rendering with Ganesh, which is really slow; even too slow for
+ // Debug mode.
+ if (!this->glContext().info().isChromium()) {
+ GrGLenum status;
+ GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
+ GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
+ }
}
#endif
fHWBoundRenderTarget = rt;
+++ /dev/null
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrBinHashKey.h"
-#include "GrDrawTarget.h"
-#include "SkMatrix.h"
-#include "GrRedBlackTree.h"
-
-// FIXME: needs to be in a header
-void gr_run_unittests();
-
-// If we aren't inheriting these as #defines from elsewhere,
-// clang demands they be declared before we #include the template
-// that relies on them.
-#ifdef SK_DEBUG
-static bool LT(const int& elem, int value) {
- return elem < value;
-}
-static bool EQ(const int& elem, int value) {
- return elem == value;
-}
-#include "GrTBSearch.h"
-
-static void test_bsearch() {
- const int array[] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99
- };
-
- for (int n = 0; n < static_cast<int>(GR_ARRAY_COUNT(array)); ++n) {
- for (int i = 0; i < n; i++) {
- int index = GrTBSearch<int, int>(array, n, array[i]);
- SkASSERT(index == (int) i);
- index = GrTBSearch<int, int>(array, n, -array[i]);
- SkASSERT(index < 0);
- }
- }
-}
-#endif
-
-// bogus empty class for GrBinHashKey
-class BogusEntry {};
-
-static void test_binHashKey()
-{
- const char* testStringA_ = "abcdABCD";
- const char* testStringB_ = "abcdBBCD";
- const uint32_t* testStringA = reinterpret_cast<const uint32_t*>(testStringA_);
- const uint32_t* testStringB = reinterpret_cast<const uint32_t*>(testStringB_);
- enum {
- kDataLenUsedForKey = 8
- };
-
- GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA;
- keyA.setKeyData(testStringA);
- // test copy constructor and comparison
- GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA);
- SkASSERT(keyA.compare(keyA2) == 0);
- SkASSERT(keyA.getHash() == keyA2.getHash());
- // test re-init
- keyA2.setKeyData(testStringA);
- SkASSERT(keyA.compare(keyA2) == 0);
- SkASSERT(keyA.getHash() == keyA2.getHash());
- // test sorting
- GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyB;
- keyB.setKeyData(testStringB);
- SkASSERT(keyA.compare(keyB) < 0);
- SkASSERT(keyA.getHash() != keyB.getHash());
-}
-
-
-void gr_run_unittests() {
- SkDEBUGCODE(test_bsearch();)
- test_binHashKey();
- GrRedBlackTree<int>::UnitTest();
-}
+#include "SkColor.h"
+#include "SkColorPriv.h"
#include "SkBlitMask.h"
+#include "SkUtilsArm.h"
+#include "SkBlitMask_opts_arm_neon.h"
SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
SkMask::Format maskFormat,
SkColor color) {
+#if SK_ARM_NEON_IS_NONE
+ return NULL;
+#else
+#if SK_ARM_NEON_IS_DYNAMIC
+ if (!sk_cpu_arm_has_neon()) {
+ return NULL;
+ }
+#endif
+ if ((SkBitmap::kARGB_8888_Config == dstConfig) &&
+ (SkMask::kA8_Format == maskFormat)) {
+ return D32_A8_Factory_neon(color);
+ }
+#endif
+
+ // We don't need to handle the SkMask::kLCD16_Format case as the default
+ // LCD16 will call us through SkBlitMask::PlatformBlitRowProcs16()
+
return NULL;
}
SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
- return NULL;
+ if (isOpaque) {
+ return SK_ARM_NEON_WRAP(SkBlitLCD16OpaqueRow);
+ } else {
+ return SK_ARM_NEON_WRAP(SkBlitLCD16Row);
+ }
}
SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
#define SkColor_opts_neon_DEFINED
#include "SkTypes.h"
+#include "SkColorPriv.h"
#include <arm_neon.h>
return ret;
}
+/* This function blends 8 pixels of the same channel in the exact same way as
+ * SkBlend32.
+ */
+static inline uint8x8_t SkBlend32_neon8(uint8x8_t src, uint8x8_t dst, uint16x8_t scale) {
+ int16x8_t src_wide, dst_wide;
+
+ src_wide = vreinterpretq_s16_u16(vmovl_u8(src));
+ dst_wide = vreinterpretq_s16_u16(vmovl_u8(dst));
+
+ src_wide = (src_wide - dst_wide) * vreinterpretq_s16_u16(scale);
+
+ dst_wide += vshrq_n_s16(src_wide, 5);
+
+ return vmovn_u16(vreinterpretq_u16_s16(dst_wide));
+}
+
#endif /* #ifndef SkColor_opts_neon_DEFINED */
return srcRect.width() * 3 * srcRect.height();
case SkBitmap::kARGB_8888_Config:
return srcRect.width() * 3 * srcRect.height();
- case SkBitmap::kA1_Config:
case SkBitmap::kA8_Config:
return 1;
default:
return stream;
}
-static SkStream* extract_a1_alpha(const SkBitmap& bitmap,
- const SkIRect& srcRect,
- bool* isOpaque,
- bool* isTransparent) {
- const int alphaRowBytes = (srcRect.width() + 7) / 8;
- SkStream* stream = SkNEW_ARGS(SkMemoryStream,
- (alphaRowBytes * srcRect.height()));
- uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase();
-
- int offset1 = srcRect.fLeft % 8;
- int offset2 = 8 - offset1;
-
- for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
- uint8_t* src = bitmap.getAddr1(0, y);
- // This may read up to one byte after src, but the
- // potentially invalid bits are never used for computation.
- for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) {
- if (offset1) {
- alphaDst[0] = src[x / 8] << offset1 |
- src[x / 8 + 1] >> offset2;
- } else {
- alphaDst[0] = src[x / 8];
- }
- if (x + 7 < srcRect.fRight) {
- *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE;
- *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT;
- }
- alphaDst++;
- }
- // Calculate the mask of bits we're interested in within the
- // last byte of alphaDst.
- // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE
- uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1);
- if (srcRect.width() % 8) {
- *isOpaque &= (alphaDst[-1] & mask) == (SK_AlphaOPAQUE & mask);
- *isTransparent &=
- (alphaDst[-1] & mask) == (SK_AlphaTRANSPARENT & mask);
- }
- }
- return stream;
-}
-
static SkStream* extract_a8_alpha(const SkBitmap& bitmap,
const SkIRect& srcRect,
bool* isOpaque,
stream = extract_argb8888_data(bitmap, srcRect, extractAlpha,
&isOpaque, &transparent);
break;
- case SkBitmap::kA1_Config:
- if (!extractAlpha) {
- stream = create_black_image();
- } else {
- stream = extract_a1_alpha(bitmap, srcRect,
- &isOpaque, &transparent);
- }
- break;
case SkBitmap::kA8_Config:
if (!extractAlpha) {
stream = create_black_image();
insertName("Type", "XObject");
insertName("Subtype", "Image");
- bool alphaOnly = (config == SkBitmap::kA1_Config ||
- config == SkBitmap::kA8_Config);
+ bool alphaOnly = (config == SkBitmap::kA8_Config);
if (!isAlpha && alphaOnly) {
// For alpha only images, we stretch a single pixel of black for
int bitsPerComp = 8;
if (config == SkBitmap::kARGB_4444_Config) {
bitsPerComp = 4;
- } else if (isAlpha && config == SkBitmap::kA1_Config) {
- bitsPerComp = 1;
}
insertInt("BitsPerComponent", bitsPerComp);
mBitmap->appendS32(bitmap.height());
const char* gConfigStrings[] = {
- "None", "A1", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888"
+ "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888"
};
- SkASSERT(SkBitmap::kConfigCount == 7);
+ SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings));
mBitmap->append(" Config: ");
mBitmap->append(gConfigStrings[bitmap.config()]);
// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
- "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
+ "None", "A8", "Index8", "565", "4444", "8888"
};
static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src,
if (bitmap.getPixels()) {
if (bitmap.getColorTable()) {
sk_bzero(bitmap.getPixels(), bitmap.getSize());
- } else if (SkBitmap::kA1_Config == bitmap.config()) {
- // The A1 config can have uninitialized bits at the
- // end of each row if eraseColor is used
- memset(bitmap.getPixels(), 0xff, bitmap.getSafeSize());
} else {
bitmap.eraseColor(SK_ColorWHITE);
}
static uint32_t getPixel(int x, int y, const SkBitmap& bm) {
uint32_t val = 0;
uint16_t val16;
- uint8_t val8, shift;
+ uint8_t val8;
SkAutoLockPixels lock(bm);
const void* rawAddr = bm.getAddr(x,y);
memcpy(&val8, rawAddr, sizeof(uint8_t));
val = val8;
break;
- case SkBitmap::kA1_Config:
- memcpy(&val8, rawAddr, sizeof(uint8_t));
- shift = x % 8;
- val = (val8 >> shift) & 0x1 ;
- break;
default:
break;
}
// converted to, but at present uint32_t can handle all formats.
static void setPixel(int x, int y, uint32_t val, SkBitmap& bm) {
uint16_t val16;
- uint8_t val8, shift;
+ uint8_t val8;
SkAutoLockPixels lock(bm);
void* rawAddr = bm.getAddr(x,y);
val8 = val & 0xFF;
memcpy(rawAddr, &val8, sizeof(uint8_t));
break;
- case SkBitmap::kA1_Config:
- shift = x % 8; // We assume we're in the right byte.
- memcpy(&val8, rawAddr, sizeof(uint8_t));
- if (val & 0x1) // Turn bit on.
- val8 |= (0x1 << shift);
- else // Turn bit off.
- val8 &= ~(0x1 << shift);
- memcpy(rawAddr, &val8, sizeof(uint8_t));
- break;
default:
// Ignore.
break;
static const char* getSkConfigName(const SkBitmap& bm) {
switch (bm.config()) {
case SkBitmap::kNo_Config: return "SkBitmap::kNo_Config";
- case SkBitmap::kA1_Config: return "SkBitmap::kA1_Config";
case SkBitmap::kA8_Config: return "SkBitmap::kA8_Config";
case SkBitmap::kIndex8_Config: return "SkBitmap::kIndex8_Config";
case SkBitmap::kRGB_565_Config: return "SkBitmap::kRGB_565_Config";
static void TestBitmapCopy(skiatest::Reporter* reporter) {
static const Pair gPairs[] = {
- { SkBitmap::kNo_Config, "00000000" },
- { SkBitmap::kA1_Config, "01000000" },
- { SkBitmap::kA8_Config, "00101010" },
- { SkBitmap::kIndex8_Config, "00111010" },
- { SkBitmap::kRGB_565_Config, "00101010" },
- { SkBitmap::kARGB_4444_Config, "00101110" },
- { SkBitmap::kARGB_8888_Config, "00101110" },
+ { SkBitmap::kNo_Config, "0000000" },
+ { SkBitmap::kA8_Config, "0101010" },
+ { SkBitmap::kIndex8_Config, "0111010" },
+ { SkBitmap::kRGB_565_Config, "0101010" },
+ { SkBitmap::kARGB_4444_Config, "0101110" },
+ { SkBitmap::kARGB_8888_Config, "0101110" },
};
static const bool isExtracted[] = {
case SkBitmap::kNo_Config:
break;
- case SkBitmap::kA1_Config:
- if (safeSize.fHi != 0x470DE ||
- safeSize.fLo != 0x4DF82000)
- sizeFail = true;
- break;
-
case SkBitmap::kA8_Config:
case SkBitmap::kIndex8_Config:
if (safeSize.fHi != 0x2386F2 ||
reporter->reportFailed(str);
}
- int subW, subH;
- // Set sizes to be height = 2 to force the last row of the
- // source to be used, thus verifying correct operation if
- // the bitmap is an extracted subset.
- if (gPairs[i].fConfig == SkBitmap::kA1_Config) {
- // If one-bit per pixel, use 9 pixels to force more than
- // one byte per row.
- subW = 9;
- subH = 2;
- } else {
- // All other configurations are at least one byte per pixel,
- // and different configs will test copying different numbers
- // of bytes.
- subW = subH = 2;
- }
+ int subW = 2;
+ int subH = 2;
// Create bitmap to act as source for copies and subsets.
SkBitmap src, subset;
// The extractedSubset() test case allows us to test copy-
// ing when src and dst mave possibly different strides.
SkIRect r;
- if (gPairs[i].fConfig == SkBitmap::kA1_Config)
- // This config seems to need byte-alignment of
- // extracted subset bits.
- r.set(0, 0, subW, subH);
- else
- r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap
+ r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap
srcReady = src.extractSubset(&subset, r);
} else {
#include "SkRect.h"
#include "SkRandom.h"
-static int nextRand(SkRandom& rand, int min, int max) {
- return min + (int)rand.nextRangeU(0, max - min);
-}
-
-static void rand_irect(SkIRect* rect, int W, int H, SkRandom& rand) {
- const int DX = W / 2;
- const int DY = H / 2;
-
- rect->fLeft = nextRand(rand, -DX, W + DX);
- rect->fTop = nextRand(rand, -DY, H + DY);
- rect->fRight = nextRand(rand, -DX, W + DX);
- rect->fBottom = nextRand(rand, -DY, H + DY);
- rect->sort();
-}
-
-static void test_equal_A1_A8(skiatest::Reporter* reporter,
- const SkBitmap& bm1, const SkBitmap& bm8) {
- SkASSERT(SkBitmap::kA1_Config == bm1.config());
- SkASSERT(SkBitmap::kA8_Config == bm8.config());
-
- REPORTER_ASSERT(reporter, bm1.width() == bm8.width());
- REPORTER_ASSERT(reporter, bm1.height() == bm8.height());
- for (int y = 0; y < bm1.height(); ++y) {
- for (int x = 0; x < bm1.width(); ++x) {
- int p1 = *bm1.getAddr1(x, y) & (1 << (7 - (x & 7)));
- SkASSERT(SkIsPow2(p1));
- p1 = p1 ? 0xFF : 0;
-
- int p8 = *bm8.getAddr8(x, y);
- SkASSERT(0 == p8 || 0xFF == p8);
-
- REPORTER_ASSERT(reporter, p1 == p8);
- }
- }
-}
-
-static void test_eraserect_A1(skiatest::Reporter* reporter) {
- const int W = 43;
- const int H = 13;
-
- SkBitmap bm1, bm8;
-
- bm1.setConfig(SkBitmap::kA1_Config, W, H);
- bm1.allocPixels();
- bm8.setConfig(SkBitmap::kA8_Config, W, H);
- bm8.allocPixels();
-
- SkRandom rand;
- for (int i = 0; i < 10000; ++i) {
- SkIRect area;
- rand_irect(&area, W, H, rand);
-
- bm1.eraseColor(0);
- bm8.eraseColor(0);
-
- bm1.eraseArea(area, SK_ColorWHITE);
- bm8.eraseArea(area, SK_ColorWHITE);
- test_equal_A1_A8(reporter, bm1, bm8);
- }
-}
-
static void TestGetColor(skiatest::Reporter* reporter) {
static const struct Rec {
SkBitmap::Config fConfig;
SkColor c = bm.getColor(1, 1);
REPORTER_ASSERT(reporter, c == gRec[i].fOutColor);
}
-
- test_eraserect_A1(reporter);
}
#include "TestClassDef.h"
// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
- "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
+ "None", "A8", "Index8", "565", "4444", "8888"
};
/** Returns -1 on success, else the x coord of the first bad pixel, return its
uint32_t getHash() const { return fKey; }
- static bool LT(const HashElement& entry, const HashKey& key) {
+ static bool LessThan(const HashElement& entry, const HashKey& key) {
return entry.fKey < key.fKey;
}
- static bool EQ(const HashElement& entry, const HashKey& key) {
+ static bool Equals(const HashElement& entry, const HashKey& key) {
return entry.fKey == key.fKey;
}
#ifdef SK_DEBUG
- static uint32_t GetHash(const HashElement& entry) {
- return entry.fKey;
- }
- static bool LT(const HashElement& a, const HashElement& b) {
+ static bool LessThan(const HashElement& a, const HashElement& b) {
return a.fKey < b.fKey;
}
- static bool EQ(const HashElement& a, const HashElement& b) {
+ static bool Equals(const HashElement& a, const HashElement& b) {
return a.fKey == b.fKey;
}
#endif
#include "TestClassDef.h"
DEFINE_TESTCLASS("ImageCache", TestImageCacheClass, TestImageCache)
+
+DEF_TEST(ImageCache_doubleAdd, r) {
+ // Adding the same key twice should be safe.
+ SkScaledImageCache cache(1024);
+
+ SkBitmap original;
+ original.setConfig(SkBitmap::kARGB_8888_Config, 40, 40);
+ original.allocPixels();
+
+ SkBitmap scaled;
+ scaled.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
+ scaled.allocPixels();
+
+ SkScaledImageCache::ID* id1 = cache.addAndLock(original, 0.5f, 0.5f, scaled);
+ SkScaledImageCache::ID* id2 = cache.addAndLock(original, 0.5f, 0.5f, scaled);
+ // We don't really care if id1 == id2 as long as unlocking both works.
+ cache.unlock(id1);
+ cache.unlock(id2);
+}
// the list is that each one is different, so we can test
// to make sure the correct config is chosen.
const SkBitmap::Config configs[] = {
- SkBitmap::kA1_Config,
+ SkBitmap::kA8_Config,
SkBitmap::kA8_Config,
SkBitmap::kIndex8_Config,
SkBitmap::kRGB_565_Config,
// Test rrect serialization
{
+ // SkRRect does not initialize anything.
+ // An uninitialized SkRRect can be serialized,
+ // but will branch on uninitialized data when deserialized.
SkRRect rrect;
+ SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30);
+ SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} };
+ rrect.setRectRadii(rect, corners);
TestAlignment(&rrect, reporter);
}
// Test readByteArray
{
- unsigned char data[kArraySize] = {0};
+ unsigned char data[kArraySize] = { 1, 2, 3 };
TestArraySerialization(data, reporter);
}
// Test readColorArray
{
- SkColor data[kArraySize];
+ SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED };
TestArraySerialization(data, reporter);
}
// Test readIntArray
{
- int32_t data[kArraySize];
+ int32_t data[kArraySize] = { 1, 2, 4, 8 };
TestArraySerialization(data, reporter);
}
// Test readPointArray
{
- SkPoint data[kArraySize];
+ SkPoint data[kArraySize] = { {6, 7}, {42, 128} };
TestArraySerialization(data, reporter);
}
// Test readScalarArray
{
- SkScalar data[kArraySize];
+ SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax };
TestArraySerialization(data, reporter);
}
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("String", StringTestClass, TestString)
+
+DEF_TEST(String_SkStrSplit, r) {
+ SkTArray<SkString> results;
+
+ SkStrSplit("a-_b_c-dee--f-_-_-g-", "-_", &results);
+ REPORTER_ASSERT(r, results.count() == 6);
+ REPORTER_ASSERT(r, results[0].equals("a"));
+ REPORTER_ASSERT(r, results[1].equals("b"));
+ REPORTER_ASSERT(r, results[2].equals("c"));
+ REPORTER_ASSERT(r, results[3].equals("dee"));
+ REPORTER_ASSERT(r, results[4].equals("f"));
+ REPORTER_ASSERT(r, results[5].equals("g"));
+}