所有权指针明确
This commit is contained in:
@@ -17,7 +17,7 @@ using namespace aethera;
|
||||
using namespace aethera::render_2d;
|
||||
|
||||
template <typename Object, typename... Arguments>
|
||||
Object* build_object(Arguments&&... arguments) {
|
||||
owner<Object*> build_object(Arguments&&... arguments) {
|
||||
typename Object::template Builder<Object> builder(std::forward<Arguments>(arguments)...);
|
||||
auto result = builder.build();
|
||||
if (!result) std::_Exit(2);
|
||||
@@ -27,7 +27,7 @@ Object* build_object(Arguments&&... arguments) {
|
||||
bool contains_color(Image_View view) {
|
||||
for (int y = 0; y < view.height; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(
|
||||
view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x)
|
||||
if (row[x] != 0) return true;
|
||||
}
|
||||
@@ -48,15 +48,16 @@ int main() {
|
||||
initialize_runtime({.workers = 4});
|
||||
auto* frequency = build_object<Frequency>();
|
||||
auto* power = build_object<Power>();
|
||||
auto* spectrum = build_object<Spectrum_Object>(frequency, power, 4u);
|
||||
auto* spectrum = build_object<Spectrum_Object>(
|
||||
not_null{frequency}, not_null{power}, 4u);
|
||||
auto* time = build_object<Time>();
|
||||
auto* waterfall = build_object<Waterfall_Object>(
|
||||
frequency, time, Plot_Partition_Grid{2, 2});
|
||||
not_null{frequency}, not_null{time}, Plot_Partition_Grid{2, 2});
|
||||
auto* afterglow = build_object<Afterglow_Object>(
|
||||
frequency, power, Plot_Partition_Grid{2, 2});
|
||||
not_null{frequency}, not_null{power}, Plot_Partition_Grid{2, 2});
|
||||
auto* q_axis = build_object<Power>();
|
||||
auto* constellation = build_object<Constellation_Object>(
|
||||
power, q_axis, 3u);
|
||||
not_null{power}, not_null{q_axis}, 3u);
|
||||
auto* spectrum_painted = new std::atomic_bool{};
|
||||
auto* topology_valid = new std::atomic_bool{true};
|
||||
auto* second_frame_valid = new std::atomic_bool{};
|
||||
@@ -75,10 +76,10 @@ int main() {
|
||||
verify_spectrum_precedes_axis);
|
||||
|
||||
typename Scene_Object::template Builder<Scene_Object> scene_builder;
|
||||
scene_builder.add_renderable(spectrum);
|
||||
scene_builder.add_renderable(waterfall);
|
||||
scene_builder.add_renderable(afterglow);
|
||||
scene_builder.add_renderable(constellation);
|
||||
scene_builder.add_renderable(not_null{spectrum});
|
||||
scene_builder.add_renderable(not_null{waterfall});
|
||||
scene_builder.add_renderable(not_null{afterglow});
|
||||
scene_builder.add_renderable(not_null{constellation});
|
||||
auto scene_result = scene_builder.build();
|
||||
if (!scene_result) return 2;
|
||||
auto* scene = std::move(scene_result).value().release();
|
||||
@@ -157,12 +158,13 @@ int main() {
|
||||
!afterglow_color_barrier)
|
||||
trace_valid->store(false, std::memory_order_relaxed);
|
||||
};
|
||||
scene->set_frame_callback(
|
||||
if (!scene->render(
|
||||
frame,
|
||||
[scene, spectrum, waterfall, afterglow, constellation, frame,
|
||||
resized_partition_frame, spectrum_painted,
|
||||
topology_valid, second_frame_valid, trace_valid,
|
||||
validate_trace](Frame_2D* completed) {
|
||||
const bool valid = completed == frame &&
|
||||
validate_trace](not_null<Frame_2D*> completed) {
|
||||
const bool valid = completed.get() == frame &&
|
||||
spectrum->read_state<Spectrum::Base_Tag>().sample_count ==
|
||||
512 &&
|
||||
topology_valid->load(std::memory_order_relaxed) &&
|
||||
@@ -181,12 +183,13 @@ int main() {
|
||||
constellation->set<
|
||||
&Constellation_Diagram::Prop::partition_count>(2u);
|
||||
spectrum_painted->store(false, std::memory_order_relaxed);
|
||||
scene->set_frame_callback(
|
||||
if (!scene->render(
|
||||
resized_partition_frame,
|
||||
[resized_partition_frame, second_frame_valid,
|
||||
topology_valid, trace_valid,
|
||||
validate_trace](Frame_2D* next) {
|
||||
validate_trace](not_null<Frame_2D*> next) {
|
||||
const bool resized_valid =
|
||||
next == resized_partition_frame &&
|
||||
next.get() == resized_partition_frame &&
|
||||
topology_valid->load(std::memory_order_relaxed) &&
|
||||
contains_color(next->image());
|
||||
second_frame_valid->store(resized_valid,
|
||||
@@ -197,10 +200,10 @@ int main() {
|
||||
trace_valid->load(std::memory_order_relaxed)
|
||||
? 0
|
||||
: 1);
|
||||
});
|
||||
if (!scene->render(resized_partition_frame)) std::_Exit(2);
|
||||
});
|
||||
if (!scene->render(frame)) return 2;
|
||||
}))
|
||||
std::_Exit(2);
|
||||
}))
|
||||
return 2;
|
||||
|
||||
/*
|
||||
* render() 是异步入口。结束提交线程但保持 Taskflow worker 和进程存活,
|
||||
|
||||
@@ -17,8 +17,8 @@ template <typename Scene>
|
||||
std::unique_ptr<Frame_2D> render_frame(Scene* scene) {
|
||||
static std::uint64_t sequence{1};
|
||||
auto frame = std::make_unique<Frame_2D>(Frame_Identity{sequence++, 0});
|
||||
scene->set_frame_callback([](Frame_2D*) {});
|
||||
EXPECT_TRUE(scene->render(frame.get()).has_value());
|
||||
EXPECT_TRUE(scene->render(
|
||||
frame.get(), [](not_null<Frame_2D*>) {}).has_value());
|
||||
return frame;
|
||||
}
|
||||
template <typename Scene>
|
||||
@@ -74,7 +74,7 @@ TEST(render_cache, copy_owns_independent_pixels) {
|
||||
ASSERT_FALSE(view.empty());
|
||||
bool contains_color{};
|
||||
for (int y = 0; y < view.height && !contains_color; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x) contains_color = contains_color || row[x] != 0;
|
||||
}
|
||||
EXPECT_TRUE(contains_color);
|
||||
@@ -107,7 +107,7 @@ TEST(axis_render, scene_prepares_and_paints_uncached_axis_into_frame) {
|
||||
ASSERT_FALSE(view.empty());
|
||||
bool contains_color{};
|
||||
for (int y = 0; y < view.height && !contains_color; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x) contains_color = contains_color || row[x] != 0;
|
||||
}
|
||||
EXPECT_TRUE(contains_color);
|
||||
|
||||
@@ -48,7 +48,7 @@ TEST(framebuffer_view, writes_only_the_requested_external_image_region) {
|
||||
ASSERT_EQ(view.height, 6);
|
||||
for (int y = 0; y < view.height; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(
|
||||
view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x) {
|
||||
const bool inside = x >= 2 && x < 5 && y >= 1 && y < 3;
|
||||
EXPECT_EQ(row[x] != 0, inside) << "pixel " << x << ',' << y;
|
||||
@@ -75,7 +75,7 @@ TEST(framebuffer_view, overlapping_views_share_the_same_authoritative_pixels) {
|
||||
const Image_View view = framebuffer.view();
|
||||
const auto pixel = [&](int x, int y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(
|
||||
view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
return row[x];
|
||||
};
|
||||
EXPECT_NE(pixel(2, 2), 0u);
|
||||
|
||||
@@ -39,16 +39,21 @@ TEST(partition_configuration,
|
||||
auto power = build_object<Power>();
|
||||
auto q_axis = build_object<Power>();
|
||||
auto time = build_object<Time>();
|
||||
auto spectrum = build_object<Spectrum_Object>(frequency.get(), power.get(),
|
||||
auto spectrum = build_object<Spectrum_Object>(not_null{frequency.get()},
|
||||
not_null{power.get()},
|
||||
6u);
|
||||
auto trace = build_object<Trace_Object>(time.get(), power.get(), 4u);
|
||||
auto sweep = build_object<Sweep_Object>(frequency.get(), power.get(), 4u);
|
||||
auto trace = build_object<Trace_Object>(not_null{time.get()},
|
||||
not_null{power.get()}, 4u);
|
||||
auto sweep = build_object<Sweep_Object>(not_null{frequency.get()},
|
||||
not_null{power.get()}, 4u);
|
||||
auto afterglow = build_object<Afterglow_Object>(
|
||||
frequency.get(), power.get(), Plot_Partition_Grid{2, 3});
|
||||
not_null{frequency.get()}, not_null{power.get()},
|
||||
Plot_Partition_Grid{2, 3});
|
||||
auto constellation = build_object<Constellation_Object>(
|
||||
power.get(), q_axis.get(), 7u);
|
||||
not_null{power.get()}, not_null{q_axis.get()}, 7u);
|
||||
auto waterfall = build_object<Waterfall_Object>(
|
||||
frequency.get(), time.get(), Plot_Partition_Grid{2, 3});
|
||||
not_null{frequency.get()}, not_null{time.get()},
|
||||
Plot_Partition_Grid{2, 3});
|
||||
|
||||
EXPECT_EQ(spectrum->read_prop<Spectrum::Base_Tag>().partition_count, 6u);
|
||||
EXPECT_EQ(constellation->read_prop<Constellation_Diagram::Base_Tag>()
|
||||
@@ -132,9 +137,9 @@ TEST(partition_configuration,
|
||||
ASSERT_EQ(actual.height, expected.height);
|
||||
for (int y = 0; y < expected.height; ++y) {
|
||||
const auto* expected_row = reinterpret_cast<const Pixel*>(
|
||||
expected.data + static_cast<std::ptrdiff_t>(y) * expected.stride);
|
||||
expected.data.data() + static_cast<std::ptrdiff_t>(y) * expected.stride);
|
||||
const auto* actual_row = reinterpret_cast<const Pixel*>(
|
||||
actual.data + static_cast<std::ptrdiff_t>(y) * actual.stride);
|
||||
actual.data.data() + static_cast<std::ptrdiff_t>(y) * actual.stride);
|
||||
for (int x = 0; x < expected.width; ++x)
|
||||
EXPECT_EQ(actual_row[x], expected_row[x])
|
||||
<< "pixel mismatch at " << x << ", " << y;
|
||||
@@ -207,9 +212,9 @@ TEST(partition_configuration,
|
||||
const Image_View actual = actual_cache.view();
|
||||
for (int y = 0; y < expected.height; ++y) {
|
||||
const auto* expected_row = reinterpret_cast<const Pixel*>(
|
||||
expected.data + static_cast<std::ptrdiff_t>(y) * expected.stride);
|
||||
expected.data.data() + static_cast<std::ptrdiff_t>(y) * expected.stride);
|
||||
const auto* actual_row = reinterpret_cast<const Pixel*>(
|
||||
actual.data + static_cast<std::ptrdiff_t>(y) * actual.stride);
|
||||
actual.data.data() + static_cast<std::ptrdiff_t>(y) * actual.stride);
|
||||
for (int x = 0; x < expected.width; ++x)
|
||||
EXPECT_EQ(actual_row[x], expected_row[x])
|
||||
<< "tile seam mismatch at " << x << ", " << y;
|
||||
|
||||
@@ -19,7 +19,7 @@ std::unique_ptr<Object> build_object(Args&&... args) {
|
||||
template <typename Scene, typename... Renderables>
|
||||
std::unique_ptr<Scene> build_scene(Renderables*... renderables) {
|
||||
typename Scene::template Builder<Scene> builder;
|
||||
(builder.add_renderable(renderables), ...);
|
||||
(builder.add_renderable(not_null{renderables}), ...);
|
||||
auto result = builder.build();
|
||||
if (!result) std::terminate();
|
||||
return std::move(result).value();
|
||||
@@ -35,8 +35,8 @@ template <typename Scene>
|
||||
void render_once(Scene* scene) {
|
||||
static std::uint64_t sequence{1};
|
||||
Frame_2D frame{Frame_Identity{sequence++, 0}};
|
||||
scene->set_frame_callback([](Frame_2D*) {});
|
||||
EXPECT_TRUE(scene->render(&frame).has_value());
|
||||
EXPECT_TRUE(scene->render(
|
||||
&frame, [](not_null<Frame_2D*>) {}).has_value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,10 @@ TEST(plottable_migration, curve_plots_share_partitioned_rendering) {
|
||||
frequency->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{0.0, 100.0});
|
||||
power->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{-100.0, 0.0});
|
||||
value->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{0.0, 100.0});
|
||||
auto trace = build_object<Trace>(time.get(), value.get(), 2u);
|
||||
auto sweep = build_object<Sweep>(frequency.get(), power.get(), 2u);
|
||||
auto trace = build_object<Trace>(not_null{time.get()},
|
||||
not_null{value.get()}, 2u);
|
||||
auto sweep = build_object<Sweep>(not_null{frequency.get()},
|
||||
not_null{power.get()}, 2u);
|
||||
trace->submit_stream<Frequency_Trace_Stream_Tag>(
|
||||
Frequency_Trace_Sample{time->append_time({1'000}), 10.0});
|
||||
trace->submit_stream<Frequency_Trace_Stream_Tag>(
|
||||
@@ -120,9 +122,11 @@ TEST(plottable_migration, raster_plots_share_partitioned_color_blocks) {
|
||||
configure_axis(time.get(), Axis_Orientation::vertical, {20.0, 100.0}, -80.0, canvas);
|
||||
frequency->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{0.0, 100.0});
|
||||
power->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{-100.0, 0.0});
|
||||
auto glow = build_object<Glow>(frequency.get(), power.get(),
|
||||
auto glow = build_object<Glow>(not_null{frequency.get()},
|
||||
not_null{power.get()},
|
||||
Plot_Partition_Grid{2, 2});
|
||||
auto waterfall = build_object<Fall>(frequency.get(), time.get(),
|
||||
auto waterfall = build_object<Fall>(not_null{frequency.get()},
|
||||
not_null{time.get()},
|
||||
Plot_Partition_Grid{2, 2});
|
||||
glow->set<&Afterglow::Prop::frequency_range>(Axis_Range{0.0, 100.0});
|
||||
glow->set<&Afterglow::Prop::power_range>(Axis_Range{-100.0, 0.0});
|
||||
@@ -172,8 +176,10 @@ TEST(plottable_migration, direct_overlay_and_constellation_build_and_render) {
|
||||
configure_axis(vertical.get(), Axis_Orientation::vertical, {20.0, 100.0}, -80.0, canvas);
|
||||
horizontal->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{-1.0, 1.0});
|
||||
vertical->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{-1.0, 1.0});
|
||||
auto diagram = build_object<Diagram>(horizontal.get(), vertical.get(), 2u);
|
||||
auto overlay = build_object<Overlay>(horizontal.get(), vertical.get());
|
||||
auto diagram = build_object<Diagram>(not_null{horizontal.get()},
|
||||
not_null{vertical.get()}, 2u);
|
||||
auto overlay = build_object<Overlay>(not_null{horizontal.get()},
|
||||
not_null{vertical.get()});
|
||||
diagram->set<&Constellation_Diagram::Prop::i_range>(Axis_Range{-1.0, 1.0});
|
||||
diagram->set<&Constellation_Diagram::Prop::q_range>(Axis_Range{-1.0, 1.0});
|
||||
diagram->submit_stream<Constellation_Stream_Tag>(
|
||||
@@ -199,7 +205,8 @@ TEST(selection_overlay, control_extends_selection_and_plain_click_clears_it) {
|
||||
configure_axis(vertical.get(), Axis_Orientation::vertical, {20.0, 100.0}, -80.0, canvas);
|
||||
horizontal->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{0.0, 100.0});
|
||||
vertical->set<&Numeric_Axis::Prop::coordinate_range>(Axis_Range{0.0, 100.0});
|
||||
auto overlay = build_object<Overlay>(horizontal.get(), vertical.get());
|
||||
auto overlay = build_object<Overlay>(not_null{horizontal.get()},
|
||||
not_null{vertical.get()});
|
||||
auto scene = build_scene<Scene>(overlay.get());
|
||||
scene->set<&Render_Scene_2D::Prop::viewport>(canvas);
|
||||
scene->activate_view();
|
||||
@@ -246,7 +253,8 @@ TEST(selection_overlay, time_axis_selection_keeps_axis_coordinates_while_window_
|
||||
time->append_time({1'000});
|
||||
time->append_time({2'000});
|
||||
time->append_time({3'000});
|
||||
auto overlay = build_object<Overlay>(time.get(), value.get());
|
||||
auto overlay = build_object<Overlay>(not_null{time.get()},
|
||||
not_null{value.get()});
|
||||
auto scene = build_scene<Scene>(overlay.get());
|
||||
scene->set<&Render_Scene_2D::Prop::viewport>(canvas);
|
||||
scene->activate_view();
|
||||
|
||||
@@ -15,14 +15,14 @@ std::unique_ptr<Object> build_object(Args&&... args) {
|
||||
template <typename Scene, typename... Renderables>
|
||||
std::unique_ptr<Scene> build_scene(Renderables*... renderables) {
|
||||
typename Scene::template Builder<Scene> builder;
|
||||
(builder.add_renderable(renderables), ...);
|
||||
(builder.add_renderable(not_null{renderables}), ...);
|
||||
auto result = builder.build();
|
||||
if (!result) std::terminate();
|
||||
return std::move(result).value();
|
||||
}
|
||||
bool contains_color(Image_View view) {
|
||||
for (int y = 0; y < view.height; ++y) {
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
const auto* row = reinterpret_cast<const Pixel*>(view.data.data() + static_cast<std::ptrdiff_t>(y) * view.stride);
|
||||
for (int x = 0; x < view.width; ++x)
|
||||
if (row[x] != 0) return true;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ bool contains_color(Image_View view) {
|
||||
std::uint64_t image_hash(Image_View view) {
|
||||
std::uint64_t value{1469598103934665603ULL};
|
||||
for (int y = 0; y < view.height; ++y) {
|
||||
const auto* row = reinterpret_cast<const std::byte*>(view.data) +
|
||||
const auto* row = view.data.data() +
|
||||
static_cast<std::ptrdiff_t>(y) * view.stride;
|
||||
for (std::ptrdiff_t index = 0;
|
||||
index < static_cast<std::ptrdiff_t>(view.width * sizeof(Pixel));
|
||||
@@ -46,8 +46,8 @@ template <typename Scene>
|
||||
std::unique_ptr<Frame_2D> render_frame(Scene* scene) {
|
||||
static std::uint64_t sequence{1};
|
||||
auto frame = std::make_unique<Frame_2D>(Frame_Identity{sequence++, 0});
|
||||
scene->set_frame_callback([](Frame_2D*) {});
|
||||
EXPECT_TRUE(scene->render(frame.get()).has_value());
|
||||
EXPECT_TRUE(scene->render(
|
||||
frame.get(), [](not_null<Frame_2D*>) {}).has_value());
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,8 @@ TEST(spectrum_data, publishes_samples_through_tagged_frame_buffer) {
|
||||
using Scene_Object = Render_Scene_2D;
|
||||
auto frequency = build_object<Frequency>();
|
||||
auto power = build_object<Power>();
|
||||
auto spectrum = build_object<Object>(frequency.get(), power.get());
|
||||
auto spectrum = build_object<Object>(not_null{frequency.get()},
|
||||
not_null{power.get()});
|
||||
spectrum->set<&Spectrum::Prop::frequency_range>(Axis_Range{0.0, 100.0});
|
||||
const double samples[]{-100.0, -50.0, 0.0};
|
||||
spectrum->pending_buffer<Spectrum_Frame_Tag>() =
|
||||
@@ -75,7 +76,8 @@ TEST(spectrum_markers, uses_tagged_properties_as_the_only_marker_interface) {
|
||||
using Scene_Object = Render_Scene_2D;
|
||||
auto frequency = build_object<Frequency>();
|
||||
auto power = build_object<Power>();
|
||||
auto spectrum = build_object<Object>(frequency.get(), power.get());
|
||||
auto spectrum = build_object<Object>(not_null{frequency.get()},
|
||||
not_null{power.get()});
|
||||
spectrum->set<&Spectrum::Prop::custom_markers>(
|
||||
std::vector<Spectrum_Frequency>{10.0, 20.0});
|
||||
spectrum->advance();
|
||||
@@ -110,7 +112,8 @@ TEST(render_scene_2d, composites_axes_and_spectrum_into_final_frame) {
|
||||
initialize_runtime({.workers = 2});
|
||||
auto frequency = build_object<Frequency>();
|
||||
auto power = build_object<Power>();
|
||||
auto spectrum = build_object<Spectrum_Object>(frequency.get(), power.get(), 3u);
|
||||
auto spectrum = build_object<Spectrum_Object>(not_null{frequency.get()},
|
||||
not_null{power.get()}, 3u);
|
||||
auto scene = build_scene<Scene_Object>(spectrum.get());
|
||||
const Size canvas{160, 120};
|
||||
frequency->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
@@ -188,7 +191,8 @@ TEST(spectrum_data, repeatedly_publishes_new_samples_during_long_running_render)
|
||||
initialize_runtime({.workers = 4});
|
||||
auto frequency = build_object<Frequency>();
|
||||
auto power = build_object<Power>();
|
||||
auto spectrum = build_object<Spectrum_Object>(frequency.get(), power.get());
|
||||
auto spectrum = build_object<Spectrum_Object>(not_null{frequency.get()},
|
||||
not_null{power.get()});
|
||||
auto scene = build_scene<Scene_Object>(spectrum.get());
|
||||
frequency->set<&Abs_Axis::Prop::position>(Point_F{20.0, 100.0});
|
||||
frequency->set<&Abs_Axis::Prop::pixel_length>(120.0);
|
||||
|
||||
Reference in New Issue
Block a user