Beispiel #1
0
static void
RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
                 const nsIntPoint& aOffset)
{
  if (aManager->CompositingDisabled()) {
    return;
  }

  aManager->MakeCurrent();

  // XXX we might be able to improve performance by using glClear

  /* Multiply color by the layer opacity, as the shader
   * ignores layer opacity and expects a final color to
   * write to the color buffer.  This saves a needless
   * multiply in the fragment shader.
   */
  gfxRGBA color(aLayer->GetColor());
  float opacity = aLayer->GetEffectiveOpacity() * color.a;
  color.r *= opacity;
  color.g *= opacity;
  color.b *= opacity;
  color.a = opacity;

  ShaderProgramOGL *program = aManager->GetProgram(ColorLayerProgramType,
                                                   aLayer->GetMaskLayer());
  program->Activate();
  program->SetLayerQuadRect(aLayer->GetBounds());
  program->SetLayerTransform(aLayer->GetEffectiveTransform());
  program->SetTextureTransform(gfx3DMatrix());
  program->SetRenderOffset(aOffset);
  program->SetRenderColor(color);
  program->LoadMask(aLayer->GetMaskLayer());

  aManager->BindAndDrawQuad(program);
}
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
ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                                 const nsIntPoint& aOffset)
{
  if (mOGLManager->CompositingDisabled()) {
    return;
  }
  mOGLManager->MakeCurrent();
  if (mImageContainerID) {
    ImageContainerParent::SetCompositorIDForImage(mImageContainerID,
                                                  mOGLManager->GetCompositorID());
    uint32_t imgVersion = ImageContainerParent::GetSharedImageVersion(mImageContainerID);
    SharedImage* img = ImageContainerParent::GetSharedImage(mImageContainerID);
    if (imgVersion != mImageVersion) {
      if (img && (img->type() == SharedImage::TYUVImage)) {
        UploadSharedYUVToTexture(img->get_YUVImage());
  
        mImageVersion = imgVersion;
      } else if (img && (img->type() == SharedImage::TYCbCrImage)) {
        ShmemYCbCrImage shmemImage(img->get_YCbCrImage().data(),
                                   img->get_YCbCrImage().offset());
        UploadSharedYCbCrToTexture(shmemImage, img->get_YCbCrImage().picture());

        mImageVersion = imgVersion;
      } else if (img && (img->type() == SharedImage::TRGBImage)) {
        UploadSharedRGBToTexture(&img->get_RGBImage().data(),
                                 img->get_RGBImage().picture(),
                                 img->get_RGBImage().rgbFormat());
        mImageVersion = imgVersion;
      }
    }
#ifdef MOZ_WIDGET_GONK
    if (img
        && (img->type() == SharedImage::TSurfaceDescriptor)
        && (img->get_SurfaceDescriptor().type() == SurfaceDescriptor::TSurfaceDescriptorGralloc)) {
      const SurfaceDescriptorGralloc& desc = img->get_SurfaceDescriptor().get_SurfaceDescriptorGralloc();
      sp<GraphicBuffer> graphicBuffer = GrallocBufferActor::GetFrom(desc);
      mSize = gfxIntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
      if (!mExternalBufferTexture.IsAllocated()) {
        mExternalBufferTexture.Allocate(gl());
      }
      gl()->MakeCurrent();
      gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
      gl()->BindExternalBuffer(mExternalBufferTexture.GetTextureID(), graphicBuffer->getNativeBuffer());
      mImageVersion = imgVersion;
    }
#endif
  }


  if (mTexImage) {
    NS_ASSERTION(mTexImage->GetContentType() != gfxASurface::CONTENT_ALPHA,
                 "Image layer has alpha image");

    ShaderProgramOGL *colorProgram =
      mOGLManager->GetProgram(mTexImage->GetShaderProgramType(), GetMaskLayer());

    colorProgram->Activate();
    colorProgram->SetTextureUnit(0);
    colorProgram->SetLayerTransform(GetEffectiveTransform());
    colorProgram->SetLayerOpacity(GetEffectiveOpacity());
    colorProgram->SetRenderOffset(aOffset);
    colorProgram->LoadMask(GetMaskLayer());

    mTexImage->SetFilter(mFilter);
    mTexImage->BeginTileIteration();

    if (gl()->CanUploadNonPowerOfTwo()) {
      do {
        nsIntRect rect = mTexImage->GetTileRect();
        if (!rect.IsEmpty()) {
          TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0);
          colorProgram->SetLayerQuadRect(rect);
          mOGLManager->BindAndDrawQuad(colorProgram);
        }
      } while (mTexImage->NextTile());
    } else {
      do {
        nsIntRect rect = mTexImage->GetTileRect();
        if (!rect.IsEmpty()) {
          TextureImage::ScopedBindTextureAndApplyFilter texBind(mTexImage, LOCAL_GL_TEXTURE0);
          colorProgram->SetLayerQuadRect(rect);
          // 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
          mOGLManager->BindAndDrawQuadWithTextureRect(colorProgram,
                                                      nsIntRect(0, 0, mTexImage->GetTileRect().width,
                                                                mTexImage->GetTileRect().height),
                                                      mTexImage->GetTileRect().Size());
        }
      } while (mTexImage->NextTile());
    }
#ifdef MOZ_WIDGET_GONK
  } else if (mExternalBufferTexture.IsAllocated()) {
    gl()->MakeCurrent();
    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, mExternalBufferTexture.GetTextureID());

    ShaderProgramOGL *program = mOGLManager->GetProgram(RGBAExternalLayerProgramType, GetMaskLayer());

    gl()->ApplyFilterToBoundTexture(LOCAL_GL_TEXTURE_EXTERNAL, mFilter);

    program->Activate();
    program->SetLayerQuadRect(nsIntRect(0, 0,
                                        mSize.width, mSize.height));
    program->SetLayerTransform(GetEffectiveTransform());
    program->SetLayerOpacity(GetEffectiveOpacity());
    program->SetRenderOffset(aOffset);
    program->SetTextureUnit(0);
    program->LoadMask(GetMaskLayer());

    mOGLManager->BindAndDrawQuad(program);

    // Make sure that we release the underlying external image
    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, 0);
    mExternalBufferTexture.Release();
