Skip to content

Commit

Permalink
Bug 1614499 - Implement XRWebGLLayer r=jgilbert,daoshengmu
Browse files Browse the repository at this point in the history
Differential Revision: https://phabricator.services.mozilla.com/D62809

--HG--
extra : moz-landing-system : lando
  • Loading branch information
MortimerGoro committed Apr 7, 2020
1 parent 5a44b5d commit 9035f18
Show file tree
Hide file tree
Showing 27 changed files with 517 additions and 110 deletions.
52 changes: 46 additions & 6 deletions dom/canvas/ClientWebGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,9 +459,9 @@ void ClientWebGLContext::Present() { Run<RPROC(Present)>(); }

void ClientWebGLContext::ClearVRFrame() const { Run<RPROC(ClearVRFrame)>(); }

RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame()
const {
return Run<RPROC(GetVRFrame)>();
RefPtr<layers::SharedSurfaceTextureClient> ClientWebGLContext::GetVRFrame(
const WebGLFramebufferJS* fb) const {
return Run<RPROC(GetVRFrame)>(fb ? fb->mId : 0);
}

already_AddRefed<layers::Layer> ClientWebGLContext::GetCanvasLayer(
Expand Down Expand Up @@ -1052,6 +1052,19 @@ already_AddRefed<WebGLFramebufferJS> ClientWebGLContext::CreateFramebuffer()
return ret.forget();
}

already_AddRefed<WebGLFramebufferJS>
ClientWebGLContext::CreateOpaqueFramebuffer(
const webgl::OpaqueFramebufferOptions& options) const {
const FuncScope funcScope(*this, "createOpaqueFramebuffer");
if (IsContextLost()) return nullptr;

auto ret = AsRefPtr(new WebGLFramebufferJS(*this, true));
if (!Run<RPROC(CreateOpaqueFramebuffer)>(ret->mId, options)) {
return nullptr;
}
return ret.forget();
}

already_AddRefed<WebGLProgramJS> ClientWebGLContext::CreateProgram() const {
const FuncScope funcScope(*this, "createProgram");
if (IsContextLost()) return nullptr;
Expand Down Expand Up @@ -1228,10 +1241,17 @@ void ClientWebGLContext::DeleteBuffer(WebGLBufferJS* const obj) {
Run<RPROC(DeleteBuffer)>(obj->mId);
}

void ClientWebGLContext::DeleteFramebuffer(WebGLFramebufferJS* const obj) {
void ClientWebGLContext::DeleteFramebuffer(WebGLFramebufferJS* const obj,
bool canDeleteOpaque) {
const FuncScope funcScope(*this, "deleteFramebuffer");
if (IsContextLost()) return;
if (!ValidateOrSkipForDelete(*this, obj)) return;
if (!canDeleteOpaque && obj->mOpaque) {
EnqueueError(
LOCAL_GL_INVALID_OPERATION,
"An opaque framebuffer's attachments cannot be inspected or changed.");
return;
}
const auto& state = State();

// Unbind
Expand Down Expand Up @@ -2033,6 +2053,12 @@ void ClientWebGLContext::GetFramebufferAttachmentParameter(
}

if (fb) {
if (fb->mOpaque) {
EnqueueError(LOCAL_GL_INVALID_OPERATION,
"An opaque framebuffer's attachments cannot be inspected or "
"changed.");
return;
}
auto attachmentSlotEnum = attachment;
if (mIsWebGL2 && attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
// In webgl2, DEPTH_STENCIL is valid iff the DEPTH and STENCIL images
Expand Down Expand Up @@ -3022,6 +3048,13 @@ void ClientWebGLContext::FramebufferAttach(
return;
}

if (fb->mOpaque) {
EnqueueError(
LOCAL_GL_INVALID_OPERATION,
"An opaque framebuffer's attachments cannot be inspected or changed.");
return;
}

// -
// Multiview-specific validation skipped by Host.

Expand Down Expand Up @@ -4467,6 +4500,12 @@ void ClientWebGLContext::ResumeTransformFeedback() {
Run<RPROC(ResumeTransformFeedback)>();
}

void ClientWebGLContext::SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS* fb,
bool value) {
fb->mInOpaqueRAF = value;
Run<RPROC(SetFramebufferIsInOpaqueRAF)>(fb->mId, value);
}

// ---------------------------- Misc Extensions ----------------------------
void ClientWebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers) {
const auto range = MakeRange(buffers);
Expand Down Expand Up @@ -5325,8 +5364,9 @@ webgl::ObjectJS::ObjectJS(const ClientWebGLContext& webgl)

// -

WebGLFramebufferJS::WebGLFramebufferJS(const ClientWebGLContext& webgl)
: webgl::ObjectJS(webgl) {
WebGLFramebufferJS::WebGLFramebufferJS(const ClientWebGLContext& webgl,
bool opaque)
: webgl::ObjectJS(webgl), mOpaque(opaque) {
(void)mAttachments[LOCAL_GL_DEPTH_ATTACHMENT];
(void)mAttachments[LOCAL_GL_STENCIL_ATTACHMENT];
if (!webgl.mIsWebGL2) {
Expand Down
16 changes: 13 additions & 3 deletions dom/canvas/ClientWebGLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ class WebGLFramebufferJS final : public nsWrapperCache, public webgl::ObjectJS {
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebufferJS)

explicit WebGLFramebufferJS(const ClientWebGLContext&);
explicit WebGLFramebufferJS(const ClientWebGLContext&, bool opaque = false);

const bool mOpaque;
bool mInOpaqueRAF = false;

private:
~WebGLFramebufferJS() = default;
Expand Down Expand Up @@ -990,7 +993,8 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,

void Present();

RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame() const;
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame(
const WebGLFramebufferJS*) const;
void ClearVRFrame() const;

private:
Expand Down Expand Up @@ -1048,6 +1052,8 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,

already_AddRefed<WebGLBufferJS> CreateBuffer() const;
already_AddRefed<WebGLFramebufferJS> CreateFramebuffer() const;
already_AddRefed<WebGLFramebufferJS> CreateOpaqueFramebuffer(
const webgl::OpaqueFramebufferOptions&) const;
already_AddRefed<WebGLProgramJS> CreateProgram() const;
already_AddRefed<WebGLQueryJS> CreateQuery() const;
already_AddRefed<WebGLRenderbufferJS> CreateRenderbuffer() const;
Expand All @@ -1060,7 +1066,7 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
already_AddRefed<WebGLVertexArrayJS> CreateVertexArray() const;

void DeleteBuffer(WebGLBufferJS*);
void DeleteFramebuffer(WebGLFramebufferJS*);
void DeleteFramebuffer(WebGLFramebufferJS*, bool canDeleteOpaque = false);
void DeleteProgram(WebGLProgramJS*) const;
void DeleteQuery(WebGLQueryJS*);
void DeleteRenderbuffer(WebGLRenderbufferJS*);
Expand Down Expand Up @@ -2020,6 +2026,10 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
void PauseTransformFeedback();
void ResumeTransformFeedback();

// -------------------------- Opaque Framebuffers ---------------------------

void SetFramebufferIsInOpaqueRAF(WebGLFramebufferJS*, bool);

// ------------------------------ Extensions ------------------------------
public:
void GetSupportedExtensions(dom::Nullable<nsTArray<nsString>>& retval,
Expand Down
18 changes: 15 additions & 3 deletions dom/canvas/HostWebGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/TextureClientSharedSurface.h"

#include "MozFramebuffer.h"
#include "TexUnpackBlob.h"
#include "WebGL2Context.h"
#include "WebGLBuffer.h"
Expand Down Expand Up @@ -100,9 +101,9 @@ void HostWebGLContext::JsWarning(const std::string& text) const {
(void)mOwnerData.outOfProcess->mParent.SendJsWarning(text);
}

RefPtr<layers::SharedSurfaceTextureClient> HostWebGLContext::GetVRFrame()
const {
return mContext->GetVRFrame();
RefPtr<layers::SharedSurfaceTextureClient> HostWebGLContext::GetVRFrame(
ObjectId id) const {
return mContext->GetVRFrame(AutoResolve(id));
}

//////////////////////////////////////////////
Expand All @@ -126,6 +127,17 @@ void HostWebGLContext::CreateFramebuffer(const ObjectId id) {
slot = mContext->CreateFramebuffer();
}

bool HostWebGLContext::CreateOpaqueFramebuffer(
const ObjectId id, const webgl::OpaqueFramebufferOptions& options) {
auto& slot = mFramebufferMap[id];
if (slot) {
MOZ_ASSERT(false, "duplicate ID");
return false;
}
slot = mContext->CreateOpaqueFramebuffer(options);
return slot;
}

void HostWebGLContext::CreateProgram(const ObjectId id) {
auto& slot = mProgramMap[id];
if (slot) {
Expand Down
12 changes: 11 additions & 1 deletion dom/canvas/HostWebGLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {

void CreateBuffer(ObjectId);
void CreateFramebuffer(ObjectId);
bool CreateOpaqueFramebuffer(ObjectId,
const webgl::OpaqueFramebufferOptions& options);
void CreateProgram(ObjectId);
void CreateQuery(ObjectId);
void CreateRenderbuffer(ObjectId);
Expand Down Expand Up @@ -716,6 +718,14 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
GetWebGL2Context()->TransformFeedbackVaryings(*obj, varyings, bufferMode);
}

// -------------------------- Opaque Framebuffers ---------------------------
void SetFramebufferIsInOpaqueRAF(ObjectId id, bool value) {
WebGLFramebuffer* fb = AutoResolve(id);
if (fb) {
fb->mInOpaqueRAF = value;
}
}

// -------------------------------------------------------------------------
// Host-side extension methods. Calls in the client are forwarded to the
// host. Some extension methods are also available in WebGL2 Contexts. For
Expand Down Expand Up @@ -774,7 +784,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {

// Etc
public:
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame() const;
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame(ObjectId id) const;

protected:
WebGL2Context* GetWebGL2Context() const {
Expand Down
82 changes: 67 additions & 15 deletions dom/canvas/WebGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,33 +885,34 @@ void WebGLContext::OnEndOfFrame() {
BumpLru();
}

void WebGLContext::BlitBackbufferToCurDriverFB() const {
void WebGLContext::BlitBackbufferToCurDriverFB(
const gl::MozFramebuffer* const source) const {
DoColorMask(0x0f);

if (mScissorTestEnabled) {
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
}

[&]() {
const auto& size = mDefaultFB->mSize;
const auto fb = source ? source : mDefaultFB.get();

if (gl->IsSupported(gl::GLFeature::framebuffer_blit)) {
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, mDefaultFB->mFB);
gl->fBlitFramebuffer(0, 0, size.width, size.height, 0, 0, size.width,
size.height, LOCAL_GL_COLOR_BUFFER_BIT,
LOCAL_GL_NEAREST);
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fb->mFB);
gl->fBlitFramebuffer(0, 0, fb->mSize.width, fb->mSize.height, 0, 0,
fb->mSize.width, fb->mSize.height,
LOCAL_GL_COLOR_BUFFER_BIT, LOCAL_GL_NEAREST);
return;
}
if (mDefaultFB->mSamples &&
gl->IsExtensionSupported(
gl::GLContext::APPLE_framebuffer_multisample)) {
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, mDefaultFB->mFB);
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fb->mFB);
gl->fResolveMultisampleFramebufferAPPLE();
return;
}

gl->BlitHelper()->DrawBlitTextureToFramebuffer(mDefaultFB->ColorTex(), size,
size);
gl->BlitHelper()->DrawBlitTextureToFramebuffer(fb->ColorTex(), fb->mSize,
fb->mSize);
}();

if (mScissorTestEnabled) {
Expand Down Expand Up @@ -988,9 +989,10 @@ bool WebGLContext::PresentScreenBuffer(gl::GLScreenBuffer* const targetScreen) {
if (!ValidateAndInitFB(nullptr)) return false;

const auto& screen = targetScreen ? targetScreen : gl->Screen();
if ((!screen->IsReadBufferReady() || mForceResizeOnPresent ||
screen->Size() != mDefaultFB->mSize) &&
!screen->Resize(mDefaultFB->mSize)) {
bool needsResize = mForceResizeOnPresent;
needsResize |=
!screen->IsReadBufferReady() || (screen->Size() != mDefaultFB->mSize);
if (needsResize && !screen->Resize(mDefaultFB->mSize)) {
GenerateWarning("screen->Resize failed. Losing context.");
LoseContext();
return false;
Expand Down Expand Up @@ -1033,6 +1035,48 @@ bool WebGLContext::PresentScreenBuffer(gl::GLScreenBuffer* const targetScreen) {
return true;
}

bool WebGLContext::PresentScreenBufferVR(
gl::GLScreenBuffer* const aTargetScreen,
const gl::MozFramebuffer* const fb) {
const FuncScope funcScope(*this, "<PresentScreenBufferVR>");
if (IsContextLost()) {
return false;
}

if (!fb) {
// WebVR fallback
return PresentScreenBuffer(aTargetScreen);
}

mDrawCallsSinceLastFlush = 0;

const auto& screen = aTargetScreen ? aTargetScreen : gl->Screen();
bool needsResize = mForceResizeOnPresent;
needsResize |= !screen->IsReadBufferReady() || (screen->Size() != fb->mSize);
if (needsResize && !screen->Resize(fb->mSize)) {
GenerateWarning("screen->Resize failed. Losing context.");
LoseContext();
return false;
}

mForceResizeOnPresent = false;

gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
BlitBackbufferToCurDriverFB(fb);

if (!screen->PublishFrame(screen->Size())) {
GenerateWarning("PublishFrame failed. Losing context.");
LoseContext();
return false;
}

mResolvedDefaultFB = nullptr;

OnEndOfFrame();

return true;
}

RefPtr<gfx::DataSourceSurface> GetTempSurface(const gfx::IntSize& aSize,
gfx::SurfaceFormat& aFormat) {
uint32_t stride =
Expand Down Expand Up @@ -1602,15 +1646,23 @@ void WebGLContext::ClearVRFrame() {
#endif
}

RefPtr<layers::SharedSurfaceTextureClient> WebGLContext::GetVRFrame() {
RefPtr<layers::SharedSurfaceTextureClient> WebGLContext::GetVRFrame(
WebGLFramebuffer* fb) {
if (!gl) return nullptr;

EnsureVRReady();
const gl::MozFramebuffer* maybeFB = nullptr;
if (fb) {
maybeFB = fb->mOpaque.get();
MOZ_ASSERT(maybeFB);
}

UniquePtr<gl::GLScreenBuffer>* maybeVrScreen = nullptr;
#if defined(MOZ_WIDGET_ANDROID)
maybeVrScreen = &mVRScreen;
#endif
RefPtr<layers::SharedSurfaceTextureClient> sharedSurface;

if (maybeVrScreen) {
auto& vrScreen = *maybeVrScreen;
// Create a custom GLScreenBuffer for VR.
Expand All @@ -1632,7 +1684,7 @@ RefPtr<layers::SharedSurfaceTextureClient> WebGLContext::GetVRFrame() {
// Swap buffers as though composition has occurred.
// We will then share the resulting front buffer to be submitted to the VR
// compositor.
PresentScreenBuffer(vrScreen.get());
PresentScreenBufferVR(vrScreen.get(), maybeFB);

if (IsContextLost()) return nullptr;

Expand All @@ -1652,7 +1704,7 @@ RefPtr<layers::SharedSurfaceTextureClient> WebGLContext::GetVRFrame() {
* We will then share the resulting front buffer to be submitted to the VR
* compositor.
*/
PresentScreenBuffer();
PresentScreenBufferVR(nullptr, maybeFB);

gl::GLScreenBuffer* screen = gl->Screen();
if (!screen) return nullptr;
Expand Down
Loading

0 comments on commit 9035f18

Please sign in to comment.