示例#1
0
GLState &GLState::setScissor(Rectangleui const &newScissorRect)
{
    Rectangleui cumulative;
    if(scissor())
    {
        cumulative = scissorRect() & newScissorRect;
    }
    else
    {
        cumulative = newScissorRect;
    }

    d->props.set(Scissor,       true);
    d->props.set(ScissorX,      cumulative.left());
    d->props.set(ScissorY,      cumulative.top());
    d->props.set(ScissorWidth,  cumulative.width());
    d->props.set(ScissorHeight, cumulative.height());
    return *this;
}
void
LayerManagerComposite::RenderToPresentationSurface()
{
#ifdef MOZ_WIDGET_ANDROID
  nsIWidget* const widget = mCompositor->GetWidget()->RealWidget();
  auto window = static_cast<ANativeWindow*>(
      widget->GetNativeData(NS_PRESENTATION_WINDOW));

  if (!window) {
    return;
  }

  EGLSurface surface = widget->GetNativeData(NS_PRESENTATION_SURFACE);

  if (!surface) {
    //create surface;
    surface = GLContextProviderEGL::CreateEGLSurface(window);
    if (!surface) {
      return;
    }

    widget->SetNativeData(NS_PRESENTATION_SURFACE,
                          reinterpret_cast<uintptr_t>(surface));
  }

  CompositorOGL* compositor = mCompositor->AsCompositorOGL();
  GLContext* gl = compositor->gl();
  GLContextEGL* egl = GLContextEGL::Cast(gl);

  if (!egl) {
    return;
  }

  const IntSize windowSize(ANativeWindow_getWidth(window),
                           ANativeWindow_getHeight(window));

#endif

  if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
    return;
  }

  ScreenRotation rotation = compositor->GetScreenRotation();

  const int actualWidth = windowSize.width;
  const int actualHeight = windowSize.height;

  const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
  const nsIntRect originalRect = nsIntRect(0, 0, originalSize.width, originalSize.height);

  int pageWidth = originalSize.width;
  int pageHeight = originalSize.height;
  if (rotation == ROTATION_90 || rotation == ROTATION_270) {
    pageWidth = originalSize.height;
    pageHeight = originalSize.width;
  }

  float scale = 1.0;

  if ((pageWidth > actualWidth) || (pageHeight > actualHeight)) {
    const float scaleWidth = (float)actualWidth / (float)pageWidth;
    const float scaleHeight = (float)actualHeight / (float)pageHeight;
    scale = scaleWidth <= scaleHeight ? scaleWidth : scaleHeight;
  }

  const gfx::IntSize actualSize(actualWidth, actualHeight);
  ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);

  const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
  ScopedContextSurfaceOverride overrideSurface(egl, surface);

  Matrix viewMatrix = ComputeTransformForRotation(originalRect,
                                                  rotation);
  viewMatrix.Invert(); // unrotate
  viewMatrix.PostScale(scale, scale);
  viewMatrix.PostTranslate(offset.x, offset.y);
  Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix);

  mRoot->ComputeEffectiveTransforms(matrix);
  nsIntRegion opaque;
  LayerIntRegion visible;
  PostProcessLayers(mRoot, opaque, visible, Nothing());

  nsIntRegion invalid;
  IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight);
  IntRect rect, actualBounds;
  MOZ_ASSERT(mRoot->GetOpacity() == 1);
  mCompositor->BeginFrame(invalid, nullptr, bounds, nsIntRegion(), &rect, &actualBounds);

  // The Java side of Fennec sets a scissor rect that accounts for
  // chrome such as the URL bar. Override that so that the entire frame buffer
  // is cleared.
  ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight);
  egl->fClearColor(0.0, 0.0, 0.0, 0.0);
  egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);

  const IntRect clipRect = IntRect::Truncate(0, 0, actualWidth, actualHeight);

  RootLayer()->Prepare(RenderTargetIntRect::FromUnknownRect(clipRect));
  RootLayer()->RenderLayer(clipRect);

  mCompositor->EndFrame();
}
void
LayerManagerComposite::RenderToPresentationSurface()
{
#ifdef MOZ_WIDGET_ANDROID
  if (!AndroidBridge::Bridge()) {
    return;
  }

  void* window = AndroidBridge::Bridge()->GetPresentationWindow();

  if (!window) {
    return;
  }

  EGLSurface surface = AndroidBridge::Bridge()->GetPresentationSurface();

  if (!surface) {
    //create surface;
    surface = GLContextProviderEGL::CreateEGLSurface(window);
    if (!surface) {
      return;
    }

    AndroidBridge::Bridge()->SetPresentationSurface(surface);
  }

  CompositorOGL* compositor = static_cast<CompositorOGL*>(mCompositor.get());
  GLContext* gl = compositor->gl();
  GLContextEGL* egl = GLContextEGL::Cast(gl);

  if (!egl) {
    return;
  }

  const IntSize windowSize = AndroidBridge::Bridge()->GetNativeWindowSize(window);

#elif defined(MOZ_WIDGET_GONK)
  CompositorOGL* compositor = static_cast<CompositorOGL*>(mCompositor.get());
  nsScreenGonk* screen = static_cast<nsWindow*>(mCompositor->GetWidget())->GetScreen();
  if (!screen->IsPrimaryScreen()) {
    // Only primary screen support mirroring
    return;
  }

  nsWindow* mirrorScreenWidget = screen->GetMirroringWidget();
  if (!mirrorScreenWidget) {
    // No mirroring
    return;
  }

  nsScreenGonk* mirrorScreen = mirrorScreenWidget->GetScreen();
  if (!mirrorScreen->GetTopWindows().IsEmpty()) {
    return;
  }

  EGLSurface surface = mirrorScreen->GetEGLSurface();
  if (surface == LOCAL_EGL_NO_SURFACE) {
    // Create GLContext
    nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateForWindow(mirrorScreenWidget);
    mirrorScreenWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
                                      reinterpret_cast<uintptr_t>(gl.get()));
    surface = mirrorScreen->GetEGLSurface();
    if (surface == LOCAL_EGL_NO_SURFACE) {
      // Failed to create EGLSurface
      return;
    }
  }
  GLContext* gl = compositor->gl();
  GLContextEGL* egl = GLContextEGL::Cast(gl);
  const IntSize windowSize = mirrorScreen->GetNaturalBounds().Size();
