Beispiel #1
0
bool SkPaintToGrPaintWithTexture(GrContext* context,
                                 const SkPaint& paint,
                                 const SkMatrix& viewM,
                                 const GrFragmentProcessor* fp,
                                 bool textureIsAlphaOnly,
                                 GrPaint* grPaint) {
    SkAutoTUnref<const GrFragmentProcessor> shaderFP;
    if (textureIsAlphaOnly) {
        if (const SkShader* shader = paint.getShader()) {
            shaderFP.reset(shader->asFragmentProcessor(context,
                                                       viewM,
                                                       nullptr,
                                                       paint.getFilterQuality()));
            if (!shaderFP) {
                return false;
            }
            const GrFragmentProcessor* fpSeries[] = { shaderFP.get(), fp };
            shaderFP.reset(GrFragmentProcessor::RunInSeries(fpSeries, 2));
        } else {
            shaderFP.reset(GrFragmentProcessor::MulOutputByInputUnpremulColor(fp));
        }
    } else {
        shaderFP.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp));
    }

    return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), grPaint);
}
Beispiel #2
0
    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));
    }
Beispiel #3
0
SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
    if (id.fDataId == SkFontIdentity::kInvalidDataId) {
        return nullptr;
    }

    SkAutoMutexAcquire ama(fDataCacheMutex);

    SkAutoTUnref<SkTypeface> dataTypeface;
    int dataTypefaceIndex = 0;
    for (int i = 0; i < fDataCache.count(); ++i) {
        const DataEntry& entry = fDataCache[i];
        if (entry.fDataId == id.fDataId) {
            if (entry.fTtcIndex == id.fTtcIndex &&
                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
            {
                return entry.fTypeface;
            }
            if (dataTypeface.get() == nullptr &&
                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
            {
                dataTypeface.reset(entry.fTypeface);
                dataTypefaceIndex = entry.fTtcIndex;
            }
        }

        if (entry.fTypeface->weak_expired()) {
            fDataCache.removeShuffle(i);
            --i;
        }
    }

    // No exact match, but did find a data match.
    if (dataTypeface.get() != nullptr) {
        SkAutoTDelete<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
        if (stream.get() != nullptr) {
            return fImpl->createFromStream(stream.release(), dataTypefaceIndex);
        }
    }

    // No data match, request data and add entry.
    SkAutoTDelete<SkStreamAsset> stream(fProxy->getData(id.fDataId));
    if (stream.get() == nullptr) {
        return nullptr;
    }

    SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream.release(), id.fTtcIndex));
    if (typeface.get() == nullptr) {
        return nullptr;
    }

    DataEntry& newEntry = fDataCache.push_back();
    typeface->weak_ref();
    newEntry.fDataId = id.fDataId;
    newEntry.fTtcIndex = id.fTtcIndex;
    newEntry.fTypeface = typeface.get();  // weak reference passed to new entry.

    return typeface.release();
}
Beispiel #4
0
static void GLInterfaceValidationTest(skiatest::Reporter* reporter) {
    typedef const GrGLInterface* (*interfaceFactory)();
    struct {
       interfaceFactory fFactory;
       const char* fName;
    } interfaceFactories[] = {
#if SK_ANGLE
        {GrGLCreateANGLEInterface, "ANGLE"},
#endif
        {GrGLCreateNativeInterface, "Native"},
#if SK_MESA
        {GrGLCreateMesaInterface, "Mesa"},
#endif
        {GrGLCreateDebugInterface, "Debug"},
        {GrGLCreateNullInterface, "Null"},
    };

    // On some platforms GrGLCreateNativeInterface will fail unless an OpenGL
    // context has been created. Also, preserve the current context that may
    // be in use by outer test harness.
    SkNativeGLContext::AutoContextRestore nglacr;
    SkNativeGLContext nglctx;
    static const int gBOGUS_SIZE = 16;
    bool nativeContextInit = nglctx.init(gBOGUS_SIZE, gBOGUS_SIZE);
    REPORTER_ASSERT(reporter, nativeContextInit);
    if (!nativeContextInit) {
        return;
    }
#if SK_MESA
    // We must have a current OSMesa context to initialize an OSMesa
    // GrGLInterface
    SkMesaGLContext::AutoContextRestore mglacr;
    SkMesaGLContext mglctx;
    bool mesaContextInit = mglctx.init(gBOGUS_SIZE, gBOGUS_SIZE);
    REPORTER_ASSERT(reporter, mesaContextInit);
    if(!mesaContextInit) {
        return;
    }
#endif

    SkAutoTUnref<const GrGLInterface> iface;
    for (size_t i = 0; i < SK_ARRAY_COUNT(interfaceFactories); ++i) {
        iface.reset(interfaceFactories[i].fFactory());
        REPORTER_ASSERT(reporter, NULL != iface.get());
        if (iface.get()) {
            for (GrGLBinding binding = kFirstGrGLBinding;
                 binding <= kLastGrGLBinding;
                 binding = static_cast<GrGLBinding>(binding << 1)) {
                if (iface.get()->fBindingsExported & binding) {
                    REPORTER_ASSERT(reporter, iface.get()->validate(binding));
                }
            }
        }
    }
}
Beispiel #5
0
/*
 *  Modulo internal errors, this should always succeed *if* the matrix is downscaling
 *  (in this case, we have the inverse, so it succeeds if fInvMatrix is upscaling)
 */
bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmapProvider& provider) {
    SkASSERT(fQuality <= kMedium_SkFilterQuality);
    if (fQuality != kMedium_SkFilterQuality) {
        return false;
    }

    // Our default return state is to downgrade the request to Low, w/ or w/o setting fBitmap
    // to a valid bitmap.
    fQuality = kLow_SkFilterQuality;

    SkSize invScaleSize;
    if (!fInvMatrix.decomposeScale(&invScaleSize, nullptr)) {
        return false;
    }

    // Use the largest (non-inverse) scale, to ensure anisotropic consistency.
    SkASSERT(invScaleSize.width() >= 0 && invScaleSize.height() >= 0);
    const SkScalar invScale = SkTMin(invScaleSize.width(), invScaleSize.height());

    if (invScale > SK_Scalar1) {
        fCurrMip.reset(SkMipMapCache::FindAndRef(provider.makeCacheDesc()));
        if (nullptr == fCurrMip.get()) {
            SkBitmap orig;
            if (!provider.asBitmap(&orig)) {
                return false;
            }
            fCurrMip.reset(SkMipMapCache::AddAndRef(orig));
            if (nullptr == fCurrMip.get()) {
                return false;
            }
        }
        // diagnostic for a crasher...
        if (nullptr == fCurrMip->data()) {
            sk_throw();
        }

        SkScalar levelScale = SkScalarInvert(invScale);
        SkMipMap::Level level;
        if (fCurrMip->extractLevel(levelScale, &level)) {
            const SkSize& invScaleFixup = level.fScale;
            fInvMatrix.postScale(invScaleFixup.width(), invScaleFixup.height());

            // todo: if we could wrap the fCurrMip in a pixelref, then we could just install
            //       that here, and not need to explicitly track it ourselves.
            return fResultBitmap.installPixels(level.fPixmap);
        } else {
            // failed to extract, so release the mipmap
            fCurrMip.reset(nullptr);
        }
    }
    return false;
}
    static GrEffectRef* Create(bool stroke) {
        // we go through this so we only have one copy of each effect (stroked/filled)
        static SkAutoTUnref<GrEffectRef> gCircleStrokeEdgeEffectRef(
                        CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (true)))));
        static SkAutoTUnref<GrEffectRef> gCircleFillEdgeEffectRef(
                        CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (false)))));

        if (stroke) {
            gCircleStrokeEdgeEffectRef.get()->ref();
            return gCircleStrokeEdgeEffectRef;
        } else {
            gCircleFillEdgeEffectRef.get()->ref();
            return gCircleFillEdgeEffectRef;
        }
    }
