void CanvasLayerOGL::Initialize(const Data& aData) { NS_ASSERTION(mCanvasSurface == nullptr, "BasicCanvasLayer::Initialize called twice!"); if (aData.mGLContext != nullptr && aData.mSurface != nullptr) { NS_WARNING("CanvasLayerOGL can't have both surface and WebGLContext"); return; } mOGLManager->MakeCurrent(); if (aData.mDrawTarget && aData.mDrawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT_ACCELERATED)) { mDrawTarget = aData.mDrawTarget; mNeedsYFlip = false; mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); return; } else if (aData.mDrawTarget) { mDrawTarget = aData.mDrawTarget; mCanvasSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget); mNeedsYFlip = false; } else if (aData.mSurface) { mCanvasSurface = aData.mSurface; mNeedsYFlip = false; #if defined(GL_PROVIDER_GLX) if (aData.mSurface->GetType() == gfxASurface::SurfaceTypeXlib) { gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(aData.mSurface); mPixmap = xsurf->GetGLXPixmap(); if (mPixmap) { mLayerProgram = ShaderProgramFromContentType(aData.mSurface->GetContentType()); MakeTextureIfNeeded(gl(), mUploadTexture); } } #endif } else if (aData.mGLContext) { mGLContext = aData.mGLContext; NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); mIsGLAlphaPremult = aData.mIsGLAlphaPremult; mNeedsYFlip = true; // [OGL Layers, MTC] WebGL layer init. GLScreenBuffer* screen = mGLContext->Screen(); SurfaceStreamType streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, screen->PreserveBuffer()); SurfaceFactory_GL* factory = nullptr; if (!mForceReadback) { factory = new SurfaceFactory_GLTexture(mGLContext, gl(), screen->Caps()); } if (factory) { screen->Morph(factory, streamType); } } else { NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!"); return; } mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); // Check the maximum texture size supported by GL. glTexImage2D supports // images of up to 2 + GL_MAX_TEXTURE_SIZE GLint texSize = 0; gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &texSize); MOZ_ASSERT(texSize != 0); if (mBounds.width > (2 + texSize) || mBounds.height > (2 + texSize)) { mDelayedUpdates = true; MakeTextureIfNeeded(gl(), mUploadTexture); // This should only ever occur with 2d canvas, WebGL can't already have a texture // of this size can it? NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "Invalid texture size when WebGL surface already exists at that size?"); } }
void ClientCanvasLayer::Initialize(const Data& aData) { CopyableCanvasLayer::Initialize(aData); mCanvasClient = nullptr; if (mGLContext) { GLScreenBuffer* screen = mGLContext->Screen(); SurfaceCaps caps; if (mStream) { // The screen caps are irrelevant if we're using a separate stream caps = aData.mHasAlpha ? SurfaceCaps::ForRGBA() : SurfaceCaps::ForRGB(); } else { caps = screen->mCaps; } MOZ_ASSERT(caps.alpha == aData.mHasAlpha); SurfaceStreamType streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread, screen->PreserveBuffer()); UniquePtr<SurfaceFactory> factory; if (!gfxPrefs::WebGLForceLayersReadback()) { switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) { case mozilla::layers::LayersBackend::LAYERS_OPENGL: { if (mGLContext->GetContextType() == GLContextType::EGL) { #ifdef MOZ_WIDGET_GONK factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, ClientManager()->AsShadowForwarder()); #else bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); if (!isCrossProcess) { // [Basic/OGL Layers, OMTC] WebGL layer init. factory = SurfaceFactory_EGLImage::Create(mGLContext, caps); } else { // we could do readback here maybe NS_NOTREACHED("isCrossProcess but not on native B2G!"); } #endif } else { // [Basic Layers, OMTC] WebGL layer init. // Well, this *should* work... #ifdef XP_MACOSX factory = SurfaceFactory_IOSurface::Create(mGLContext, caps); #else GLContext* nullConsGL = nullptr; // Bug 1050044. factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps); #endif } break; } case mozilla::layers::LayersBackend::LAYERS_D3D10: case mozilla::layers::LayersBackend::LAYERS_D3D11: { #ifdef XP_WIN if (mGLContext->IsANGLE()) { factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps); } #endif break; } default: break; } } if (mStream) { // We're using a stream other than the one in the default screen mFactory = Move(factory); if (!mFactory) { // Absolutely must have a factory here, so create a basic one mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps); } gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height); mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext, mGLContext->GetGLFormats(), size, caps.alpha, aData.mTexID); SharedSurface* producer = mStream->SwapProducer(mFactory.get(), size); if (!producer) { // Fallback to basic factory mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps); producer = mStream->SwapProducer(mFactory.get(), size); MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory"); } } else if (factory) { screen->Morph(Move(factory), streamType); } } }
void CanvasLayerD3D10::Initialize(const Data& aData) { NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!"); if (aData.mGLContext) { mGLContext = aData.mGLContext; NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); mDataIsPremultiplied = aData.mIsGLAlphaPremult; mNeedsYFlip = true; GLScreenBuffer* screen = mGLContext->Screen(); SurfaceStreamType streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, screen->PreserveBuffer()); SurfaceFactory_GL* factory = nullptr; if (!gfxPrefs::WebGLForceLayersReadback()) { if (mGLContext->IsANGLE()) { factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, device(), screen->Caps()); } } if (factory) { screen->Morph(factory, streamType); } } else if (aData.mDrawTarget) { mDrawTarget = aData.mDrawTarget; mNeedsYFlip = false; mDataIsPremultiplied = true; void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE); if (texture) { mTexture = static_cast<ID3D10Texture2D*>(texture); NS_ASSERTION(!aData.mGLContext, "CanvasLayer can't have both DrawTarget and WebGLContext/Surface"); mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView)); return; } // XXX we should store mDrawTarget and use it directly in UpdateSurface, // bypassing Thebes mSurface = mDrawTarget->Snapshot(); } else { NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); } mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); mIsD2DTexture = false; // Create a texture in case we need to readback. CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1); desc.Usage = D3D10_USAGE_DYNAMIC; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture)); if (FAILED(hr)) { NS_WARNING("Failed to create texture for CanvasLayer!"); return; } device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mUploadSRView)); }
void ClientCanvasLayer::Initialize(const Data& aData) { CopyableCanvasLayer::Initialize(aData); mCanvasClient = nullptr; if (mGLContext) { GLScreenBuffer* screen = mGLContext->Screen(); SurfaceCaps caps = screen->Caps(); if (mStream) { // The screen caps are irrelevant if we're using a separate stream caps = GetContentFlags() & CONTENT_OPAQUE ? SurfaceCaps::ForRGB() : SurfaceCaps::ForRGBA(); } SurfaceStreamType streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread, screen->PreserveBuffer()); SurfaceFactory_GL* factory = nullptr; if (!gfxPrefs::WebGLForceLayersReadback()) { if (ClientManager()->AsShadowForwarder()->GetCompositorBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) { if (mGLContext->GetContextType() == GLContextType::EGL) { bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); if (!isCrossProcess) { // [Basic/OGL Layers, OMTC] WebGL layer init. factory = SurfaceFactory_EGLImage::Create(mGLContext, caps); } else { // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing) #ifdef MOZ_WIDGET_GONK factory = new SurfaceFactory_Gralloc(mGLContext, caps, ClientManager()->AsShadowForwarder()); #else // we could do readback here maybe NS_NOTREACHED("isCrossProcess but not on native B2G!"); #endif } } else { // [Basic Layers, OMTC] WebGL layer init. // Well, this *should* work... #ifdef XP_MACOSX factory = new SurfaceFactory_IOSurface(mGLContext, caps); #else factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, caps); #endif } } } if (mStream) { // We're using a stream other than the one in the default screen mFactory = factory; if (!mFactory) { // Absolutely must have a factory here, so create a basic one mFactory = new SurfaceFactory_Basic(mGLContext, caps); } gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height); mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext, mGLContext->GetGLFormats(), size, caps.alpha, aData.mTexID); SharedSurface* producer = mStream->SwapProducer(mFactory, size); if (!producer) { // Fallback to basic factory delete mFactory; mFactory = new SurfaceFactory_Basic(mGLContext, caps); producer = mStream->SwapProducer(mFactory, size); MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory"); } } else if (factory) { screen->Morph(factory, streamType); } } }