image_pict.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * Copyright 2015 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. #include "gm/gm.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkColorSpace.h"
  12. #include "include/core/SkImage.h"
  13. #include "include/core/SkImageGenerator.h"
  14. #include "include/core/SkImageInfo.h"
  15. #include "include/core/SkMatrix.h"
  16. #include "include/core/SkPaint.h"
  17. #include "include/core/SkPicture.h"
  18. #include "include/core/SkPictureRecorder.h"
  19. #include "include/core/SkPoint.h"
  20. #include "include/core/SkRect.h"
  21. #include "include/core/SkRefCnt.h"
  22. #include "include/core/SkScalar.h"
  23. #include "include/core/SkSize.h"
  24. #include "include/core/SkString.h"
  25. #include "include/core/SkSurface.h"
  26. #include "include/core/SkTypes.h"
  27. #include "include/gpu/GrContext.h"
  28. #include "include/gpu/GrSamplerState.h"
  29. #include "include/gpu/GrTypes.h"
  30. #include "include/private/GrTypesPriv.h"
  31. #include "src/core/SkMakeUnique.h"
  32. #include "src/gpu/GrContextPriv.h"
  33. #include "src/gpu/GrSurfaceContext.h"
  34. #include "src/gpu/GrTextureProxy.h"
  35. #include "src/image/SkImage_Base.h"
  36. #include "src/image/SkImage_Gpu.h"
  37. #include <memory>
  38. #include <utility>
  39. class GrRecordingContext;
  40. static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
  41. SkPaint paint;
  42. paint.setAntiAlias(true);
  43. paint.setColor(SK_ColorRED);
  44. paint.setStyle(SkPaint::kStroke_Style);
  45. paint.setStrokeWidth(10);
  46. canvas->drawRect(bounds, paint);
  47. paint.setStyle(SkPaint::kFill_Style);
  48. paint.setColor(SK_ColorBLUE);
  49. canvas->drawOval(bounds, paint);
  50. }
  51. /*
  52. * Exercise drawing pictures inside an image, showing that the image version is pixelated
  53. * (correctly) when it is inside an image.
  54. */
  55. class ImagePictGM : public skiagm::GM {
  56. sk_sp<SkPicture> fPicture;
  57. sk_sp<SkImage> fImage0;
  58. sk_sp<SkImage> fImage1;
  59. public:
  60. ImagePictGM() {}
  61. protected:
  62. SkString onShortName() override {
  63. return SkString("image-picture");
  64. }
  65. SkISize onISize() override {
  66. return SkISize::Make(850, 450);
  67. }
  68. void onOnceBeforeDraw() override {
  69. const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
  70. SkPictureRecorder recorder;
  71. draw_something(recorder.beginRecording(bounds), bounds);
  72. fPicture = recorder.finishRecordingAsPicture();
  73. // extract enough just for the oval.
  74. const SkISize size = SkISize::Make(100, 100);
  75. auto srgbColorSpace = SkColorSpace::MakeSRGB();
  76. SkMatrix matrix;
  77. matrix.setTranslate(-100, -100);
  78. fImage0 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr,
  79. SkImage::BitDepth::kU8, srgbColorSpace);
  80. matrix.postTranslate(-50, -50);
  81. matrix.postRotate(45);
  82. matrix.postTranslate(50, 50);
  83. fImage1 = SkImage::MakeFromPicture(fPicture, size, &matrix, nullptr,
  84. SkImage::BitDepth::kU8, srgbColorSpace);
  85. }
  86. void drawSet(SkCanvas* canvas) const {
  87. SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
  88. canvas->drawPicture(fPicture, &matrix, nullptr);
  89. canvas->drawImage(fImage0.get(), 150, 0);
  90. canvas->drawImage(fImage1.get(), 300, 0);
  91. }
  92. void onDraw(SkCanvas* canvas) override {
  93. canvas->translate(20, 20);
  94. this->drawSet(canvas);
  95. canvas->save();
  96. canvas->translate(0, 130);
  97. canvas->scale(0.25f, 0.25f);
  98. this->drawSet(canvas);
  99. canvas->restore();
  100. canvas->save();
  101. canvas->translate(0, 200);
  102. canvas->scale(2, 2);
  103. this->drawSet(canvas);
  104. canvas->restore();
  105. }
  106. private:
  107. typedef skiagm::GM INHERITED;
  108. };
  109. DEF_GM( return new ImagePictGM; )
  110. ///////////////////////////////////////////////////////////////////////////////////////////////////
  111. static std::unique_ptr<SkImageGenerator> make_pic_generator(GrContext*, sk_sp<SkPicture> pic) {
  112. SkMatrix matrix;
  113. matrix.setTranslate(-100, -100);
  114. return SkImageGenerator::MakeFromPicture({ 100, 100 }, std::move(pic), &matrix, nullptr,
  115. SkImage::BitDepth::kU8,
  116. SkColorSpace::MakeSRGB());
  117. }
  118. class RasterGenerator : public SkImageGenerator {
  119. public:
  120. RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm)
  121. {}
  122. protected:
  123. bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
  124. const Options&) override {
  125. SkASSERT(fBM.width() == info.width());
  126. SkASSERT(fBM.height() == info.height());
  127. return fBM.readPixels(info, pixels, rowBytes, 0, 0);
  128. }
  129. private:
  130. SkBitmap fBM;
  131. };
  132. static std::unique_ptr<SkImageGenerator> make_ras_generator(GrContext*, sk_sp<SkPicture> pic) {
  133. SkBitmap bm;
  134. bm.allocN32Pixels(100, 100);
  135. SkCanvas canvas(bm);
  136. canvas.clear(0);
  137. canvas.translate(-100, -100);
  138. canvas.drawPicture(pic);
  139. return skstd::make_unique<RasterGenerator>(bm);
  140. }
  141. class EmptyGenerator : public SkImageGenerator {
  142. public:
  143. EmptyGenerator(const SkImageInfo& info) : SkImageGenerator(info) {}
  144. };
  145. class TextureGenerator : public SkImageGenerator {
  146. public:
  147. TextureGenerator(GrContext* ctx, const SkImageInfo& info, sk_sp<SkPicture> pic)
  148. : SkImageGenerator(info)
  149. , fCtx(SkRef(ctx)) {
  150. sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, info, 0,
  151. kTopLeft_GrSurfaceOrigin, nullptr));
  152. if (surface) {
  153. surface->getCanvas()->clear(0);
  154. surface->getCanvas()->translate(-100, -100);
  155. surface->getCanvas()->drawPicture(pic);
  156. sk_sp<SkImage> image(surface->makeImageSnapshot());
  157. fProxy = as_IB(image)->asTextureProxyRef(fCtx.get());
  158. }
  159. }
  160. protected:
  161. sk_sp<GrTextureProxy> onGenerateTexture(GrRecordingContext* ctx, const SkImageInfo& info,
  162. const SkIPoint& origin,
  163. bool willBeMipped) override {
  164. SkASSERT(ctx);
  165. SkASSERT(ctx == fCtx.get());
  166. if (!fProxy) {
  167. return nullptr;
  168. }
  169. if (origin.fX == 0 && origin.fY == 0 &&
  170. info.width() == fProxy->width() && info.height() == fProxy->height()) {
  171. return fProxy;
  172. }
  173. GrMipMapped mipMapped = willBeMipped ? GrMipMapped::kYes : GrMipMapped::kNo;
  174. return GrSurfaceProxy::Copy(fCtx.get(), fProxy.get(), mipMapped,
  175. SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
  176. SkBackingFit::kExact, SkBudgeted::kYes);
  177. }
  178. private:
  179. sk_sp<GrContext> fCtx;
  180. sk_sp<GrTextureProxy> fProxy;
  181. };
  182. static std::unique_ptr<SkImageGenerator> make_tex_generator(GrContext* ctx, sk_sp<SkPicture> pic) {
  183. const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
  184. if (!ctx) {
  185. return skstd::make_unique<EmptyGenerator>(info);
  186. }
  187. return skstd::make_unique<TextureGenerator>(ctx, info, pic);
  188. }
  189. class ImageCacheratorGM : public skiagm::GM {
  190. SkString fName;
  191. std::unique_ptr<SkImageGenerator> (*fFactory)(GrContext*, sk_sp<SkPicture>);
  192. sk_sp<SkPicture> fPicture;
  193. sk_sp<SkImage> fImage;
  194. sk_sp<SkImage> fImageSubset;
  195. public:
  196. ImageCacheratorGM(const char suffix[],
  197. std::unique_ptr<SkImageGenerator> (*factory)(GrContext*, sk_sp<SkPicture>))
  198. : fFactory(factory)
  199. {
  200. fName.printf("image-cacherator-from-%s", suffix);
  201. }
  202. protected:
  203. SkString onShortName() override {
  204. return fName;
  205. }
  206. SkISize onISize() override {
  207. return SkISize::Make(960, 450);
  208. }
  209. void onOnceBeforeDraw() override {
  210. const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
  211. SkPictureRecorder recorder;
  212. draw_something(recorder.beginRecording(bounds), bounds);
  213. fPicture = recorder.finishRecordingAsPicture();
  214. }
  215. void makeCaches(GrContext* ctx) {
  216. auto gen = fFactory(ctx, fPicture);
  217. fImage = SkImage::MakeFromGenerator(std::move(gen));
  218. const SkIRect subset = SkIRect::MakeLTRB(50, 50, 100, 100);
  219. gen = fFactory(ctx, fPicture);
  220. fImageSubset = SkImage::MakeFromGenerator(std::move(gen), &subset);
  221. SkASSERT(fImage->dimensions() == SkISize::Make(100, 100));
  222. SkASSERT(fImageSubset->dimensions() == SkISize::Make(50, 50));
  223. }
  224. static void draw_as_bitmap(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
  225. SkBitmap bitmap;
  226. as_IB(image)->getROPixels(&bitmap);
  227. canvas->drawBitmap(bitmap, x, y);
  228. }
  229. static void draw_as_tex(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
  230. sk_sp<GrTextureProxy> proxy(as_IB(image)->asTextureProxyRef(
  231. canvas->getGrContext(), GrSamplerState::ClampBilerp(), nullptr));
  232. if (!proxy) {
  233. // show placeholder if we have no texture
  234. SkPaint paint;
  235. paint.setStyle(SkPaint::kStroke_Style);
  236. SkRect r = SkRect::MakeXYWH(x, y, SkIntToScalar(image->width()),
  237. SkIntToScalar(image->width()));
  238. canvas->drawRect(r, paint);
  239. canvas->drawLine(r.left(), r.top(), r.right(), r.bottom(), paint);
  240. canvas->drawLine(r.left(), r.bottom(), r.right(), r.top(), paint);
  241. return;
  242. }
  243. // No API to draw a GrTexture directly, so we cheat and create a private image subclass
  244. sk_sp<SkImage> texImage(new SkImage_Gpu(sk_ref_sp(canvas->getGrContext()),
  245. image->uniqueID(), kPremul_SkAlphaType,
  246. std::move(proxy), image->refColorSpace()));
  247. canvas->drawImage(texImage.get(), x, y);
  248. }
  249. void drawSet(SkCanvas* canvas) const {
  250. SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
  251. canvas->drawPicture(fPicture, &matrix, nullptr);
  252. // Draw the tex first, so it doesn't hit a lucky cache from the raster version. This
  253. // way we also can force the generateTexture call.
  254. draw_as_tex(canvas, fImage.get(), 310, 0);
  255. draw_as_tex(canvas, fImageSubset.get(), 310+101, 0);
  256. draw_as_bitmap(canvas, fImage.get(), 150, 0);
  257. draw_as_bitmap(canvas, fImageSubset.get(), 150+101, 0);
  258. }
  259. void onDraw(SkCanvas* canvas) override {
  260. this->makeCaches(canvas->getGrContext());
  261. canvas->translate(20, 20);
  262. this->drawSet(canvas);
  263. canvas->save();
  264. canvas->translate(0, 130);
  265. canvas->scale(0.25f, 0.25f);
  266. this->drawSet(canvas);
  267. canvas->restore();
  268. canvas->save();
  269. canvas->translate(0, 200);
  270. canvas->scale(2, 2);
  271. this->drawSet(canvas);
  272. canvas->restore();
  273. }
  274. private:
  275. typedef skiagm::GM INHERITED;
  276. };
  277. DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator); )
  278. DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator); )
  279. DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator); )