Beispiel #7
0
    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setLCDRenderText(true);
        paint.setSubpixelText(true);
        paint.setTextSize(17);

        static const char* gNames[] = {
            "Helvetica Neue", "Arial"
        };

        SkAutoTUnref<SkFontStyleSet> fset;
        for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
            fset.reset(fFM->matchFamily(gNames[i]));
            if (fset->count() > 0) {
                break;
            }
        }
        if (nullptr == fset.get()) {
            return;
        }

        canvas->translate(20, 40);
        this->exploreFamily(canvas, paint, fset);
        canvas->translate(150, 0);
        this->iterateFamily(canvas, paint, fset);
    }
static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
    android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
    if (asset == NULL) return NULL;
    SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset));
    SkMovie* moov = SkMovie::DecodeStream(stream.get());
    return create_jmovie(env, moov);
}
Beispiel #9
0
/*
 *  Modulo internal errors, this should always succeed *if* the matrix is downscaling
 *  (in this case, we have the inverse, so it succeeds if fInvMatrix is upscaling)
 */
bool SkDefaultBitmapControllerState::processMediumRequest(const SkBitmap& origBitmap) {
    SkASSERT(fQuality <= kMedium_SkFilterQuality);
    if (fQuality != kMedium_SkFilterQuality) {
        return false;
    }
    
    // Our default return state is to downgrade the request to Low, w/ or w/o setting fBitmap
    // to a valid bitmap.
    fQuality = kLow_SkFilterQuality;
    
    SkSize invScaleSize;
    if (!fInvMatrix.decomposeScale(&invScaleSize, NULL)) {
        return false;
    }
    SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height());
    
    if (invScale > SK_Scalar1) {
        fCurrMip.reset(SkMipMapCache::FindAndRef(origBitmap));
        if (NULL == fCurrMip.get()) {
            fCurrMip.reset(SkMipMapCache::AddAndRef(origBitmap));
            if (NULL == fCurrMip.get()) {
                return false;
            }
        }
        // diagnostic for a crasher...
        if (NULL == fCurrMip->data()) {
            sk_throw();
        }
        
        SkScalar levelScale = SkScalarInvert(invScale);
        SkMipMap::Level level;
        if (fCurrMip->extractLevel(levelScale, &level)) {
            SkScalar invScaleFixup = level.fScale;
            fInvMatrix.postScale(invScaleFixup, invScaleFixup);
            
            const SkImageInfo info = origBitmap.info().makeWH(level.fWidth, level.fHeight);
            // todo: if we could wrap the fCurrMip in a pixelref, then we could just install
            //       that here, and not need to explicitly track it ourselves.
            return fResultBitmap.installPixels(info, level.fPixels, level.fRowBytes);
        } else {
            // failed to extract, so release the mipmap
            fCurrMip.reset(NULL);
        }
    }
    return false;
}
Beispiel #10
0
const GrFragmentProcessor* SkImageShader::asFragmentProcessor(GrContext* context,
        const SkMatrix& viewM,
        const SkMatrix* localMatrix,
        SkFilterQuality filterQuality,
        GrProcessorDataManager* mgr) const {
    SkMatrix matrix;
    matrix.setIDiv(fImage->width(), fImage->height());

    SkMatrix lmInverse;
    if (!this->getLocalMatrix().invert(&lmInverse)) {
        return nullptr;
    }
    if (localMatrix) {
        SkMatrix inv;
        if (!localMatrix->invert(&inv)) {
            return nullptr;
        }
        lmInverse.postConcat(inv);
    }
    matrix.preConcat(lmInverse);

    SkShader::TileMode tm[] = { fTileModeX, fTileModeY };

    // Must set wrap and filter on the sampler before requesting a texture. In two places below
    // we check the matrix scale factors to determine how to interpret the filter quality setting.
    // This completely ignores the complexity of the drawVertices case where explicit local coords
    // are provided by the caller.
    bool doBicubic;
    GrTextureParams::FilterMode textureFilterMode =
        GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(), &doBicubic);
    GrTextureParams params(tm, textureFilterMode);

    SkImageUsageType usageType;
    if (kClamp_TileMode == fTileModeX && kClamp_TileMode == fTileModeY) {
        usageType = kUntiled_SkImageUsageType;
    } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
        usageType = kTiled_Unfiltered_SkImageUsageType;
    } else {
        usageType = kTiled_Filtered_SkImageUsageType;
    }

    SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(context, usageType));
    if (!texture) {
        return nullptr;
    }

    SkAutoTUnref<GrFragmentProcessor> inner;
    if (doBicubic) {
        inner.reset(GrBicubicEffect::Create(mgr, texture, matrix, tm));
    } else {
        inner.reset(GrSimpleTextureEffect::Create(mgr, texture, matrix, params));
    }

    if (GrPixelConfigIsAlphaOnly(texture->config())) {
        return SkRef(inner.get());
    }
    return GrFragmentProcessor::MulOuputByInputAlpha(inner);
}
Beispiel #11
0
/**
 *  If --readExpectationsPath is set, compare this bitmap to the json expectations
 *  provided.
 *
 *  @param digest GmResultDigest, computed from the decoded bitmap, to compare to
 *         the existing expectation.
 *  @param filename String used to find the expected value. Will be combined with the
 *         preferred config, as specified by "--config", to match the pattern of
 *         gm_json.py's IMAGE_FILENAME_PATTERN: "filename_config.png". The resulting
 *         key will be used to find the proper expectations.
 *  @param failureArray Array to add a failure message to on failure.
 *  @param missingArray Array to add failure message to when missing image
 *          expectation.
 *  @param ignoreArray Array to add failure message to when the image does not match
 *          the expectation, but this is a failure we can ignore.
 *  @return bool True in any of these cases:
 *                  - the bitmap matches the expectation.
 *               False in any of these cases:
 *                  - there is no expectations file.
 *                  - there is an expectations file, but no expectation for this bitmap.
 *                  - there is an expectation for this bitmap, but it did not match.
 *                  - expectation could not be computed from the bitmap.
 */
