GrMipMappedTest.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * Copyright 2017 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 "include/core/SkTypes.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkPoint.h"
  10. #include "include/core/SkSurface.h"
  11. #include "include/gpu/GrBackendSurface.h"
  12. #include "include/gpu/GrContext.h"
  13. #include "src/gpu/GrBackendTextureImageGenerator.h"
  14. #include "src/gpu/GrContextPriv.h"
  15. #include "src/gpu/GrGpu.h"
  16. #include "src/gpu/GrRenderTargetContext.h"
  17. #include "src/gpu/GrSemaphore.h"
  18. #include "src/gpu/GrSurfaceProxyPriv.h"
  19. #include "src/gpu/GrTexturePriv.h"
  20. #include "src/gpu/GrTextureProxy.h"
  21. #include "src/gpu/SkGpuDevice.h"
  22. #include "src/image/SkImage_Base.h"
  23. #include "src/image/SkSurface_Gpu.h"
  24. #include "tests/Test.h"
  25. static constexpr int kSize = 8;
  26. // Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
  27. // SkImages and SkSurfaces
  28. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
  29. GrContext* context = ctxInfo.grContext();
  30. if (!context->priv().caps()->mipMapSupport()) {
  31. return;
  32. }
  33. for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
  34. for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
  35. // createBackendTexture currently doesn't support uploading data to mip maps
  36. // so we don't send any. However, we pretend there is data for the checks below which is
  37. // fine since we are never actually using these textures for any work on the gpu.
  38. GrBackendTexture backendTex = context->createBackendTexture(
  39. kSize, kSize, kRGBA_8888_SkColorType,
  40. SkColors::kTransparent, mipMapped, renderable, GrProtected::kNo);
  41. sk_sp<GrTextureProxy> proxy;
  42. sk_sp<SkImage> image;
  43. if (GrRenderable::kYes == renderable) {
  44. sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
  45. context,
  46. backendTex,
  47. kTopLeft_GrSurfaceOrigin,
  48. 0,
  49. kRGBA_8888_SkColorType,
  50. nullptr,
  51. nullptr);
  52. SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
  53. proxy = device->accessRenderTargetContext()->asTextureProxyRef();
  54. } else {
  55. image = SkImage::MakeFromTexture(context, backendTex,
  56. kTopLeft_GrSurfaceOrigin,
  57. kRGBA_8888_SkColorType,
  58. kPremul_SkAlphaType, nullptr,
  59. nullptr, nullptr);
  60. proxy = as_IB(image)->asTextureProxyRef(context);
  61. }
  62. REPORTER_ASSERT(reporter, proxy);
  63. if (!proxy) {
  64. context->deleteBackendTexture(backendTex);
  65. return;
  66. }
  67. REPORTER_ASSERT(reporter, proxy->isInstantiated());
  68. GrTexture* texture = proxy->peekTexture();
  69. REPORTER_ASSERT(reporter, texture);
  70. if (!texture) {
  71. context->deleteBackendTexture(backendTex);
  72. return;
  73. }
  74. if (GrMipMapped::kYes == mipMapped) {
  75. REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
  76. if (GrRenderable::kYes == renderable) {
  77. REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
  78. } else {
  79. REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
  80. }
  81. } else {
  82. REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
  83. }
  84. context->deleteBackendTexture(backendTex);
  85. }
  86. }
  87. }
  88. // Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
  89. // based on if we will use mips in the draw and the mip status of the GrBackendTexture.
  90. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
  91. GrContext* context = ctxInfo.grContext();
  92. if (!context->priv().caps()->mipMapSupport()) {
  93. return;
  94. }
  95. for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
  96. for (auto willUseMips : {false, true}) {
  97. GrBackendTexture backendTex = context->createBackendTexture(
  98. kSize, kSize, kRGBA_8888_SkColorType,
  99. SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
  100. sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
  101. kTopLeft_GrSurfaceOrigin,
  102. kRGBA_8888_SkColorType,
  103. kPremul_SkAlphaType, nullptr,
  104. nullptr, nullptr);
  105. GrTextureProxy* proxy = as_IB(image)->peekProxy();
  106. REPORTER_ASSERT(reporter, proxy);
  107. if (!proxy) {
  108. context->deleteBackendTexture(backendTex);
  109. return;
  110. }
  111. REPORTER_ASSERT(reporter, proxy->isInstantiated());
  112. sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
  113. REPORTER_ASSERT(reporter, texture);
  114. if (!texture) {
  115. context->deleteBackendTexture(backendTex);
  116. return;
  117. }
  118. std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
  119. texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
  120. kPremul_SkAlphaType, nullptr);
  121. REPORTER_ASSERT(reporter, imageGen);
  122. if (!imageGen) {
  123. context->deleteBackendTexture(backendTex);
  124. return;
  125. }
  126. SkIPoint origin = SkIPoint::Make(0,0);
  127. SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
  128. kPremul_SkAlphaType);
  129. sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
  130. origin, willUseMips);
  131. REPORTER_ASSERT(reporter, genProxy);
  132. if (!genProxy) {
  133. context->deleteBackendTexture(backendTex);
  134. return;
  135. }
  136. if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
  137. genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
  138. } else if (!genProxy->isInstantiated()) {
  139. genProxy->instantiate(context->priv().resourceProvider());
  140. }
  141. REPORTER_ASSERT(reporter, genProxy->isInstantiated());
  142. if (!genProxy->isInstantiated()) {
  143. context->deleteBackendTexture(backendTex);
  144. return;
  145. }
  146. GrTexture* genTexture = genProxy->peekTexture();
  147. REPORTER_ASSERT(reporter, genTexture);
  148. if (!genTexture) {
  149. context->deleteBackendTexture(backendTex);
  150. return;
  151. }
  152. GrBackendTexture genBackendTex = genTexture->getBackendTexture();
  153. if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
  154. GrGLTextureInfo genTexInfo;
  155. GrGLTextureInfo origTexInfo;
  156. if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
  157. backendTex.getGLTextureInfo(&origTexInfo)) {
  158. if (willUseMips && GrMipMapped::kNo == mipMapped) {
  159. // We did a copy so the texture IDs should be different
  160. REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
  161. } else {
  162. REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
  163. }
  164. } else {
  165. ERRORF(reporter, "Failed to get GrGLTextureInfo");
  166. }
  167. #ifdef SK_VULKAN
  168. } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
  169. GrVkImageInfo genImageInfo;
  170. GrVkImageInfo origImageInfo;
  171. if (genBackendTex.getVkImageInfo(&genImageInfo) &&
  172. backendTex.getVkImageInfo(&origImageInfo)) {
  173. if (willUseMips && GrMipMapped::kNo == mipMapped) {
  174. // We did a copy so the texture IDs should be different
  175. REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
  176. } else {
  177. REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
  178. }
  179. } else {
  180. ERRORF(reporter, "Failed to get GrVkImageInfo");
  181. }
  182. #endif
  183. #ifdef SK_METAL
  184. } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
  185. GrMtlTextureInfo genImageInfo;
  186. GrMtlTextureInfo origImageInfo;
  187. if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
  188. backendTex.getMtlTextureInfo(&origImageInfo)) {
  189. if (willUseMips && GrMipMapped::kNo == mipMapped) {
  190. // We did a copy so the texture IDs should be different
  191. REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
  192. } else {
  193. REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
  194. }
  195. } else {
  196. ERRORF(reporter, "Failed to get GrMtlTextureInfo");
  197. }
  198. #endif
  199. } else {
  200. REPORTER_ASSERT(reporter, false);
  201. }
  202. // Must make sure the uses of the backend texture have finished (we possibly have a
  203. // queued up copy) before we delete the backend texture.
  204. context->flush();
  205. context->priv().getGpu()->testingOnly_flushGpuAndSync();
  206. context->deleteBackendTexture(backendTex);
  207. }
  208. }
  209. }
  210. // Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
  211. // resource we took the snapshot of.
  212. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
  213. GrContext* context = ctxInfo.grContext();
  214. if (!context->priv().caps()->mipMapSupport()) {
  215. return;
  216. }
  217. auto resourceProvider = context->priv().resourceProvider();
  218. for (auto willUseMips : {false, true}) {
  219. for (auto isWrapped : {false, true}) {
  220. GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
  221. sk_sp<SkSurface> surface;
  222. GrBackendTexture backendTex = context->createBackendTexture(
  223. kSize, kSize, kRGBA_8888_SkColorType,
  224. SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
  225. if (isWrapped) {
  226. surface = SkSurface::MakeFromBackendTexture(context,
  227. backendTex,
  228. kTopLeft_GrSurfaceOrigin,
  229. 0,
  230. kRGBA_8888_SkColorType,
  231. nullptr,
  232. nullptr);
  233. } else {
  234. SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
  235. kPremul_SkAlphaType);
  236. surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
  237. kTopLeft_GrSurfaceOrigin, nullptr,
  238. willUseMips);
  239. }
  240. REPORTER_ASSERT(reporter, surface);
  241. if (!surface) {
  242. context->deleteBackendTexture(backendTex);
  243. }
  244. SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
  245. GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
  246. REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
  247. texProxy->instantiate(resourceProvider);
  248. GrTexture* texture = texProxy->peekTexture();
  249. REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
  250. sk_sp<SkImage> image = surface->makeImageSnapshot();
  251. REPORTER_ASSERT(reporter, image);
  252. if (!image) {
  253. context->deleteBackendTexture(backendTex);
  254. }
  255. texProxy = as_IB(image)->peekProxy();
  256. REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
  257. texProxy->instantiate(resourceProvider);
  258. texture = texProxy->peekTexture();
  259. REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
  260. // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
  261. // to the gpu before we delete the backendHandle.
  262. context->flush();
  263. context->priv().getGpu()->testingOnly_flushGpuAndSync();
  264. context->deleteBackendTexture(backendTex);
  265. }
  266. }
  267. }
  268. // Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
  269. // to use mips. This test passes by not crashing or hitting asserts in code.
  270. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
  271. GrContext* context = ctxInfo.grContext();
  272. if (!context->priv().caps()->mipMapSupport()) {
  273. return;
  274. }
  275. // Make surface to draw into
  276. SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
  277. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
  278. // Make 1x1 raster bitmap
  279. SkBitmap bmp;
  280. bmp.allocN32Pixels(1, 1);
  281. SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
  282. *pixel = 0;
  283. sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
  284. // Make sure we scale so we don't optimize out the use of mips.
  285. surface->getCanvas()->scale(0.5f, 0.5f);
  286. SkPaint paint;
  287. // This should upload the image to a non mipped GrTextureProxy.
  288. surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
  289. surface->flush();
  290. // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
  291. // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
  292. // instead of trying to do a copy to a mipped texture.
  293. paint.setFilterQuality(kHigh_SkFilterQuality);
  294. surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
  295. surface->flush();
  296. }