Draw render targets in the renderer process
CI / build (push) Successful in 48s

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]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 19:09:48 -07:00
1 parent fa883892db
commit 6e4fe589e5
18 files changed
+523 -58

No files matched your search

+32 -9
View File
@@ -232,39 +232,62 @@ imvu::PiInternalVertexBuffer* Engine::newDynamicVertexBuffer(std::uint32_t eleme
imvu::SharedPtr<imvu::PiPixmapRenderTarget> Engine::newPixmapRenderTarget(imvu::Vec2i size)
{
log::info("engine: frame {}: a {}x{} pixmap render target", frames_, size.x, size.y);
return inner_->newPixmapRenderTarget(size);
if (!recorder_->active() || size.x <= 0 || size.y <= 0) {
return inner_->newPixmapRenderTarget(size);
}
return imvu::SharedPtr<PixmapTarget>(std::make_unique<PixmapTarget>(recorder_, size));
}
imvu::SharedPtr<imvu::PiTextureRenderTarget> Engine::newTextureRenderTarget(imvu::Vec2i size)
{
log::info("engine: frame {}: a {}x{} texture render target", frames_, size.x, size.y);
return inner_->newTextureRenderTarget(size);
if (!recorder_->active() || size.x <= 0 || size.y <= 0) {
return inner_->newTextureRenderTarget(size);
}
return imvu::SharedPtr<TextureTarget>(std::make_unique<TextureTarget>(recorder_, size));
}
void Engine::beginRendering(imvu::PiRenderTarget* target)
{
inner_->beginRendering(target);
// Decided per frame: frames into render targets, and frames while the renderer process doesn't cover the view, are
// drawn by the client's renderer.
const bool takenOver = target == nullptr && recorder_->covering();
// Frames into our render targets are drawn by the renderer process only; the client's renderer doesn't know them.
ourTarget_ = ours(target) ? target : nullptr;
if (ourTarget_ == nullptr) {
inner_->beginRendering(target);
}
// Decided per frame: frames into the client renderer's render targets, and frames while the renderer process
// doesn't cover the view, are drawn by the client's renderer.
const bool takenOver = ourTarget_ != nullptr || (target == nullptr && recorder_->covering());
if (takenOver != takenOver_ && target == nullptr) {
log::info("engine: frame {}: {}", frames_, takenOver ? "drawn by the renderer process" : "drawn by the client's renderer");
}
takenOver_ = takenOver;
if (target != nullptr && foreignLogged_ < 20) {
++foreignLogged_;
log::info("engine: frame {}: drawing into a render target ({})", frames_, static_cast<void*>(target));
log::info("engine: frame {}: drawing into {} render target ({})", frames_,
ourTarget_ != nullptr ? "our" : "the client renderer's", static_cast<void*>(target));
}
recorder_->add(Op::BeginFrame, protocol::BeginFrame{target != nullptr});
protocol::BeginFrame begin{target == nullptr ? 0 : protocol::foreignTarget, 0};
if (const auto* pixmap = dynamic_cast<const PixmapTarget*>(ourTarget_)) {
begin = {pixmap->id(), 1};
} else if (const auto* texture = dynamic_cast<const TextureTarget*>(ourTarget_)) {
begin = {texture->id(), 0};
}
recorder_->add(Op::BeginFrame, begin);
}
void Engine::endRendering()
{
inner_->endRendering();
if (ourTarget_ == nullptr) {
inner_->endRendering();
}
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
recorder_->add(Op::EndFrame, protocol::EndFrame{static_cast<std::uint64_t>(now.QuadPart)});
recorder_->flush(true);
if (auto* pixmap = dynamic_cast<PixmapTarget*>(ourTarget_)) {
pixmap->setPixels(recorder_->readBack());
}
ourTarget_ = nullptr;
++frames_;
if (frames_ % 300 == 0 && statsLogged_ < 6) {
++statsLogged_;