Files
workinf_Blender_Wasm/blender-5.2.0/intern/ghost/intern/GHOST_ContextWeb.cc
mes123456 f3e21c6b98
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-10 11:18:01 +08:00

100 lines
3.0 KiB
C++

/* SPDX-FileCopyrightText: 2026 Blender Authors
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "GHOST_ContextWeb.hh"
#include <GLES2/gl2.h>
#include <emscripten.h>
GHOST_ContextWeb::GHOST_ContextWeb(const GHOST_ContextParams &params, const char *selector)
: GHOST_Context(params), selector_(selector)
{
}
GHOST_ContextWeb::~GHOST_ContextWeb()
{
if (handle_ > 0) {
if (active_context_ == this) releaseDrawingContext();
emscripten_webgl_destroy_context(handle_);
}
EM_ASM({ delete GL.offscreenCanvases[UTF8ToString($0).slice(1)]; }, selector_.c_str());
}
GHOST_TSuccess GHOST_ContextWeb::initializeDrawingContext()
{
if (handle_ > 0) return activateDrawingContext();
EM_ASM({ GL.offscreenCanvases[UTF8ToString($0).slice(1)] = Module['canvas']; }, selector_.c_str());
EmscriptenWebGLContextAttributes attributes;
emscripten_webgl_init_context_attributes(&attributes);
attributes.alpha = EM_FALSE;
attributes.depth = EM_TRUE;
attributes.stencil = EM_TRUE;
attributes.antialias = EM_FALSE;
/* File-save thumbnails read the last native window contents without drawing
* again (drawing can mutate Main during save). Keep those pixels available
* after OffscreenCanvas presentation and the worker event-loop yield. */
attributes.preserveDrawingBuffer = EM_TRUE;
attributes.majorVersion = 2;
attributes.enableExtensionsByDefault = EM_TRUE;
/* OffscreenCanvas presents when the owning worker yields to its event loop. */
attributes.explicitSwapControl = EM_FALSE;
handle_ = emscripten_webgl_create_context(selector_.c_str(), &attributes);
return activateDrawingContext();
}
GHOST_TSuccess GHOST_ContextWeb::activateDrawingContext()
{
if (handle_ <= 0 || emscripten_is_webgl_context_lost(handle_) ||
emscripten_webgl_make_context_current(handle_) != EMSCRIPTEN_RESULT_SUCCESS)
{
return GHOST_kFailure;
}
active_context_ = this;
return GHOST_kSuccess;
}
bool GHOST_ContextWeb::isContextLost() const
{
return handle_ > 0 && emscripten_is_webgl_context_lost(handle_);
}
GHOST_TSuccess GHOST_ContextWeb::releaseDrawingContext()
{
if (active_context_ != this) return GHOST_kSuccess;
if (emscripten_webgl_make_context_current(0) != EMSCRIPTEN_RESULT_SUCCESS) return GHOST_kFailure;
active_context_ = nullptr;
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextWeb::updateDrawingContext()
{
return activateDrawingContext();
}
GHOST_TSuccess GHOST_ContextWeb::releaseNativeHandles()
{
/* The canvas must remain alive until the context is destroyed. */
return GHOST_kFailure;
}
GHOST_TSuccess GHOST_ContextWeb::swapBufferAcquire()
{
return activateDrawingContext();
}
GHOST_TSuccess GHOST_ContextWeb::swapBufferRelease()
{
if (!activateDrawingContext()) return GHOST_kFailure;
glFlush();
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_ContextWeb::setSwapInterval(int interval)
{
return interval == 1 ? GHOST_kSuccess : GHOST_kFailure;
}
GHOST_TSuccess GHOST_ContextWeb::getSwapInterval(int &interval)
{
interval = 1;
return GHOST_kSuccess;
}