feat: add production-like particle field feed

This commit is contained in:
OpenAI Codex
2026-09-04 14:51:42 +08:00
parent 885e7aebef
commit 7c679f09ac
23 changed files with 545 additions and 26 deletions

View File

@@ -13,6 +13,8 @@ struct ParticleFieldDescriptor {
std::string fieldID;
std::string fieldType;
std::string displayDomain;
// Assigned by the producer before decoding. The adapter never invents a revision.
uint64_t generation = 0;
uint64_t validTime = 0;
uint32_t width = 0;
uint32_t height = 0;

View File

@@ -0,0 +1,17 @@
#pragma once
#include <mbgl/particle/field/field_data_adapter.hpp>
#include <string>
#include <vector>
namespace mbgl::particle {
// Decodes the small provider-neutral local feed contract. File/asset loading
// remains outside this class; callers provide metadata text and payload bytes.
class LocalParticleFieldFeed final {
public:
static ParticleFieldAdapterResult load(const std::string& metadataText, const std::vector<char>& payload);
};
} // namespace mbgl::particle

View File

@@ -26,6 +26,13 @@ struct RasterArrayRuntimeFieldDescriptor {
uint64_t timestamp = 0;
};
// A provider-neutral local feed pair. The source only transports the two
// resources; LocalParticleFieldFeed owns metadata decoding and validation.
struct RasterArrayLocalFieldDescriptor {
std::string metadataURL;
std::string fieldURL;
};
enum class RasterArrayPlaybackState : uint8_t {
Ready,
Playing,
@@ -105,6 +112,7 @@ public:
std::string nextMetadataURL = {},
std::string nextFieldURL = {},
std::vector<RasterArrayRuntimeFieldDescriptor> runtimeFields = {});
RasterArraySource(std::string id, std::vector<RasterArrayLocalFieldDescriptor> localFields);
~RasterArraySource() override;
class Impl;
@@ -114,6 +122,9 @@ public:
// The caller transfers an immutable, already decoded Field snapshot; the
// renderer observes the resulting Source change and owns GPU reuse/upload.
RasterArrayRuntimeFieldUpdateResult updateRuntimeFieldWindow(particle::ParticleFieldSnapshot newT1);
// Thin Core-owned submit point for a producer-supplied initial window.
RasterArrayRuntimeFieldUpdateResult submitInitialRuntimeFieldWindow(particle::ParticleFieldSnapshot t0,
particle::ParticleFieldSnapshot t1);
// Validation convenience: advance using the next Source-owned preloaded
// candidate. Android supplies no T0/T1 state and no GPU resource here.
RasterArrayRuntimeFieldUpdateResult advanceRuntimeFieldWindow();
@@ -137,9 +148,18 @@ private:
std::optional<std::vector<char>> fieldBytes;
std::optional<particle::ParticleFieldSnapshot> snapshot;
};
struct LocalFieldCandidate {
RasterArrayLocalFieldDescriptor descriptor;
std::unique_ptr<AsyncRequest> metadataRequest;
std::unique_ptr<AsyncRequest> fieldRequest;
std::optional<std::string> metadata;
std::optional<std::vector<char>> fieldBytes;
std::optional<particle::ParticleFieldSnapshot> snapshot;
};
void tryLoad();
void tryLoadRuntimeField(size_t);
void tryLoadLocalField(size_t);
void tryInitializeTimeline();
RasterArrayRuntimeFieldUpdateResult rejectRuntimeFieldUpdate(RasterArrayRuntimeFieldUpdateResult,
const std::string& reason) const;
@@ -153,6 +173,7 @@ private:
std::optional<std::string> nextMetadata;
std::optional<std::vector<char>> nextFieldBytes;
std::vector<RuntimeFieldCandidate> runtimeFields;
std::vector<LocalFieldCandidate> localFields;
size_t nextRuntimeField = 0;
uint64_t runtimeUpdateSequence = 0;
std::shared_ptr<RasterArrayTimelineRuntime> timeline;