blob: e391c3470383df9bd5df53e25c651d385160388e [file] [log] [blame]
robertphillipsb6c65e92016-02-04 10:52:42 -08001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file
6 */
7
John Stilesfbd050b2020-08-03 13:21:46 -04008#include "src/core/SkSpecialSurface.h"
9
10#include <memory>
11
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkCanvas.h"
13#include "src/core/SkSpecialImage.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkSurfacePriv.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080015
16 ///////////////////////////////////////////////////////////////////////////////
17class SkSpecialSurface_Base : public SkSpecialSurface {
18public:
robertphillips3e302272016-04-20 11:48:36 -070019 SkSpecialSurface_Base(const SkIRect& subset, const SkSurfaceProps* props)
20 : INHERITED(subset, props)
robertphillipsb6c65e92016-02-04 10:52:42 -080021 , fCanvas(nullptr) {
22 }
23
robertphillipsb6c65e92016-02-04 10:52:42 -080024 // reset is called after an SkSpecialImage has been snapped
25 void reset() { fCanvas.reset(); }
26
27 // This can return nullptr if reset has already been called or something when wrong in the ctor
Hal Canary704cd322016-11-07 14:13:52 -050028 SkCanvas* onGetCanvas() { return fCanvas.get(); }
robertphillipsb6c65e92016-02-04 10:52:42 -080029
robertphillips37bd7c32016-03-17 14:31:39 -070030 virtual sk_sp<SkSpecialImage> onMakeImageSnapshot() = 0;
robertphillipsb6c65e92016-02-04 10:52:42 -080031
32protected:
Mike Reed5df49342016-11-12 08:06:55 -060033 std::unique_ptr<SkCanvas> fCanvas; // initialized by derived classes in ctors
robertphillipsb6c65e92016-02-04 10:52:42 -080034
35private:
John Stiles7571f9e2020-09-02 22:42:33 -040036 using INHERITED = SkSpecialSurface;
robertphillipsb6c65e92016-02-04 10:52:42 -080037};
38
39///////////////////////////////////////////////////////////////////////////////
40static SkSpecialSurface_Base* as_SB(SkSpecialSurface* surface) {
41 return static_cast<SkSpecialSurface_Base*>(surface);
42}
43
robertphillips3e302272016-04-20 11:48:36 -070044SkSpecialSurface::SkSpecialSurface(const SkIRect& subset,
robertphillips3b087f42016-02-18 08:48:03 -080045 const SkSurfaceProps* props)
robertphillips0b7e5a12016-04-13 07:18:41 -070046 : fProps(SkSurfacePropsCopyOrDefault(props).flags(), kUnknown_SkPixelGeometry)
robertphillips3e302272016-04-20 11:48:36 -070047 , fSubset(subset) {
robertphillipsb6c65e92016-02-04 10:52:42 -080048 SkASSERT(fSubset.width() > 0);
49 SkASSERT(fSubset.height() > 0);
50}
51
52SkCanvas* SkSpecialSurface::getCanvas() {
53 return as_SB(this)->onGetCanvas();
54}
55
robertphillips37bd7c32016-03-17 14:31:39 -070056sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() {
57 sk_sp<SkSpecialImage> image(as_SB(this)->onMakeImageSnapshot());
robertphillipsb6c65e92016-02-04 10:52:42 -080058 as_SB(this)->reset();
robertphillips16aad782016-02-04 14:59:58 -080059 return image; // the caller gets the creation ref
robertphillipsb6c65e92016-02-04 10:52:42 -080060}
61
62///////////////////////////////////////////////////////////////////////////////
Mike Kleinc0bd9f92019-04-23 12:05:21 -050063#include "include/core/SkMallocPixelRef.h"
robertphillipsb6c65e92016-02-04 10:52:42 -080064
65class SkSpecialSurface_Raster : public SkSpecialSurface_Base {
66public:
Matt Saretta6e976a2017-04-28 15:43:35 -040067 SkSpecialSurface_Raster(const SkImageInfo& info,
68 sk_sp<SkPixelRef> pr,
robertphillips3b087f42016-02-18 08:48:03 -080069 const SkIRect& subset,
70 const SkSurfaceProps* props)
robertphillips3e302272016-04-20 11:48:36 -070071 : INHERITED(subset, props) {
Matt Saretta6e976a2017-04-28 15:43:35 -040072 SkASSERT(info.width() == pr->width() && info.height() == pr->height());
robertphillipsb6c65e92016-02-04 10:52:42 -080073 fBitmap.setInfo(info, info.minRowBytes());
Hal Canary1b3387b2016-12-12 13:48:12 -050074 fBitmap.setPixelRef(std::move(pr), 0, 0);
robertphillipsb6c65e92016-02-04 10:52:42 -080075
John Stilesfbd050b2020-08-03 13:21:46 -040076 fCanvas = std::make_unique<SkCanvas>(fBitmap, this->props());
robertphillips4c13db22016-04-19 14:23:42 -070077 fCanvas->clipRect(SkRect::Make(subset));
robertphillips3806b8f2016-05-12 10:46:39 -070078#ifdef SK_IS_BOT
79 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
80#endif
robertphillipsb6c65e92016-02-04 10:52:42 -080081 }
82
83 ~SkSpecialSurface_Raster() override { }
84
robertphillips37bd7c32016-03-17 14:31:39 -070085 sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
robertphillips3e302272016-04-20 11:48:36 -070086 return SkSpecialImage::MakeFromRaster(this->subset(), fBitmap, &this->props());
robertphillipsb6c65e92016-02-04 10:52:42 -080087 }
88
89private:
90 SkBitmap fBitmap;
91
John Stiles7571f9e2020-09-02 22:42:33 -040092 using INHERITED = SkSpecialSurface_Base;
robertphillipsb6c65e92016-02-04 10:52:42 -080093};
94
robertphillips3e302272016-04-20 11:48:36 -070095sk_sp<SkSpecialSurface> SkSpecialSurface::MakeFromBitmap(const SkIRect& subset, SkBitmap& bm,
robertphillips37bd7c32016-03-17 14:31:39 -070096 const SkSurfaceProps* props) {
Florin Malitaf40b2492017-05-03 15:23:21 -040097 if (subset.isEmpty() || !SkSurfaceValidateRasterInfo(bm.info(), bm.rowBytes())) {
98 return nullptr;
99 }
Matt Saretta6e976a2017-04-28 15:43:35 -0400100 return sk_make_sp<SkSpecialSurface_Raster>(bm.info(), sk_ref_sp(bm.pixelRef()), subset, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800101}
102
robertphillips3e302272016-04-20 11:48:36 -0700103sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRaster(const SkImageInfo& info,
robertphillips37bd7c32016-03-17 14:31:39 -0700104 const SkSurfaceProps* props) {
Florin Malitaf40b2492017-05-03 15:23:21 -0400105 if (!SkSurfaceValidateRasterInfo(info)) {
106 return nullptr;
107 }
108
Mike Klein930c2952019-04-12 11:50:39 -0500109 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0);
Mike Reed6b3155c2017-04-03 14:41:44 -0400110 if (!pr) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800111 return nullptr;
112 }
113
Matt Saretta6e976a2017-04-28 15:43:35 -0400114 const SkIRect subset = SkIRect::MakeWH(info.width(), info.height());
robertphillipsb6c65e92016-02-04 10:52:42 -0800115
Matt Saretta6e976a2017-04-28 15:43:35 -0400116 return sk_make_sp<SkSpecialSurface_Raster>(info, std::move(pr), subset, props);
robertphillipsb6c65e92016-02-04 10:52:42 -0800117}
118
119#if SK_SUPPORT_GPU
120///////////////////////////////////////////////////////////////////////////////
Robert Phillipsb7bfbc22020-07-01 12:55:01 -0400121#include "include/gpu/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500122#include "src/gpu/GrRecordingContextPriv.h"
123#include "src/gpu/SkGpuDevice.h"
robertphillipsb6c65e92016-02-04 10:52:42 -0800124
125class SkSpecialSurface_Gpu : public SkSpecialSurface_Base {
126public:
Robert Phillipsbc429442019-02-20 08:26:03 -0500127 SkSpecialSurface_Gpu(GrRecordingContext* context,
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500128 std::unique_ptr<GrSurfaceDrawContext> surfaceDrawContext,
Robert Phillips9fab7e92016-11-17 12:45:04 -0500129 int width, int height, const SkIRect& subset)
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500130 : INHERITED(subset, &surfaceDrawContext->surfaceProps())
131 , fReadView(surfaceDrawContext->readSurfaceView()) {
132 auto device = SkGpuDevice::Make(context, std::move(surfaceDrawContext),
Brian Salomonbf6b9792019-08-21 09:38:10 -0400133 SkGpuDevice::kUninit_InitContents);
robertphillipsb6c65e92016-02-04 10:52:42 -0800134 if (!device) {
135 return;
136 }
137
John Stilesfbd050b2020-08-03 13:21:46 -0400138 fCanvas = std::make_unique<SkCanvas>(std::move(device));
robertphillips4c13db22016-04-19 14:23:42 -0700139 fCanvas->clipRect(SkRect::Make(subset));
robertphillips3806b8f2016-05-12 10:46:39 -0700140#ifdef SK_IS_BOT
141 fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
142#endif
robertphillipsb6c65e92016-02-04 10:52:42 -0800143 }
144
robertphillips37bd7c32016-03-17 14:31:39 -0700145 sk_sp<SkSpecialImage> onMakeImageSnapshot() override {
Greg Danielc52db712020-01-28 17:03:46 -0500146 if (!fReadView.asTextureProxy()) {
Robert Phillips833dcf42016-11-18 08:44:13 -0500147 return nullptr;
148 }
Robert Phillips40b05c32019-09-20 12:40:55 -0400149 GrColorType ct = SkColorTypeToGrColorType(fCanvas->imageInfo().colorType());
150
Greg Danielc52db712020-01-28 17:03:46 -0500151 // Note: SkSpecialImages can only be snapShotted once, so this call is destructive and we
152 // move fReadMove.
Robert Phillips16bf7d32020-07-07 10:20:27 -0400153 return SkSpecialImage::MakeDeferredFromGpu(fCanvas->recordingContext(),
Brian Salomonbf6b9792019-08-21 09:38:10 -0400154 this->subset(),
155 kNeedNewImageUniqueID_SpecialImage,
Greg Danielc52db712020-01-28 17:03:46 -0500156 std::move(fReadView), ct,
Brian Salomonbf6b9792019-08-21 09:38:10 -0400157 fCanvas->imageInfo().refColorSpace(),
158 &this->props());
robertphillipsb6c65e92016-02-04 10:52:42 -0800159 }
160
161private:
Greg Danielc52db712020-01-28 17:03:46 -0500162 GrSurfaceProxyView fReadView;
John Stiles7571f9e2020-09-02 22:42:33 -0400163 using INHERITED = SkSpecialSurface_Base;
robertphillipsb6c65e92016-02-04 10:52:42 -0800164};
165
Robert Phillipsbc429442019-02-20 08:26:03 -0500166sk_sp<SkSpecialSurface> SkSpecialSurface::MakeRenderTarget(GrRecordingContext* context,
robertphillips4df16562016-04-28 15:09:34 -0700167 int width, int height,
Brian Salomon27ae52c2019-07-03 11:27:44 -0400168 GrColorType colorType,
Robert Phillipse0e83932018-09-20 14:18:13 -0400169 sk_sp<SkColorSpace> colorSpace,
170 const SkSurfaceProps* props) {
robertphillips4df16562016-04-28 15:09:34 -0700171 if (!context) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800172 return nullptr;
173 }
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500174 auto surfaceDrawContext = GrSurfaceDrawContext::Make(
Greg Daniele20fcad2020-01-08 11:52:34 -0500175 context, colorType, std::move(colorSpace), SkBackingFit::kApprox, {width, height}, 1,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400176 GrMipmapped::kNo, GrProtected::kNo, kBottomLeft_GrSurfaceOrigin, SkBudgeted::kYes,
Greg Daniele20fcad2020-01-08 11:52:34 -0500177 props);
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500178 if (!surfaceDrawContext) {
robertphillipsb6c65e92016-02-04 10:52:42 -0800179 return nullptr;
180 }
181
robertphillips4df16562016-04-28 15:09:34 -0700182 const SkIRect subset = SkIRect::MakeWH(width, height);
robertphillipsb6c65e92016-02-04 10:52:42 -0800183
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500184 return sk_make_sp<SkSpecialSurface_Gpu>(context, std::move(surfaceDrawContext),
Robert Phillips9fab7e92016-11-17 12:45:04 -0500185 width, height, subset);
robertphillipsb6c65e92016-02-04 10:52:42 -0800186}
187
188#endif