static void ContainerRender(Container* aContainer, int aPreviousFrameBuffer, const nsIntPoint& aOffset, LayerManagerOGL* aManager) { /** * Setup our temporary texture for rendering the contents of this container. */ GLuint containerSurface; GLuint frameBuffer; nsIntPoint childOffset(aOffset); nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds(); nsIntRect cachedScissor = aContainer->gl()->ScissorRect(); aContainer->gl()->PushScissorRect(); aContainer->mSupportsComponentAlphaChildren = false; float opacity = aContainer->GetEffectiveOpacity(); const gfx3DMatrix& transform = aContainer->GetEffectiveTransform(); bool needsFramebuffer = aContainer->UseIntermediateSurface(); if (needsFramebuffer) { nsIntRect framebufferRect = visibleRect; // we're about to create a framebuffer backed by textures to use as an intermediate // surface. What to do if its size (as given by framebufferRect) would exceed the // maximum texture size supported by the GL? The present code chooses the compromise // of just clamping the framebuffer's size to the max supported size. // This gives us a lower resolution rendering of the intermediate surface (children layers). // See bug 827170 for a discussion. GLint maxTexSize; aContainer->gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTexSize); framebufferRect.width = std::min(framebufferRect.width, maxTexSize); framebufferRect.height = std::min(framebufferRect.height, maxTexSize); LayerManagerOGL::InitMode mode = LayerManagerOGL::InitModeClear; if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 && (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff aContainer->mSupportsComponentAlphaChildren = true; mode = LayerManagerOGL::InitModeNone; } else { const gfx3DMatrix& transform3D = aContainer->GetEffectiveTransform(); gfxMatrix transform; // If we have an opaque ancestor layer, then we can be sure that // all the pixels we draw into are either opaque already or will be // covered by something opaque. Otherwise copying up the background is // not safe. if (HasOpaqueAncestorLayer(aContainer) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { mode = gfxPlatform::GetPlatform()->UsesSubpixelAATextRendering() ? LayerManagerOGL::InitModeCopy : LayerManagerOGL::InitModeClear; framebufferRect.x += transform.x0; framebufferRect.y += transform.y0; aContainer->mSupportsComponentAlphaChildren = gfxPlatform::GetPlatform()->UsesSubpixelAATextRendering(); } } aContainer->gl()->PushViewportRect(); framebufferRect -= childOffset; if (!aManager->CompositingDisabled()) { aManager->CreateFBOWithTexture(framebufferRect, mode, aPreviousFrameBuffer, &frameBuffer, &containerSurface); } childOffset.x = visibleRect.x; childOffset.y = visibleRect.y; } else { frameBuffer = aPreviousFrameBuffer; aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) || (aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren()); } nsAutoTArray<Layer*, 12> children; aContainer->SortChildrenBy3DZOrder(children); /** * Render this container's contents. */ for (uint32_t i = 0; i < children.Length(); i++) { LayerOGL* layerToRender = static_cast<LayerOGL*>(children.ElementAt(i)->ImplData()); if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } nsIntRect scissorRect = layerToRender->GetLayer()-> CalculateScissorRect(cachedScissor, &aManager->GetWorldTransform()); if (scissorRect.IsEmpty()) { continue; } aContainer->gl()->fScissor(scissorRect.x, scissorRect.y, scissorRect.width, scissorRect.height); layerToRender->RenderLayer(frameBuffer, childOffset); aContainer->gl()->MakeCurrent(); } if (needsFramebuffer) { // Unbind the current framebuffer and rebind the previous one. #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { nsRefPtr<gfxImageSurface> surf = aContainer->gl()->GetTexImage(containerSurface, true, aManager->GetFBOLayerProgramType()); WriteSnapshotToDumpFile(aContainer, surf); } #endif // Restore the viewport aContainer->gl()->PopViewportRect(); nsIntRect viewport = aContainer->gl()->ViewportRect(); aManager->SetupPipeline(viewport.width, viewport.height, LayerManagerOGL::ApplyWorldTransform); aContainer->gl()->PopScissorRect(); aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); if (!aManager->CompositingDisabled()) { aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer); aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0); aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface); MaskType maskType = MaskNone; if (aContainer->GetMaskLayer()) { if (!aContainer->GetTransform().CanDraw2D()) { maskType = Mask3d; } else { maskType = Mask2d; } } ShaderProgramOGL *rgb = aManager->GetFBOLayerProgram(maskType); rgb->Activate(); rgb->SetLayerQuadRect(visibleRect); rgb->SetLayerTransform(transform); rgb->SetLayerOpacity(opacity); rgb->SetRenderOffset(aOffset); rgb->SetTextureUnit(0); rgb->LoadMask(aContainer->GetMaskLayer()); if (rgb->GetTexCoordMultiplierUniformLocation() != -1) { // 2DRect case, get the multiplier right for a sampler2DRect rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height); } // Drawing is always flipped, but when copying between surfaces we want to avoid // this. Pass true for the flip parameter to introduce a second flip // that cancels the other one out. aManager->BindAndDrawQuad(rgb, true); // Clean up resources. This also unbinds the texture. aContainer->gl()->fDeleteTextures(1, &containerSurface); } } else { aContainer->gl()->PopScissorRect(); } }
void CanvasLayerOGL::RenderLayer(int aPreviousDestination, const nsIntPoint& aOffset) { FirePreTransactionCallback(); UpdateSurface(); if (mOGLManager->CompositingDisabled()) { return; } FireDidTransactionCallback(); mOGLManager->MakeCurrent(); // XXX We're going to need a different program depending on if // mGLBufferIsPremultiplied is TRUE or not. The RGBLayerProgram // assumes that it's true. gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (mTexture) { gl()->fBindTexture(mTextureTarget, mTexture); } ShaderProgramOGL *program = nullptr; nsIntRect drawRect = mBounds; if (mDelayedUpdates) { NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload"); drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds()); gfx::SurfaceFormat format = gl()->UploadSurfaceToTexture(mCanvasSurface, nsIntRect(0, 0, drawRect.width, drawRect.height), mUploadTexture, true, drawRect.TopLeft()); mLayerProgram = ShaderProgramFromSurfaceFormat(format); mTexture = mUploadTexture; } if (!program) { program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer()); } #if defined(GL_PROVIDER_GLX) if (mPixmap && !mDelayedUpdates) { sDefGLXLib.BindTexImage(mPixmap); } #endif gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); if (mLayerProgram == RGBARectLayerProgramType || mLayerProgram == RGBXRectLayerProgramType) { // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1. program->SetTexCoordMultiplier(mBounds.width, mBounds.height); } program->SetLayerQuadRect(drawRect); program->SetLayerTransform(GetEffectiveTransform()); program->SetTextureTransform(gfx3DMatrix()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); if (gl()->CanUploadNonPowerOfTwo()) { mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false); } else { mOGLManager->BindAndDrawQuadWithTextureRect(program, drawRect, drawRect.Size()); } #if defined(GL_PROVIDER_GLX) if (mPixmap && !mDelayedUpdates) { sDefGLXLib.ReleaseTexImage(mPixmap); } #endif }
void ImageLayerOGL::RenderLayer(int, const nsIntPoint& aOffset) { nsRefPtr<ImageContainer> container = GetContainer(); if (!container || mOGLManager->CompositingDisabled()) return; mOGLManager->MakeCurrent(); AutoLockImage autoLock(container); Image *image = autoLock.GetImage(); if (!image) { return; } NS_ASSERTION(image->GetFormat() != REMOTE_IMAGE_BITMAP, "Remote images aren't handled yet in OGL layers!"); if (image->GetFormat() == PLANAR_YCBCR) { PlanarYCbCrImage *yuvImage = static_cast<PlanarYCbCrImage*>(image); if (!yuvImage->IsValid()) { return; } PlanarYCbCrOGLBackendData *data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LAYERS_OPENGL)); if (data && data->mTextures->GetGLContext() != gl()) { // If these textures were allocated by another layer manager, // clear them out and re-allocate below. data = nullptr; yuvImage->SetBackendData(LAYERS_OPENGL, nullptr); } if (!data) { AllocateTexturesYCbCr(yuvImage); data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LAYERS_OPENGL)); } if (!data || data->mTextures->GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE2); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[2].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE1); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[1].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); ShaderProgramOGL *program = mOGLManager->GetProgram(YCbCrLayerProgramType, GetMaskLayer()); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, yuvImage->GetSize().width, yuvImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetYCbCrTextureUnits(0, 1, 2); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuadWithTextureRect(program, yuvImage->GetData()->GetPictureRect(), nsIntSize(yuvImage->GetData()->mYSize.width, yuvImage->GetData()->mYSize.height)); // We shouldn't need to do this, but do it anyway just in case // someone else forgets. gl()->fActiveTexture(LOCAL_GL_TEXTURE0); } else if (image->GetFormat() == CAIRO_SURFACE) { CairoImage *cairoImage = static_cast<CairoImage*>(image); if (!cairoImage->mSurface) { return; } NS_ASSERTION(cairoImage->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA, "Image layer has alpha image"); CairoOGLBackendData *data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LAYERS_OPENGL)); if (data && data->mTexture.GetGLContext() != gl()) { // If this texture was allocated by another layer manager, clear // it out and re-allocate below. data = nullptr; cairoImage->SetBackendData(LAYERS_OPENGL, nullptr); } if (!data) { AllocateTexturesCairo(cairoImage); data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LAYERS_OPENGL)); } if (!data || data->mTexture.GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID()); ShaderProgramOGL *program = mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer()); gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, cairoImage->GetSize().width, cairoImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuad(program); #ifdef XP_MACOSX } else if (image->GetFormat() == MAC_IO_SURFACE) { MacIOSurfaceImage *ioImage = static_cast<MacIOSurfaceImage*>(image); if (!mOGLManager->GetThebesLayerCallback()) { // If its an empty transaction we still need to update // the plugin IO Surface and make sure we grab the // new image ioImage->Update(GetContainer()); image = nullptr; autoLock.Refresh(); image = autoLock.GetImage(); gl()->MakeCurrent(); ioImage = static_cast<MacIOSurfaceImage*>(image); } if (!ioImage) { return; } gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (!ioImage->GetBackendData(LAYERS_OPENGL)) { AllocateTextureIOSurface(ioImage, gl()); } MacIOSurfaceImageOGLBackendData *data = static_cast<MacIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LAYERS_OPENGL)); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, data->mTexture.GetTextureID()); ShaderProgramOGL *program = mOGLManager->GetProgram(gl::RGBARectLayerProgramType, GetMaskLayer()); program->Activate(); if (program->GetTexCoordMultiplierUniformLocation() != -1) { // 2DRect case, get the multiplier right for a sampler2DRect program->SetTexCoordMultiplier(ioImage->GetSize().width, ioImage->GetSize().height); } else { NS_ASSERTION(0, "no rects?"); } program->SetLayerQuadRect(nsIntRect(0, 0, ioImage->GetSize().width, ioImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuad(program); gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0); #endif #ifdef MOZ_WIDGET_GONK } else if (image->GetFormat() == GONK_IO_SURFACE) { GonkIOSurfaceImage *ioImage = static_cast<GonkIOSurfaceImage*>(image); if (!ioImage) { return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (!ioImage->GetBackendData(LAYERS_OPENGL)) { AllocateTextureIOSurface(ioImage, gl()); } GonkIOSurfaceImageOGLBackendData *data = static_cast<GonkIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LAYERS_OPENGL)); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->BindExternalBuffer(data->mTexture.GetTextureID(), ioImage->GetNativeBuffer()); ShaderProgramOGL *program = mOGLManager->GetProgram(RGBAExternalLayerProgramType, GetMaskLayer()); gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, ioImage->GetSize().width, ioImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuadWithTextureRect(program, GetVisibleRegion().GetBounds(), nsIntSize(ioImage->GetSize().width, ioImage->GetSize().height)); #endif } GetContainer()->NotifyPaintedImage(image); }
void ImageLayerOGL::RenderLayer(int, const nsIntPoint& aOffset) { nsRefPtr<ImageContainer> container = GetContainer(); if (!container || mOGLManager->CompositingDisabled()) return; mOGLManager->MakeCurrent(); AutoLockImage autoLock(container); Image *image = autoLock.GetImage(); if (!image) { return; } NS_ASSERTION(image->GetFormat() != REMOTE_IMAGE_BITMAP, "Remote images aren't handled yet in OGL layers!"); if (image->GetFormat() == PLANAR_YCBCR) { PlanarYCbCrImage *yuvImage = static_cast<PlanarYCbCrImage*>(image); if (!yuvImage->IsValid()) { return; } PlanarYCbCrOGLBackendData *data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LAYERS_OPENGL)); if (data && data->mTextures->GetGLContext() != gl()) { // If these textures were allocated by another layer manager, // clear them out and re-allocate below. data = nullptr; yuvImage->SetBackendData(LAYERS_OPENGL, nullptr); } if (!data) { AllocateTexturesYCbCr(yuvImage); data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LAYERS_OPENGL)); } if (!data || data->mTextures->GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE2); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[2].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE1); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[1].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); ShaderProgramOGL *program = mOGLManager->GetProgram(YCbCrLayerProgramType, GetMaskLayer()); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, yuvImage->GetSize().width, yuvImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetYCbCrTextureUnits(0, 1, 2); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuadWithTextureRect(program, yuvImage->GetData()->GetPictureRect(), nsIntSize(yuvImage->GetData()->mYSize.width, yuvImage->GetData()->mYSize.height)); // We shouldn't need to do this, but do it anyway just in case // someone else forgets. gl()->fActiveTexture(LOCAL_GL_TEXTURE0); } else if (image->GetFormat() == CAIRO_SURFACE) { CairoImage *cairoImage = static_cast<CairoImage*>(image); if (!cairoImage->mSurface) { return; } NS_ASSERTION(cairoImage->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA, "Image layer has alpha image"); CairoOGLBackendData *data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LAYERS_OPENGL)); if (data && data->mTexture.GetGLContext() != gl()) { // If this texture was allocated by another layer manager, clear // it out and re-allocate below. data = nullptr; cairoImage->SetBackendData(LAYERS_OPENGL, nullptr); } if (!data) { AllocateTexturesCairo(cairoImage); data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LAYERS_OPENGL)); } if (!data || data->mTexture.GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID()); ShaderProgramOGL *program = mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer()); gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, cairoImage->GetSize().width, cairoImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuad(program); } else if (image->GetFormat() == SHARED_TEXTURE) { SharedTextureImage* texImage = static_cast<SharedTextureImage*>(image); const SharedTextureImage::Data* data = texImage->GetData(); GLContext::SharedHandleDetails handleDetails; if (!gl()->GetSharedHandleDetails(data->mShareType, data->mHandle, handleDetails)) { NS_ERROR("Failed to get shared handle details"); return; } ShaderProgramOGL* program = mOGLManager->GetProgram(handleDetails.mProgramType, GetMaskLayer()); program->Activate(); if (handleDetails.mProgramType == gl::RGBARectLayerProgramType) { // 2DRect case, get the multiplier right for a sampler2DRect program->SetTexCoordMultiplier(data->mSize.width, data->mSize.height); } program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->SetTextureTransform(handleDetails.mTextureTransform); program->LoadMask(GetMaskLayer()); if (!texImage->GetBackendData(LAYERS_OPENGL)) { AllocateTextureSharedTexture(texImage, gl(), handleDetails.mTarget); } ImageOGLBackendData *backendData = static_cast<ImageOGLBackendData*>(texImage->GetBackendData(LAYERS_OPENGL)); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(handleDetails.mTarget, backendData->mTexture.GetTextureID()); if (!gl()->AttachSharedHandle(data->mShareType, data->mHandle)) { NS_ERROR("Failed to bind shared texture handle"); return; } gl()->ApplyFilterToBoundTexture(handleDetails.mTarget, mFilter); program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), data->mSize)); mOGLManager->BindAndDrawQuad(program, data->mInverted); gl()->fBindTexture(handleDetails.mTarget, 0); gl()->DetachSharedHandle(data->mShareType, data->mHandle); #ifdef MOZ_WIDGET_GONK } else if (image->GetFormat() == GONK_IO_SURFACE) { GonkIOSurfaceImage *ioImage = static_cast<GonkIOSurfaceImage*>(image); if (!ioImage) { return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (!ioImage->GetBackendData(LAYERS_OPENGL)) { AllocateTextureIOSurface(ioImage, gl()); } GonkIOSurfaceImageOGLBackendData *data = static_cast<GonkIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LAYERS_OPENGL)); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->BindExternalBuffer(data->mTexture.GetTextureID(), ioImage->GetNativeBuffer()); ShaderProgramOGL *program = mOGLManager->GetProgram(RGBAExternalLayerProgramType, GetMaskLayer()); gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, ioImage->GetSize().width, ioImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuadWithTextureRect(program, GetVisibleRegion().GetBounds(), nsIntSize(ioImage->GetSize().width, ioImage->GetSize().height)); #endif } GetContainer()->NotifyPaintedImage(image); }
void CanvasLayerOGL::RenderLayer(int aPreviousDestination, const nsIntPoint& aOffset) { UpdateSurface(); if (mOGLManager->CompositingDisabled()) { return; } FireDidTransactionCallback(); mOGLManager->MakeCurrent(); // XXX We're going to need a different program depending on if // mGLBufferIsPremultiplied is TRUE or not. The RGBLayerProgram // assumes that it's true. gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (mTexture) { gl()->fBindTexture(mTextureTarget, mTexture); } ShaderProgramOGL *program = nullptr; bool useGLContext = mCanvasGLContext && !mForceReadback && mCanvasGLContext->GetContextType() == gl()->GetContextType(); nsIntRect drawRect = mBounds; if (useGLContext) { gl()->BindTex2DOffscreen(mCanvasGLContext); program = mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(), true, GetMaskLayer() ? Mask2d : MaskNone); } else if (mDelayedUpdates) { NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload"); drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds()); mLayerProgram = gl()->UploadSurfaceToTexture(mCanvasSurface, nsIntRect(0, 0, drawRect.width, drawRect.height), mTexture, true, drawRect.TopLeft()); } if (!program) { program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer()); } #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO) if (mPixmap && !mDelayedUpdates) { sGLXLibrary.BindTexImage(mPixmap); } #endif gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); if (mLayerProgram == gl::RGBARectLayerProgramType) { // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1. program->SetTexCoordMultiplier(mDrawTarget->GetSize().width, mDrawTarget->GetSize().height); } program->SetLayerQuadRect(drawRect); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); if (gl()->CanUploadNonPowerOfTwo()) { mOGLManager->BindAndDrawQuad(program, mNeedsYFlip ? true : false); } else { mOGLManager->BindAndDrawQuadWithTextureRect(program, drawRect, drawRect.Size()); } #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO) if (mPixmap && !mDelayedUpdates) { sGLXLibrary.ReleaseTexImage(mPixmap); } #endif if (useGLContext) { gl()->UnbindTex2DOffscreen(mCanvasGLContext); } }
void ImageLayerOGL::RenderLayer(int, const nsIntPoint& aOffset) { nsRefPtr<ImageContainer> container = GetContainer(); if (!container || mOGLManager->CompositingDisabled()) return; mOGLManager->MakeCurrent(); AutoLockImage autoLock(container); Image *image = autoLock.GetImage(); if (!image) { return; } NS_ASSERTION(image->GetFormat() != Image::REMOTE_IMAGE_BITMAP, "Remote images aren't handled yet in OGL layers!"); NS_ASSERTION(mScaleMode == SCALE_NONE, "Scale modes other than none not handled yet in OGL layers!"); if (image->GetFormat() == Image::PLANAR_YCBCR) { PlanarYCbCrImage *yuvImage = static_cast<PlanarYCbCrImage*>(image); if (!yuvImage->mBufferSize) { return; } PlanarYCbCrOGLBackendData *data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LayerManager::LAYERS_OPENGL)); if (data && data->mTextures->GetGLContext() != gl()) { // If these textures were allocated by another layer manager, // clear them out and re-allocate below. data = nsnull; yuvImage->SetBackendData(LayerManager::LAYERS_OPENGL, nsnull); } if (!data) { AllocateTexturesYCbCr(yuvImage); data = static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LayerManager::LAYERS_OPENGL)); } if (!data || data->mTextures->GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); gl()->fActiveTexture(LOCAL_GL_TEXTURE2); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[2].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE1); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[1].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID()); gl()->ApplyFilterToBoundTexture(mFilter); ShaderProgramOGL *program = mOGLManager->GetProgram(YCbCrLayerProgramType, GetMaskLayer()); program->Activate(); program->SetLayerQuadRect(nsIntRect(0, 0, yuvImage->mSize.width, yuvImage->mSize.height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetYCbCrTextureUnits(0, 1, 2); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuadWithTextureRect(program, yuvImage->mData.GetPictureRect(), nsIntSize(yuvImage->mData.mYSize.width, yuvImage->mData.mYSize.height)); // We shouldn't need to do this, but do it anyway just in case // someone else forgets. gl()->fActiveTexture(LOCAL_GL_TEXTURE0); } else if (image->GetFormat() == Image::CAIRO_SURFACE) { CairoImage *cairoImage = static_cast<CairoImage*>(image); if (!cairoImage->mSurface) { return; } NS_ASSERTION(cairoImage->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA, "Image layer has alpha image"); CairoOGLBackendData *data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_OPENGL)); if (data && data->mTexture.GetGLContext() != gl()) { // If this texture was allocated by another layer manager, clear // it out and re-allocate below. data = nsnull; cairoImage->SetBackendData(LayerManager::LAYERS_OPENGL, nsnull); } if (!data) { AllocateTexturesCairo(cairoImage); data = static_cast<CairoOGLBackendData*>(cairoImage->GetBackendData(LayerManager::LAYERS_OPENGL)); } if (!data || data->mTexture.GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } gl()->MakeCurrent(); unsigned int iwidth = cairoImage->mSize.width; unsigned int iheight = cairoImage->mSize.height; gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID()); #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO) GLXPixmap pixmap; if (cairoImage->mSurface) { pixmap = sGLXLibrary.CreatePixmap(cairoImage->mSurface); NS_ASSERTION(pixmap, "Failed to create pixmap!"); if (pixmap) { sGLXLibrary.BindTexImage(pixmap); } } #endif ShaderProgramOGL *program = mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer()); gl()->ApplyFilterToBoundTexture(mFilter); program->Activate(); // The following uniform controls the scaling of the vertex coords. // Instead of setting the scale here and using coords in the range [0,1], we // set an identity transform and use pixel coordinates below program->SetLayerQuadRect(nsIntRect(0, 0, 1, 1)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); nsIntRect rect = GetVisibleRegion().GetBounds(); GLContext::RectTriangles triangleBuffer; float tex_offset_u = float(rect.x % iwidth) / iwidth; float tex_offset_v = float(rect.y % iheight) / iheight; triangleBuffer.addRect(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, tex_offset_u, tex_offset_v, tex_offset_u + float(rect.width) / float(iwidth), tex_offset_v + float(rect.height) / float(iheight)); GLuint vertAttribIndex = program->AttribLocation(ShaderProgramOGL::VertexCoordAttrib); GLuint texCoordAttribIndex = program->AttribLocation(ShaderProgramOGL::TexCoordAttrib); NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?"); gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); gl()->fVertexAttribPointer(vertAttribIndex, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, triangleBuffer.vertexPointer()); gl()->fVertexAttribPointer(texCoordAttribIndex, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, triangleBuffer.texCoordPointer()); { gl()->fEnableVertexAttribArray(texCoordAttribIndex); { gl()->fEnableVertexAttribArray(vertAttribIndex); gl()->fDrawArrays(LOCAL_GL_TRIANGLES, 0, triangleBuffer.elements()); gl()->fDisableVertexAttribArray(vertAttribIndex); } gl()->fDisableVertexAttribArray(texCoordAttribIndex); } #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO) if (cairoImage->mSurface && pixmap) { sGLXLibrary.ReleaseTexImage(pixmap); sGLXLibrary.DestroyPixmap(pixmap); } #endif #ifdef XP_MACOSX } else if (image->GetFormat() == Image::MAC_IO_SURFACE) { MacIOSurfaceImage *ioImage = static_cast<MacIOSurfaceImage*>(image); if (!mOGLManager->GetThebesLayerCallback()) { // If its an empty transaction we still need to update // the plugin IO Surface and make sure we grab the // new image ioImage->Update(GetContainer()); image = nsnull; autoLock.Refresh(); image = autoLock.GetImage(); gl()->MakeCurrent(); ioImage = static_cast<MacIOSurfaceImage*>(image); } if (!ioImage) { return; } gl()->fActiveTexture(LOCAL_GL_TEXTURE0); if (!ioImage->GetBackendData(LayerManager::LAYERS_OPENGL)) { AllocateTextureIOSurface(ioImage, gl()); } MacIOSurfaceImageOGLBackendData *data = static_cast<MacIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LayerManager::LAYERS_OPENGL)); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, data->mTexture.GetTextureID()); ShaderProgramOGL *program = mOGLManager->GetProgram(gl::RGBARectLayerProgramType, GetMaskLayer()); program->Activate(); if (program->GetTexCoordMultiplierUniformLocation() != -1) { // 2DRect case, get the multiplier right for a sampler2DRect program->SetTexCoordMultiplier(ioImage->GetSize().width, ioImage->GetSize().height); } else { NS_ASSERTION(0, "no rects?"); } program->SetLayerQuadRect(nsIntRect(0, 0, ioImage->GetSize().width, ioImage->GetSize().height)); program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); mOGLManager->BindAndDrawQuad(program); gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0); #endif } GetContainer()->NotifyPaintedImage(image); }