fake_skia_output_surface.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/viz/test/fake_skia_output_surface.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/logging.h"
  9. #include "base/task/bind_post_task.h"
  10. #include "base/task/sequenced_task_runner.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "build/build_config.h"
  13. #include "components/viz/common/frame_sinks/copy_output_request.h"
  14. #include "components/viz/common/frame_sinks/copy_output_util.h"
  15. #include "components/viz/common/resources/resource_format_utils.h"
  16. #include "components/viz/service/display/output_surface_client.h"
  17. #include "components/viz/service/display/output_surface_frame.h"
  18. #include "gpu/GLES2/gl2extchromium.h"
  19. #include "gpu/command_buffer/common/mailbox_holder.h"
  20. #include "gpu/command_buffer/common/shared_image_usage.h"
  21. #include "third_party/khronos/GLES2/gl2ext.h"
  22. #include "third_party/skia/include/core/SkPixelRef.h"
  23. #include "third_party/skia/include/gpu/GrBackendSurface.h"
  24. #include "third_party/skia/include/gpu/GrDirectContext.h"
  25. #include "third_party/skia/include/gpu/gl/GrGLTypes.h"
  26. #include "ui/gfx/gpu_fence_handle.h"
  27. #include "ui/gfx/presentation_feedback.h"
  28. #include "ui/gfx/swap_result.h"
  29. #include "ui/gl/gl_utils.h"
  30. namespace viz {
  31. FakeSkiaOutputSurface::FakeSkiaOutputSurface(
  32. scoped_refptr<ContextProvider> context_provider)
  33. : SkiaOutputSurface(SkiaOutputSurface::Type::kOpenGL),
  34. context_provider_(std::move(context_provider)) {}
  35. FakeSkiaOutputSurface::~FakeSkiaOutputSurface() {
  36. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  37. }
  38. void FakeSkiaOutputSurface::BindToClient(OutputSurfaceClient* client) {
  39. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  40. DCHECK(client);
  41. DCHECK(!client_);
  42. client_ = client;
  43. }
  44. void FakeSkiaOutputSurface::EnsureBackbuffer() {
  45. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  46. }
  47. void FakeSkiaOutputSurface::DiscardBackbuffer() {
  48. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  49. }
  50. void FakeSkiaOutputSurface::Reshape(const ReshapeParams& params) {
  51. auto& sk_surface = sk_surfaces_[AggregatedRenderPassId{0}];
  52. SkColorType color_type = kRGBA_8888_SkColorType;
  53. SkImageInfo image_info = SkImageInfo::Make(
  54. params.size.width(), params.size.height(), color_type,
  55. kPremul_SkAlphaType, params.color_space.ToSkColorSpace());
  56. sk_surface =
  57. SkSurface::MakeRenderTarget(gr_context(), SkBudgeted::kNo, image_info);
  58. DCHECK(sk_surface);
  59. }
  60. void FakeSkiaOutputSurface::SwapBuffers(OutputSurfaceFrame frame) {
  61. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  62. if (frame.delegated_ink_metadata)
  63. last_delegated_ink_metadata_ = std::move(frame.delegated_ink_metadata);
  64. base::ThreadTaskRunnerHandle::Get()->PostTask(
  65. FROM_HERE, base::BindOnce(&FakeSkiaOutputSurface::SwapBuffersAck,
  66. weak_ptr_factory_.GetWeakPtr()));
  67. }
  68. void FakeSkiaOutputSurface::ScheduleOutputSurfaceAsOverlay(
  69. OverlayProcessorInterface::OutputSurfaceOverlayPlane output_surface_plane) {
  70. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  71. NOTIMPLEMENTED();
  72. }
  73. bool FakeSkiaOutputSurface::IsDisplayedAsOverlayPlane() const {
  74. return false;
  75. }
  76. void FakeSkiaOutputSurface::SetNeedsSwapSizeNotifications(
  77. bool needs_swap_size_notifications) {
  78. NOTIMPLEMENTED();
  79. }
  80. void FakeSkiaOutputSurface::SetUpdateVSyncParametersCallback(
  81. UpdateVSyncParametersCallback callback) {
  82. NOTIMPLEMENTED();
  83. }
  84. gfx::OverlayTransform FakeSkiaOutputSurface::GetDisplayTransform() {
  85. return gfx::OVERLAY_TRANSFORM_NONE;
  86. }
  87. SkCanvas* FakeSkiaOutputSurface::BeginPaintCurrentFrame() {
  88. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  89. auto& sk_surface = sk_surfaces_[AggregatedRenderPassId{0}];
  90. DCHECK(sk_surface);
  91. DCHECK_EQ(current_render_pass_id_, AggregatedRenderPassId{0u});
  92. return sk_surface->getCanvas();
  93. }
  94. void FakeSkiaOutputSurface::MakePromiseSkImage(ImageContext* image_context) {
  95. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  96. if (image_context->has_image())
  97. return;
  98. GrBackendTexture backend_texture;
  99. if (!GetGrBackendTexture(*image_context, &backend_texture)) {
  100. DLOG(ERROR) << "Failed to GetGrBackendTexture from mailbox.";
  101. return;
  102. }
  103. auto sk_color_type = ResourceFormatToClosestSkColorType(
  104. true /* gpu_compositing */, image_context->resource_format());
  105. image_context->SetImage(
  106. SkImage::MakeFromTexture(gr_context(), backend_texture,
  107. kTopLeft_GrSurfaceOrigin, sk_color_type,
  108. image_context->alpha_type(),
  109. image_context->color_space()),
  110. backend_texture.getBackendFormat());
  111. }
  112. sk_sp<SkImage> FakeSkiaOutputSurface::MakePromiseSkImageFromYUV(
  113. const std::vector<ImageContext*>& contexts,
  114. sk_sp<SkColorSpace> image_color_space,
  115. SkYUVAInfo::PlaneConfig plane_config,
  116. SkYUVAInfo::Subsampling subsampling) {
  117. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  118. NOTIMPLEMENTED();
  119. return nullptr;
  120. }
  121. gpu::SyncToken FakeSkiaOutputSurface::ReleaseImageContexts(
  122. std::vector<std::unique_ptr<ImageContext>> image_contexts) {
  123. return gpu::SyncToken();
  124. }
  125. std::unique_ptr<ExternalUseClient::ImageContext>
  126. FakeSkiaOutputSurface::CreateImageContext(
  127. const gpu::MailboxHolder& holder,
  128. const gfx::Size& size,
  129. ResourceFormat format,
  130. bool concurrent_reads,
  131. const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
  132. sk_sp<SkColorSpace> color_space,
  133. bool raw_draw_if_possible) {
  134. return std::make_unique<ExternalUseClient::ImageContext>(
  135. holder, size, format, ycbcr_info, std::move(color_space));
  136. }
  137. SkCanvas* FakeSkiaOutputSurface::BeginPaintRenderPass(
  138. const AggregatedRenderPassId& id,
  139. const gfx::Size& surface_size,
  140. ResourceFormat format,
  141. bool mipmap,
  142. sk_sp<SkColorSpace> color_space,
  143. bool is_overlay,
  144. const gpu::Mailbox& mailbox) {
  145. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  146. // Make sure there is no unsubmitted PaintFrame or PaintRenderPass.
  147. DCHECK_EQ(current_render_pass_id_, AggregatedRenderPassId{0u});
  148. auto& sk_surface = sk_surfaces_[id];
  149. if (!sk_surface) {
  150. SkColorType color_type =
  151. ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format);
  152. SkImageInfo image_info = SkImageInfo::Make(
  153. surface_size.width(), surface_size.height(), color_type,
  154. kPremul_SkAlphaType, std::move(color_space));
  155. sk_surface =
  156. SkSurface::MakeRenderTarget(gr_context(), SkBudgeted::kNo, image_info);
  157. }
  158. return sk_surface->getCanvas();
  159. }
  160. SkCanvas* FakeSkiaOutputSurface::RecordOverdrawForCurrentPaint() {
  161. NOTIMPLEMENTED();
  162. return nullptr;
  163. }
  164. void FakeSkiaOutputSurface::EndPaint(
  165. base::OnceClosure on_finished,
  166. base::OnceCallback<void(gfx::GpuFenceHandle)> return_release_fence_cb) {
  167. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  168. sk_surfaces_[current_render_pass_id_]->flushAndSubmit();
  169. current_render_pass_id_ = AggregatedRenderPassId{0};
  170. if (on_finished)
  171. std::move(on_finished).Run();
  172. if (return_release_fence_cb)
  173. std::move(return_release_fence_cb).Run(gfx::GpuFenceHandle());
  174. }
  175. sk_sp<SkImage> FakeSkiaOutputSurface::MakePromiseSkImageFromRenderPass(
  176. const AggregatedRenderPassId& id,
  177. const gfx::Size& size,
  178. ResourceFormat format,
  179. bool mipmap,
  180. sk_sp<SkColorSpace> color_space,
  181. const gpu::Mailbox& mailbox) {
  182. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  183. auto it = sk_surfaces_.find(id);
  184. DCHECK(it != sk_surfaces_.end());
  185. return it->second->makeImageSnapshot();
  186. }
  187. void FakeSkiaOutputSurface::RemoveRenderPassResource(
  188. std::vector<AggregatedRenderPassId> ids) {
  189. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  190. DCHECK(!ids.empty());
  191. for (const auto& id : ids) {
  192. auto it = sk_surfaces_.find(id);
  193. DCHECK(it != sk_surfaces_.end());
  194. sk_surfaces_.erase(it);
  195. }
  196. }
  197. void FakeSkiaOutputSurface::CopyOutput(
  198. AggregatedRenderPassId id,
  199. const copy_output::RenderPassGeometry& geometry,
  200. const gfx::ColorSpace& color_space,
  201. std::unique_ptr<CopyOutputRequest> request,
  202. const gpu::Mailbox& mailbox) {
  203. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  204. DCHECK(sk_surfaces_.find(id) != sk_surfaces_.end());
  205. auto* surface = sk_surfaces_[id].get();
  206. if (request->result_format() != CopyOutputResult::Format::RGBA ||
  207. request->is_scaled() ||
  208. geometry.result_bounds != geometry.result_selection) {
  209. // TODO(crbug.com/644851): Complete the implementation for all request
  210. // types, scaling, etc.
  211. NOTIMPLEMENTED();
  212. return;
  213. }
  214. if (request->result_destination() ==
  215. CopyOutputResult::Destination::kNativeTextures) {
  216. // TODO(rivr): This implementation is incomplete and doesn't copy
  217. // anything into the mailbox, but currently the only tests that use this
  218. // don't actually check the returned texture data.
  219. auto* sii = GetSharedImageInterface();
  220. gpu::Mailbox local_mailbox = sii->CreateSharedImage(
  221. ResourceFormat::RGBA_8888, geometry.result_selection.size(),
  222. color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
  223. gpu::SHARED_IMAGE_USAGE_GLES2, gpu::kNullSurfaceHandle);
  224. CopyOutputResult::ReleaseCallbacks release_callbacks;
  225. release_callbacks.push_back(base::BindPostTask(
  226. base::SequencedTaskRunnerHandle::Get(),
  227. base::BindOnce(&FakeSkiaOutputSurface::DestroyCopyOutputTexture,
  228. weak_ptr_factory_.GetWeakPtr(), local_mailbox)));
  229. request->SendResult(std::make_unique<CopyOutputTextureResult>(
  230. CopyOutputResult::Format::RGBA, geometry.result_bounds,
  231. CopyOutputResult::TextureResult(local_mailbox, GenerateSyncToken(),
  232. color_space),
  233. std::move(release_callbacks)));
  234. return;
  235. }
  236. GrDirectContext* direct = GrAsDirectContext(gr_context());
  237. auto copy_image = surface->makeImageSnapshot()->makeSubset(
  238. RectToSkIRect(geometry.sampling_bounds), direct);
  239. // Send copy request by copying into a bitmap.
  240. SkBitmap bitmap;
  241. copy_image->asLegacyBitmap(&bitmap);
  242. // TODO(crbug.com/795132): Plumb color space throughout SkiaRenderer up to
  243. // the SkSurface/SkImage here. Until then, play "musical chairs" with the
  244. // SkPixelRef to hack-in the RenderPass's |color_space|.
  245. sk_sp<SkPixelRef> pixels(SkSafeRef(bitmap.pixelRef()));
  246. SkIPoint origin = bitmap.pixelRefOrigin();
  247. bitmap.setInfo(bitmap.info().makeColorSpace(color_space.ToSkColorSpace()),
  248. bitmap.rowBytes());
  249. bitmap.setPixelRef(std::move(pixels), origin.x(), origin.y());
  250. request->SendResult(std::make_unique<CopyOutputSkBitmapResult>(
  251. geometry.result_bounds, std::move(bitmap)));
  252. }
  253. gpu::SharedImageInterface* FakeSkiaOutputSurface::GetSharedImageInterface() {
  254. return context_provider_->SharedImageInterface();
  255. }
  256. void FakeSkiaOutputSurface::AddContextLostObserver(
  257. ContextLostObserver* observer) {}
  258. void FakeSkiaOutputSurface::RemoveContextLostObserver(
  259. ContextLostObserver* observer) {}
  260. gpu::SyncToken FakeSkiaOutputSurface::Flush() {
  261. return GenerateSyncToken();
  262. }
  263. bool FakeSkiaOutputSurface::EnsureMinNumberOfBuffers(int n) {
  264. return false;
  265. }
  266. void FakeSkiaOutputSurface::SetOutOfOrderCallbacks(
  267. bool out_of_order_callbacks) {
  268. TestContextSupport* support =
  269. static_cast<TestContextSupport*>(context_provider()->ContextSupport());
  270. support->set_out_of_order_callbacks(out_of_order_callbacks);
  271. }
  272. gpu::SyncToken FakeSkiaOutputSurface::GenerateSyncToken() {
  273. gpu::SyncToken sync_token(
  274. gpu::CommandBufferNamespace::VIZ_SKIA_OUTPUT_SURFACE,
  275. gpu::CommandBufferId(), ++next_sync_fence_release_);
  276. sync_token.SetVerifyFlush();
  277. return sync_token;
  278. }
  279. bool FakeSkiaOutputSurface::GetGrBackendTexture(
  280. const ImageContext& image_context,
  281. GrBackendTexture* backend_texture) {
  282. DCHECK(!image_context.mailbox_holder().mailbox.IsZero());
  283. auto* gl = context_provider()->ContextGL();
  284. gl->WaitSyncTokenCHROMIUM(
  285. image_context.mailbox_holder().sync_token.GetConstData());
  286. auto texture_id = gl->CreateAndTexStorage2DSharedImageCHROMIUM(
  287. image_context.mailbox_holder().mailbox.name);
  288. auto gl_format = TextureStorageFormat(
  289. image_context.resource_format(),
  290. context_provider()->ContextCapabilities().angle_rgbx_internal_format);
  291. GrGLTextureInfo gl_texture_info = {
  292. image_context.mailbox_holder().texture_target, texture_id, gl_format};
  293. *backend_texture = GrBackendTexture(image_context.size().width(),
  294. image_context.size().height(),
  295. GrMipMapped::kNo, gl_texture_info);
  296. return true;
  297. }
  298. void FakeSkiaOutputSurface::SwapBuffersAck() {
  299. base::TimeTicks now = base::TimeTicks::Now();
  300. client_->DidReceiveSwapBuffersAck({now, now},
  301. /*release_fence=*/gfx::GpuFenceHandle());
  302. client_->DidReceivePresentationFeedback({now, base::TimeDelta(), 0});
  303. }
  304. void FakeSkiaOutputSurface::DestroyCopyOutputTexture(
  305. const gpu::Mailbox& mailbox,
  306. const gpu::SyncToken& sync_token,
  307. bool is_lost) {
  308. GetSharedImageInterface()->DestroySharedImage(sync_token, mailbox);
  309. }
  310. void FakeSkiaOutputSurface::ScheduleGpuTaskForTesting(
  311. base::OnceClosure callback,
  312. std::vector<gpu::SyncToken> sync_tokens) {
  313. NOTIMPLEMENTED();
  314. }
  315. void FakeSkiaOutputSurface::InitDelegatedInkPointRendererReceiver(
  316. mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
  317. pending_receiver) {
  318. delegated_ink_renderer_receiver_arrived_ = true;
  319. }
  320. } // namespace viz