void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) { SkTArray<double, true> ts; toQuadraticTs(&cubic, precision, &ts); if (ts.count() <= 0) { SkDQuad quad = cubic.toQuad(); quads.push_back(quad); return; } double tStart = 0; for (int i1 = 0; i1 <= ts.count(); ++i1) { const double tEnd = i1 < ts.count() ? ts[i1] : 1; SkDRect bounds; bounds.setBounds(cubic); SkDCubic part = cubic.subDivide(tStart, tEnd); SkDQuad quad = part.toQuad(); if (quad[1].fX < bounds.fLeft) { quad[1].fX = bounds.fLeft; } else if (quad[1].fX > bounds.fRight) { quad[1].fX = bounds.fRight; } if (quad[1].fY < bounds.fTop) { quad[1].fY = bounds.fTop; } else if (quad[1].fY > bounds.fBottom) { quad[1].fY = bounds.fBottom; } quads.push_back(quad); tStart = tEnd; } }
static void handle_cmd(struct android_app* app, int32_t cmd) { struct VisualBenchState* state = (struct VisualBenchState*)app->userData; switch (cmd) { case APP_CMD_INIT_WINDOW: // The window is being shown, get it ready. if (state->fApp->window != nullptr && kInit_State == state->fState) { // drain any events that occurred before |window| was assigned. while (SkEvent::ProcessEvent()); // Start normal Skia sequence application_init(); SkTArray<const char*> args; args.push_back("VisualBench"); for (int i = 0; i < state->fFlags.count(); i++) { SkDebugf(state->fFlags[i].c_str()); args.push_back(state->fFlags[i].c_str()); } state->fWindow = create_sk_window((void*)state->fApp->window, args.count(), const_cast<char**>(args.begin())); state->fWindow->forceInvalAll(); state->fState = kAnimate_State; } break; case APP_CMD_TERM_WINDOW: state->fState = kDestroyRequested_State; break; } }
void onDraw(SkCanvas* canvas) override { // This GM exists to test a specific feature of the GPU backend. It does not work with the // sw rasterizer, tile modes, etc. if (nullptr == canvas->getGrContext()) { skiagm::GM::DrawGpuOnlyMessage(canvas); return; } SkPaint paint; SkTArray<SkMatrix> devMats; devMats.push_back().reset(); devMats.push_back().setRotate(45, 500, 500); devMats.push_back().setRotate(-30, 200, 200); devMats.back().setPerspX(-SK_Scalar1 / 2000); devMats.back().setPerspY(SK_Scalar1 / 1000); SkTArray<SkMatrix> viewMats; viewMats.push_back().setScale(0.75f, 0.75f); viewMats.push_back().setRotate(45, 50, 50); viewMats.back().postScale(0.5f, 1.1f); canvas->translate(10, 20); canvas->save(); SkScalar tx = 0, maxTy = 0; static const SkScalar kW = 900; for (int aa = 0; aa < 2; ++aa) { for (int i = 0; i < fPrims.count(); ++i) { for (int j = 0; j < devMats.count(); ++j) { for (int k = 0; k < viewMats.count(); ++k) { paint.setShader(new DCShader(devMats[j]))->unref(); paint.setAntiAlias(SkToBool(aa)); canvas->save(); canvas->concat(viewMats[k]); SkRect bounds = fPrims[i]->draw(canvas, paint); canvas->restore(); viewMats[k].mapRect(&bounds); // add margins bounds.fRight += 20; bounds.fBottom += 20; canvas->translate(bounds.fRight, 0); tx += bounds.fRight; maxTy = SkTMax(bounds.fBottom, maxTy); if (tx > kW) { tx = 0; canvas->restore(); canvas->translate(0, maxTy); canvas->save(); maxTy = 0; } } } } } canvas->restore(); }
/** * Helper function to write a bitmap subset to a file. Only called if subsets were created * and a writePath was provided. Behaves differently depending on * FLAGS_writeChecksumBasedFilenames. If true: * Writes the image to a PNG file named according to the digest hash, as described in * write_bitmap. * If false: * Creates a subdirectory called 'subsets' and writes a PNG to that directory. Also * creates a subdirectory called 'extracted' and writes a bitmap created using * extractSubset to a PNG in that directory. Both files will represent the same * subrectangle and have the same name for convenient comparison. In this case, the * digest is ignored. * * @param writePath Parent directory to hold the folders for the PNG files to write. Must * not be NULL. * @param subsetName Basename of the original file, with the dimensions of the subset tacked * on. Used to name the new file/folder. * @param bitmapAndDigestFromDecodeSubset SkBitmap (with digest) created by * SkImageDecoder::DecodeSubset, using rect as the area to decode. * @param rect Rectangle of the area decoded into bitmapFromDecodeSubset. Used to call * extractSubset on originalBitmap to create a bitmap with the same dimensions/pixels as * bitmapFromDecodeSubset (assuming decodeSubset worked properly). * @param originalBitmap SkBitmap decoded from the same stream as bitmapFromDecodeSubset, * using SkImageDecoder::decode to get the entire image. Used to create a PNG file for * comparison to the PNG created by bitmapAndDigestFromDecodeSubset's bitmap. * @return bool Whether the function succeeded at drawing the decoded subset and the extracted * subset to files. */ static bool write_subset(const char* writePath, const SkString& subsetName, const skiagm::BitmapAndDigest bitmapAndDigestFromDecodeSubset, SkIRect rect, const SkBitmap& originalBitmap) { // All parameters must be valid. SkASSERT(writePath != NULL); SkString subsetPath; if (FLAGS_writeChecksumBasedFilenames) { subsetPath.set(writePath); } else { // Create a subdirectory to hold the results of decodeSubset. subsetPath = SkOSPath::SkPathJoin(writePath, "subsets"); if (!sk_mkdir(subsetPath.c_str())) { gFailedSubsetDecodes.push_back().printf("Successfully decoded subset %s, but " "failed to create a directory to write to.", subsetName.c_str()); return false; } } SkAssertResult(write_bitmap(subsetPath.c_str(), subsetName.c_str(), bitmapAndDigestFromDecodeSubset)); gSuccessfulSubsetDecodes.push_back().printf("\twrote %s", subsetName.c_str()); if (!FLAGS_writeChecksumBasedFilenames) { // FIXME: The goal of extracting the subset is for visual comparison/using skdiff/skpdiff. // Currently disabling for writeChecksumBasedFilenames since it will be trickier to // determine which files to compare. // Also use extractSubset from the original for visual comparison. // Write the result to a file in a separate subdirectory. SkBitmap extractedSubset; if (!originalBitmap.extractSubset(&extractedSubset, rect)) { gFailedSubsetDecodes.push_back().printf("Successfully decoded subset %s, but failed " "to extract a similar subset for comparison.", subsetName.c_str()); return false; } SkString dirExtracted = SkOSPath::SkPathJoin(writePath, "extracted"); if (!sk_mkdir(dirExtracted.c_str())) { gFailedSubsetDecodes.push_back().printf("Successfully decoded subset%s, but failed " "to create a directory for extractSubset " "comparison.", subsetName.c_str()); return false; } skiagm::BitmapAndDigest bitmapAndDigestFromExtractSubset(extractedSubset); SkAssertResult(write_bitmap(dirExtracted.c_str(), subsetName.c_str(), bitmapAndDigestFromExtractSubset)); } return true; }
JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env, jobject thiz, jobject jsampleActivity, jint msaaSampleCount) { // setup jni hooks to the java activity gActivityGlue.m_env = env; jclass clazz = env->FindClass("com/skia/SkiaSampleActivity"); gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V"); gActivityGlue.m_addToDownloads = GetJMethod(env, clazz, "addToDownloads", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); env->DeleteLocalRef(clazz); // setup jni hooks to the java renderer clazz = env->FindClass("com/skia/SkiaSampleRenderer"); gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz); gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V"); gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V"); gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V"); gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I"); env->DeleteLocalRef(clazz); application_init(); SkTArray<const char*> args; args.push_back("SampleApp"); // TODO: push ability to select skp dir into the UI args.push_back("--pictureDir"); args.push_back("/sdcard/skiabot/skia_skp"); SkString msaaSampleCountString; if (msaaSampleCount > 0) { args.push_back("--msaa"); msaaSampleCountString.appendS32(static_cast<uint32_t>(msaaSampleCount)); args.push_back(msaaSampleCountString.c_str()); } gWindow = new SampleWindow(NULL, args.count(), const_cast<char**>(args.begin()), NULL); // send the list of slides up to the activity const int slideCount = gWindow->sampleCount(); jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int i = 0; i < slideCount; i++) { jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str()); env->SetObjectArrayElement(slideList, i, slideTitle); env->DeleteLocalRef(slideTitle); } env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList); env->DeleteLocalRef(slideList); }
CameraView() { fRX = fRY = fRZ = 0; fShaderIndex = 0; fFrontFace = false; for (int i = 0;; i++) { SkString str; str.printf("/skimages/elephant%d.jpeg", i); SkBitmap bm; if (decode_file(str.c_str(), &bm)) { SkRect src = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; SkRect dst = { -150, -150, 150, 150 }; SkMatrix matrix; matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit); fShaders.push_back(SkShader::MakeBitmapShader(bm, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix)); } else { break; } } this->setBGColor(0xFFDDDDDD); }
void GLCpuPosInstancedArraysBench::setupSingleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // Constants for our various shader programs Vertex vertices[kVerticesPerTri * kNumTri]; for (uint32_t i = 0; i < kNumTri; i++) { Vertex* v = &vertices[i * kVerticesPerTri]; v[0].fPositions.set(-1.0f, -1.0f); v[1].fPositions.set( 1.0f, -1.0f); v[2].fPositions.set( 1.0f, 1.0f); SkPoint* position = reinterpret_cast<SkPoint*>(v); viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesPerTri); // set colors float color = i == kNumTri - 1 ? 1.0f : 0.0f; for (uint32_t j = 0; j < kVerticesPerTri; j++) { uint32_t offset = 0; v->fColors[offset++] = color; v->fColors[offset++] = 0.0f; v->fColors[offset++] = 0.0f; v++; } } GrGLuint vbo; // setup VBO GR_GL_CALL(gl, GenBuffers(1, &vbo)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, vbo)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)(sizeof(SkPoint)))); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR_GL_STATIC_DRAW)); fBuffers.push_back(vbo); }
int FindOrAdd(IDWriteFontFileLoader* fontFileLoader, const void* refKey, UINT32 refKeySize) const { SkTScopedComPtr<IUnknown> fontFileLoaderId; HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId), "Failed to re-convert to IDWriteFontFileLoader.", SkFontIdentity::kInvalidDataId); SkAutoMutexAcquire ama(fDataIdCacheMutex); int count = fDataIdCache.count(); int i; for (i = 0; i < count; ++i) { const DataId& current = fDataIdCache[i]; if (fontFileLoaderId.get() == current.fLoader && refKeySize == current.fKeySize && 0 == memcmp(refKey, current.fKey, refKeySize)) { return i; } } DataId& added = fDataIdCache.push_back(); added.fLoader = fontFileLoaderId.release(); // Ref is passed. added.fKey = sk_malloc_throw(refKeySize); memcpy(added.fKey, refKey, refKeySize); added.fKeySize = refKeySize; return i; }
static void push_sink(const SkCommandLineConfig& config, Sink* s) { SkAutoTDelete<Sink> sink(s); // Try a simple Src as a canary. If it fails, skip this sink. struct : public Src { Error draw(SkCanvas* c) const override { c->drawRect(SkRect::MakeWH(1,1), SkPaint()); return ""; } SkISize size() const override { return SkISize::Make(16, 16); } Name name() const override { return "justOneRect"; } } justOneRect; SkBitmap bitmap; SkDynamicMemoryWStream stream; SkString log; Error err = sink->draw(justOneRect, &bitmap, &stream, &log); if (err.isFatal()) { info("Could not run %s: %s\n", config.getTag().c_str(), err.c_str()); exit(1); } TaggedSink& ts = gSinks.push_back(); ts.reset(sink.release()); ts.tag = config.getTag(); }
void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { for (int i = 0; i < families.count(); i++) { FontFamily& family = *families[i]; SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap; if (family.fIsFallbackFont) { nameToFamily = &fFallbackNameToFamilyMap; if (0 == family.fNames.count()) { SkString& fallbackName = family.fNames.push_back(); fallbackName.printf("%.2x##fallback", i); } } SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family, fScanner)); if (0 == newSet->count()) { SkDELETE(newSet); continue; } fFontStyleSets.push_back().reset(newSet); for (int j = 0; j < family.fNames.count(); j++) { NameToFamily* nextEntry = nameToFamily->append(); SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j])); nextEntry->styleSet = newSet; } } }
void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) { for (int i = 0; i < families.count(); i++) { FontFamily& family = *families[i]; SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap; if (family.fIsFallbackFont) { nameToFamily = &fFallbackNameToFamilyMap; if (0 == family.fNames.count()) { SkString& fallbackName = family.fNames.push_back(); fallbackName.printf("%.2x##fallback", i); } } SkFontStyleSet_Android* newSet = new SkFontStyleSet_Android(family, fScanner, isolated); if (0 == newSet->count()) { delete newSet; continue; } fFontStyleSets.push_back().reset(newSet); for (int j = 0; j < family.fNames.count(); j++) { NameToFamily* nextEntry = nameToFamily->append(); new (&nextEntry->name) SkString(family.fNames[j]); nextEntry->styleSet = newSet; } } }
static void start(ImplicitString config, ImplicitString src, ImplicitString srcOptions, ImplicitString name) { SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(), srcOptions.c_str(), name.c_str()); SkAutoMutexAcquire lock(gRunningMutex); gRunning.push_back(id); }
static void push_sink(const char* tag, Sink* s) { SkAutoTDelete<Sink> sink(s); if (!FLAGS_config.contains(tag)) { return; } // Try a simple Src as a canary. If it fails, skip this sink. struct : public Src { Error draw(SkCanvas* c) const override { c->drawRect(SkRect::MakeWH(1,1), SkPaint()); return ""; } SkISize size() const override { return SkISize::Make(16, 16); } Name name() const override { return "justOneRect"; } } justOneRect; SkBitmap bitmap; SkDynamicMemoryWStream stream; SkString log; Error err = sink->draw(justOneRect, &bitmap, &stream, &log); if (err.isFatal()) { SkDebugf("Could not run %s: %s\n", tag, err.c_str()); exit(1); } TaggedSink& ts = gSinks.push_back(); ts.reset(sink.detach()); ts.tag = tag; }
void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) { SkTArray<double, true> ts; toQuadraticTs(&cubic, precision, &ts); if (ts.count() <= 0) { SkDQuad quad = cubic.toQuad(); quads.push_back(quad); return; } double tStart = 0; for (int i1 = 0; i1 <= ts.count(); ++i1) { const double tEnd = i1 < ts.count() ? ts[i1] : 1; SkDCubic part = cubic.subDivide(tStart, tEnd); SkDQuad quad = part.toQuad(); quads.push_back(quad); tStart = tEnd; } }
static void TestTSet_basic(skiatest::Reporter* reporter) { SkTArray<int, MEM_MOVE> a; // Starts empty. REPORTER_ASSERT(reporter, a.empty()); REPORTER_ASSERT(reporter, a.count() == 0); // { }, add a default constructed element a.push_back() = 0; REPORTER_ASSERT(reporter, !a.empty()); REPORTER_ASSERT(reporter, a.count() == 1); // { 0 }, removeShuffle the only element. a.removeShuffle(0); REPORTER_ASSERT(reporter, a.empty()); REPORTER_ASSERT(reporter, a.count() == 0); // { }, add a default, add a 1, remove first a.push_back() = 0; REPORTER_ASSERT(reporter, a.push_back() = 1); a.removeShuffle(0); REPORTER_ASSERT(reporter, !a.empty()); REPORTER_ASSERT(reporter, a.count() == 1); REPORTER_ASSERT(reporter, a[0] == 1); // { 1 }, replace with new array int b[5] = { 0, 1, 2, 3, 4 }; a.reset(b, SK_ARRAY_COUNT(b)); REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b)); REPORTER_ASSERT(reporter, a[2] == 2); REPORTER_ASSERT(reporter, a[4] == 4); // { 0, 1, 2, 3, 4 }, removeShuffle the last a.removeShuffle(4); REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b) - 1); REPORTER_ASSERT(reporter, a[3] == 3); // { 0, 1, 2, 3 }, remove a middle, note shuffle a.removeShuffle(1); REPORTER_ASSERT(reporter, a.count() == SK_ARRAY_COUNT(b) - 2); REPORTER_ASSERT(reporter, a[0] == 0); REPORTER_ASSERT(reporter, a[1] == 3); REPORTER_ASSERT(reporter, a[2] == 2); // {0, 3, 2 } }
// TODO(chudy): Free command string memory. SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const { SkTArray<SkString>* commandString = new SkTArray<SkString>(fCommandVector.count()); if (!fCommandVector.isEmpty()) { for (int i = 0; i < fCommandVector.count(); i ++) { commandString->push_back() = fCommandVector[i]->toString(); } } return commandString; }
static int find_or_append(SkTArray<sk_sp<T>>& array, T* obj) { for (int i = 0; i < array.count(); i++) { if (equals(array[i].get(), obj)) { return i; } } array.push_back(sk_ref_sp(obj)); return array.count() - 1; }
static void push_src(const char* tag, const char* options, Src* s) { SkAutoTDelete<Src> src(s); if (in_shard() && FLAGS_src.contains(tag) && !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) { TaggedSrc& s = gSrcs.push_back(); s.reset(src.detach()); s.tag = tag; s.options = options; } }
void GLCpuPosInstancedArraysBench::setupInstanceVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // We draw all of the instances at a single place because we aren't allowed to have per vertex // per instance attributes SkPoint positions[kVerticesPerTri]; positions[0].set(-1.0f, -1.0f); positions[1].set( 1.0f, -1.0f); positions[2].set( 1.0f, 1.0f); viewMatrices[0].mapPointsWithStride(positions, sizeof(SkPoint), kVerticesPerTri); // setup colors so we can detect we are actually drawing instances(the last triangle will be // a different color) GrGLfloat colors[kVerticesPerTri * kNumTri]; for (uint32_t i = 0; i < kNumTri; i++) { // set colors uint32_t offset = i * kVerticesPerTri; float color = i == kNumTri - 1 ? 1.0f : 0.0f; colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] = 0.0f; } GrGLuint posVBO; // setup position VBO GR_GL_CALL(gl, GenBuffers(1, &posVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, GR_GL_STATIC_DRAW)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeof(GrGLfloat), (GrGLvoid*)0)); // setup color VBO GrGLuint instanceVBO; GR_GL_CALL(gl, GenBuffers(1, &instanceVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, instanceVBO)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_STATIC_DRAW)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribDivisor(1, 1)); fBuffers.push_back(posVBO); fBuffers.push_back(instanceVBO); }
static void test_self_assignment(skiatest::Reporter* reporter) { SkTArray<int> a; a.push_back(1); REPORTER_ASSERT(reporter, !a.empty()); REPORTER_ASSERT(reporter, a.count() == 1); REPORTER_ASSERT(reporter, a[0] == 1); a = static_cast<decltype(a)&>(a); REPORTER_ASSERT(reporter, !a.empty()); REPORTER_ASSERT(reporter, a.count() == 1); REPORTER_ASSERT(reporter, a[0] == 1); }
DEF_TEST(GrAllocator, reporter) { // Test combinations of allocators with and without stack storage and with different block // sizes. SkTArray<GrTAllocator<C>*> allocators; GrTAllocator<C> a1(1); allocators.push_back(&a1); GrTAllocator<C> a2(2); allocators.push_back(&a2); GrTAllocator<C> a5(5); allocators.push_back(&a5); GrSTAllocator<1, C> sa1; allocators.push_back(&a1); GrSTAllocator<3, C> sa3; allocators.push_back(&sa3); GrSTAllocator<4, C> sa4; allocators.push_back(&sa4); for (int i = 0; i < allocators.count(); ++i) { check_allocator(allocators[i], 0, 0, reporter); check_allocator(allocators[i], 1, 1, reporter); check_allocator(allocators[i], 2, 2, reporter); check_allocator(allocators[i], 10, 1, reporter); check_allocator(allocators[i], 10, 5, reporter); check_allocator(allocators[i], 10, 10, reporter); check_allocator(allocators[i], 100, 10, reporter); } }
void GLCpuPosInstancedArraysBench::setupDoubleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // Constants for our various shader programs SkPoint positions[kVerticesPerTri * kNumTri]; GrGLfloat colors[kVerticesPerTri * kNumTri * 3]; for (uint32_t i = 0; i < kNumTri; i++) { SkPoint* position = &positions[i * kVerticesPerTri]; position[0].set(-1.0f, -1.0f); position[1].set( 1.0f, -1.0f); position[2].set( 1.0f, 1.0f); viewMatrices[i].mapPointsWithStride(position, sizeof(SkPoint), kVerticesPerTri); // set colors float color = i == kNumTri - 1 ? 1.0f : 0.0f; uint32_t offset = i * kVerticesPerTri * 3; for (uint32_t j = 0; j < kVerticesPerTri; j++) { colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] = 0.0f; } } GrGLuint posVBO, colorVBO; // setup position VBO GR_GL_CALL(gl, GenBuffers(1, &posVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, GR_GL_STATIC_DRAW)); // setup color VBO GR_GL_CALL(gl, GenBuffers(1, &colorVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, colorVBO)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_STATIC_DRAW)); fBuffers.push_back(posVBO); fBuffers.push_back(colorVBO); }
static void test_swap(skiatest::Reporter* reporter) { typedef SkTArray<int>* (*ArrayMaker)(); ArrayMaker arrayMakers[] = {make, make_s<5>, make_s<10>, make_s<20>}; static int kSizes[] = {0, 1, 5, 10, 15, 20, 25}; for (size_t arrayA = 0; arrayA < SK_ARRAY_COUNT(arrayMakers); ++arrayA) { for (size_t arrayB = arrayA; arrayB < SK_ARRAY_COUNT(arrayMakers); ++arrayB) { for (size_t dataSizeA = 0; dataSizeA < SK_ARRAY_COUNT(kSizes); ++dataSizeA) { for (size_t dataSizeB = 0; dataSizeB < SK_ARRAY_COUNT(kSizes); ++dataSizeB) { int curr = 0; SkTArray<int>* a = arrayMakers[arrayA](); SkTArray<int>* b = arrayMakers[arrayB](); for (int i = 0; i < kSizes[dataSizeA]; ++i) { a->push_back(curr++); } for (int i = 0; i < kSizes[dataSizeB]; ++i) { b->push_back(curr++); } a->swap(b); REPORTER_ASSERT(reporter, kSizes[dataSizeA] == b->count()); REPORTER_ASSERT(reporter, kSizes[dataSizeB] == a->count()); curr = 0; for (int i = 0; i < kSizes[dataSizeA]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*b)[i]); } for (int i = 0; i < kSizes[dataSizeB]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*a)[i]); } delete b; a->swap(a); curr = kSizes[dataSizeA]; for (int i = 0; i < kSizes[dataSizeB]; ++i) { REPORTER_ASSERT(reporter, curr++ == (*a)[i]); } delete a; } } } } }
void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list, bool evenOdd, bool oppEvenOdd) { int count = contours.count(); if (count == 0) { return; } for (int index = 0; index < count; ++index) { SkOpContour& contour = contours[index]; contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd); list.push_back(&contour); } SkTQSort<SkOpContour>(list.begin(), list.end() - 1); }
void SkConvolutionFilter1D::AddFilter(int filterOffset, const float* filterValues, int filterLength) { SkASSERT(filterLength > 0); SkTArray<ConvolutionFixed> fixedValues; fixedValues.reset(filterLength); for (int i = 0; i < filterLength; ++i) { fixedValues.push_back(FloatToFixed(filterValues[i])); } AddFilter(filterOffset, &fixedValues[0], filterLength); }
void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int saveCountToBackup) { // Each SkClipStack::Element stores the index of the canvas save // with which it is associated. Backup only those Elements that // are associated with 'saveCountToBackup' SkClipStack::Iter clipIterator(*mCanvas->getClipStack(), SkClipStack::Iter::kTop_IterStart); while (const SkClipStack::Element* elem = clipIterator.prev()) { if (elem->getSaveCount() < saveCountToBackup) { // done with the target save count. break; } SkASSERT(elem->getSaveCount() == saveCountToBackup); clips.push_back(*elem); } }
static void push_codec_srcs(Path path) { SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); if (!encoded) { SkDebugf("Couldn't read %s.", path.c_str()); return; } SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); if (nullptr == codec.get()) { SkDebugf("Couldn't create codec for %s.", path.c_str()); return; } // Native Scales // TODO (msarett): Implement scaling tests for SkImageDecoder in order to compare with these // tests. SkImageDecoder supports downscales by integer factors. // SkJpegCodec natively supports scaling to: 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875 const float nativeScales[] = { 0.125f, 0.25f, 0.375f, 0.5f, 0.625f, 0.750f, 0.875f, 1.0f }; const CodecSrc::Mode nativeModes[] = { CodecSrc::kCodec_Mode, CodecSrc::kCodecZeroInit_Mode, CodecSrc::kScanline_Mode, CodecSrc::kStripe_Mode, CodecSrc::kSubset_Mode, CodecSrc::kGen_Mode }; CodecSrc::DstColorType colorTypes[3]; uint32_t numColorTypes; switch (codec->getInfo().colorType()) { case kGray_8_SkColorType: // FIXME: Is this a long term solution for testing wbmps decodes to kIndex8? // Further discussion on this topic is at https://bug.skia.org/3683 . // This causes us to try to convert grayscale jpegs to kIndex8. We currently // fail non-fatally in this case. colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; colorTypes[1] = CodecSrc::kGrayscale_Always_DstColorType; colorTypes[2] = CodecSrc::kIndex8_Always_DstColorType; numColorTypes = 3; break; case kIndex_8_SkColorType: colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; colorTypes[1] = CodecSrc::kIndex8_Always_DstColorType; numColorTypes = 2; break; default: colorTypes[0] = CodecSrc::kGetFromCanvas_DstColorType; numColorTypes = 1; break; } SkTArray<SkAlphaType> alphaModes; alphaModes.push_back(kPremul_SkAlphaType); alphaModes.push_back(kUnpremul_SkAlphaType); if (codec->getInfo().alphaType() == kOpaque_SkAlphaType) { alphaModes.push_back(kOpaque_SkAlphaType); } for (CodecSrc::Mode mode : nativeModes) { // SkCodecImageGenerator only runs for the default colorType // recommended by SkCodec. There is no need to generate multiple // tests for different colorTypes. // TODO (msarett): Add scaling support to SkCodecImageGenerator. if (CodecSrc::kGen_Mode == mode) { // FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822) if (kGray_8_SkColorType != codec->getInfo().colorType()) { push_codec_src(path, mode, CodecSrc::kGetFromCanvas_DstColorType, codec->getInfo().alphaType(), 1.0f); } continue; } for (float scale : nativeScales) { for (uint32_t i = 0; i < numColorTypes; i++) { for (SkAlphaType alphaType : alphaModes) { push_codec_src(path, mode, colorTypes[i], alphaType, scale); } } } } // https://bug.skia.org/4428 bool subset = false; // The following image types are supported by BitmapRegionDecoder, // so we will test full image decodes and subset decodes. static const char* const exts[] = { "jpg", "jpeg", "png", "webp", "JPG", "JPEG", "PNG", "WEBP", }; for (const char* ext : exts) { if (path.endsWith(ext)) { subset = true; break; } } const int sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; for (int sampleSize : sampleSizes) { for (uint32_t i = 0; i < numColorTypes; i++) { for (SkAlphaType alphaType : alphaModes) { push_android_codec_src(path, AndroidCodecSrc::kFullImage_Mode, colorTypes[i], alphaType, sampleSize); if (subset) { push_android_codec_src(path, AndroidCodecSrc::kDivisor_Mode, colorTypes[i], alphaType, sampleSize); } } } } }
void WriteTask::draw() { SkString md5; { SkAutoLockPixels lock(fBitmap); md5 = fData ? get_md5(fData) : get_md5(fBitmap.getPixels(), fBitmap.getSize()); } SkASSERT(fSuffixes.count() > 0); SkString config = fSuffixes.back(); SkString mode("direct"); if (fSuffixes.count() > 1) { mode = fSuffixes.fromBack(1); } JsonData entry = { fBaseName, config, mode, fSourceType, md5 }; { SkAutoMutexAcquire lock(&gJsonDataLock); gJsonData.push_back(entry); } SkString dir(FLAGS_writePath[0]); #if defined(SK_BUILD_FOR_IOS) if (dir.equals("@")) { dir.set(FLAGS_resourcePath[0]); } #endif this->makeDirOrFail(dir); SkString path; if (FLAGS_nameByHash) { // Flat directory of hash-named files. path = SkOSPath::Join(dir.c_str(), md5.c_str()); path.append(fExtension); // We're content-addressed, so it's possible two threads race to write // this file. We let the first one win. This also means we won't // overwrite identical files from previous runs. if (sk_exists(path.c_str())) { return; } } else { // Nested by mode, config, etc. for (int i = 0; i < fSuffixes.count(); i++) { dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str()); this->makeDirOrFail(dir); } path = SkOSPath::Join(dir.c_str(), fBaseName.c_str()); path.append(fExtension); // The path is unique, so two threads can't both write to the same file. // If already present we overwrite here, since the content may have changed. } SkFILEWStream file(path.c_str()); if (!file.isValid()) { return this->fail("Can't open file."); } bool ok = fData ? write_asset(fData, &file) : SkImageEncoder::EncodeStream(&file, fBitmap, SkImageEncoder::kPNG_Type, 100); if (!ok) { return this->fail("Can't write to file."); } }
int dm_main() { SetupCrashHandler(); JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); gCreateTypefaceDelegate = &create_from_name; start_keepalive(); gather_gold(); gather_uninteresting_hashes(); if (!gather_srcs()) { return 1; } gather_sinks(); gather_tests(); gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count(); SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending); // Kick off as much parallel work as we can, making note of any serial work we'll need to do. SkTaskGroup parallel; SkTArray<Task> serial; for (auto& sink : gSinks) for (auto& src : gSrcs) { Task task(src, sink); if (src->serial() || sink->serial()) { serial.push_back(task); } else { parallel.add([task] { Task::Run(task); }); } } for (auto test : gParallelTests) { parallel.add([test] { run_test(test); }); } // With the parallel work running, run serial tasks and tests here on main thread. for (auto task : serial) { Task::Run(task); } for (auto test : gSerialTests) { run_test(test); } // Wait for any remaining parallel work to complete (including any spun off of serial tasks). parallel.wait(); gDefinitelyThreadSafeWork.wait(); // At this point we're back in single-threaded land. sk_tool_utils::release_portable_typefaces(); if (FLAGS_verbose && gNoteTally.count() > 0) { SkDebugf("\nNote tally:\n"); gNoteTally.foreach([](const SkString& note, int* tally) { SkDebugf("%dx\t%s\n", *tally, note.c_str()); }); } SkDebugf("\n"); if (gFailures.count() > 0) { SkDebugf("Failures:\n"); for (int i = 0; i < gFailures.count(); i++) { SkDebugf("\t%s\n", gFailures[i].c_str()); } SkDebugf("%d failures\n", gFailures.count()); return 1; } if (gPending > 0) { SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n"); return 1; } #ifdef SK_PDF_IMAGE_STATS SkPDFImageDumpStats(); #endif // SK_PDF_IMAGE_STATS SkDebugf("Finished!\n"); return 0; }
static void fail(ImplicitString err) { SkAutoMutexAcquire lock(gFailuresMutex); SkDebugf("\n\nFAILURE: %s\n\n", err.c_str()); gFailures.push_back(err); }