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

+21 -3
View File
@@ -72,7 +72,9 @@ std::unique_ptr<RendererProcess> RendererProcess::start(HWND window, protocol::V
static_cast<protocol::Channel*>(MapViewOfFile(renderer->mapping_, FILE_MAP_ALL_ACCESS, 0, 0, size));
renderer->ready_ = CreateEventW(nullptr, FALSE, FALSE, (name + protocol::readyEventSuffix).c_str());
renderer->consumed_ = CreateEventW(nullptr, FALSE, TRUE, (name + protocol::consumedEventSuffix).c_str());
if (renderer->channel_ == nullptr || renderer->ready_ == nullptr || renderer->consumed_ == nullptr) {
renderer->read_ = CreateEventW(nullptr, FALSE, FALSE, (name + protocol::readEventSuffix).c_str());
if (renderer->channel_ == nullptr || renderer->ready_ == nullptr || renderer->consumed_ == nullptr
|| renderer->read_ == nullptr) {
log::info("renderer process: can't set up the channel: error {}", GetLastError());
return nullptr;
}
@@ -86,7 +88,7 @@ std::unique_ptr<RendererProcess> RendererProcess::start(HWND window, protocol::V
.chunkSize = 0,
.chunkFlags = 0,
.covering = 0,
.reserved = 0};
.readSize = 0};
// The renderer's window goes on top of the client's 3D view, as a child window. The client's window mustn't clip
// its children (WS_CLIPCHILDREN, which the client creates it with): the client draws a frame when its window gets
@@ -117,7 +119,7 @@ RendererProcess::~RendererProcess()
}
UnmapViewOfFile(channel_);
}
for (HANDLE handle : {ready_, consumed_, mapping_, process_}) {
for (HANDLE handle : {ready_, consumed_, read_, mapping_, process_}) {
if (handle != nullptr) {
CloseHandle(handle);
}
@@ -150,4 +152,20 @@ bool RendererProcess::send(std::span<const std::byte> commands, bool endsFrame)
return true;
}
std::span<const std::byte> RendererProcess::readBack()
{
if (!alive_) {
return {};
}
const HANDLE waits[] = {read_, process_};
const DWORD result = WaitForMultipleObjects(2, waits, FALSE, consumeTimeout);
if (result != WAIT_OBJECT_0) {
log::info("renderer process: {} reading back a frame; giving up on it",
result == WAIT_OBJECT_0 + 1 ? "exited" : "not responding");
alive_ = false;
return {};
}
return {data_, std::min<std::size_t>(channel_->readSize, channel_->capacity)};
}
} // namespace t5de