// https://bug.skia.org/2894 DEF_TEST(BitmapCache_add_rect, reporter) { SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory(); SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator(); SkAutoTDelete<SkResourceCache> cache; if (factory) { cache.reset(new SkResourceCache(factory)); } else { const size_t byteLimit = 100 * 1024; cache.reset(new SkResourceCache(byteLimit)); } SkBitmap cachedBitmap; make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator); cachedBitmap.setImmutable(); SkBitmap bm; SkIRect rect = SkIRect::MakeWH(5, 5); uint32_t cachedID = cachedBitmap.getGenerationID(); SkPixelRef* cachedPR = cachedBitmap.pixelRef(); // Wrong subset size REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedPR, SkIRect::MakeWH(4, 6), cachedBitmap, cache)); REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedID, rect, &bm, cache)); // Wrong offset value REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedPR, SkIRect::MakeXYWH(-1, 0, 5, 5), cachedBitmap, cache)); REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedID, rect, &bm, cache)); // Should not be in the cache REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedID, rect, &bm, cache)); REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedPR, rect, cachedBitmap, cache)); // Should be in the cache, we just added it REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedID, rect, &bm, cache)); }
virtual Result onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&, SkPMColor ctableEntries[], int* ctableCount) override { SkMemoryStream stream(fData->data(), fData->size(), false); SkAutoTUnref<BareMemoryAllocator> allocator(SkNEW_ARGS(BareMemoryAllocator, (info, pixels, rowBytes))); fDecoder->setAllocator(allocator); fDecoder->setRequireUnpremultipliedColors(kUnpremul_SkAlphaType == info.alphaType()); SkBitmap bm; const SkImageDecoder::Result result = fDecoder->decode(&stream, &bm, info.colorType(), SkImageDecoder::kDecodePixels_Mode); if (SkImageDecoder::kFailure == result) { return kInvalidInput; } SkASSERT(info.colorType() == bm.info().colorType()); if (kIndex_8_SkColorType == info.colorType()) { SkASSERT(ctableEntries); SkColorTable* ctable = bm.getColorTable(); if (NULL == ctable) { return kInvalidConversion; } const int count = ctable->count(); memcpy(ctableEntries, ctable->readColors(), count * sizeof(SkPMColor)); *ctableCount = count; } if (SkImageDecoder::kPartialSuccess == result) { return kIncompleteInput; } return kSuccess; }
void SkPicturePlayback::draw(SkCanvas* canvas, SkPicture::AbortCallback* callback, const SkReadBuffer* buffer) { AutoResetOpID aroi(this); SkASSERT(0 == fCurOffset); SkAutoTDelete<SkReadBuffer> reader; if (buffer) { reader.reset(buffer->clone(fPictureData->opData()->bytes(), fPictureData->opData()->size())); } else { reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(), fPictureData->opData()->size())); } // Record this, so we can concat w/ it if we encounter a setMatrix() SkMatrix initialMatrix = canvas->getTotalMatrix(); SkAutoCanvasRestore acr(canvas, false); while (!reader->eof()) { if (callback && callback->abort()) { return; } fCurOffset = reader->offset(); uint32_t size; DrawType op = ReadOpAndSize(reader, &size); this->handleOp(reader, op, size, canvas, initialMatrix); } }
void BitmapRegionDecoderBench::onDraw(const int n, SkCanvas* canvas) { SkAutoTDelete<SkBitmap> bitmap; for (int i = 0; i < n; i++) { bitmap.reset(fBRD->decodeRegion(fSubset.left(), fSubset.top(), fSubset.width(), fSubset.height(), fSampleSize, fColorType)); SkASSERT(nullptr != bitmap.get()); } }
void onDraw(SkCanvas* canvas) override { SkDrawable* const* drawables = NULL; int drawableCount = 0; if (fDrawableList) { drawables = fDrawableList->begin(); drawableCount = fDrawableList->count(); } SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/); }
void runTest(skiatest::Reporter* reporter) { SkAutoTDelete<SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t> > result; result.reset(getAdvanceData((void*)this, fAdvancesLen, fSubset, fSubsetLen, getAdvance)); SkString stringResult = stringify_advance_data(result); if (!stringResult.equals(fExpected)) { ERRORF(reporter, "Expected: %s\n Result: %s\n", fExpected, stringResult.c_str()); } }
SkBitmapRegionDecoder* SkBitmapRegionDecoder::Create( SkStreamRewindable* stream, Strategy strategy) { SkAutoTDelete<SkStreamRewindable> streamDeleter(stream); switch (strategy) { case kCanvas_Strategy: { SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(streamDeleter.detach())); if (nullptr == codec) { SkCodecPrintf("Error: Failed to create decoder.\n"); return nullptr; } SkEncodedFormat format = codec->getEncodedFormat(); switch (format) { case SkEncodedFormat::kJPEG_SkEncodedFormat: case SkEncodedFormat::kPNG_SkEncodedFormat: break; default: // FIXME: Support webp using a special case. Webp does not support // scanline decoding. return nullptr; } // If the image is a jpeg or a png, the scanline ordering should always be // kTopDown or kNone. It is relevant to check because this implementation // only supports these two scanline orderings. SkASSERT(SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder() || SkCodec::kNone_SkScanlineOrder == codec->getScanlineOrder()); return new SkBitmapRegionCanvas(codec.detach()); } case kAndroidCodec_Strategy: { SkAutoTDelete<SkAndroidCodec> codec = SkAndroidCodec::NewFromStream(streamDeleter.detach()); if (nullptr == codec) { SkCodecPrintf("Error: Failed to create codec.\n"); return NULL; } SkEncodedFormat format = codec->getEncodedFormat(); switch (format) { case SkEncodedFormat::kJPEG_SkEncodedFormat: case SkEncodedFormat::kPNG_SkEncodedFormat: case SkEncodedFormat::kWEBP_SkEncodedFormat: break; default: return nullptr; } return new SkBitmapRegionCodec(codec.detach()); } default: SkASSERT(false); return nullptr; } }
void AndroidCodecBench::onDraw(int n, SkCanvas* canvas) { SkAutoTDelete<SkAndroidCodec> codec; SkAndroidCodec::AndroidOptions options; options.fSampleSize = fSampleSize; for (int i = 0; i < n; i++) { codec.reset(SkAndroidCodec::NewFromData(fData)); #ifdef SK_DEBUG const SkCodec::Result result = #endif codec->getAndroidPixels(fInfo, fPixelStorage.get(), fInfo.minRowBytes(), &options); SkASSERT(result == SkCodec::kSuccess || result == SkCodec::kIncompleteInput); } }
/** * Extract either the color or image data from a SkBitmap into a SkStream. * @param bitmap Bitmap to extract data from. * @param srcRect Region in the bitmap to extract. * @param extractAlpha Set to true to extract the alpha data or false to * extract the color data. * @param isTransparent Pointer to a bool to output whether the alpha is * completely transparent. May be NULL. Only valid when * extractAlpha == true. * @return Unencoded image data, or NULL if either data was not * available or alpha data was requested but the image was * entirely transparent or opaque. */ static SkStream* extract_image_data(const SkBitmap& bitmap, const SkIRect& srcRect, bool extractAlpha, bool* isTransparent) { SkColorType colorType = bitmap.colorType(); if (extractAlpha && (kIndex_8_SkColorType == colorType || kRGB_565_SkColorType == colorType)) { if (isTransparent != NULL) { *isTransparent = false; } return NULL; } SkAutoLockPixels lock(bitmap); if (NULL == bitmap.getPixels()) { return NULL; } bool isOpaque = true; bool transparent = extractAlpha; SkAutoTDelete<SkStream> stream; switch (colorType) { case kIndex_8_SkColorType: if (!extractAlpha) { stream.reset(extract_index8_image(bitmap, srcRect)); } break; case kARGB_4444_SkColorType: stream.reset(extract_argb4444_data(bitmap, srcRect, extractAlpha, &isOpaque, &transparent)); break; case kRGB_565_SkColorType: if (!extractAlpha) { stream.reset(extract_rgb565_image(bitmap, srcRect)); } break; case kN32_SkColorType: stream.reset(extract_argb8888_data(bitmap, srcRect, extractAlpha, &isOpaque, &transparent)); break; case kAlpha_8_SkColorType: if (!extractAlpha) { stream.reset(create_black_image()); } else { stream.reset(extract_a8_alpha(bitmap, srcRect, &isOpaque, &transparent)); } break; default: SkASSERT(false); } if (isTransparent != NULL) { *isTransparent = transparent; } if (extractAlpha && (transparent || isOpaque)) { return NULL; } return stream.detach(); }
SkPicture* onNewPictureSnapshot() override { SkBigPicture::SnapshotArray* pictList = NULL; if (fDrawableList) { // TODO: should we plumb-down the BBHFactory and recordFlags from our host // PictureRecorder? pictList = fDrawableList->newDrawableSnapshot(); } SkAutoTUnref<SkLayerInfo> saveLayerData; if (fBBH && fDoSaveLayerInfo) { saveLayerData.reset(SkNEW(SkLayerInfo)); SkBBoxHierarchy* bbh = NULL; // we've already computed fBBH (received in constructor) // TODO: update saveLayer info computation to reuse the already computed // bounds in 'fBBH' SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData); } size_t subPictureBytes = 0; for (int i = 0; pictList && i < pictList->count(); i++) { subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]); } // SkBigPicture will take ownership of a ref on both fRecord and fBBH. // We're not willing to give up our ownership, so we must ref them for SkPicture. return SkNEW_ARGS(SkBigPicture, (fBounds, SkRef(fRecord.get()), pictList, SkSafeRef(fBBH.get()), saveLayerData.detach(), subPictureBytes)); }
void CodecBench::onDraw(const int n, SkCanvas* canvas) { SkAutoTDelete<SkCodec> codec; SkPMColor colorTable[256]; int colorCount; for (int i = 0; i < n; i++) { colorCount = 256; codec.reset(SkCodec::NewFromData(fData)); #ifdef SK_DEBUG const SkCodec::Result result = #endif codec->getPixels(fInfo, fPixelStorage.get(), fInfo.minRowBytes(), nullptr, colorTable, &colorCount); SkASSERT(result == SkCodec::kSuccess || result == SkCodec::kIncompleteInput); } }
bool FrontBufferedStream::isAtEnd() const { if (fOffset < fBufferedSoFar) { // Even if the underlying stream is at the end, this stream has been // rewound after buffering, so it is not at the end. return false; } return fStream->isAtEnd(); }
bool GrGLShaderBuilder::GenProgram(GrGpuGL* gpu, GrGLUniformManager* uman, const GrGLProgramDesc& desc, const GrEffectStage* inColorStages[], const GrEffectStage* inCoverageStages[], GenProgramOutput* output) { SkAutoTDelete<GrGLShaderBuilder> builder; if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) { builder.reset(SkNEW_ARGS(GrGLFullShaderBuilder, (gpu, uman, desc))); } else { builder.reset(SkNEW_ARGS(GrGLFragmentOnlyShaderBuilder, (gpu, uman, desc))); } if (builder->genProgram(inColorStages, inCoverageStages)) { *output = builder->getOutput(); return true; } return false; }
// static SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, const SkIRect& srcRect) { if (bitmap.colorType() == kUnknown_SkColorType) { return NULL; } bool isTransparent = false; SkAutoTDelete<SkStream> alphaData; if (!bitmap.isOpaque()) { // Note that isOpaque is not guaranteed to return false for bitmaps // with alpha support but a completely opaque alpha channel, // so alphaData may still be NULL if we have a completely opaque // (or transparent) bitmap. alphaData.reset( extract_image_data(bitmap, srcRect, true, &isTransparent)); } if (isTransparent) { return NULL; } SkPDFImage* image; SkColorType colorType = bitmap.colorType(); if (alphaData.get() != NULL && (kN32_SkColorType == colorType || kARGB_4444_SkColorType == colorType)) { if (kN32_SkColorType == colorType) { image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, SkIRect::MakeWH(srcRect.width(), srcRect.height()))); } else { SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect); image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false, SkIRect::MakeWH(srcRect.width(), srcRect.height()))); } } else { image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect)); } if (alphaData.get() != NULL) { SkAutoTUnref<SkPDFImage> mask( SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap, true, srcRect))); image->insert("SMask", new SkPDFObjRef(mask))->unref(); } return image; }
HRESULT StreamFontFileLoader::CreateStreamFromKey( void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream** fontFileStream) { SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; HR(SkDWriteFontFileStreamWrapper::Create(fStream->duplicate(), &stream)); *fontFileStream = stream.release(); return S_OK; }
/** * Creates a ExtGState with the SMask set to the luminosityShader in * luminosity mode. The shader pattern extends to the bbox. */ SkPDFGraphicState* SkPDFAlphaFunctionShader::CreateSMaskGraphicState() { SkRect bbox; bbox.set(fState.get()->fBBox); SkAutoTUnref<SkPDFObject> luminosityShader( SkPDFShader::GetPDFShaderByState( fState->CreateAlphaToLuminosityState())); SkAutoTUnref<SkStream> alphaStream(create_pattern_fill_content(-1, bbox)); SkAutoTUnref<SkPDFResourceDict> resources(get_gradient_resource_dict(luminosityShader, NULL)); SkAutoTUnref<SkPDFFormXObject> alphaMask( new SkPDFFormXObject(alphaStream.get(), bbox, resources.get())); return SkPDFGraphicState::GetSMaskGraphicState( alphaMask.get(), false, SkPDFGraphicState::kLuminosity_SMaskMode); }
SkBitmapRegionDecoder* SkBitmapRegionDecoder::Create( SkStreamRewindable* stream, Strategy strategy) { SkAutoTDelete<SkStreamRewindable> streamDeleter(stream); switch (strategy) { case kCanvas_Strategy: { SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(streamDeleter.detach())); if (nullptr == codec) { SkCodecPrintf("Error: Failed to create decoder.\n"); return nullptr; } if (SkEncodedFormat::kWEBP_SkEncodedFormat == codec->getEncodedFormat()) { // FIXME: Support webp using a special case. Webp does not support // scanline decoding. return nullptr; } switch (codec->getScanlineOrder()) { case SkCodec::kTopDown_SkScanlineOrder: case SkCodec::kNone_SkScanlineOrder: break; default: SkCodecPrintf("Error: Scanline ordering not supported.\n"); return nullptr; } return new SkBitmapRegionCanvas(codec.detach()); } case kAndroidCodec_Strategy: { SkAutoTDelete<SkAndroidCodec> codec = SkAndroidCodec::NewFromStream(streamDeleter.detach()); if (NULL == codec) { SkCodecPrintf("Error: Failed to create codec.\n"); return NULL; } return new SkBitmapRegionCodec(codec.detach()); } default: SkASSERT(false); return nullptr; } }
/* * Tries to handle the image with PIEX. If PIEX returns kOk and finds the preview image, create a * SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr. In other cases, * fallback to create SkRawCodec for DNG images. */ SkCodec* SkRawCodec::NewFromStream(SkStream* stream) { SkAutoTDelete<SkRawStream> rawStream; if (is_asset_stream(*stream)) { rawStream.reset(new SkRawAssetStream(stream)); } else { rawStream.reset(new SkRawBufferedStream(stream)); } // Does not take the ownership of rawStream. SkPiexStream piexStream(rawStream.get()); ::piex::PreviewImageData imageData; if (::piex::IsRaw(&piexStream)) { ::piex::Error error = ::piex::GetPreviewImageData(&piexStream, &imageData); if (error == ::piex::Error::kOk && imageData.preview.length > 0) { // transferBuffer() is destructive to the rawStream. Abandon the rawStream after this // function call. // FIXME: one may avoid the copy of memoryStream and use the buffered rawStream. SkMemoryStream* memoryStream = rawStream->transferBuffer(imageData.preview.offset, imageData.preview.length); return memoryStream ? SkJpegCodec::NewFromStream(memoryStream) : nullptr; } else if (error == ::piex::Error::kFail) { return nullptr; } } // Takes the ownership of the rawStream. SkAutoTDelete<SkDngImage> dngImage(SkDngImage::NewFromStream(rawStream.release())); if (!dngImage) { return nullptr; } return new SkRawCodec(dngImage.release()); }
bool SkImage_Generator::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int srcX, int srcY, CachingHint chint) const { SkBitmap bm; if (kDisallow_CachingHint == chint) { if (fCache->lockAsBitmapOnlyIfAlreadyCached(&bm)) { return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY); } else { // Try passing the caller's buffer directly down to the generator. If this fails we // may still succeed in the general case, as the generator may prefer some other // config, which we could then convert via SkBitmap::readPixels. if (fCache->directGeneratePixels(dstInfo, dstPixels, dstRB, srcX, srcY)) { return true; } // else fall through } } if (this->getROPixels(&bm, chint)) { return bm.readPixels(dstInfo, dstPixels, dstRB, srcX, srcY); } return false; }
size_t FrontBufferedStream::read(void* voidDst, size_t size) { // Cast voidDst to a char* for easy addition. char* dst = reinterpret_cast<char*>(voidDst); SkDEBUGCODE(const size_t totalSize = size;) const size_t start = fOffset; // First, read any data that was previously buffered. if (fOffset < fBufferedSoFar) { const size_t bytesCopied = this->readFromBuffer(dst, size); // Update the remaining number of bytes needed to read // and the destination buffer. size -= bytesCopied; SkASSERT(size + (fOffset - start) == totalSize); if (dst != NULL) { dst += bytesCopied; } } // Buffer any more data that should be buffered, and copy it to the // destination. if (size > 0 && fBufferedSoFar < fBufferSize && !fStream->isAtEnd()) { const size_t buffered = this->bufferAndWriteTo(dst, size); // Update the remaining number of bytes needed to read // and the destination buffer. size -= buffered; SkASSERT(size + (fOffset - start) == totalSize); if (dst != NULL) { dst += buffered; } } if (size > 0 && !fStream->isAtEnd()) { SkDEBUGCODE(const size_t bytesReadDirectly =) this->readDirectlyFromStream(dst, size); SkDEBUGCODE(size -= bytesReadDirectly;)
size_t FrontBufferedStream::readDirectlyFromStream(char* dst, size_t size) { SkASSERT(size > 0); // If we get here, we have buffered all that can be buffered. SkASSERT(fBufferSize == fBufferedSoFar && fOffset >= fBufferSize); const size_t bytesReadDirectly = fStream->read(dst, size); fOffset += bytesReadDirectly; // If we have read past the end of the buffer, rewinding is no longer // supported, so we can go ahead and free the memory. if (bytesReadDirectly > 0) { sk_free(fBuffer.detach()); } return bytesReadDirectly; }
size_t FrontBufferedStream::bufferAndWriteTo(char* dst, size_t size) { SkASSERT(size > 0); SkASSERT(fOffset >= fBufferedSoFar); SkASSERT(fBuffer); // Data needs to be buffered. Buffer up to the lesser of the size requested // and the remainder of the max buffer size. const size_t bytesToBuffer = SkTMin(size, fBufferSize - fBufferedSoFar); char* buffer = fBuffer + fOffset; const size_t buffered = fStream->read(buffer, bytesToBuffer); fBufferedSoFar += buffered; fOffset = fBufferedSoFar; SkASSERT(fBufferedSoFar <= fBufferSize); // Copy the buffer to the destination buffer and update the amount read. if (dst != NULL) { memcpy(dst, buffer, buffered); } return buffered; }
void DecodingBench::onDraw(const int n, SkCanvas* canvas) { SkBitmap bitmap; // Declare the allocator before the decoder, so it will outlive the // decoder, which will unref it. UseExistingAllocator allocator(fBitmap.pixelRef()); SkAutoTDelete<SkImageDecoder> decoder; SkAutoTDelete<SkStreamRewindable> stream; for (int i = 0; i < n; i++) { // create a new stream and a new decoder to mimic the behavior of // CodecBench. stream.reset(new SkMemoryStream(fData)); decoder.reset(SkImageDecoder::Factory(stream)); decoder->setAllocator(&allocator); decoder->decode(stream, &bitmap, fColorType, SkImageDecoder::kDecodePixels_Mode); } }
SkData* SkImage_Generator::onRefEncoded(GrContext* ctx) const { return fCache->refEncoded(ctx); }
Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const { // Do all setup in this function because we don't know the size // for the RenderNode and RenderProxy during the constructor. // In practice this doesn't seem too expensive. const SkISize size = src.size(); // Based on android::SurfaceTexture_init() android::sp<android::IGraphicBufferProducer> producer; android::sp<android::IGraphicBufferConsumer> consumer; android::BufferQueue::createBufferQueue(&producer, &consumer); // Consumer setup android::sp<android::CpuConsumer> cpuConsumer = new android::CpuConsumer(consumer, 1); cpuConsumer->setName(android::String8("SkiaTestClient")); cpuConsumer->setDefaultBufferSize(size.width(), size.height()); // Producer setup android::sp<android::Surface> surface = new android::Surface(producer); native_window_set_buffers_dimensions(surface.get(), size.width(), size.height()); native_window_set_buffers_format(surface.get(), android::PIXEL_FORMAT_RGBA_8888); native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_RENDER); // RenderNode setup based on hwui/tests/main.cpp:TreeContentAnimation SkAutoTDelete<android::uirenderer::RenderNode> rootNode (new android::uirenderer::RenderNode()); rootNode->incStrong(nullptr); // Values set here won't be applied until the framework has called // RenderNode::pushStagingPropertiesChanges() during RenderProxy::syncAndDrawFrame(). rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, size.width(), size.height()); rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::X | android::uirenderer::RenderNode::Y); rootNode->mutateStagingProperties().setClipToBounds(false); rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC); // RenderProxy setup based on hwui/tests/main.cpp:TreeContentAnimation ContextFactory factory; SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy (new android::uirenderer::renderthread::RenderProxy(false, rootNode, &factory)); proxy->loadSystemProperties(); proxy->initialize(surface.get()); float lightX = size.width() / 2.0f; android::uirenderer::Vector3 lightVector { lightX, dp(-200.0f), dp(800.0f) }; proxy->setup(size.width(), size.height(), lightVector, dp(800.0f), 255 * 0.075f, 255 * 0.15f, kDensity); // Do the draw SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer (new android::uirenderer::DisplayListRenderer()); renderer->setViewport(size.width(), size.height()); renderer->prepare(); renderer->clipRect(0, 0, size.width(), size.height(), SkRegion::Op::kReplace_Op); Error err = src.draw(renderer->asSkCanvas()); if (!err.isEmpty()) { return err; } renderer->finish(); rootNode->setStagingDisplayList(renderer->finishRecording()); proxy->syncAndDrawFrame(); proxy->fence(); // Capture pixels SkImageInfo destinationConfig = SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType); dst->allocPixels(destinationConfig); sk_memset32((uint32_t*) dst->getPixels(), SK_ColorRED, size.width() * size.height()); android::CpuConsumer::LockedBuffer nativeBuffer; android::status_t retval = cpuConsumer->lockNextBuffer(&nativeBuffer); if (retval == android::BAD_VALUE) { SkDebugf("HWUISink::draw() got no buffer; returning transparent"); // No buffer ready to read - commonly triggered by dm sending us // a no-op source, or calling code that doesn't do anything on this // backend. dst->eraseColor(SK_ColorTRANSPARENT); return ""; } else if (retval) { return SkStringPrintf("Failed to lock buffer to read pixels: %d.", retval); } // Move the pixels into the destination SkBitmap SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 && "Native buffer not RGBA!"); SkImageInfo nativeConfig = SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height, kRGBA_8888_SkColorType, kPremul_SkAlphaType); // Android stride is in pixels, Skia stride is in bytes SkBitmap nativeWrapper; bool success = nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4); if (!success) { return "Failed to wrap HWUI buffer in a SkBitmap"; } SK_ALWAYSBREAK(dst->colorType() == kRGBA_8888_SkColorType && "Destination buffer not RGBA!"); success = nativeWrapper.readPixels(destinationConfig, dst->getPixels(), dst->rowBytes(), 0, 0); if (!success) { return "Failed to extract pixels from HWUI buffer"; } cpuConsumer->unlockBuffer(nativeBuffer); return ""; }
int tool_main(int argc, char** argv) { SetupCrashHandler(); SkString usage; usage.printf("Time drawing .skp files.\n" "\tPossible arguments for --filter: [%s]\n\t\t[%s]", filterTypesUsage().c_str(), filterFlagsUsage().c_str()); SkCommandLineFlags::SetUsage(usage.c_str()); SkCommandLineFlags::Parse(argc, argv); if (FLAGS_repeat < 1) { SkString error; error.printf("--repeats must be >= 1. Was %i\n", FLAGS_repeat); gLogger.logError(error); exit(-1); } if (FLAGS_logFile.count() == 1) { if (!gLogger.SetLogFile(FLAGS_logFile[0])) { SkString str; str.printf("Could not open %s for writing.\n", FLAGS_logFile[0]); gLogger.logError(str); // TODO(borenet): We're disabling this for now, due to // write-protected Android devices. The very short-term // solution is to ignore the fact that we have no log file. //exit(-1); } } SkAutoTDelete<PictureJSONResultsWriter> jsonWriter; if (FLAGS_jsonLog.count() == 1) { SkASSERT(FLAGS_builderName.count() == 1 && FLAGS_gitHash.count() == 1); jsonWriter.reset(SkNEW(PictureJSONResultsWriter( FLAGS_jsonLog[0], FLAGS_builderName[0], FLAGS_buildNumber, FLAGS_timestamp, FLAGS_gitHash[0], FLAGS_gitNumber))); gWriter.add(jsonWriter.get()); } gWriter.add(&gLogWriter); #if SK_ENABLE_INST_COUNT gPrintInstCount = true; #endif SkAutoGraphics ag; sk_tools::PictureBenchmark benchmark; setup_benchmark(&benchmark); int failures = 0; for (int i = 0; i < FLAGS_readPath.count(); ++i) { failures += process_input(FLAGS_readPath[i], benchmark); } if (failures != 0) { SkString err; err.printf("Failed to run %i benchmarks.\n", failures); gLogger.logError(err); return 1; } #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { SkDebugf("Total cache hit rate: %f\n", (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses)); } #endif gWriter.end(); return 0; }
GrTexture* SkImage_Generator::asTextureRef(GrContext* ctx, const GrTextureParams& params) const { return fCache->lockAsTexture(ctx, params, this); }
bool SkImage_Generator::getROPixels(SkBitmap* bitmap, CachingHint chint) const { return fCache->lockAsBitmap(bitmap, this, chint); }
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) { for (int i = 0; i < fContexts.count(); ++i) { Context& context = fContexts[i]; if (context.fType == type && context.fOptions == options && !context.fAbandoned) { if (context.fGLContext) { context.fGLContext->makeCurrent(); } return ContextInfo(context.fGrContext, context.fGLContext); } } SkAutoTDelete<GLTestContext> glCtx; sk_sp<GrContext> grCtx; GrBackendContext backendContext = 0; sk_sp<const GrGLInterface> glInterface; #ifdef SK_VULKAN sk_sp<const GrVkBackendContext> vkBackend; #endif GrBackend backend = ContextTypeBackend(type); switch (backend) { case kOpenGL_GrBackend: switch (type) { case kGL_ContextType: glCtx.reset(CreatePlatformGLTestContext(kGL_GrGLStandard)); break; case kGLES_ContextType: glCtx.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard)); break; #if SK_ANGLE # ifdef SK_BUILD_FOR_WIN case kANGLE_ContextType: glCtx.reset(CreateANGLEDirect3DGLTestContext()); break; # endif case kANGLE_GL_ContextType: glCtx.reset(CreateANGLEOpenGLGLTestContext()); break; #endif #if SK_COMMAND_BUFFER case kCommandBuffer_ContextType: glCtx.reset(CommandBufferGLTestContext::Create()); break; #endif #if SK_MESA case kMESA_ContextType: glCtx.reset(CreateMesaGLTestContext()); break; #endif case kNullGL_ContextType: glCtx.reset(CreateNullGLTestContext()); break; case kDebugGL_ContextType: glCtx.reset(CreateDebugGLTestContext()); break; default: return ContextInfo(); } if (nullptr == glCtx.get()) { return ContextInfo(); } glInterface.reset(SkRef(glCtx->gl())); // Block NVPR from non-NVPR types. if (!(kEnableNVPR_ContextOptions & options)) { glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get())); if (!glInterface) { return ContextInfo(); } } backendContext = reinterpret_cast<GrBackendContext>(glInterface.get()); glCtx->makeCurrent(); break; #ifdef SK_VULKAN case kVulkan_GrBackend: SkASSERT(kVulkan_ContextType == type); if ((kEnableNVPR_ContextOptions & options) || (kRequireSRGBSupport_ContextOptions & options)) { return ContextInfo(); } vkBackend.reset(GrVkBackendContext::Create()); if (!vkBackend) { return ContextInfo(); } backendContext = reinterpret_cast<GrBackendContext>(vkBackend.get()); // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice // destruction will hang occaisonally. For some reason having an existing GL // context fixes this. if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard)); if (!fSentinelGLContext) { fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard)); } } break; #endif default: return ContextInfo(); } grCtx.reset(GrContext::Create(backend, backendContext, fGlobalOptions)); if (!grCtx.get()) { return ContextInfo(); } if (kEnableNVPR_ContextOptions & options) { if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) { return ContextInfo(); } } if (kRequireSRGBSupport_ContextOptions & options) { if (!grCtx->caps()->srgbSupport()) { return ContextInfo(); } } Context& context = fContexts.push_back(); context.fGLContext = glCtx.release(); context.fGrContext = SkRef(grCtx.get()); context.fType = type; context.fOptions = options; context.fAbandoned = false; return ContextInfo(context.fGrContext, context.fGLContext); }
static int filter_picture(const SkString& inFile, const SkString& outFile) { SkAutoTDelete<SkPicture> inPicture; SkFILEStream inStream(inFile.c_str()); if (inStream.isValid()) { inPicture.reset(SkPicture::CreateFromStream(&inStream)); } if (NULL == inPicture.get()) { SkDebugf("Could not read file %s\n", inFile.c_str()); return -1; } int localCount[SK_ARRAY_COUNT(gOptTable)]; memset(localCount, 0, sizeof(localCount)); SkDebugCanvas debugCanvas(inPicture->width(), inPicture->height()); debugCanvas.setBounds(inPicture->width(), inPicture->height()); inPicture->draw(&debugCanvas); // delete the initial save and restore since replaying the commands will // re-add them if (debugCanvas.getSize() > 1) { debugCanvas.deleteDrawCommandAt(0); debugCanvas.deleteDrawCommandAt(debugCanvas.getSize()-1); } bool changed = true; int numBefore = debugCanvas.getSize(); while (changed) { changed = false; for (int i = 0; i < debugCanvas.getSize(); ++i) { for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if ((*gOptTable[opt].fCheck)(&debugCanvas, i)) { (*gOptTable[opt].fApply)(&debugCanvas, i); ++gOptTable[opt].fNumTimesApplied; ++localCount[opt]; if (debugCanvas.getSize() == i) { // the optimization removed all the remaining operations break; } opt = 0; // try all the opts all over again changed = true; } } } } int numAfter = debugCanvas.getSize(); if (!outFile.isEmpty()) { SkPicture outPicture; SkCanvas* canvas = outPicture.beginRecording(inPicture->width(), inPicture->height()); debugCanvas.draw(canvas); outPicture.endRecording(); SkFILEWStream outStream(outFile.c_str()); outPicture.serialize(&outStream); } bool someOptFired = false; for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if (0 != localCount[opt]) { SkDebugf("%d: %d ", opt, localCount[opt]); someOptFired = true; } } if (!someOptFired) { SkDebugf("No opts fired\n"); } else { SkDebugf("\t before: %d after: %d delta: %d\n", numBefore, numAfter, numBefore-numAfter); } return 0; }