gm.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright 2011 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/SkBlendMode.h"
  10. #include "include/core/SkCanvas.h"
  11. #include "include/core/SkFilterQuality.h"
  12. #include "include/core/SkFont.h"
  13. #include "include/core/SkFontTypes.h"
  14. #include "include/core/SkMatrix.h"
  15. #include "include/core/SkPaint.h"
  16. #include "include/core/SkRect.h"
  17. #include "include/core/SkShader.h"
  18. #include "include/core/SkTileMode.h"
  19. #include "include/core/SkTypeface.h"
  20. #include "include/gpu/GrContext.h"
  21. #include "src/core/SkTraceEvent.h"
  22. #include "tools/ToolUtils.h"
  23. #include <stdarg.h>
  24. class GrRenderTargetContext;
  25. using namespace skiagm;
  26. constexpr char GM::kErrorMsg_DrawSkippedGpuOnly[];
  27. static void draw_failure_message(SkCanvas* canvas, const char format[], ...) {
  28. SkString failureMsg;
  29. va_list argp;
  30. va_start(argp, format);
  31. failureMsg.appendVAList(format, argp);
  32. va_end(argp);
  33. constexpr SkScalar kOffset = 5.0f;
  34. canvas->drawColor(SkColorSetRGB(200,0,0));
  35. SkFont font;
  36. SkRect bounds;
  37. font.measureText(failureMsg.c_str(), failureMsg.size(), SkTextEncoding::kUTF8, &bounds);
  38. SkPaint textPaint(SkColors::kWhite);
  39. canvas->drawString(failureMsg, kOffset, bounds.height() + kOffset, font, textPaint);
  40. }
  41. static void draw_gpu_only_message(SkCanvas* canvas) {
  42. SkBitmap bmp;
  43. bmp.allocN32Pixels(128, 64);
  44. SkCanvas bmpCanvas(bmp);
  45. bmpCanvas.drawColor(SK_ColorWHITE);
  46. SkFont font(ToolUtils::create_portable_typeface(), 20);
  47. SkPaint paint(SkColors::kRed);
  48. bmpCanvas.drawString("GPU Only", 20, 40, font, paint);
  49. SkMatrix localM;
  50. localM.setRotate(35.f);
  51. localM.postTranslate(10.f, 0.f);
  52. paint.setShader(bmp.makeShader(SkTileMode::kMirror, SkTileMode::kMirror, &localM));
  53. paint.setFilterQuality(kMedium_SkFilterQuality);
  54. canvas->drawPaint(paint);
  55. }
  56. GM::GM(SkColor bgColor) {
  57. fMode = kGM_Mode;
  58. fBGColor = bgColor;
  59. fCanvasIsDeferred = false;
  60. fHaveCalledOnceBeforeDraw = false;
  61. }
  62. GM::~GM() {}
  63. DrawResult GM::draw(SkCanvas* canvas, SkString* errorMsg) {
  64. TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName()));
  65. this->drawBackground(canvas);
  66. return this->drawContent(canvas, errorMsg);
  67. }
  68. DrawResult GM::drawContent(SkCanvas* canvas, SkString* errorMsg) {
  69. TRACE_EVENT0("GM", TRACE_FUNC);
  70. if (!fHaveCalledOnceBeforeDraw) {
  71. fHaveCalledOnceBeforeDraw = true;
  72. this->onOnceBeforeDraw();
  73. }
  74. SkAutoCanvasRestore acr(canvas, true);
  75. DrawResult drawResult = this->onDraw(canvas, errorMsg);
  76. if (DrawResult::kOk != drawResult) {
  77. if (DrawResult::kFail == drawResult) {
  78. draw_failure_message(canvas, "DRAW FAILED: %s", errorMsg->c_str());
  79. } else if (SkString(kErrorMsg_DrawSkippedGpuOnly) == *errorMsg) {
  80. draw_gpu_only_message(canvas);
  81. } else {
  82. draw_failure_message(canvas, "DRAW SKIPPED: %s", errorMsg->c_str());
  83. }
  84. }
  85. return drawResult;
  86. }
  87. void GM::drawBackground(SkCanvas* canvas) {
  88. TRACE_EVENT0("GM", TRACE_FUNC);
  89. if (!fHaveCalledOnceBeforeDraw) {
  90. fHaveCalledOnceBeforeDraw = true;
  91. this->onOnceBeforeDraw();
  92. }
  93. SkAutoCanvasRestore acr(canvas, true);
  94. canvas->drawColor(fBGColor, SkBlendMode::kSrc);
  95. }
  96. DrawResult GM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
  97. this->onDraw(canvas);
  98. return DrawResult::kOk;
  99. }
  100. void GM::onDraw(SkCanvas*) { SK_ABORT("Not implemented."); }
  101. SkISize SimpleGM::onISize() { return fSize; }
  102. SkString SimpleGM::onShortName() { return fName; }
  103. DrawResult SimpleGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
  104. return fDrawProc(canvas, errorMsg);
  105. }
  106. SkISize SimpleGpuGM::onISize() { return fSize; }
  107. SkString SimpleGpuGM::onShortName() { return fName; }
  108. DrawResult SimpleGpuGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
  109. SkString* errorMsg) {
  110. return fDrawProc(ctx, rtc, canvas, errorMsg);
  111. }
  112. const char* GM::getName() {
  113. if (fShortName.size() == 0) {
  114. fShortName = this->onShortName();
  115. }
  116. return fShortName.c_str();
  117. }
  118. void GM::setBGColor(SkColor color) {
  119. fBGColor = color;
  120. }
  121. bool GM::animate(double nanos) { return this->onAnimate(nanos); }
  122. bool GM::runAsBench() const { return false; }
  123. void GM::modifyGrContextOptions(GrContextOptions* options) {}
  124. void GM::onOnceBeforeDraw() {}
  125. bool GM::onAnimate(double /*nanos*/) { return false; }
  126. bool GM::onChar(SkUnichar uni) { return false; }
  127. bool GM::onGetControls(SkMetaData*) { return false; }
  128. void GM::onSetControls(const SkMetaData&) {}
  129. /////////////////////////////////////////////////////////////////////////////////////////////
  130. void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
  131. canvas->drawRect(SkRect::Make(this->getISize()), SkPaint(SkColor4f::FromColor(color)));
  132. }
  133. // need to explicitly declare this, or we get some weird infinite loop llist
  134. template GMRegistry* GMRegistry::gHead;
  135. DrawResult GpuGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
  136. SkString* errorMsg) {
  137. this->onDraw(ctx, rtc, canvas);
  138. return DrawResult::kOk;
  139. }
  140. void GpuGM::onDraw(GrContext*, GrRenderTargetContext*, SkCanvas*) {
  141. SK_ABORT("Not implemented.");
  142. }
  143. DrawResult GpuGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
  144. GrContext* ctx = canvas->getGrContext();
  145. GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
  146. if (!ctx || !rtc) {
  147. *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
  148. return DrawResult::kSkip;
  149. }
  150. if (ctx->abandoned()) {
  151. *errorMsg = "GrContext abandoned.";
  152. return DrawResult::kSkip;
  153. }
  154. return this->onDraw(ctx, rtc, canvas, errorMsg);
  155. }
  156. template <typename Fn>
  157. static void mark(SkCanvas* canvas, SkScalar x, SkScalar y, Fn&& fn) {
  158. SkPaint alpha;
  159. alpha.setAlpha(0x50);
  160. canvas->saveLayer(nullptr, &alpha);
  161. canvas->translate(x,y);
  162. canvas->scale(2,2);
  163. fn();
  164. canvas->restore();
  165. }
  166. void MarkGMGood(SkCanvas* canvas, SkScalar x, SkScalar y) {
  167. mark(canvas, x,y, [&]{
  168. // A green circle.
  169. canvas->drawCircle(0, 0, 12, SkPaint(SkColor4f::FromColor(SkColorSetRGB(27, 158, 119))));
  170. // Cut out a check mark.
  171. SkPaint paint(SkColors::kTransparent);
  172. paint.setBlendMode(SkBlendMode::kSrc);
  173. paint.setStrokeWidth(2);
  174. paint.setStyle(SkPaint::kStroke_Style);
  175. canvas->drawLine(-6, 0,
  176. -1, 5, paint);
  177. canvas->drawLine(-1, +5,
  178. +7, -5, paint);
  179. });
  180. }
  181. void MarkGMBad(SkCanvas* canvas, SkScalar x, SkScalar y) {
  182. mark(canvas, x,y, [&] {
  183. // A red circle.
  184. canvas->drawCircle(0,0, 12, SkPaint(SkColor4f::FromColor(SkColorSetRGB(231, 41, 138))));
  185. // Cut out an 'X'.
  186. SkPaint paint(SkColors::kTransparent);
  187. paint.setBlendMode(SkBlendMode::kSrc);
  188. paint.setStrokeWidth(2);
  189. paint.setStyle(SkPaint::kStroke_Style);
  190. canvas->drawLine(-5,-5,
  191. +5,+5, paint);
  192. canvas->drawLine(+5,-5,
  193. -5,+5, paint);
  194. });
  195. }