static bool compare_to_expectations_if_necessary(const skiagm::GmResultDigest& digest,
        const char* filename,
        SkTArray<SkString, false>* failureArray,
        SkTArray<SkString, false>* missingArray,
        SkTArray<SkString, false>* ignoreArray) {
    // For both writing and reading, the key for this entry will include the name
    // of the file and the pref config, matching the pattern of gm_json.py's
    // IMAGE_FILENAME_PATTERN: "name_config.png"
    const SkString name_config = create_json_key(filename);

    if (!digest.isValid()) {
        if (failureArray != NULL) {
            failureArray->push_back().printf("decoded %s, but could not create a GmResultDigest.",
                                             filename);
        }
        return false;
    }

    if (NULL == gJsonExpectations.get()) {
        return false;
    }

    skiagm::Expectations jsExpectation = gJsonExpectations->get(name_config.c_str());
    if (jsExpectation.empty()) {
        if (missingArray != NULL) {
            missingArray->push_back().printf("decoded %s, but could not find expectation.",
                                             filename);
        }
        return false;
    }

    if (jsExpectation.match(digest)) {
        return true;
    }

    if (jsExpectation.ignoreFailure()) {
        ignoreArray->push_back().printf("%s does not match expectation, but this is known.",
                                        filename);
    } else if (failureArray != NULL) {
        failureArray->push_back().printf("decoded %s, but the result does not match "
                                         "expectations.",
                                         filename);
    }
    return false;
}
			~ImageRenderingContext()
			{
				if (IsGpu)
				{
					SkAutoTUnref<SkImage> image;
					image.reset(Surface->newImageSnapshot(SkSurface::kNo_Budgeted));
					image.get()->readPixels(Image->Bitmap.info(), Image->Bitmap.getPixels(), Image->Bitmap.rowBytes(), 0, 0);
				}
				Surface.reset(nullptr);
			}
Beispiel #13
0
SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
    SkCanvas* canvas;
    switch(fDeviceType) {
        case kBitmap_DeviceType: {
            SkBitmap bitmap;
            sk_tools::setup_bitmap(&bitmap, width, height);
            canvas = SkNEW_ARGS(SkCanvas, (bitmap));
        }
        break;
#if SK_SUPPORT_GPU
#if SK_ANGLE
        case kAngle_DeviceType:
            // fall through
#endif
#if SK_MESA
        case kMesa_DeviceType:
            // fall through
#endif
        case kGPU_DeviceType:
        case kNVPR_DeviceType: {
            SkAutoTUnref<GrSurface> target;
            if (fGrContext) {
                // create a render target to back the device
                GrTextureDesc desc;
                desc.fConfig = kSkia8888_GrPixelConfig;
                desc.fFlags = kRenderTarget_GrTextureFlagBit;
                desc.fWidth = width;
                desc.fHeight = height;
                desc.fSampleCnt = fSampleCount;
                target.reset(fGrContext->createUncachedTexture(desc, NULL, 0));
            }
            if (NULL == target.get()) {
                SkASSERT(0);
                return NULL;
            }

            SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target));
            canvas = SkNEW_ARGS(SkCanvas, (device.get()));
            break;
        }
#endif
        default:
            SkASSERT(0);
            return NULL;
    }
    setUpFilter(canvas, fDrawFilters);
    this->scaleToScaleFactor(canvas);

    // Pictures often lie about their extent (i.e., claim to be 100x100 but
    // only ever draw to 90x100). Clear here so the undrawn portion will have
    // a consistent color
    canvas->clear(SK_ColorTRANSPARENT);
    return canvas;
}
Beispiel #14
0
const GrFragmentProcessor* SkBitmapProcShader::asFragmentProcessor(GrContext* context,
                                             const SkMatrix& viewM, const SkMatrix* localMatrix,
                                             SkFilterQuality filterQuality,
                                             GrProcessorDataManager* procDataManager) const {
    SkMatrix matrix;
    matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());

    SkMatrix lmInverse;
    if (!this->getLocalMatrix().invert(&lmInverse)) {
        return nullptr;
    }
    if (localMatrix) {
        SkMatrix inv;
        if (!localMatrix->invert(&inv)) {
            return nullptr;
        }
        lmInverse.postConcat(inv);
    }
    matrix.preConcat(lmInverse);

    SkShader::TileMode tm[] = {
        (TileMode)fTileModeX,
        (TileMode)fTileModeY,
    };

    // Must set wrap and filter on the sampler before requesting a texture. In two places below
    // we check the matrix scale factors to determine how to interpret the filter quality setting.
    // This completely ignores the complexity of the drawVertices case where explicit local coords
    // are provided by the caller.
    bool doBicubic;
    GrTextureParams::FilterMode textureFilterMode =
            GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(),
                                            &doBicubic);
    GrTextureParams params(tm, textureFilterMode);
    SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, fRawBitmap, &params));

    if (!texture) {
        SkErrorInternals::SetError( kInternalError_SkError,
                                    "Couldn't convert bitmap to texture.");
        return nullptr;
    }

    SkAutoTUnref<GrFragmentProcessor> inner;
    if (doBicubic) {
        inner.reset(GrBicubicEffect::Create(procDataManager, texture, matrix, tm));
    } else {
        inner.reset(GrSimpleTextureEffect::Create(procDataManager, texture, matrix, params));
    }

    if (kAlpha_8_SkColorType == fRawBitmap.colorType()) {
        return SkRef(inner.get());
    }
    return GrExtractAlphaFragmentProcessor::Create(inner);
}
Beispiel #15
0
// static
SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
                                    const SkIRect& srcRect,
                                    SkPicture::EncodeBitmap encoder) {
    if (bitmap.colorType() == kUnknown_SkColorType) {
        return NULL;
    }

    bool isTransparent = false;
    SkAutoTUnref<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)) {
        SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect);
        image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false,
                           SkIRect::MakeWH(srcRect.width(), srcRect.height()),
                           encoder));
    } else {
        image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect, encoder));
    }
    if (alphaData.get() != NULL) {
        SkAutoTUnref<SkPDFImage> mask(
                SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap,
                                        true, srcRect, NULL)));
        image->addSMask(mask);
    }

    return image;
}
Beispiel #16
0
SkData* SkImage::encode(SkPixelSerializer* serializer) const {
    SkAutoTUnref<SkPixelSerializer> defaultSerializer;
    SkPixelSerializer* effectiveSerializer = serializer;
    if (!effectiveSerializer) {
        defaultSerializer.reset(SkImageEncoder::CreatePixelSerializer());
        SkASSERT(defaultSerializer.get());
        effectiveSerializer = defaultSerializer.get();
    }
    SkAutoTUnref<SkData> encoded(this->refEncoded());
    if (encoded && effectiveSerializer->useEncodedData(encoded->data(), encoded->size())) {
        return encoded.detach();
    }

    SkBitmap bm;
    SkAutoPixmapUnlock apu;
    if (as_IB(this)->getROPixels(&bm) && bm.requestLock(&apu)) {
        return effectiveSerializer->encode(apu.pixmap());
    }

    return nullptr;
}
Beispiel #17
0
GrContext* GpuTest::GetContext() {
#if SK_SUPPORT_GPU
    // preserve this order, we want gGrContext destroyed after gEGLContext
    static SkTLazy<SkNativeGLContext> gGLContext;
    static SkAutoTUnref<GrContext> gGrContext;

    if (NULL == gGrContext.get()) {
        gGLContext.init();
        if (gGLContext.get()->init(800, 600)) {
            GrPlatform3DContext ctx = reinterpret_cast<GrPlatform3DContext>(gGLContext.get()->gl());
            gGrContext.reset(GrContext::Create(kOpenGL_Shaders_GrEngine, ctx));
        }
    }
    if (gGLContext.get()) {
        gGLContext.get()->makeCurrent();
    }
    return gGrContext.get();
#else
    return NULL;
#endif
}
Beispiel #18
0
void PDFTask::draw() {
    SkAutoTUnref<SkData> pdfData;
    bool rasterize = true;
    if (fGM.get()) {
        rasterize = 0 == (fGM->getFlags() & skiagm::GM::kSkipPDFRasterization_Flag);
        SinglePagePDF pdf(fGM->width(), fGM->height());
        //TODO(mtklein): GM doesn't do this.  Why not?
        //pdf.canvas()->concat(fGM->getInitialTransform());
        fGM->draw(pdf.canvas());
        pdfData.reset(pdf.end());
    } else {
        SinglePagePDF pdf(SkIntToScalar(fPicture->width()), SkIntToScalar(fPicture->height()));
        fPicture->draw(pdf.canvas());
        pdfData.reset(pdf.end());
    }

    SkASSERT(pdfData.get());
    if (rasterize) {
        this->spawnChild(SkNEW_ARGS(PDFRasterizeTask, (*this, pdfData.get(), fRasterize)));
    }
    this->spawnChild(SkNEW_ARGS(WriteTask, (*this, pdfData.get(), ".pdf")));
}
Beispiel #19
0
DEF_TEST(Recorder_drawImage_takeReference, reporter) {

    SkAutoTUnref<SkImage> image;
    {
        SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100));
        surface->getCanvas()->clear(SK_ColorGREEN);
        image.reset(surface->newImageSnapshot());
    }
    {
        SkRecord record;
        SkRecorder recorder(&record, 100, 100);

        // DrawImage is supposed to take a reference
        recorder.drawImage(image.get(), 0, 0);
        REPORTER_ASSERT(reporter, !image->unique());

        Tally tally;
        tally.apply(record);

        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImage>());
    }
    REPORTER_ASSERT(reporter, image->unique());

    {
        SkRecord record;
        SkRecorder recorder(&record, 100, 100);

        // DrawImageRect is supposed to take a reference
        recorder.drawImageRect(image.get(), 0, SkRect::MakeWH(100, 100));
        REPORTER_ASSERT(reporter, !image->unique());

        Tally tally;
        tally.apply(record);

        REPORTER_ASSERT(reporter, 1 == tally.count<SkRecords::DrawImageRect>());
    }
    REPORTER_ASSERT(reporter, image->unique());
}
Beispiel #20
0
    Benchmark* innerNext() {
        // Render skps
        while (fCurrentSKP < fSKPs.count()) {
            const SkString& path = fSKPs[fCurrentSKP++];
            SkAutoTUnref<SkPicture> pic;
            if (!ReadPicture(path.c_str(), &pic)) {
                continue;
            }

            SkString name = SkOSPath::Basename(path.c_str());
            return new VisualSKPBench(name.c_str(), pic.get());
        }

        return nullptr;
    }
