123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkTypes.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkPoint.h"
- #include "include/core/SkSurface.h"
- #include "include/gpu/GrBackendSurface.h"
- #include "include/gpu/GrContext.h"
- #include "src/gpu/GrBackendTextureImageGenerator.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrGpu.h"
- #include "src/gpu/GrRenderTargetContext.h"
- #include "src/gpu/GrSemaphore.h"
- #include "src/gpu/GrSurfaceProxyPriv.h"
- #include "src/gpu/GrTexturePriv.h"
- #include "src/gpu/GrTextureProxy.h"
- #include "src/gpu/SkGpuDevice.h"
- #include "src/image/SkImage_Base.h"
- #include "src/image/SkSurface_Gpu.h"
- #include "tests/Test.h"
- static constexpr int kSize = 8;
- // Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
- // SkImages and SkSurfaces
- DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
- GrContext* context = ctxInfo.grContext();
- if (!context->priv().caps()->mipMapSupport()) {
- return;
- }
- for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
- for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
- // createBackendTexture currently doesn't support uploading data to mip maps
- // so we don't send any. However, we pretend there is data for the checks below which is
- // fine since we are never actually using these textures for any work on the gpu.
- GrBackendTexture backendTex = context->createBackendTexture(
- kSize, kSize, kRGBA_8888_SkColorType,
- SkColors::kTransparent, mipMapped, renderable, GrProtected::kNo);
- sk_sp<GrTextureProxy> proxy;
- sk_sp<SkImage> image;
- if (GrRenderable::kYes == renderable) {
- sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
- context,
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- 0,
- kRGBA_8888_SkColorType,
- nullptr,
- nullptr);
- SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
- proxy = device->accessRenderTargetContext()->asTextureProxyRef();
- } else {
- image = SkImage::MakeFromTexture(context, backendTex,
- kTopLeft_GrSurfaceOrigin,
- kRGBA_8888_SkColorType,
- kPremul_SkAlphaType, nullptr,
- nullptr, nullptr);
- proxy = as_IB(image)->asTextureProxyRef(context);
- }
- REPORTER_ASSERT(reporter, proxy);
- if (!proxy) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- REPORTER_ASSERT(reporter, proxy->isInstantiated());
- GrTexture* texture = proxy->peekTexture();
- REPORTER_ASSERT(reporter, texture);
- if (!texture) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- if (GrMipMapped::kYes == mipMapped) {
- REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
- if (GrRenderable::kYes == renderable) {
- REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
- } else {
- REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
- }
- } else {
- REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
- }
- context->deleteBackendTexture(backendTex);
- }
- }
- }
- // Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
- // based on if we will use mips in the draw and the mip status of the GrBackendTexture.
- DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
- GrContext* context = ctxInfo.grContext();
- if (!context->priv().caps()->mipMapSupport()) {
- return;
- }
- for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
- for (auto willUseMips : {false, true}) {
- GrBackendTexture backendTex = context->createBackendTexture(
- kSize, kSize, kRGBA_8888_SkColorType,
- SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
- sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
- kTopLeft_GrSurfaceOrigin,
- kRGBA_8888_SkColorType,
- kPremul_SkAlphaType, nullptr,
- nullptr, nullptr);
- GrTextureProxy* proxy = as_IB(image)->peekProxy();
- REPORTER_ASSERT(reporter, proxy);
- if (!proxy) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- REPORTER_ASSERT(reporter, proxy->isInstantiated());
- sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
- REPORTER_ASSERT(reporter, texture);
- if (!texture) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
- texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType, nullptr);
- REPORTER_ASSERT(reporter, imageGen);
- if (!imageGen) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- SkIPoint origin = SkIPoint::Make(0,0);
- SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType);
- sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
- origin, willUseMips);
- REPORTER_ASSERT(reporter, genProxy);
- if (!genProxy) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
- genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
- } else if (!genProxy->isInstantiated()) {
- genProxy->instantiate(context->priv().resourceProvider());
- }
- REPORTER_ASSERT(reporter, genProxy->isInstantiated());
- if (!genProxy->isInstantiated()) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- GrTexture* genTexture = genProxy->peekTexture();
- REPORTER_ASSERT(reporter, genTexture);
- if (!genTexture) {
- context->deleteBackendTexture(backendTex);
- return;
- }
- GrBackendTexture genBackendTex = genTexture->getBackendTexture();
- if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
- GrGLTextureInfo genTexInfo;
- GrGLTextureInfo origTexInfo;
- if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
- backendTex.getGLTextureInfo(&origTexInfo)) {
- if (willUseMips && GrMipMapped::kNo == mipMapped) {
- // We did a copy so the texture IDs should be different
- REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
- } else {
- REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
- }
- } else {
- ERRORF(reporter, "Failed to get GrGLTextureInfo");
- }
- #ifdef SK_VULKAN
- } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
- GrVkImageInfo genImageInfo;
- GrVkImageInfo origImageInfo;
- if (genBackendTex.getVkImageInfo(&genImageInfo) &&
- backendTex.getVkImageInfo(&origImageInfo)) {
- if (willUseMips && GrMipMapped::kNo == mipMapped) {
- // We did a copy so the texture IDs should be different
- REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
- } else {
- REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
- }
- } else {
- ERRORF(reporter, "Failed to get GrVkImageInfo");
- }
- #endif
- #ifdef SK_METAL
- } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
- GrMtlTextureInfo genImageInfo;
- GrMtlTextureInfo origImageInfo;
- if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
- backendTex.getMtlTextureInfo(&origImageInfo)) {
- if (willUseMips && GrMipMapped::kNo == mipMapped) {
- // We did a copy so the texture IDs should be different
- REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
- } else {
- REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
- }
- } else {
- ERRORF(reporter, "Failed to get GrMtlTextureInfo");
- }
- #endif
- } else {
- REPORTER_ASSERT(reporter, false);
- }
- // Must make sure the uses of the backend texture have finished (we possibly have a
- // queued up copy) before we delete the backend texture.
- context->flush();
- context->priv().getGpu()->testingOnly_flushGpuAndSync();
- context->deleteBackendTexture(backendTex);
- }
- }
- }
- // Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
- // resource we took the snapshot of.
- DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
- GrContext* context = ctxInfo.grContext();
- if (!context->priv().caps()->mipMapSupport()) {
- return;
- }
- auto resourceProvider = context->priv().resourceProvider();
- for (auto willUseMips : {false, true}) {
- for (auto isWrapped : {false, true}) {
- GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
- sk_sp<SkSurface> surface;
- GrBackendTexture backendTex = context->createBackendTexture(
- kSize, kSize, kRGBA_8888_SkColorType,
- SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
- if (isWrapped) {
- surface = SkSurface::MakeFromBackendTexture(context,
- backendTex,
- kTopLeft_GrSurfaceOrigin,
- 0,
- kRGBA_8888_SkColorType,
- nullptr,
- nullptr);
- } else {
- SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType);
- surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
- kTopLeft_GrSurfaceOrigin, nullptr,
- willUseMips);
- }
- REPORTER_ASSERT(reporter, surface);
- if (!surface) {
- context->deleteBackendTexture(backendTex);
- }
- SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
- GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
- REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
- texProxy->instantiate(resourceProvider);
- GrTexture* texture = texProxy->peekTexture();
- REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
- sk_sp<SkImage> image = surface->makeImageSnapshot();
- REPORTER_ASSERT(reporter, image);
- if (!image) {
- context->deleteBackendTexture(backendTex);
- }
- texProxy = as_IB(image)->peekProxy();
- REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
- texProxy->instantiate(resourceProvider);
- texture = texProxy->peekTexture();
- REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
- // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
- // to the gpu before we delete the backendHandle.
- context->flush();
- context->priv().getGpu()->testingOnly_flushGpuAndSync();
- context->deleteBackendTexture(backendTex);
- }
- }
- }
- // Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
- // to use mips. This test passes by not crashing or hitting asserts in code.
- DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
- GrContext* context = ctxInfo.grContext();
- if (!context->priv().caps()->mipMapSupport()) {
- return;
- }
- // Make surface to draw into
- SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
- sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
- // Make 1x1 raster bitmap
- SkBitmap bmp;
- bmp.allocN32Pixels(1, 1);
- SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
- *pixel = 0;
- sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
- // Make sure we scale so we don't optimize out the use of mips.
- surface->getCanvas()->scale(0.5f, 0.5f);
- SkPaint paint;
- // This should upload the image to a non mipped GrTextureProxy.
- surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
- surface->flush();
- // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
- // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
- // instead of trying to do a copy to a mipped texture.
- paint.setFilterQuality(kHigh_SkFilterQuality);
- surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
- surface->flush();
- }
|