#endif

  if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
    return;
  }

  ScreenRotation rotation = compositor->GetScreenRotation();

  const int actualWidth = windowSize.width;
  const int actualHeight = windowSize.height;

  const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
  const nsIntRect originalRect = nsIntRect(0, 0, originalSize.width, originalSize.height);

  int pageWidth = originalSize.width;
  int pageHeight = originalSize.height;
  if (rotation == ROTATION_90 || rotation == ROTATION_270) {
    pageWidth = originalSize.height;
    pageHeight = originalSize.width;
  }

  float scale = 1.0;

  if ((pageWidth > actualWidth) || (pageHeight > actualHeight)) {
    const float scaleWidth = (float)actualWidth / (float)pageWidth;
    const float scaleHeight = (float)actualHeight / (float)pageHeight;
    scale = scaleWidth <= scaleHeight ? scaleWidth : scaleHeight;
  }

  const gfx::IntSize actualSize(actualWidth, actualHeight);
  ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);

  const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
  ScopedContextSurfaceOverride overrideSurface(egl, surface);

  Matrix viewMatrix = ComputeTransformForRotation(originalRect,
                                                  rotation);
  viewMatrix.Invert(); // unrotate
  viewMatrix.PostScale(scale, scale);
  viewMatrix.PostTranslate(offset.x, offset.y);
  Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix);

  mRoot->ComputeEffectiveTransforms(matrix);
  nsIntRegion opaque;
  ApplyOcclusionCulling(mRoot, opaque);

  nsIntRegion invalid;
  Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight);
  Rect rect, actualBounds;

  mCompositor->BeginFrame(invalid, nullptr, bounds, &rect, &actualBounds);

  // The Java side of Fennec sets a scissor rect that accounts for
  // chrome such as the URL bar. Override that so that the entire frame buffer
  // is cleared.
  ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight);
  egl->fClearColor(0.0, 0.0, 0.0, 0.0);
  egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);

  const IntRect clipRect = IntRect(0, 0, actualWidth, actualHeight);

  RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
  RootLayer()->RenderLayer(clipRect);

  mCompositor->EndFrame();
  mCompositor->SetDispAcquireFence(mRoot); // Call after EndFrame()