#endif
  } else if (mSharedHandle) {
    GLContext::SharedHandleDetails handleDetails;
    if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
      NS_ERROR("Failed to get shared handle details");
      return;
    }

    ShaderProgramOGL* program = mOGLManager->GetProgram(handleDetails.mProgramType, GetMaskLayer());
   
    program->Activate();
    program->SetLayerTransform(GetEffectiveTransform());
    program->SetLayerOpacity(GetEffectiveOpacity());
    program->SetRenderOffset(aOffset);
    program->SetTextureUnit(0);
    program->SetTextureTransform(handleDetails.mTextureTransform);
    program->LoadMask(GetMaskLayer());

    MakeTextureIfNeeded(gl(), mTexture);
    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
    gl()->fBindTexture(handleDetails.mTarget, mTexture);
    
    if (!gl()->AttachSharedHandle(mShareType, mSharedHandle)) {
      NS_ERROR("Failed to bind shared texture handle");
      return;
    }

    gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                             LOCAL_GL_ONE, LOCAL_GL_ONE);
    gl()->ApplyFilterToBoundTexture(mFilter);
    program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mSize));
    mOGLManager->BindAndDrawQuad(program, mInverted);
    gl()->fBindTexture(handleDetails.mTarget, 0);
    gl()->DetachSharedHandle(mShareType, mSharedHandle);
  } else if (mRGBTexture.IsAllocated()) {
    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mRGBTexture.GetTextureID());
    gl()->ApplyFilterToBoundTexture(mFilter);

    ShaderProgramOGL *shader = mOGLManager->GetProgram(RGBALayerProgramType, GetMaskLayer());
    shader->Activate();

    shader->SetLayerQuadRect(nsIntRect(0, 0,
                                           mPictureRect.width,
                                           mPictureRect.height));
    shader->SetTextureUnit(0);
    shader->SetLayerTransform(GetEffectiveTransform());
    shader->SetLayerOpacity(GetEffectiveOpacity());
    shader->SetRenderOffset(aOffset);
    shader->LoadMask(GetMaskLayer());

    mOGLManager->BindAndDrawQuadWithTextureRect(shader,
                                                mPictureRect,
                                                nsIntSize(mSize.width, mSize.height));
  } else {
    gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[0].GetTextureID());
    gl()->ApplyFilterToBoundTexture(mFilter);
    gl()->fActiveTexture(LOCAL_GL_TEXTURE1);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[1].GetTextureID());
    gl()->ApplyFilterToBoundTexture(mFilter);
    gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[2].GetTextureID());
    gl()->ApplyFilterToBoundTexture(mFilter);

    ShaderProgramOGL *yuvProgram = mOGLManager->GetProgram(YCbCrLayerProgramType, GetMaskLayer());

    yuvProgram->Activate();
    yuvProgram->SetLayerQuadRect(nsIntRect(0, 0,
                                           mPictureRect.width,
                                           mPictureRect.height));
    yuvProgram->SetYCbCrTextureUnits(0, 1, 2);
    yuvProgram->SetLayerTransform(GetEffectiveTransform());
    yuvProgram->SetLayerOpacity(GetEffectiveOpacity());
    yuvProgram->SetRenderOffset(aOffset);
    yuvProgram->LoadMask(GetMaskLayer());

    mOGLManager->BindAndDrawQuadWithTextureRect(yuvProgram,
                                                mPictureRect,
                                                nsIntSize(mSize.width, mSize.height));
 }
}
Beispiel #4
0
void
ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                               const nsIntPoint& aOffset)
{
  /**
   * Setup our temporary texture for rendering the contents of this container.
   */
  GLuint containerSurface;
  GLuint frameBuffer;

  nsIntPoint childOffset(aOffset);
  nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds();

  nsIntRect cachedScissor = gl()->ScissorRect();
  gl()->PushScissorRect();
  mSupportsComponentAlphaChildren = false;

  float opacity = GetEffectiveOpacity();
  const gfx3DMatrix& transform = GetEffectiveTransform();
  bool needsFramebuffer = 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;
    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 (GetEffectiveVisibleRegion().GetNumRects() == 1 && 
        (GetContentFlags() & Layer::CONTENT_OPAQUE))
    {
      // don't need a background, we're going to paint all opaque stuff
      mSupportsComponentAlphaChildren = true;
      mode = LayerManagerOGL::InitModeNone;
    } else {
      const gfx3DMatrix& transform3D = 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(this) &&
          transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
        mode = gfxPlatform::ComponentAlphaEnabled() ?
          LayerManagerOGL::InitModeCopy :
          LayerManagerOGL::InitModeClear;
        framebufferRect.x += transform.x0;
        framebufferRect.y += transform.y0;
        mSupportsComponentAlphaChildren = gfxPlatform::ComponentAlphaEnabled();
      }
    }

    gl()->PushViewportRect();
    framebufferRect -= childOffset;
    if (!mOGLManager->CompositingDisabled()) {
      if (!mOGLManager->CreateFBOWithTexture(framebufferRect,
                                          mode,
                                          aPreviousFrameBuffer,
                                          &frameBuffer,
                                          &containerSurface)) {
        gl()->PopViewportRect();
        gl()->PopScissorRect();
        gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
        return;
      }
    }
    childOffset.x = visibleRect.x;
    childOffset.y = visibleRect.y;
  } else {
    frameBuffer = aPreviousFrameBuffer;
    mSupportsComponentAlphaChildren = (GetContentFlags() & Layer::CONTENT_OPAQUE) ||
      (GetParent() && GetParent()->SupportsComponentAlphaChildren());
  }

  nsAutoTArray<Layer*, 12> children;
  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, &mOGLManager->GetWorldTransform());
    if (scissorRect.IsEmpty()) {
      continue;
    }

    gl()->fScissor(scissorRect.x, 
                               scissorRect.y, 
                               scissorRect.width, 
                               scissorRect.height);

    layerToRender->RenderLayer(frameBuffer, childOffset);
    gl()->MakeCurrent();
  }


  if (needsFramebuffer) {
    // Unbind the current framebuffer and rebind the previous one.
#ifdef MOZ_DUMP_PAINTING
    if (gfxUtils::sDumpPainting) {
      nsRefPtr<gfxImageSurface> surf = 
        gl()->GetTexImage(containerSurface, true, mOGLManager->GetFBOTextureFormat());

      WriteSnapshotToDumpFile(this, surf);
    }
#endif
    
    // Restore the viewport
    gl()->PopViewportRect();
    nsIntRect viewport = gl()->ViewportRect();
    mOGLManager->SetupPipeline(viewport.width, viewport.height,
                            LayerManagerOGL::ApplyWorldTransform);
    gl()->PopScissorRect();

    if (!mOGLManager->CompositingDisabled()) {
      gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
      gl()->fDeleteFramebuffers(1, &frameBuffer);

      gl()->fActiveTexture(LOCAL_GL_TEXTURE0);

      gl()->fBindTexture(mOGLManager->FBOTextureTarget(), containerSurface);

      MaskType maskType = MaskNone;
      if (GetMaskLayer()) {
        if (!GetTransform().CanDraw2D()) {
          maskType = Mask3d;
        } else {
          maskType = Mask2d;
        }
      }
      ShaderProgramOGL *rgb =
        mOGLManager->GetFBOLayerProgram(maskType);

      rgb->Activate();
      rgb->SetLayerQuadRect(visibleRect);
      rgb->SetLayerTransform(transform);
      rgb->SetTextureTransform(gfx3DMatrix());
      rgb->SetLayerOpacity(opacity);
      rgb->SetRenderOffset(aOffset);
      rgb->SetTextureUnit(0);
      rgb->LoadMask(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.
      mOGLManager->BindAndDrawQuad(rgb, true);

      // Clean up resources.  This also unbinds the texture.
      gl()->fDeleteTextures(1, &containerSurface);
    }
  } else {
    gl()->PopScissorRect();
  }
}
Beispiel #5
0
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);
}