Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 8b91867

Browse files
committed
Add test context that can be passed around, create a skia context for snapshotting surfaces, create a Vulkan image wrapper for making an SkSurfaces
1 parent 3a28a65 commit 8b91867

File tree

8 files changed

+295
-47
lines changed

8 files changed

+295
-47
lines changed

shell/platform/embedder/tests/embedder_config_builder.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -455,25 +455,25 @@ void EmbedderConfigBuilder::InitializeVulkanRendererConfig() {
455455
vulkan_renderer_config_.struct_size = sizeof(FlutterVulkanRendererConfig);
456456
vulkan_renderer_config_.instance =
457457
static_cast<EmbedderTestContextVulkan&>(context_)
458-
.application_->GetInstance();
458+
.context_.application_->GetInstance();
459459
vulkan_renderer_config_.physical_device =
460460
static_cast<EmbedderTestContextVulkan&>(context_)
461-
.logical_device_->GetPhysicalDeviceHandle();
461+
.context_.device_->GetPhysicalDeviceHandle();
462462
vulkan_renderer_config_.device =
463463
static_cast<EmbedderTestContextVulkan&>(context_)
464-
.logical_device_->GetHandle();
464+
.context_.device_->GetHandle();
465465
vulkan_renderer_config_.queue_family_index =
466466
static_cast<EmbedderTestContextVulkan&>(context_)
467-
.logical_device_->GetGraphicsQueueIndex();
467+
.context_.device_->GetGraphicsQueueIndex();
468468
vulkan_renderer_config_.queue =
469469
static_cast<EmbedderTestContextVulkan&>(context_)
470-
.logical_device_->GetQueueHandle();
470+
.context_.device_->GetQueueHandle();
471471
vulkan_renderer_config_.get_instance_proc_address_callback =
472472
[](void* context, FlutterVulkanInstanceHandle instance,
473473
const char* name) -> void* {
474474
return reinterpret_cast<EmbedderTestContextVulkan*>(context)
475-
->vk_->GetInstanceProcAddr(reinterpret_cast<VkInstance>(instance),
476-
name);
475+
->context_.vk_->GetInstanceProcAddr(
476+
reinterpret_cast<VkInstance>(instance), name);
477477
};
478478
vulkan_renderer_config_.get_next_image_callback =
479479
[](void* context,

shell/platform/embedder/tests/embedder_test_context_vulkan.cc

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,42 +14,11 @@
1414
#include "flutter/vulkan/vulkan_device.h"
1515
#include "flutter/vulkan/vulkan_proc_table.h"
1616

17-
#ifdef OS_MACOSX
18-
#define VULKAN_SO_PATH "libvk_swiftshader.dylib"
19-
#elif OS_WIN
20-
#define VULKAN_SO_PATH "vk_swiftshader.dll"
21-
#else
22-
#define VULKAN_SO_PATH "libvk_swiftshader.so"
23-
#endif
24-
2517
namespace flutter {
2618
namespace testing {
2719

2820
EmbedderTestContextVulkan::EmbedderTestContextVulkan(std::string assets_path)
29-
: EmbedderTestContext(assets_path) {
30-
vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(VULKAN_SO_PATH);
31-
if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
32-
FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
33-
return;
34-
}
35-
36-
application_ = std::unique_ptr<vulkan::VulkanApplication>(
37-
new vulkan::VulkanApplication(*vk_, "Flutter Unittests", {}));
38-
if (!application_->IsValid()) {
39-
FML_DLOG(ERROR) << "Failed to initialize basic Vulkan state.";
40-
return;
41-
}
42-
if (!vk_->AreInstanceProcsSetup()) {
43-
FML_DLOG(ERROR) << "Failed to acquire full proc table.";
44-
return;
45-
}
46-
47-
logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();
48-
if (!logical_device_ || !logical_device_->IsValid()) {
49-
FML_DLOG(ERROR) << "Failed to create compatible logical device.";
50-
return;
51-
}
52-
}
21+
: EmbedderTestContext(assets_path), context_() {}
5322

5423
EmbedderTestContextVulkan::~EmbedderTestContextVulkan() {}
5524

shell/platform/embedder/tests/embedder_test_context_vulkan.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_CONTEXT_VULKAN_H_
66
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_CONTEXT_VULKAN_H_
77

8-
#include "tests/embedder_test_context.h"
9-
#include "vulkan/vulkan_application.h"
8+
#include "flutter/shell/platform/embedder/tests/embedder_test_context.h"
9+
#include "flutter/testing/test_vulkan_context.h"
10+
#include "flutter/vulkan/vulkan_application.h"
1011

1112
namespace flutter {
1213
namespace testing {
@@ -31,18 +32,15 @@ class EmbedderTestContextVulkan : public EmbedderTestContext {
3132
bool PresentImage(VkImage image);
3233

3334
private:
34-
// This allows the builder to access the hooks.
35-
friend class EmbedderConfigBuilder;
36-
37-
fml::RefPtr<vulkan::VulkanProcTable> vk_;
38-
std::unique_ptr<vulkan::VulkanApplication> application_;
39-
std::unique_ptr<vulkan::VulkanDevice> logical_device_;
35+
TestVulkanContext context_;
4036

4137
SkISize surface_size_ = SkISize::MakeEmpty();
4238
size_t present_count_ = 0;
4339

4440
void SetupSurface(SkISize surface_size) override;
4541

42+
friend class EmbedderConfigBuilder;
43+
4644
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestContextVulkan);
4745
};
4846

testing/BUILD.gn

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,19 @@ if (enable_unittests) {
125125
source_set("vulkan") {
126126
testonly = true
127127

128+
sources = [
129+
"test_vulkan_context.cc",
130+
"test_vulkan_context.h",
131+
"test_vulkan_surface.cc",
132+
"test_vulkan_surface.h",
133+
]
134+
128135
defines = [ "TEST_VULKAN_PROCS" ]
129136

130137
deps = [
131138
":skia",
132139
"//flutter/fml",
140+
"//flutter/shell/common",
133141
"//flutter/vulkan",
134142
]
135143

testing/test_vulkan_context.cc

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2013 The Flutter 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+
5+
#include "flutter/testing/test_vulkan_context.h"
6+
#include "flutter/fml/logging.h"
7+
#include "flutter/shell/common/context_options.h"
8+
9+
#include "include/gpu/GrDirectContext.h"
10+
#include "third_party/skia/include/core/SkSurface.h"
11+
12+
#ifdef OS_MACOSX
13+
#define VULKAN_SO_PATH "libvk_swiftshader.dylib"
14+
#elif OS_WIN
15+
#define VULKAN_SO_PATH "vk_swiftshader.dll"
16+
#else
17+
#define VULKAN_SO_PATH "libvk_swiftshader.so"
18+
#endif
19+
20+
namespace flutter {
21+
namespace testing {
22+
23+
TestVulkanContext::TestVulkanContext() {
24+
// ---------------------------------------------------------------------------
25+
// Initialize basic Vulkan state using the Swiftshader ICD.
26+
// ---------------------------------------------------------------------------
27+
28+
vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(VULKAN_SO_PATH);
29+
if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
30+
FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
31+
return;
32+
}
33+
34+
application_ = std::unique_ptr<vulkan::VulkanApplication>(
35+
new vulkan::VulkanApplication(*vk_, "Flutter Unittests", {}));
36+
if (!application_->IsValid()) {
37+
FML_DLOG(ERROR) << "Failed to initialize basic Vulkan state.";
38+
return;
39+
}
40+
if (!vk_->AreInstanceProcsSetup()) {
41+
FML_DLOG(ERROR) << "Failed to acquire full proc table.";
42+
return;
43+
}
44+
45+
device_ = application_->AcquireFirstCompatibleLogicalDevice();
46+
if (!device_ || !device_->IsValid()) {
47+
FML_DLOG(ERROR) << "Failed to create compatible logical device.";
48+
return;
49+
}
50+
51+
// ---------------------------------------------------------------------------
52+
// Create a Skia context.
53+
// For creating SkSurfaces from VkImages and snapshotting them, etc.
54+
// ---------------------------------------------------------------------------
55+
56+
uint32_t skia_features = 0;
57+
if (!device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
58+
FML_LOG(ERROR) << "Failed to get physical device features.";
59+
60+
return;
61+
}
62+
63+
auto get_proc = vk_->CreateSkiaGetProc();
64+
if (get_proc == nullptr) {
65+
FML_LOG(ERROR) << "Failed to create Vulkan getProc for Skia.";
66+
return;
67+
}
68+
69+
GrVkBackendContext backend_context = {
70+
.fInstance = application_->GetInstance(),
71+
.fPhysicalDevice = device_->GetPhysicalDeviceHandle(),
72+
.fDevice = device_->GetHandle(),
73+
.fQueue = device_->GetQueueHandle(),
74+
.fGraphicsQueueIndex = device_->GetGraphicsQueueIndex(),
75+
.fMinAPIVersion = VK_MAKE_VERSION(1, 0, 0),
76+
.fMaxAPIVersion = VK_MAKE_VERSION(1, 0, 0),
77+
.fFeatures = skia_features,
78+
.fGetProc = get_proc,
79+
.fOwnsInstanceAndDevice = false,
80+
};
81+
82+
GrContextOptions options =
83+
MakeDefaultContextOptions(ContextType::kRender, GrBackendApi::kVulkan);
84+
options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
85+
context_ = GrDirectContext::MakeVulkan(backend_context, options);
86+
}
87+
88+
VkImage TestVulkanContext::CreateImage(const SkISize& size) const {
89+
assert(false); // TODO(bdero)
90+
return nullptr;
91+
}
92+
93+
sk_sp<GrDirectContext> TestVulkanContext::GetGrDirectContext() const {
94+
return context_;
95+
}
96+
97+
} // namespace testing
98+
} // namespace flutter

testing/test_vulkan_context.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2013 The Flutter 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+
5+
#ifndef FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_
6+
#define FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_
7+
8+
#include "flutter/fml/macros.h"
9+
#include "flutter/fml/memory/ref_ptr.h"
10+
#include "flutter/vulkan/vulkan_application.h"
11+
#include "flutter/vulkan/vulkan_device.h"
12+
#include "flutter/vulkan/vulkan_proc_table.h"
13+
14+
#include "third_party/skia/include/core/SkSize.h"
15+
#include "third_party/skia/include/gpu/GrDirectContext.h"
16+
17+
namespace flutter {
18+
namespace testing {
19+
20+
class TestVulkanContext {
21+
public:
22+
TestVulkanContext();
23+
24+
VkImage CreateImage(const SkISize& size) const;
25+
26+
sk_sp<GrDirectContext> GetGrDirectContext() const;
27+
28+
private:
29+
fml::RefPtr<vulkan::VulkanProcTable> vk_;
30+
std::unique_ptr<vulkan::VulkanApplication> application_;
31+
std::unique_ptr<vulkan::VulkanDevice> device_;
32+
33+
sk_sp<GrDirectContext> context_;
34+
35+
friend class EmbedderTestContextVulkan;
36+
friend class EmbedderConfigBuilder;
37+
38+
FML_DISALLOW_COPY_AND_ASSIGN(TestVulkanContext);
39+
};
40+
41+
} // namespace testing
42+
} // namespace flutter
43+
44+
#endif // FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_

testing/test_vulkan_surface.cc

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2013 The Flutter 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+
5+
#include "flutter/testing/test_vulkan_surface.h"
6+
#include "flutter/fml/logging.h"
7+
#include "flutter/testing/test_vulkan_context.h"
8+
9+
#include "third_party/skia/include/core/SkSurface.h"
10+
#include "third_party/skia/include/core/SkSurfaceProps.h"
11+
12+
namespace flutter {
13+
namespace testing {
14+
15+
TestVulkanSurface::TestVulkanSurface(const TestVulkanContext& context,
16+
const SkISize& surface_size) {
17+
VkImage image = context.CreateImage(surface_size);
18+
19+
if (!image) {
20+
FML_LOG(ERROR) << "Could not create VkImage.";
21+
return;
22+
}
23+
24+
GrVkImageInfo image_info = {
25+
.fImage = static_cast<VkImage>(image),
26+
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
27+
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
28+
.fFormat = VK_FORMAT_R8G8B8A8_UNORM,
29+
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
30+
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
31+
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
32+
VK_IMAGE_USAGE_SAMPLED_BIT,
33+
.fSampleCount = 1,
34+
.fLevelCount = 1,
35+
};
36+
GrBackendTexture backend_texture(surface_size.width(), //
37+
surface_size.height(), //
38+
image_info //
39+
);
40+
41+
SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
42+
43+
surface_ = SkSurface::MakeFromBackendTexture(
44+
context.GetGrDirectContext().get(), // context
45+
backend_texture, // back-end texture
46+
kTopLeft_GrSurfaceOrigin, // surface origin
47+
1, // sample count
48+
kRGBA_8888_SkColorType, // color type
49+
SkColorSpace::MakeSRGB(), // color space
50+
&surface_properties, // surface properties
51+
nullptr, // release proc
52+
nullptr // release context
53+
);
54+
55+
if (!surface_) {
56+
FML_LOG(ERROR)
57+
<< "Could not wrap VkImage as an SkSurface Vulkan render texture.";
58+
return;
59+
}
60+
}
61+
62+
bool TestVulkanSurface::IsValid() const {
63+
return surface_ != nullptr;
64+
}
65+
66+
sk_sp<SkImage> TestVulkanSurface::GetSurfaceSnapshot() const {
67+
if (!IsValid()) {
68+
return nullptr;
69+
}
70+
71+
if (!surface_) {
72+
FML_LOG(ERROR) << "Aborting snapshot because of on-screen surface "
73+
"acquisition failure.";
74+
return nullptr;
75+
}
76+
77+
auto device_snapshot = surface_->makeImageSnapshot();
78+
79+
if (!device_snapshot) {
80+
FML_LOG(ERROR) << "Could not create the device snapshot while attempting "
81+
"to snapshot the Vulkan surface.";
82+
return nullptr;
83+
}
84+
85+
auto host_snapshot = device_snapshot->makeRasterImage();
86+
87+
if (!host_snapshot) {
88+
FML_LOG(ERROR) << "Could not create the host snapshot while attempting to "
89+
"snapshot the Vulkan surface.";
90+
return nullptr;
91+
}
92+
93+
return host_snapshot;
94+
}
95+
96+
} // namespace testing
97+
} // namespace flutter

0 commit comments

Comments
 (0)