#ifdef MOZ_WIDGET_GONK
  nsRefPtr<Composer2D> composer2D;
  composer2D = mCompositor->GetWidget()->GetComposer2D();
  if (composer2D) {
    composer2D->Render(mirrorScreenWidget);
  }
#endif
}
示例#4
0
// Updates the contents of the root layer texture that fall inside the updateRect
// and re-composits all sublayers.
void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& visibleRect,
                                       const IntRect& contentRect, const IntPoint& scrollPosition)
{
    ASSERT(m_hardwareCompositing);

    if (!m_rootLayer)
        return;

    makeContextCurrent();

    GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId));

    // If the size of the visible area has changed then allocate a new texture
    // to store the contents of the root layer and adjust the projection matrix
    // and viewport.
    int visibleRectWidth = visibleRect.width();
    int visibleRectHeight = visibleRect.height();
    if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) {
        m_rootLayerTextureWidth = visibleRect.width();
        m_rootLayerTextureHeight = visibleRect.height();

        m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000);
        GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
    }

    // The GL viewport covers the entire visible area, including the scrollbars.
    GLC(glViewport(0, 0, visibleRectWidth, visibleRectHeight));

    // Bind the common vertex attributes used for drawing all the layers.
    LayerChromium::prepareForDraw(layerSharedValues());

    // FIXME: These calls can be made once, when the compositor context is initialized.
    GLC(glDisable(GL_DEPTH_TEST));
    GLC(glDisable(GL_CULL_FACE));
    GLC(glDepthFunc(GL_LEQUAL));
    GLC(glClearStencil(0));

    if (m_scrollPosition == IntPoint(-1, -1))
        m_scrollPosition = scrollPosition;

    IntPoint scrollDelta = toPoint(scrollPosition - m_scrollPosition);
    // Scroll only when the updateRect contains pixels for the newly uncovered region to avoid flashing.
    if ((scrollDelta.x() && updateRect.width() >= abs(scrollDelta.x()) && updateRect.height() >= contentRect.height())
        || (scrollDelta.y() && updateRect.height() >= abs(scrollDelta.y()) && updateRect.width() >= contentRect.width())) {
        // Scrolling works as follows: We render a quad with the current root layer contents
        // translated by the amount the page has scrolled since the last update and then read the
        // pixels of the content area (visible area excluding the scroll bars) back into the
        // root layer texture. The newly exposed area is subesquently filled as usual with
        // the contents of the updateRect.
        TransformationMatrix scrolledLayerMatrix;
#if PLATFORM(SKIA)
        float scaleFactor = 1.0f;
#elif PLATFORM(CG)
        // Because the contents of the OpenGL texture are inverted
        // vertically compared to the Skia backend, we need to move
        // the backing store in the opposite direction.
        float scaleFactor = -1.0f;
#else
#error "Need to implement for your platform."
#endif

        scrolledLayerMatrix.translate3d(0.5 * visibleRect.width() - scrollDelta.x(),
            0.5 * visibleRect.height() + scaleFactor * scrollDelta.y(), 0);
        scrolledLayerMatrix.scale3d(1, -1, 1);

        useShader(m_scrollShaderProgram);
        GLC(glUniform1i(m_scrollShaderSamplerLocation, 0));
        LayerChromium::drawTexturedQuad(m_projectionMatrix, scrolledLayerMatrix,
                                        visibleRect.width(), visibleRect.height(), 1,
                                        m_scrollShaderMatrixLocation, -1);

        GLC(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
        m_scrollPosition = scrollPosition;
    } else if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) {
        // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is
        // no need to copy framebuffer pixels back into the texture.
        m_scrollPosition = scrollPosition;
    }

    // FIXME: The following check should go away when the compositor renders independently from its own thread.
    // Ignore a 1x1 update rect at (0, 0) as that's used a way to kick off a redraw for the compositor.
    if (!(!updateRect.x() && !updateRect.y() && updateRect.width() == 1 && updateRect.height() == 1)) {
        // Update the root layer texture.
        ASSERT((updateRect.x() + updateRect.width() <= m_rootLayerTextureWidth)
               && (updateRect.y() + updateRect.height() <= m_rootLayerTextureHeight));

#if PLATFORM(SKIA)
        // Get the contents of the updated rect.
        const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false);
        int rootLayerWidth = bitmap.width();
        int rootLayerHeight = bitmap.height();
        ASSERT(rootLayerWidth == updateRect.width() && rootLayerHeight == updateRect.height());
        void* pixels = bitmap.getPixels();

        // Copy the contents of the updated rect to the root layer texture.
        GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels));
