blob: 71cebb0eb1a97c9043aabd00f91c859d4ef9cb20 [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImage_Gpu_DEFINED
#define SkImage_Gpu_DEFINED
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/private/SkSpinlock.h"
#include "include/private/base/SkThreadAnnotations.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/image/SkImage_Base.h"
#include "src/image/SkImage_GpuBase.h"
#include <cstddef>
#include <cstdint>
#include <memory>
#include <tuple>
class GrDirectContext;
class GrFragmentProcessor;
class GrImageContext;
class GrRecordingContext;
class GrRenderTask;
class GrSurfaceProxy;
class SkColorInfo;
class SkColorSpace;
class SkImage;
class SkMatrix;
enum GrSurfaceOrigin : int;
enum SkColorType : int;
enum SkYUVColorSpace : int;
enum class GrColorType;
enum class GrImageTexGenPolicy : int;
enum class GrSemaphoresSubmitted : bool;
enum class SkTileMode;
struct GrFlushInfo;
struct SkIRect;
struct SkISize;
struct SkImageInfo;
struct SkRect;
namespace skgpu {
enum class Mipmapped : bool;
}
class SkImage_Gpu final : public SkImage_GpuBase {
public:
SkImage_Gpu(sk_sp<GrImageContext> context,
uint32_t uniqueID,
GrSurfaceProxyView view,
SkColorInfo info);
static sk_sp<SkImage> MakeWithVolatileSrc(sk_sp<GrRecordingContext> rContext,
GrSurfaceProxyView volatileSrc,
SkColorInfo colorInfo);
~SkImage_Gpu() override;
// If this is image is a cached SkSurface snapshot then this method is called by the SkSurface
// before a write to check if the surface must make a copy to avoid modifying the image's
// contents.
bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const;
bool onHasMipmaps() const override;
GrSemaphoresSubmitted onFlush(GrDirectContext*, const GrFlushInfo&) const override;
GrBackendTexture onGetBackendTexture(bool flushPendingGrContextIO,
GrSurfaceOrigin* origin) const final;
SkImage_Base::Type type() const override { return SkImage_Base::Type::kGanesh; }
size_t onTextureSize() const override;
using SkImage_GpuBase::onMakeColorTypeAndColorSpace;
sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType,
sk_sp<SkColorSpace>,
GrDirectContext*) const final;
sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final;
void onAsyncRescaleAndReadPixels(const SkImageInfo&,
SkIRect srcRect,
RescaleGamma,
RescaleMode,
ReadPixelsCallback,
ReadPixelsContext) const override;
void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace,
sk_sp<SkColorSpace>,
SkIRect srcRect,
SkISize dstSize,
RescaleGamma,
RescaleMode,
ReadPixelsCallback,
ReadPixelsContext) const override;
void generatingSurfaceIsDeleted() override;
private:
SkImage_Gpu(sk_sp<GrDirectContext>,
GrSurfaceProxyView volatileSrc,
sk_sp<GrSurfaceProxy> stableCopy,
sk_sp<GrRenderTask> copyTask,
int volatileSrcTargetCount,
SkColorInfo);
std::tuple<GrSurfaceProxyView, GrColorType> onAsView(GrRecordingContext*,
skgpu::Mipmapped,
GrImageTexGenPolicy) const override;
std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(GrRecordingContext*,
SkSamplingOptions,
const SkTileMode[2],
const SkMatrix&,
const SkRect*,
const SkRect*) const override;
GrSurfaceProxyView makeView(GrRecordingContext*) const;
// Thread-safe wrapper around the proxies backing this image. Handles dynamically switching
// from a "volatile" proxy that may be overwritten (by an SkSurface that this image was snapped
// from) to a "stable" proxy that is a copy of the volatile proxy. It allows the image to cancel
// the copy if the stable proxy is never required because the contents of the volatile proxy
// were never mutated by the SkSurface during the image lifetime.
class ProxyChooser {
public:
ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy,
sk_sp<GrSurfaceProxy> volatileProxy,
sk_sp<GrRenderTask> copyTask,
int volatileProxyTargetCount);
ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy);
~ProxyChooser();
// Checks if there is a volatile proxy that is safe to use. If so returns it, otherwise
// returns the stable proxy (and drops the volatile one if it exists).
sk_sp<GrSurfaceProxy> chooseProxy(GrRecordingContext* context) SK_EXCLUDES(fLock);
// Call when it is known copy is necessary.
sk_sp<GrSurfaceProxy> switchToStableProxy() SK_EXCLUDES(fLock);
// Call when it is known for sure copy won't be necessary.
sk_sp<GrSurfaceProxy> makeVolatileProxyStable() SK_EXCLUDES(fLock);
bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const SK_EXCLUDES(fLock);
// Queries that should be independent of which proxy is in use.
size_t gpuMemorySize() const SK_EXCLUDES(fLock);
skgpu::Mipmapped mipmapped() const SK_EXCLUDES(fLock);
#ifdef SK_DEBUG
GrBackendFormat backendFormat() SK_EXCLUDES(fLock);
#endif
private:
mutable SkSpinlock fLock;
sk_sp<GrSurfaceProxy> fStableProxy SK_GUARDED_BY(fLock);
sk_sp<GrSurfaceProxy> fVolatileProxy SK_GUARDED_BY(fLock);
sk_sp<GrRenderTask> fVolatileToStableCopyTask;
// The number of GrRenderTasks targeting the volatile proxy at creation time. If the
// proxy's target count increases it indicates additional writes and we must switch
// to using the stable copy.
const int fVolatileProxyTargetCount = 0;
};
mutable ProxyChooser fChooser;
skgpu::Swizzle fSwizzle;
GrSurfaceOrigin fOrigin;
using INHERITED = SkImage_GpuBase;
};
#endif