| /* |
| * Copyright 2020 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "tools/gpu/BackendTextureImageFactory.h" |
| |
| #include "include/core/SkImage.h" |
| #include "include/core/SkPixmap.h" |
| #include "include/gpu/GrBackendSurface.h" |
| #include "include/gpu/GrContext.h" |
| #include "src/core/SkAutoPixmapStorage.h" |
| |
| namespace { |
| class ManagedBackendTexture : public SkNVRefCnt<ManagedBackendTexture> { |
| public: |
| ~ManagedBackendTexture() { |
| if (fContext && fTexture.isValid()) { |
| fContext->submit(true); |
| fContext->deleteBackendTexture(fTexture); |
| } |
| } |
| |
| static void Proc(void* context) { static_cast<ManagedBackendTexture*>(context)->unref(); } |
| |
| template <typename... Args> |
| static sk_sp<ManagedBackendTexture> Make(GrContext* context, Args&&... args) { |
| sk_sp<ManagedBackendTexture> mbet(new ManagedBackendTexture); |
| mbet->fContext = context; |
| mbet->fTexture = context->createBackendTexture(std::forward<Args>(args)..., |
| Proc, |
| mbet->refAndPassAsContext()); |
| return mbet; |
| } |
| |
| const GrBackendTexture& texture() { return fTexture; } |
| |
| void* refAndPassAsContext() { |
| this->ref(); |
| return static_cast<void*>(this); |
| } |
| |
| private: |
| ManagedBackendTexture() = default; |
| GrContext* fContext = nullptr; |
| GrBackendTexture fTexture; |
| }; |
| } // namespace |
| |
| namespace sk_gpu_test { |
| sk_sp<SkImage> MakeBackendTextureImage(GrContext* context, |
| const SkPixmap& pixmap, |
| GrRenderable renderable, |
| GrSurfaceOrigin origin) { |
| const SkPixmap* src = &pixmap; |
| SkAutoPixmapStorage temp; |
| if (origin == kBottomLeft_GrSurfaceOrigin) { |
| temp.alloc(src->info()); |
| auto s = static_cast<const char*>(src->addr(0, pixmap.height() - 1)); |
| auto d = static_cast<char*>(temp.writable_addr(0, 0)); |
| for (int y = 0; y < temp.height(); ++y, s -= pixmap.rowBytes(), d += temp.rowBytes()) { |
| std::copy_n(s, temp.info().minRowBytes(), d); |
| } |
| src = &temp; |
| } |
| auto mbet = ManagedBackendTexture::Make(context, src, 1, renderable, GrProtected::kNo); |
| auto image = SkImage::MakeFromTexture(context, mbet->texture(), origin, src->colorType(), |
| src->alphaType(), src->refColorSpace(), |
| ManagedBackendTexture::Proc, mbet->refAndPassAsContext()); |
| // We currently have an issue where depending on how MakeFromTexture fails it may not |
| // call the release proc (to be fixed soon, crbug.com/1097484). For now we use this hack |
| // to see if it failed without calling Proc. |
| if (!image) { |
| context->submit(true); |
| if (!mbet->unique()) { |
| ManagedBackendTexture::Proc(mbet.get()); |
| } |
| } |
| return image; |
| } |
| } // namespace sk_gpu_test |