Beispiel #21
0
ECode Movie::NativeDecodeAsset(
    /* [in] */ Int64 native_asset,
    /* [out] */IMovie** movie)
{
    VALIDATE_NOT_NULL(movie);
    android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
    if (asset == NULL) {
        *movie = NULL;
        return NOERROR;
    }
    SkAutoTUnref<SkStreamRewindable> stream (new AssetStreamAdaptor(asset,
            AssetStreamAdaptor::kNo_OwnAsset,
            AssetStreamAdaptor::kNo_HasMemoryBase));
    SkMovie* moov = SkMovie::DecodeStream(stream.get());

    return CreateMovie(moov, movie);
}
			ImageRenderingContext(BitmapContainer*image)
			{
				Image = image;
				IsGpu = false;
				if (Context != nullptr && Options[proForceSoftware] == nullptr)
					Surface.reset(SkSurface::NewRenderTarget(Context, SkSurface::kNo_Budgeted, Image->Bitmap.info()));
				if (Surface.get() != nullptr)
					IsGpu = true;
				else
				{
					Surface.reset(SkSurface::NewRasterDirect(image->Bitmap.info(), image->Bitmap.getPixels(), image->Bitmap.rowBytes()));
				}
				
				Surface.reset(SkSurface::NewRasterDirect(image->Bitmap.info(), image->Bitmap.getPixels(), image->Bitmap.rowBytes()));

				Canvas = Surface->getCanvas();
				Canvas->clear(SkColor());
			}
Beispiel #23
0
sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, const void* data,
                                                         SkBudgeted budgeted) {
    if (!data) {
        return nullptr;
    }
    const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImage*>(data);

    if (!context || context->uniqueID() != dti->fContextUniqueID) {
        return nullptr;
    }
    SkAutoTUnref<SkColorTable> colorTable;
    if (dti->fData.fColorTableCnt) {
        SkASSERT(dti->fData.fColorTableData);
        colorTable.reset(new SkColorTable(dti->fData.fColorTableData, dti->fData.fColorTableCnt));
    }
    SkPixmap pixmap;
    pixmap.reset(dti->fData.fInfo, dti->fData.fPixelData, dti->fData.fRowBytes, colorTable.get());
    return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
}
    void onPrepareDraws(Target* target) const override {
        SkAutoTUnref<const GrGeometryProcessor> gp;
        {
            using namespace GrDefaultGeoProcFactory;

            Color color(fColor);
            LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ?
                                    LocalCoords::kUsePosition_Type :
                                    LocalCoords::kUnused_Type);
            Coverage::Type coverageType;
            if (fPipelineInfo.readsCoverage()) {
                coverageType = Coverage::kSolid_Type;
            } else {
                coverageType = Coverage::kNone_Type;
            }
            Coverage coverage(coverageType);
            gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords,
                                                     fViewMatrix));
        }
        this->draw(target, gp.get());
    }
