Files
t5de-renderer/adapter/recorder.hpp
T
dhkatzandClaude Opus 5.5 6e4fe589e5
CI / build (push) Successful in 48s
Draw render targets in the renderer process
While the renderer process runs, the adapter makes the client's render targets
itself and the renderer process draws frames into them: texture targets are
drawn with like any texture, and a pixmap target's frame is read back through
the channel into its Pixmap (protocol version 4: BeginFrame names its target,
CreateRenderTarget, Channel::readSize and the -read event). Frames into render
targets are drawn even while the window is hidden.

The client uses pixmap targets for snapshots (outfit pictures, photos), checked
to look right. The render target interfaces are declared from IMVU's vtables.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 19:09:48 -07:00

68 lines
2.7 KiB
C++

#pragma once
// Records what the client draws as commands (include/t5de/protocol/commands.hpp) and sends them to the renderer
// process. Shared by an engine and the resources it creates (which can outlive it); once the renderer process is
// gone, it records nothing.
#include <cstdint>
#include <memory>
#include <span>
#include "renderer_process.hpp"
#include "t5de/imvu/types.hpp"
#include "t5de/protocol/commands.hpp"
namespace t5de {
class Recorder {
public:
explicit Recorder(std::unique_ptr<RendererProcess> process);
[[nodiscard]] bool active() const { return process_ && process_->alive(); }
// Whether the renderer process draws the whole 3D view, so the client's renderer needn't.
[[nodiscard]] bool covering() const { return process_ && process_->covering(); }
// Records a command (if active); returns its payload to fill, or null.
template <class Body>
std::byte* add(protocol::Op op, const Body& body, std::size_t payloadSize = 0)
{
if (!active()) {
return nullptr;
}
std::byte* payload = writer_.add(op, body, payloadSize);
return payload;
}
// Sends what's recorded: at the end of each frame, and between frames when a lot is waiting (resources).
void flush(bool endsFrame);
void flushIfLarge();
std::uint32_t createTexture(const imvu::Pixmap& pixmap, std::uint32_t flags);
// Destroyed with destroyTexture.
std::uint32_t createRenderTarget(std::uint32_t width, std::uint32_t height);
// After flushing a frame that reads its render target back: its pixels (RendererProcess::readBack).
std::span<const std::byte> readBack();
void updateTexture(std::uint32_t id, const imvu::Pixmap& pixmap);
void destroyTexture(std::uint32_t id);
// Copies count elements of elementSize bytes, stride bytes apart (0: packed), from data (null: none yet).
std::uint32_t createBuffer(protocol::BufferKind kind, const void* data, std::uint32_t stride,
std::uint32_t elementSize, std::uint32_t count);
void updateBuffer(std::uint32_t id, const void* data, std::uint32_t stride, std::uint32_t elementSize,
std::uint32_t count);
void destroyBuffer(std::uint32_t id);
private:
void addPixels(protocol::Op op, std::uint32_t id, const imvu::Pixmap& pixmap, std::uint32_t flags);
std::unique_ptr<RendererProcess> process_;
protocol::Writer writer_;
std::uint32_t nextId_ = 1;
};
// Copies count elements of elementSize bytes, stride bytes apart (0: packed), into destination, packed.
void pack(std::byte* destination, const void* source, std::uint32_t stride, std::uint32_t elementSize,
std::uint32_t count);
} // namespace t5de