void GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) { // This happens during the layers transaction. // All of the gralloc magic goes here. The only thing that happens externally // and that is good to keep in mind is that when the TextureSource is deleted, // it destroys its gl texture handle which is important for genlock. // If this TextureHost's mGLTextureSource member is non-null, it means we are // still bound to the TextureSource, in which case we can skip the driver // overhead of binding the texture again (fEGLImageTargetTexture2D) // As a result, if the TextureHost is used with several CompositableHosts, // it will be bound to only one TextureSource, and we'll do the driver work // only once, which is great. This means that all of the compositables that // use this TextureHost will keep a reference to this TextureSource at least // for the duration of this frame. // If the compositable already has a TextureSource (the aTextureSource parameter), // that is compatible and is not in use by several compositable, we try to // attach to it. This has the effect of unlocking the previous TextureHost that // we attached to the TextureSource (the previous frame) // If the TextureSource used by the compositable is also used by other // compositables (see NumCompositableRefs), we have to create a new TextureSource, // because otherwise we would be modifying the content of every layer that uses // the TextureSource in question, even thoug they don't use this TextureHost. MOZ_ASSERT(!mTilingTextureSource); android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); MOZ_ASSERT(graphicBuffer); if (!graphicBuffer) { mGLTextureSource = nullptr; return; } if (mGLTextureSource && !mGLTextureSource->IsValid()) { mGLTextureSource = nullptr; } if (mGLTextureSource) { // We are already attached to a TextureSource, nothing to do except tell // the compositable to use it. aTextureSource = mGLTextureSource.get(); return; } gl::GLContext* gl = GetGLContext(); if (!gl || !gl->MakeCurrent()) { mGLTextureSource = nullptr; return; } if (mEGLImage == EGL_NO_IMAGE) { // Should only happen the first time. mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer()); } GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat()); GLTextureSource* glSource = aTextureSource.get() ? aTextureSource->AsSourceOGL()->AsGLTextureSource() : nullptr; bool shouldCreateTextureSource = !glSource || !glSource->IsValid() || glSource->NumCompositableRefs() > 1 || glSource->GetTextureTarget() != textureTarget; if (shouldCreateTextureSource) { GLuint textureHandle; gl->fGenTextures(1, &textureHandle); gl->fBindTexture(textureTarget, textureHandle); gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage); mGLTextureSource = new GLTextureSource(mCompositor, textureHandle, textureTarget, mSize, mFormat); aTextureSource = mGLTextureSource.get(); } else { gl->fBindTexture(textureTarget, glSource->GetTextureHandle()); gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage); glSource->SetSize(mSize); glSource->SetFormat(mFormat); mGLTextureSource = glSource; } }
TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocator, const SurfaceDescriptorTiles& aDescriptor, const nsIntRegion& aOldPaintedRegion, Compositor* aCompositor) { mIsValid = true; mHasDoubleBufferedTiles = false; mValidRegion = aDescriptor.validRegion(); mPaintedRegion = aDescriptor.paintedRegion(); mRetainedWidth = aDescriptor.retainedWidth(); mRetainedHeight = aDescriptor.retainedHeight(); mResolution = aDescriptor.resolution(); mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution()); if (mResolution == 0 || IsNaN(mResolution)) { // There are divisions by mResolution so this protects the compositor process // against malicious content processes and fuzzing. mIsValid = false; return; } // Combine any valid content that wasn't already uploaded nsIntRegion oldPaintedRegion(aOldPaintedRegion); oldPaintedRegion.And(oldPaintedRegion, mValidRegion); mPaintedRegion.Or(mPaintedRegion, oldPaintedRegion); bool isSameProcess = aAllocator->IsSameProcess(); const InfallibleTArray<TileDescriptor>& tiles = aDescriptor.tiles(); for(size_t i = 0; i < tiles.Length(); i++) { CompositableTextureHostRef texture; CompositableTextureHostRef textureOnWhite; const TileDescriptor& tileDesc = tiles[i]; switch (tileDesc.type()) { case TileDescriptor::TTexturedTileDescriptor : { texture = TextureHost::AsTextureHost(tileDesc.get_TexturedTileDescriptor().textureParent()); MaybeTexture onWhite = tileDesc.get_TexturedTileDescriptor().textureOnWhite(); if (onWhite.type() == MaybeTexture::TPTextureParent) { textureOnWhite = TextureHost::AsTextureHost(onWhite.get_PTextureParent()); } const TileLock& ipcLock = tileDesc.get_TexturedTileDescriptor().sharedLock(); nsRefPtr<gfxSharedReadLock> sharedLock; if (ipcLock.type() == TileLock::TShmemSection) { sharedLock = gfxShmSharedReadLock::Open(aAllocator, ipcLock.get_ShmemSection()); } else { if (!isSameProcess) { // Trying to use a memory based lock instead of a shmem based one in // the cross-process case is a bad security violation. NS_ERROR("A client process may be trying to peek at the host's address space!"); // This tells the TiledContentHost that deserialization failed so that // it can propagate the error. mIsValid = false; mRetainedTiles.Clear(); return; } sharedLock = reinterpret_cast<gfxMemorySharedReadLock*>(ipcLock.get_uintptr_t()); if (sharedLock) { // The corresponding AddRef is in TiledClient::GetTileDescriptor sharedLock.get()->Release(); } } CompositableTextureSourceRef textureSource; CompositableTextureSourceRef textureSourceOnWhite; if (texture) { texture->SetCompositor(aCompositor); texture->PrepareTextureSource(textureSource); } if (textureOnWhite) { textureOnWhite->SetCompositor(aCompositor); textureOnWhite->PrepareTextureSource(textureSourceOnWhite); } mRetainedTiles.AppendElement(TileHost(sharedLock, texture.get(), textureOnWhite.get(), textureSource.get(), textureSourceOnWhite.get())); break; } default: NS_WARNING("Unrecognised tile descriptor type"); // Fall through case TileDescriptor::TPlaceholderTileDescriptor : mRetainedTiles.AppendElement(GetPlaceholderTile()); break; } if (texture && !texture->HasInternalBuffer()) { mHasDoubleBufferedTiles = true; } } }