#elif PLATFORM(CG)
        // Get the contents of the updated rect.
        ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_rootLayerCGContext.get())) == updateRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_rootLayerCGContext.get())) == updateRect.height());
        void* pixels = m_rootLayerBackingStore.data();

        // Copy the contents of the updated rect to the root layer texture.
        // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here.
        GLC(glTexSubImage2D(GL_TEXTURE_2D, 0,
                            updateRect.x(), m_rootLayerTextureHeight - updateRect.y() - updateRect.height(),
                            updateRect.width(), updateRect.height(),
                            GL_RGBA, GL_UNSIGNED_BYTE, pixels));
#else
#error "Need to implement for your platform."
#endif
    }

    glClearColor(0, 0, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render the root layer using a quad that takes up the entire visible area of the window.
    // We reuse the shader program used by ContentLayerChromium.
    const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues();
    useShader(contentLayerValues->contentShaderProgram());
    GLC(glUniform1i(contentLayerValues->shaderSamplerLocation(), 0));
    TransformationMatrix layerMatrix;
    layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0);
    LayerChromium::drawTexturedQuad(m_projectionMatrix, layerMatrix,
                                    visibleRect.width(), visibleRect.height(), 1,
                                    contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());

    // If culling is enabled then we will cull the backface.
    GLC(glCullFace(GL_BACK));
    // The orthographic projection is setup such that Y starts at zero and
    // increases going down the page so we need to adjust the winding order of
    // front facing triangles.
    GLC(glFrontFace(GL_CW));

    // The shader used to render layers returns pre-multiplied alpha colors
    // so we need to send the blending mode appropriately.
    GLC(glEnable(GL_BLEND));
    GLC(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));

    // Translate all the composited layers by the scroll position.
    TransformationMatrix matrix;
    matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0);

    // Traverse the layer tree and update the layer transforms.
    float opacity = 1;
    const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers();
    size_t i;
    for (i = 0; i < sublayers.size(); i++)
        updateLayersRecursive(sublayers[i].get(), matrix, opacity);

    m_rootVisibleRect = visibleRect;

    // Enable scissoring to avoid rendering composited layers over the scrollbars.
    GLC(glEnable(GL_SCISSOR_TEST));
    FloatRect scissorRect(contentRect);
    // The scissorRect should not include the scroll offset.
    scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y());
    scissorToRect(scissorRect);

    // Clear the stencil buffer to 0.
    GLC(glClear(GL_STENCIL_BUFFER_BIT));
    // Disable writes to the stencil buffer.
    GLC(glStencilMask(0));

    // Traverse the layer tree one more time to draw the layers.
    for (i = 0; i < sublayers.size(); i++)
        drawLayersRecursive(sublayers[i].get(), scissorRect);

    GLC(glDisable(GL_SCISSOR_TEST));

    m_gles2Context->swapBuffers();

    m_needsDisplay = false;
}