void CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = screen->Stream(); bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); bool bufferCreated = false; if (isCrossProcess) { #ifdef MOZ_WIDGET_GONK SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); MOZ_ASSERT(false); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); GrallocTextureClientOGL* grallocTextureClient = static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient()); // If IPDLActor is null means this TextureClient didn't AddTextureClient yet if (!grallocTextureClient->GetIPDLActor()) { grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags); AddTextureClient(grallocTextureClient); } if (grallocTextureClient->GetIPDLActor()) { GetForwarder()->UseTexture(this, grallocTextureClient); } #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif } else { if (!mBuffer) { StreamTextureClientOGL* textureClient = new StreamTextureClientOGL(mTextureInfo.mTextureFlags); textureClient->InitWith(stream); mBuffer = textureClient; bufferCreated = true; } if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; } if (mBuffer) { GetForwarder()->UseTexture(this, mBuffer); } } aLayer->Painted(); }
void CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (!mTextureClient) { mTextureClient = CreateTextureClient(TEXTURE_STREAM_GL); MOZ_ASSERT(mTextureClient, "Failed to create texture client"); } NS_ASSERTION(aLayer->mGLContext, "CanvasClientSurfaceStream should only be used with GL canvases"); // the content type won't be used mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR); GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = screen->Stream(); bool isCrossProcess = !(XRE_GetProcessType() == GoannaProcessType_Default); if (isCrossProcess) { // swap staging -> consumer so we can send it to the compositor SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } #ifdef MOZ_WIDGET_GONK if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); mTextureClient->SetDescriptor(grallocSurf->GetDescriptor()); #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif mNeedsUpdate = true; } else { SurfaceStreamHandle handle = stream->GetShareHandle(); SurfaceDescriptor *desc = mTextureClient->GetDescriptor(); if (desc->type() != SurfaceDescriptor::TSurfaceStreamDescriptor || desc->get_SurfaceStreamDescriptor().handle() != handle) { *desc = SurfaceStreamDescriptor(handle, false); // Ref this so the SurfaceStream doesn't disappear unexpectedly. The // Compositor will need to unref it when finished. aLayer->mGLContext->AddRef(); mNeedsUpdate = true; } } aLayer->Painted(); }
void DeprecatedCanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (!mDeprecatedTextureClient) { mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_STREAM_GL, aLayer->GetSurfaceMode() == SurfaceMode::SURFACE_OPAQUE ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA); MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client"); } NS_ASSERTION(aLayer->mGLContext, "CanvasClientSurfaceStream should only be used with GL canvases"); // the content type won't be used mDeprecatedTextureClient->EnsureAllocated(aSize, gfxContentType::COLOR); GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = nullptr; if (aLayer->mStream) { stream = aLayer->mStream; stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory); stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height)); } else { stream = screen->Stream(); } bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); if (isCrossProcess) { // swap staging -> consumer so we can send it to the compositor SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } #ifdef MOZ_WIDGET_GONK if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); //XXX todo //mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor()); #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif } else { SurfaceStreamHandle handle = stream->GetShareHandle(); mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false)); // Bug 894405 // // Ref this so the SurfaceStream doesn't disappear unexpectedly. The // Compositor will need to unref it when finished. aLayer->mGLContext->AddRef(); } aLayer->Painted(); }
void CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { aLayer->mGLContext->MakeCurrent(); GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = nullptr; if (aLayer->mStream) { stream = aLayer->mStream; // Copy our current surface to the current producer surface in our stream, then // call SwapProducer to make a new buffer ready. stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory); stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height)); } else { stream = screen->Stream(); } bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); bool bufferCreated = false; if (isCrossProcess) { #ifdef MOZ_WIDGET_GONK SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); MOZ_ASSERT(false); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); RefPtr<GrallocTextureClientOGL> grallocTextureClient = static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient()); // If IPDLActor is null means this TextureClient didn't AddTextureClient yet if (!grallocTextureClient->GetIPDLActor()) { grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags); AddTextureClient(grallocTextureClient); } if (grallocTextureClient->GetIPDLActor()) { UseTexture(grallocTextureClient); } if (mBuffer && CompositorChild::ChildProcessHasCompositor()) { // remove old buffer from CompositableHost RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker(); // Hold TextureClient until transaction complete. tracker->SetTextureClient(mBuffer); mBuffer->SetRemoveFromCompositableTracker(tracker); // RemoveTextureFromCompositableAsync() expects CompositorChild's presence. GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mBuffer); } mBuffer = grallocTextureClient; #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif } else { if (!mBuffer) { StreamTextureClientOGL* textureClient = new StreamTextureClientOGL(mTextureInfo.mTextureFlags); textureClient->InitWith(stream); mBuffer = textureClient; bufferCreated = true; } if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; } if (mBuffer) { GetForwarder()->UseTexture(this, mBuffer); } } aLayer->Painted(); }
void ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset) { if (!mTexImage && !IsValidSharedTexDescriptor(mFrontBufferDescriptor) && !IsValidSurfaceStreamDescriptor(mFrontBufferDescriptor)) { return; } if (mOGLManager->CompositingDisabled()) { return; } mOGLManager->MakeCurrent(); gl()->EmptyTexGarbageBin(); //ScopedBindTexture autoTex(gl()); gfx3DMatrix effectiveTransform = GetEffectiveTransform(); gfxPattern::GraphicsFilter filter = mFilter; #ifdef ANDROID // Bug 691354 // Using the LINEAR filter we get unexplained artifacts. // Use NEAREST when no scaling is required. gfxMatrix matrix; bool is2D = GetEffectiveTransform().Is2D(&matrix); if (is2D && !matrix.HasNonTranslationOrFlip()) { filter = gfxPattern::FILTER_NEAREST; } #endif SurfaceStream* surfStream = nullptr; SharedSurface* sharedSurf = nullptr; if (IsValidSurfaceStreamDescriptor(mFrontBufferDescriptor)) { const SurfaceStreamDescriptor& streamDesc = mFrontBufferDescriptor.get_SurfaceStreamDescriptor(); surfStream = SurfaceStream::FromHandle(streamDesc.handle()); MOZ_ASSERT(surfStream); sharedSurf = surfStream->SwapConsumer(); if (!sharedSurf) { // We don't have a valid surf to show yet. return; } gfxImageSurface* toUpload = nullptr; switch (sharedSurf->Type()) { case SharedSurfaceType::GLTextureShare: { mCurTexture = SharedSurface_GLTexture::Cast(sharedSurf)->Texture(); MOZ_ASSERT(mCurTexture); mShaderType = sharedSurf->HasAlpha() ? RGBALayerProgramType : RGBXLayerProgramType; break; } case SharedSurfaceType::EGLImageShare: { SharedSurface_EGLImage* eglImageSurf = SharedSurface_EGLImage::Cast(sharedSurf); mCurTexture = eglImageSurf->AcquireConsumerTexture(gl()); if (!mCurTexture) { toUpload = eglImageSurf->GetPixels(); MOZ_ASSERT(toUpload); } else { mShaderType = sharedSurf->HasAlpha() ? RGBALayerProgramType : RGBXLayerProgramType; } break; } case SharedSurfaceType::Basic: { toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData(); MOZ_ASSERT(toUpload); break; } default: MOZ_NOT_REACHED("Invalid SharedSurface type."); return; } if (toUpload) { // mBounds seems to end up as (0,0,0,0) a lot, so don't use it? nsIntSize size(toUpload->GetSize()); nsIntRect rect(nsIntPoint(0,0), size); nsIntRegion bounds(rect); mShaderType = gl()->UploadSurfaceToTexture(toUpload, bounds, mUploadTexture, true); mCurTexture = mUploadTexture; } MOZ_ASSERT(mCurTexture); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mCurTexture); gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); } else if (mTexImage) { mShaderType = mTexImage->GetShaderProgramType(); } else { MOZ_NOT_REACHED("What can we do?"); return; } ShaderProgramOGL* program = mOGLManager->GetProgram(mShaderType, GetMaskLayer()); program->Activate(); program->SetLayerTransform(effectiveTransform); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); if (surfStream) { MOZ_ASSERT(sharedSurf); gl()->ApplyFilterToBoundTexture(filter); program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), sharedSurf->Size())); mOGLManager->BindAndDrawQuad(program, mNeedsYFlip); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, 0); } else { // Tiled texture image rendering path mTexImage->SetFilter(filter); mTexImage->BeginTileIteration(); if (gl()->CanUploadNonPowerOfTwo()) { do { TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0); program->SetLayerQuadRect(mTexImage->GetTileRect()); mOGLManager->BindAndDrawQuad(program, mNeedsYFlip); // FIXME flip order of tiles? } while (mTexImage->NextTile()); } else { do { TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0); program->SetLayerQuadRect(mTexImage->GetTileRect()); // We can't use BindAndDrawQuad because that always uploads the whole texture from 0.0f -> 1.0f // in x and y. We use BindAndDrawQuadWithTextureRect to actually draw a subrect of the texture // We need to reset the origin to 0,0 from the tile rect because the tile originates at 0,0 in the // actual texture, even though its origin in the composed (tiled) texture is not 0,0 // FIXME: we need to handle mNeedsYFlip, Bug #728625 mOGLManager->BindAndDrawQuadWithTextureRect(program, nsIntRect(0, 0, mTexImage->GetTileRect().width, mTexImage->GetTileRect().height), mTexImage->GetTileRect().Size(), mTexImage->GetWrapMode(), mNeedsYFlip); } while (mTexImage->NextTile()); } } }
bool SurfaceStreamHostOGL::Lock() { mGL->MakeCurrent(); SurfaceStream* surfStream = nullptr; SharedSurface* sharedSurf = nullptr; const SurfaceStreamDescriptor& streamDesc = mBuffer->get_SurfaceStreamDescriptor(); surfStream = SurfaceStream::FromHandle(streamDesc.handle()); MOZ_ASSERT(surfStream); sharedSurf = surfStream->SwapConsumer(); if (!sharedSurf) { // We don't have a valid surf to show yet. return false; } mGL->MakeCurrent(); mSize = IntSize(sharedSurf->Size().width, sharedSurf->Size().height); gfxImageSurface* toUpload = nullptr; switch (sharedSurf->Type()) { case SharedSurfaceType::GLTextureShare: { SharedSurface_GLTexture* glTexSurf = SharedSurface_GLTexture::Cast(sharedSurf); glTexSurf->SetConsumerGL(mGL); mTextureHandle = glTexSurf->Texture(); MOZ_ASSERT(mTextureHandle); mFormat = sharedSurf->HasAlpha() ? FORMAT_R8G8B8A8 : FORMAT_R8G8B8X8; break; } case SharedSurfaceType::EGLImageShare: { SharedSurface_EGLImage* eglImageSurf = SharedSurface_EGLImage::Cast(sharedSurf); mTextureHandle = eglImageSurf->AcquireConsumerTexture(mGL); if (!mTextureHandle) { toUpload = eglImageSurf->GetPixels(); MOZ_ASSERT(toUpload); } else { mFormat = sharedSurf->HasAlpha() ? FORMAT_R8G8B8A8 : FORMAT_R8G8B8X8; } break; } case SharedSurfaceType::Basic: { toUpload = SharedSurface_Basic::Cast(sharedSurf)->GetData(); MOZ_ASSERT(toUpload); break; } default: MOZ_CRASH("Invalid SharedSurface type."); } if (toUpload) { // mBounds seems to end up as (0,0,0,0) a lot, so don't use it? nsIntSize size(toUpload->GetSize()); nsIntRect rect(nsIntPoint(0,0), size); nsIntRegion bounds(rect); mFormat = mGL->UploadSurfaceToTexture(toUpload, bounds, mUploadTexture, true); mTextureHandle = mUploadTexture; } MOZ_ASSERT(mTextureHandle); mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextureHandle); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); return true; }