void
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);
 
  mCanvasClient = nullptr;

  if (mGLContext) {
    GLScreenBuffer* screen = mGLContext->Screen();
    SurfaceStreamType streamType =
        SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
                                          screen->PreserveBuffer());
    SurfaceFactory_GL* factory = nullptr;
    if (!mForceReadback) {
      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, screen->Caps());
          } else {
            // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
#ifdef MOZ_WIDGET_GONK
            factory = new SurfaceFactory_Gralloc(mGLContext, screen->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, screen->Caps());
#else
          factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps());
#endif
        }
      }
    }

    if (factory) {
      screen->Morph(factory, streamType);
    }
  }
}
void
ClientCanvasLayer::Initialize(const Data& aData)
{
    CopyableCanvasLayer::Initialize(aData);

    mCanvasClient = nullptr;

    if (!mGLContext)
        return;

    GLScreenBuffer* screen = mGLContext->Screen();

    SurfaceCaps caps;
    if (mGLFrontbuffer) {
        // The screen caps are irrelevant if we're using a separate frontbuffer.
        caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
               : SurfaceCaps::ForRGB();
    } else {
        MOZ_ASSERT(screen);
        caps = screen->mCaps;
    }
    MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

    auto forwarder = ClientManager()->AsShadowForwarder();

    mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
    if (!aData.mIsGLAlphaPremult) {
        mFlags |= TextureFlags::NON_PREMULTIPLIED;
    }

    UniquePtr<SurfaceFactory> factory = GLScreenBuffer::CreateFactory(mGLContext, caps, forwarder, mFlags);

    if (mGLFrontbuffer) {
        // We're using a source other than the one in the default screen.
        // (SkiaGL)
        mFactory = Move(factory);
        if (!mFactory) {
            // Absolutely must have a factory here, so create a basic one
            mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
        }
    } else {
        if (factory)
            screen->Morph(Move(factory));
    }
}
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)
    return;

  GLScreenBuffer* screen = mGLContext->Screen();

  SurfaceCaps caps;
  if (mGLFrontbuffer) {
    // The screen caps are irrelevant if we're using a separate frontbuffer.
    caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
                                     : SurfaceCaps::ForRGB();
  } else {
    MOZ_ASSERT(screen);
    caps = screen->mCaps;
  }
  MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

  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
          TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT |
                               TextureFlags::ORIGIN_BOTTOM_LEFT;
          if (!aData.mIsGLAlphaPremult) {
            flags |= TextureFlags::NON_PREMULTIPLIED;
          }
          factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
                                                       caps,
                                                       flags,
                                                       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_D3D11: {
#ifdef XP_WIN
        if (mGLContext->IsANGLE() && DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device())) {
          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
        }
#endif
        break;
      }
      default:
        break;
    }
  }

  if (mGLFrontbuffer) {
    // We're using a source other than the one in the default screen.
    // (SkiaGL)
    mFactory = Move(factory);
    if (!mFactory) {
      // Absolutely must have a factory here, so create a basic one
      mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
    }
  } else {
    if (factory)
      screen->Morph(Move(factory));
  }
}
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;
    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
ClientCanvasLayer::Initialize(const Data& aData)
{
  CopyableCanvasLayer::Initialize(aData);

  mCanvasClient = nullptr;

  if (!mGLContext)
    return;

  GLScreenBuffer* screen = mGLContext->Screen();

  SurfaceCaps caps;
  if (mGLFrontbuffer) {
    // The screen caps are irrelevant if we're using a separate frontbuffer.
    caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
                                     : SurfaceCaps::ForRGB();
  } else {
    MOZ_ASSERT(screen);
    caps = screen->mCaps;
  }
  MOZ_ASSERT(caps.alpha == aData.mHasAlpha);

  auto forwarder = ClientManager()->AsShadowForwarder();

  mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
  if (!aData.mIsGLAlphaPremult) {
    mFlags |= TextureFlags::NON_PREMULTIPLIED;
  }

  UniquePtr<SurfaceFactory> factory;

  if (!gfxPrefs::WebGLForceLayersReadback()) {
    switch (forwarder->GetCompositorBackendType()) {
      case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
        factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
#elif defined(MOZ_WIDGET_GONK)
        factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
#else
        if (mGLContext->GetContextType() == GLContextType::EGL) {
          bool isCrossProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
          if (!isCrossProcess) {
            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
                                                      mFlags);
          }
        }
#endif
        break;
      }
      case mozilla::layers::LayersBackend::LAYERS_D3D11: {
#ifdef XP_WIN
        if (mGLContext->IsANGLE() &&
            DoesD3D11TextureSharingWork(gfxWindowsPlatform::GetPlatform()->GetD3D11Device()))
        {
          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps, forwarder,
                                                            mFlags);
        }
#endif
        break;
      }
      default:
        break;
    }
  }

  if (mGLFrontbuffer) {
    // We're using a source other than the one in the default screen.
    // (SkiaGL)
    mFactory = Move(factory);
    if (!mFactory) {
      // Absolutely must have a factory here, so create a basic one
      mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
    }
  } else {
    if (factory)
      screen->Morph(Move(factory));
  }
}
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);
    }
  }
}