Пример #1
0
void
LayerManagerOGL::Render()
{
    SAMPLE_LABEL("LayerManagerOGL", "Render");
    if (mDestroyed) {
        NS_WARNING("Call on destroyed layer manager");
        return;
    }

    nsIntRect rect;
    mWidget->GetClientBounds(rect);
    WorldTransformRect(rect);

    GLint width = rect.width;
    GLint height = rect.height;

    // We can't draw anything to something with no area
    // so just return
    if (width == 0 || height == 0)
        return;

    // If the widget size changed, we have to force a MakeCurrent
    // to make sure that GL sees the updated widget size.
    if (mWidgetSize.width != width ||
            mWidgetSize.height != height)
    {
        MakeCurrent(true);

        mWidgetSize.width = width;
        mWidgetSize.height = height;
    } else {
        MakeCurrent();
    }

    SetupBackBuffer(width, height);
    SetupPipeline(width, height, ApplyWorldTransform);

    // Default blend function implements "OVER"
    mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                   LOCAL_GL_ONE, LOCAL_GL_ONE);
    mGLContext->fEnable(LOCAL_GL_BLEND);

    const nsIntRect *clipRect = mRoot->GetClipRect();

    if (clipRect) {
        nsIntRect r = *clipRect;
        WorldTransformRect(r);
        mGLContext->fScissor(r.x, r.y, r.width, r.height);
    } else {
        mGLContext->fScissor(0, 0, width, height);
    }

    mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);

    mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
    mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);

    // Render our layers.
    RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
                             nsIntPoint(0, 0));

    mWidget->DrawWindowOverlay(this, rect);

#ifdef MOZ_DUMP_PAINTING
    if (gfxUtils::sDumpPainting) {
        nsIntRect rect;
        mWidget->GetBounds(rect);
        nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(rect.Size(), gfxASurface::CONTENT_COLOR_ALPHA);
        nsRefPtr<gfxContext> ctx = new gfxContext(surf);
        CopyToTarget(ctx);

        WriteSnapshotToDumpFile(this, surf);
    }
#endif

    if (mTarget) {
        CopyToTarget(mTarget);
        mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
        return;
    }

    if (sDrawFPS) {
        mFPS.DrawFPS(mGLContext, GetCopy2DProgram());
    }

    if (mGLContext->IsDoubleBuffered()) {
        mGLContext->SwapBuffers();
        LayerManager::PostPresent();
        mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
        return;
    }

    mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);

    mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);

    CopyProgram *copyprog = GetCopy2DProgram();

    if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
        copyprog = GetCopy2DRectProgram();
    }

    mGLContext->fBindTexture(mFBOTextureTarget, mBackBufferTexture);

    copyprog->Activate();
    copyprog->SetTextureUnit(0);

    if (copyprog->GetTexCoordMultiplierUniformLocation() != -1) {
        float f[] = { float(width), float(height) };
        copyprog->SetUniform(copyprog->GetTexCoordMultiplierUniformLocation(),
                             2, f);
    }

    // we're going to use client-side vertex arrays for this.
    mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);

    // "COPY"
    mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
                                   LOCAL_GL_ONE, LOCAL_GL_ZERO);

    // enable our vertex attribs; we'll call glVertexPointer below
    // to fill with the correct data.
    GLint vcattr = copyprog->AttribLocation(CopyProgram::VertexCoordAttrib);
    GLint tcattr = copyprog->AttribLocation(CopyProgram::TexCoordAttrib);

    mGLContext->fEnableVertexAttribArray(vcattr);
    mGLContext->fEnableVertexAttribArray(tcattr);

    const nsIntRect *r;
    nsIntRegionRectIterator iter(mClippingRegion);

    while ((r = iter.Next()) != nsnull) {
        nsIntRect cRect = *r;
        r = &cRect;
        WorldTransformRect(cRect);
        float left = (GLfloat)r->x / width;
        float right = (GLfloat)r->XMost() / width;
        float top = (GLfloat)r->y / height;
        float bottom = (GLfloat)r->YMost() / height;

        float vertices[] = { left * 2.0f - 1.0f,
                             -(top * 2.0f - 1.0f),
                             right * 2.0f - 1.0f,
                             -(top * 2.0f - 1.0f),
                             left * 2.0f - 1.0f,
                             -(bottom * 2.0f - 1.0f),
                             right * 2.0f - 1.0f,
                             -(bottom * 2.0f - 1.0f)
                           };

        // Use flipped texture coordinates since our
        // projection matrix also has a flip and we
        // need to cancel that out.
        float coords[] = { left, bottom,
                           right, bottom,
                           left, top,
                           right, top
                         };

        mGLContext->fVertexAttribPointer(vcattr,
                                         2, LOCAL_GL_FLOAT,
                                         LOCAL_GL_FALSE,
                                         0, vertices);

        mGLContext->fVertexAttribPointer(tcattr,
                                         2, LOCAL_GL_FLOAT,
                                         LOCAL_GL_FALSE,
                                         0, coords);

        mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
    }

    mGLContext->fDisableVertexAttribArray(vcattr);
    mGLContext->fDisableVertexAttribArray(tcattr);

    mGLContext->fFlush();
    mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
Пример #2
0
Window2DImpl::Window2DImpl(CORECSTR title, int clientWidth, int clientHeight) : WindowBaseImpl(title, clientWidth, clientHeight)
{
	SetupBackBuffer();
}