Beispiel #25
0
sk_sp<SkImage> SkImage::MakeFromDeferredTextureImageData(GrContext* context, const void* data,
                                                         SkBudgeted budgeted) {
    if (!data) {
        return nullptr;
    }
    const DeferredTextureImage* dti = reinterpret_cast<const DeferredTextureImage*>(data);

    if (!context || context->uniqueID() != dti->fContextUniqueID) {
        return nullptr;
    }
    SkAutoTUnref<SkColorTable> colorTable;
    if (dti->fColorTableCnt) {
        SkASSERT(dti->fColorTableData);
        colorTable.reset(new SkColorTable(dti->fColorTableData, dti->fColorTableCnt));
    }
    int mipLevelCount = dti->fMipMapLevelCount;
    SkASSERT(mipLevelCount >= 1);
    sk_sp<SkColorSpace> colorSpace;
    if (dti->fColorSpaceSize) {
        colorSpace = SkColorSpace::Deserialize(dti->fColorSpace, dti->fColorSpaceSize);
    }
    SkImageInfo info = SkImageInfo::Make(dti->fWidth, dti->fHeight,
                                         dti->fColorType, dti->fAlphaType, colorSpace);
    if (mipLevelCount == 1) {
        SkPixmap pixmap;
        pixmap.reset(info, dti->fMipMapLevelData[0].fPixelData,
                     dti->fMipMapLevelData[0].fRowBytes, colorTable.get());
        return SkImage::MakeTextureFromPixmap(context, pixmap, budgeted);
    } else {
        SkAutoTDeleteArray<GrMipLevel> texels(new GrMipLevel[mipLevelCount]);
        for (int i = 0; i < mipLevelCount; i++) {
            texels[i].fPixels = dti->fMipMapLevelData[i].fPixelData;
            texels[i].fRowBytes = dti->fMipMapLevelData[i].fRowBytes;
        }

        return SkImage::MakeTextureFromMipMap(context, info, texels.get(),
                                              mipLevelCount, SkBudgeted::kYes,
                                              dti->fGammaTreatment);
    }
}
    int tessellate(GrUniqueKey* key,
                   GrResourceProvider* resourceProvider,
                   SkAutoTUnref<GrVertexBuffer>& vertexBuffer,
                   bool canMapVB) const {
        SkPath path;
        GrStrokeInfo stroke(fStroke);
        if (stroke.isDashed()) {
            if (!stroke.applyDashToPath(&path, &stroke, fPath)) {
                return 0;
            }
        } else {
            path = fPath;
        }
        if (!stroke.isFillStyle()) {
            stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale()));
            if (!stroke.applyToPath(&path, path)) {
                return 0;
            }
            stroke.setFillStyle();
        }
        SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
        SkRect pathBounds = path.getBounds();
        SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, pathBounds);

        bool isLinear;
        int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, resourceProvider, 
                                                   vertexBuffer, canMapVB, &isLinear);
        if (!fPath.isVolatile()) {
            TessInfo info;
            info.fTolerance = isLinear ? 0 : tol;
            info.fCount = count;
            SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info)));
            key->setCustomData(data.get());
            resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get());
            SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key));
        }
        return count;
    }
const GrGLInterface* GrGLDefaultInterface() {
    static SkAutoTUnref<GrGLInterface> glInterface;
    if (!glInterface.get()) {
        GrGLInteface* interface = new GrGLInterface;
        glInterface.reset(interface);

        interface->fActiveTexture = glActiveTexture;
        interface->fAttachShader = glAttachShader;
        interface->fBindAttribLocation = glBindAttribLocation;
        interface->fBindBuffer = glBindBuffer;
        interface->fBindTexture = glBindTexture;
        interface->fBlendColor = glBlendColor;
        interface->fBlendEquation = glBlendEquation;
        interface->fBlendFunc = glBlendFunc;
        interface->fBufferData = (GrGLBufferDataProc)glBufferData;
        interface->fBufferSubData = (GrGLBufferSubDataProc)glBufferSubData;
        interface->fClear = glClear;
        interface->fClearColor = glClearColor;
        interface->fClearStencil = glClearStencil;
        interface->fColorMask = glColorMask;
        interface->fColorPointer = glColorPointer;
        interface->fCompileShader = glCompileShader;
        interface->fCompressedTexImage2D = glCompressedTexImage2D;
        interface->fCreateProgram = glCreateProgram;
        interface->fCreateShader = glCreateShader;
        interface->fCullFace = glCullFace;
        interface->fDeleteBuffers = glDeleteBuffers;
        interface->fDeleteProgram = glDeleteProgram;
        interface->fDeleteShader = glDeleteShader;
        interface->fDeleteTextures = glDeleteTextures;
        interface->fDepthMask = glDepthMask;
        interface->fDisable = glDisable;
        interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
        interface->fDrawArrays = glDrawArrays;
        interface->fDrawBuffer = NULL;
        interface->fDrawBuffers = NULL;
        interface->fDrawElements = glDrawElements;
        interface->fEnable = glEnable;
        interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
        interface->fFrontFace = glFrontFace;
        interface->fGenBuffers = glGenBuffers;
        interface->fGetBufferParameteriv = glGetBufferParameteriv;
        interface->fGetError = glGetError;
        interface->fGetIntegerv = glGetIntegerv;
        interface->fGetProgramInfoLog = glGetProgramInfoLog;
        interface->fGetProgramiv = glGetProgramiv;
        interface->fGetShaderInfoLog = glGetShaderInfoLog;
        interface->fGetShaderiv = glGetShaderiv;
        interface->fGetString = glGetString;
        interface->fGenTextures = glGenTextures;
        interface->fGetUniformLocation = glGetUniformLocation;
        interface->fLineWidth = glLineWidth;
        interface->fLinkProgram = glLinkProgram;
        interface->fPixelStorei = glPixelStorei;
        interface->fReadBuffer = NULL;
        interface->fReadPixels = glReadPixels;
        interface->fScissor = glScissor;
        interface->fShaderSource = glShaderSource;
        interface->fStencilFunc = glStencilFunc;
        interface->fStencilFuncSeparate = glStencilFuncSeparate;
        interface->fStencilMask = glStencilMask;
        interface->fStencilMaskSeparate = glStencilMaskSeparate;
        interface->fStencilOp = glStencilOp;
        interface->fStencilOpSeparate = glStencilOpSeparate;
        // mac uses GLenum for internalFormat param (non-standard)
        // amounts to int vs. uint.
        interface->fTexImage2D = (GrGLTexImage2DProc)glTexImage2D;
    #if GL_ARB_texture_storage
        interface->fTexStorage2D = glTexStorage2D;
    #elif GL_EXT_texture_storage
        interface->fTexStorage2D = glTexStorage2DEXT;
    #endif
        interface->fTexParameteri = glTexParameteri;
        interface->fTexSubImage2D = glTexSubImage2D;
        interface->fUniform1f = glUniform1f;
        interface->fUniform1i = glUniform1i;
        interface->fUniform1fv = glUniform1fv;
        interface->fUniform1iv = glUniform1iv;
        interface->fUniform2f = glUniform2f;
        interface->fUniform2i = glUniform2i;
        interface->fUniform2fv = glUniform2fv;
        interface->fUniform2iv = glUniform2iv;
        interface->fUniform3f = glUniform3f;
        interface->fUniform3i = glUniform3i;
        interface->fUniform3fv = glUniform3fv;
        interface->fUniform3iv = glUniform3iv;
        interface->fUniform4f = glUniform4f;
        interface->fUniform4i = glUniform4i;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniform4iv = glUniform4iv;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniformMatrix2fv = glUniformMatrix2fv;
        interface->fUniformMatrix3fv = glUniformMatrix3fv;
        interface->fUniformMatrix4fv = glUniformMatrix4fv;
        interface->fUseProgram = glUseProgram;
        interface->fVertexAttrib4fv = glVertexAttrib4fv;
        interface->fVertexAttribPointer = glVertexAttribPointer;
        interface->fViewport = glViewport;
        interface->fGenFramebuffers = glGenFramebuffers;
        interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
        interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
        interface->fBindFramebuffer = glBindFramebuffer;
        interface->fFramebufferTexture2D = glFramebufferTexture2D;
        interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
        interface->fDeleteFramebuffers = glDeleteFramebuffers;
        interface->fRenderbufferStorage = glRenderbufferStorage;
        interface->fGenRenderbuffers = glGenRenderbuffers;
        interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
        interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
        interface->fBindRenderbuffer = glBindRenderbuffer;
       
    #if GL_OES_mapbuffer
        interface->fMapBuffer = glMapBufferOES;
        interface->fUnmapBuffer = glUnmapBufferOES;
    #endif
        
    #if GL_APPLE_framebuffer_multisample
        interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleAPPLE;
        interface->fResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE;
    #endif
        interface->fBindFragDataLocationIndexed = NULL;
        
        interface->fBindingsExported = kES2_GrGLBinding;
    }
    glInterface.get()->ref();
    return glInterface.get();
}
const GrGLInterface* GrGLCreateNativeInterface() {
    // The gl functions are not context-specific so we create one global
    // interface
    static SkAutoTUnref<GrGLInterface> glInterface;
    if (!glInterface.get()) {
        GrGLInterface* interface = new GrGLInterface;
        glInterface.reset(interface);
        const char* verStr = (const char*) glGetString(GL_VERSION);
        GrGLVersion ver = GrGLGetVersionFromString(verStr);
        const char* extStr = (const char*) glGetString(GL_EXTENSIONS);

        interface->fBindingsExported = kDesktop_GrGLBinding;
        interface->fActiveTexture = glActiveTexture;
        interface->fAttachShader = glAttachShader;
        interface->fBeginQuery = glBeginQuery;
        interface->fBindAttribLocation = glBindAttribLocation;
        interface->fBindBuffer = glBindBuffer;
        if (ver >= GR_GL_VER(3,0)) {
            #if GL_VERSION_3_0
                interface->fBindFragDataLocation = glBindFragDataLocation;
            #else
                interface->fBindFragDataLocation = GET_PROC(BindFragDataLocation);
            #endif
        }
        interface->fBindTexture = glBindTexture;
        interface->fBlendFunc = glBlendFunc;

        if (ver >= GR_GL_VER(1,4)) {
            interface->fBlendColor = glBlendColor;
        } else if (GrGLHasExtensionFromString("GL_ARB_imaging", extStr) ||
                   GrGLHasExtensionFromString("GL_EXT_blend_color", extStr)) {
            GET_PROC(BlendColor);
        }

        interface->fBufferData = glBufferData;
        interface->fBufferSubData = glBufferSubData;
        interface->fClear = glClear;
        interface->fClearColor = glClearColor;
        interface->fClearStencil = glClearStencil;
        interface->fColorMask = glColorMask;
        interface->fCompileShader = glCompileShader;
        interface->fCompressedTexImage2D = glCompressedTexImage2D;
        interface->fCreateProgram = glCreateProgram;
        interface->fCreateShader = glCreateShader;
        interface->fCullFace = glCullFace;
        interface->fDeleteBuffers = glDeleteBuffers;
        interface->fDeleteProgram = glDeleteProgram;
        interface->fDeleteQueries = glDeleteQueries;
        interface->fDeleteShader = glDeleteShader;
        interface->fDeleteTextures = glDeleteTextures;
        interface->fDepthMask = glDepthMask;
        interface->fDisable = glDisable;
        interface->fDisableVertexAttribArray =
                                            glDisableVertexAttribArray;
        interface->fDrawArrays = glDrawArrays;
        interface->fDrawBuffer = glDrawBuffer;
        interface->fDrawBuffers = glDrawBuffers;
        interface->fDrawElements = glDrawElements;
        interface->fEnable = glEnable;
        interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
        interface->fEndQuery = glEndQuery;
        interface->fFinish = glFinish;
        interface->fFlush = glFlush;
        interface->fFrontFace = glFrontFace;
        interface->fGenBuffers = glGenBuffers;
        interface->fGenQueries = glGenQueries;
        interface->fGetBufferParameteriv = glGetBufferParameteriv;
        interface->fGetError = glGetError;
        interface->fGetIntegerv = glGetIntegerv;
        interface->fGetProgramInfoLog = glGetProgramInfoLog;
        interface->fGetProgramiv = glGetProgramiv;
        interface->fGetQueryiv = glGetQueryiv;
        interface->fGetQueryObjectiv = glGetQueryObjectiv;
        interface->fGetQueryObjectuiv = glGetQueryObjectuiv;
        interface->fGetShaderInfoLog = glGetShaderInfoLog;
        interface->fGetShaderiv = glGetShaderiv;
        interface->fGetString = glGetString;
        interface->fGetTexLevelParameteriv = glGetTexLevelParameteriv;
        interface->fGenTextures = glGenTextures;
        interface->fGetUniformLocation = glGetUniformLocation;
        interface->fLineWidth = glLineWidth;
        interface->fLinkProgram = glLinkProgram;
        interface->fMapBuffer = glMapBuffer;
        interface->fPixelStorei = glPixelStorei;
        interface->fReadBuffer = glReadBuffer;
        interface->fReadPixels = glReadPixels;
        interface->fScissor = glScissor;
        interface->fShaderSource = glShaderSource;
        interface->fStencilFunc = glStencilFunc;
        interface->fStencilFuncSeparate = glStencilFuncSeparate;
        interface->fStencilMask = glStencilMask;
        interface->fStencilMaskSeparate = glStencilMaskSeparate;
        interface->fStencilOp = glStencilOp;
        interface->fStencilOpSeparate = glStencilOpSeparate;
        // mac uses GLenum for internalFormat param (non-standard)
        // amounts to int vs. uint.
        interface->fTexImage2D = (GrGLTexImage2DProc)glTexImage2D;
        interface->fTexParameteri = glTexParameteri;
        interface->fTexParameteriv = glTexParameteriv;
    #if GL_ARB_texture_storage || GL_VERSION_4_2
        interface->fTexStorage2D = glTexStorage2D
    #elif GL_EXT_texture_storage
        interface->fTexStorage2D = glTexStorage2DEXT;
    #else
        if (ver >= GR_GL_VER(4,2) ||
            GrGLHasExtensionFromString("GL_ARB_texture_storage", extStr)) {
            GET_PROC(TexStorage2D);
        } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", extStr)) {
            GET_PROC_SUFFIX(TexStorage2D, EXT);
        }
    #endif
        interface->fTexSubImage2D = glTexSubImage2D;
        interface->fUniform1f = glUniform1f;
        interface->fUniform1i = glUniform1i;
        interface->fUniform1fv = glUniform1fv;
        interface->fUniform1iv = glUniform1iv;
        interface->fUniform2f = glUniform2f;
        interface->fUniform2i = glUniform2i;
        interface->fUniform2fv = glUniform2fv;
        interface->fUniform2iv = glUniform2iv;
        interface->fUniform3f = glUniform3f;
        interface->fUniform3i = glUniform3i;
        interface->fUniform3fv = glUniform3fv;
        interface->fUniform3iv = glUniform3iv;
        interface->fUniform4f = glUniform4f;
        interface->fUniform4i = glUniform4i;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniform4iv = glUniform4iv;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniformMatrix2fv = glUniformMatrix2fv;
        interface->fUniformMatrix3fv = glUniformMatrix3fv;
        interface->fUniformMatrix4fv = glUniformMatrix4fv;
        interface->fUnmapBuffer = glUnmapBuffer;
        interface->fUseProgram = glUseProgram;
        interface->fVertexAttrib4fv = glVertexAttrib4fv;
        interface->fVertexAttribPointer = glVertexAttribPointer;
        interface->fViewport = glViewport;

        if (ver >= GR_GL_VER(3,3) || GrGLHasExtensionFromString("GL_ARB_timer_query", extStr)) {
            // ARB extension doesn't use the ARB suffix on the function name
            #if GL_ARB_timer_query || GL_VERSION_3_3
                interface->fQueryCounter = glQueryCounter;
                interface->fGetQueryObjecti64v = glGetQueryObjecti64v;
                interface->fGetQueryObjectui64v = glGetQueryObjectui64v;
            #else
                interface->fQueryCounter = GET_PROC(QueryCounter);
                interface->fGetQueryObjecti64v = GET_PROC(GetQueryObjecti64v);
                interface->fGetQueryObjectui64v = GET_PROC(GetQueryObjectui64v);
            #endif
        } else if (GrGLHasExtensionFromString("GL_EXT_timer_query", extStr)) {
            #if GL_EXT_timer_query
                interface->fGetQueryObjecti64v = glGetQueryObjecti64vEXT;
                interface->fGetQueryObjectui64v = glGetQueryObjectui64vEXT;
            #else
                interface->fGetQueryObjecti64v = GET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
                interface->fGetQueryObjectui64v = GET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
            #endif
        }

        if (ver >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", extStr)) {
            // ARB extension doesn't use the ARB suffix on the function names
            #if GL_VERSION_3_0 || GL_ARB_framebuffer_object
                interface->fGenFramebuffers = glGenFramebuffers;
                interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
                interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
                interface->fBindFramebuffer = glBindFramebuffer;
                interface->fFramebufferTexture2D = glFramebufferTexture2D;
                interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
                interface->fDeleteFramebuffers = glDeleteFramebuffers;
                interface->fRenderbufferStorage = glRenderbufferStorage;
                interface->fGenRenderbuffers = glGenRenderbuffers;
                interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
                interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
                interface->fBindRenderbuffer = glBindRenderbuffer;
                interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisample;
                interface->fBlitFramebuffer = glBlitFramebuffer;
            #else
                interface->fGenFramebuffers = GET_PROC(GenFramebuffers);
                interface->fGetFramebufferAttachmentParameteriv = GET_PROC(GetFramebufferAttachmentParameteriv);
                interface->fGetRenderbufferParameteriv = GET_PROC(GetRenderbufferParameteriv);
                interface->fBindFramebuffer = GET_PROC(BindFramebuffer);
                interface->fFramebufferTexture2D = GET_PROC(FramebufferTexture2D);
                interface->fCheckFramebufferStatus = GET_PROC(CheckFramebufferStatus);
                interface->fDeleteFramebuffers = GET_PROC(DeleteFramebuffers);
                interface->fRenderbufferStorage = GET_PROC(RenderbufferStorage);
                interface->fGenRenderbuffers = GET_PROC(GenRenderbuffers);
                interface->fDeleteRenderbuffers = GET_PROC(DeleteRenderbuffers);
                interface->fFramebufferRenderbuffer = GET_PROC(FramebufferRenderbuffer);
                interface->fBindRenderbuffer = GET_PROC(BindRenderbuffer);
                interface->fRenderbufferStorageMultisample = GET_PROC(RenderbufferStorageMultisample);
                interface->fBlitFramebuffer = GET_PROC(BlitFramebuffer);
            #endif
        } else {
            if (GrGLHasExtensionFromString("GL_EXT_framebuffer_object", extStr)) {
                #if GL_EXT_framebuffer_object
                    interface->fGenFramebuffers = glGenFramebuffersEXT;
                    interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameterivEXT;
                    interface->fGetRenderbufferParameteriv = glGetRenderbufferParameterivEXT;
                    interface->fBindFramebuffer = glBindFramebufferEXT;
                    interface->fFramebufferTexture2D = glFramebufferTexture2DEXT;
                    interface->fCheckFramebufferStatus = glCheckFramebufferStatusEXT;
                    interface->fDeleteFramebuffers = glDeleteFramebuffersEXT;
                    interface->fRenderbufferStorage = glRenderbufferStorageEXT;
                    interface->fGenRenderbuffers = glGenRenderbuffersEXT;
                    interface->fDeleteRenderbuffers = glDeleteRenderbuffersEXT;
                    interface->fFramebufferRenderbuffer = glFramebufferRenderbufferEXT;
                    interface->fBindRenderbuffer = glBindRenderbufferEXT;
                #else
                    interface->fGenFramebuffers = GET_PROC_SUFFIX(GenFramebuffers, EXT);
                    interface->fGetFramebufferAttachmentParameteriv = GET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
                    interface->fGetRenderbufferParameteriv = GET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
                    interface->fBindFramebuffer = GET_PROC_SUFFIX(BindFramebuffer, EXT);
                    interface->fFramebufferTexture2D = GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
                    interface->fCheckFramebufferStatus = GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
                    interface->fDeleteFramebuffers = GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
                    interface->fRenderbufferStorage = GET_PROC_SUFFIX(RenderbufferStorage, EXT);
                    interface->fGenRenderbuffers = GET_PROC_SUFFIX(GenRenderbuffers, EXT);
                    interface->fDeleteRenderbuffers = GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
                    interface->fFramebufferRenderbuffer = GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
                    interface->fBindRenderbuffer = GET_PROC_SUFFIX(BindRenderbuffer, EXT);
                #endif
            }
            if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", extStr)) {
                #if GL_EXT_framebuffer_multisample
                    interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleEXT;
                #else
                    interface->fRenderbufferStorageMultisample = GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
                #endif
            }
            if (GrGLHasExtensionFromString("", extStr)) {
                #if GL_EXT_framebuffer_blit
                    interface->fBlitFramebuffer = glBlitFramebufferEXT;
                #else
                    interface->fBlitFramebuffer = GET_PROC_SUFFIX(BlitFramebuffer, EXT);
                #endif
            }
        }
        if (ver >= GR_GL_VER(3,3) || GrGLHasExtensionFromString("GL_ARB_blend_func_extended", extStr)) {
            // ARB extension doesn't use the ARB suffix on the function name
            #if GL_VERSION_3_3 || GL_ARB_blend_func_extended
                interface->fBindFragDataLocationIndexed = glBindFragDataLocationIndexed;
            #else
                interface->fBindFragDataLocationIndexed = GET_PROC(BindFragDataLocationIndexed);
            #endif
        }

        interface->fBindingsExported = kDesktop_GrGLBinding;
    }
    glInterface.get()->ref();
    return glInterface.get();
}
bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
                                                     const SkBitmap& src,
                                                     const Context& ctx,
                                                     SkBitmap* result,
                                                     SkIPoint* offset) const {
    GrContext* context = nullptr;
    SkBitmap background = src;
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
        background.reset();
    }
    GrTexture* backgroundTex = background.getTexture();
    if (backgroundTex) {
        context = backgroundTex->getContext();
    }

    SkBitmap foreground = src;
    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
        foreground.reset();
    }
    GrTexture* foregroundTex = foreground.getTexture();
    if (foregroundTex) {
        context = foregroundTex->getContext();
    }

    if (!context) {
        return false;
    }

    SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
    bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
    if (bounds.isEmpty()) {
        return false;
    }

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
    if (!dst) {
        return false;
    }

    GrPaint paint;
    SkAutoTUnref<const GrFragmentProcessor> bgFP;

    if (backgroundTex) {
        SkMatrix backgroundMatrix;
        backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
        backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
                                      SkIntToScalar(-backgroundOffset.fY));
        bgFP.reset(GrTextureDomainEffect::Create(
                            backgroundTex, backgroundMatrix,
                            GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
                            GrTextureDomain::kDecal_Mode,
                            GrTextureParams::kNone_FilterMode));
    } else {
        bgFP.reset(GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
                                                 GrConstColorProcessor::kIgnore_InputMode));
    }

    if (foregroundTex) {
        SkMatrix foregroundMatrix;
        foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
        foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
                                      SkIntToScalar(-foregroundOffset.fY));

        SkAutoTUnref<const GrFragmentProcessor> foregroundFP;

        foregroundFP.reset(GrTextureDomainEffect::Create(
                            foregroundTex, foregroundMatrix,
                            GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
                            GrTextureDomain::kDecal_Mode,
                            GrTextureParams::kNone_FilterMode));

        paint.addColorFragmentProcessor(foregroundFP.get());

        // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
        SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
        if (!mode) {
            // It would be awesome to use SkXfermode::Create here but it knows better
            // than us and won't return a kSrcOver_Mode SkXfermode. That means we
            // have to get one the hard way.
            struct ProcCoeff rec;
            rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
            SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);

            mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
        }

        SkAutoTUnref<const GrFragmentProcessor> xferFP(mode->getFragmentProcessorForImageFilter(bgFP));

        // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
        if (xferFP) {
            paint.addColorFragmentProcessor(xferFP);
        }
    } else {
        paint.addColorFragmentProcessor(bgFP);
    }

    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
    if (!drawContext) {
        return false;
    }

    SkMatrix matrix;
    matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));

    offset->fX = bounds.left();
    offset->fY = bounds.top();
    GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
    return true;
}
const GrGLInterface* GrGLCreateNativeInterface() {
    static SkAutoTUnref<GrGLInterface> glInterface;
    if (!glInterface.get()) {
        GrGLInterface* interface = new GrGLInterface;
        glInterface.reset(interface);
        interface->fBindingsExported = kES2_GrGLBinding;
        interface->fActiveTexture = glActiveTexture;
        interface->fAttachShader = glAttachShader;
        interface->fBindAttribLocation = glBindAttribLocation;
        interface->fBindBuffer = glBindBuffer;
        interface->fBindTexture = glBindTexture;
        interface->fBlendColor = glBlendColor;
        interface->fBlendFunc = glBlendFunc;
        interface->fBufferData = glBufferData;
        interface->fBufferSubData = glBufferSubData;
        interface->fClear = glClear;
        interface->fClearColor = glClearColor;
        interface->fClearStencil = glClearStencil;
        interface->fColorMask = glColorMask;
        interface->fCompileShader = glCompileShader;
        interface->fCompressedTexImage2D = glCompressedTexImage2D;
        interface->fCreateProgram = glCreateProgram;
        interface->fCreateShader = glCreateShader;
        interface->fCullFace = glCullFace;
        interface->fDeleteBuffers = glDeleteBuffers;
        interface->fDeleteProgram = glDeleteProgram;
        interface->fDeleteShader = glDeleteShader;
        interface->fDeleteTextures = glDeleteTextures;
        interface->fDepthMask = glDepthMask;
        interface->fDisable = glDisable;
        interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
        interface->fDrawArrays = glDrawArrays;
        interface->fDrawElements = glDrawElements;
        interface->fEnable = glEnable;
        interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
        interface->fFrontFace = glFrontFace;
        interface->fGenBuffers = glGenBuffers;
        interface->fGenTextures = glGenTextures;
        interface->fGetBufferParameteriv = glGetBufferParameteriv;
        interface->fGetError = glGetError;
        interface->fGetIntegerv = glGetIntegerv;
        interface->fGetProgramInfoLog = glGetProgramInfoLog;
        interface->fGetProgramiv = glGetProgramiv;
        interface->fGetShaderInfoLog = glGetShaderInfoLog;
        interface->fGetShaderiv = glGetShaderiv;
        interface->fGetString = glGetString;
        interface->fGetUniformLocation = glGetUniformLocation;
        interface->fLineWidth = glLineWidth;
        interface->fLinkProgram = glLinkProgram;
        interface->fPixelStorei = glPixelStorei;
        interface->fReadPixels = glReadPixels;
        interface->fScissor = glScissor;
        interface->fShaderSource = glShaderSource;
        interface->fStencilFunc = glStencilFunc;
        interface->fStencilFuncSeparate = glStencilFuncSeparate;
        interface->fStencilMask = glStencilMask;
        interface->fStencilMaskSeparate = glStencilMaskSeparate;
        interface->fStencilOp = glStencilOp;
        interface->fStencilOpSeparate = glStencilOpSeparate;
        interface->fTexImage2D = glTexImage2D;
        interface->fTexParameteri = glTexParameteri;
        interface->fTexSubImage2D = glTexSubImage2D;
        interface->fUniform1f = glUniform1f;
        interface->fUniform1i = glUniform1i;
        interface->fUniform1fv = glUniform1fv;
        interface->fUniform1iv = glUniform1iv;
        interface->fUniform2f = glUniform2f;
        interface->fUniform2i = glUniform2i;
        interface->fUniform2fv = glUniform2fv;
        interface->fUniform2iv = glUniform2iv;
        interface->fUniform3f = glUniform3f;
        interface->fUniform3i = glUniform3i;
        interface->fUniform3fv = glUniform3fv;
        interface->fUniform3iv = glUniform3iv;
        interface->fUniform4f = glUniform4f;
        interface->fUniform4i = glUniform4i;
        interface->fUniform4fv = glUniform4fv;
        interface->fUniform4iv = glUniform4iv;
        interface->fUniformMatrix2fv = glUniformMatrix2fv;
        interface->fUniformMatrix3fv = glUniformMatrix3fv;
        interface->fUniformMatrix4fv = glUniformMatrix4fv;
        interface->fUseProgram = glUseProgram;
        interface->fVertexAttrib4fv = glVertexAttrib4fv;
        interface->fVertexAttribPointer = glVertexAttribPointer;
        interface->fViewport = glViewport;
        interface->fBindFramebuffer = glBindFramebuffer;
        interface->fBindRenderbuffer = glBindRenderbuffer;
        interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
        interface->fDeleteFramebuffers = glDeleteFramebuffers;
        interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
        interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
        interface->fFramebufferTexture2D = glFramebufferTexture2D;
        interface->fGenFramebuffers = glGenFramebuffers;
        interface->fGenRenderbuffers = glGenRenderbuffers;
        interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
        interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
        interface->fRenderbufferStorage = glRenderbufferStorage;
    #if GL_OES_mapbuffer
        interface->fMapBuffer = glMapBufferOES;
        interface->fUnmapBuffer = glUnmapBufferOES;
    #endif
    }
    glInterface.get()->ref();
    return glInterface.get();
}