示例#1
0
void
LayerManagerOGL::CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
                                      GLuint aCurrentFrameBuffer,
                                      GLuint *aFBO, GLuint *aTexture)
{
    GLuint tex, fbo;

    mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
    mGLContext->fGenTextures(1, &tex);
    mGLContext->fBindTexture(mFBOTextureTarget, tex);
    if (aInit == InitModeCopy) {
        // We're going to create an RGBA temporary fbo.  But to
        // CopyTexImage() from the current framebuffer, the framebuffer's
        // format has to be compatible with the new texture's.  So we
        // check the format of the framebuffer here and take a slow path
        // if it's incompatible.
        GLenum format =
            GetFrameBufferInternalFormat(gl(), aCurrentFrameBuffer, mWidget);
        if (AreFormatsCompatibleForCopyTexImage2D(format, LOCAL_GL_RGBA)) {
            mGLContext->fCopyTexImage2D(mFBOTextureTarget,
                                        0,
                                        LOCAL_GL_RGBA,
                                        aRect.x, aRect.y,
                                        aRect.width, aRect.height,
                                        0);
        } else {
            // Curses, incompatible formats.  Take a slow path.
            //
            // XXX Technically CopyTexSubImage2D also has the requirement of
            // matching formats, but it doesn't seem to affect us in the
            // real world.
            mGLContext->fTexImage2D(mFBOTextureTarget,
                                    0,
                                    LOCAL_GL_RGBA,
                                    aRect.width, aRect.height,
                                    0,
                                    LOCAL_GL_RGBA,
                                    LOCAL_GL_UNSIGNED_BYTE,
                                    NULL);
            mGLContext->fCopyTexSubImage2D(mFBOTextureTarget,
                                           0,    // level
                                           0, 0, // offset
                                           aRect.x, aRect.y,
                                           aRect.width, aRect.height);
        }
    } else {
        mGLContext->fTexImage2D(mFBOTextureTarget,
                                0,
                                LOCAL_GL_RGBA,
                                aRect.width, aRect.height,
                                0,
                                LOCAL_GL_RGBA,
                                LOCAL_GL_UNSIGNED_BYTE,
                                NULL);
    }
    mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MIN_FILTER,
                               LOCAL_GL_LINEAR);
    mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER,
                               LOCAL_GL_LINEAR);
    mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S,
                               LOCAL_GL_CLAMP_TO_EDGE);
    mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T,
                               LOCAL_GL_CLAMP_TO_EDGE);
    mGLContext->fBindTexture(mFBOTextureTarget, 0);

    mGLContext->fGenFramebuffers(1, &fbo);
    mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
    mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
                                      LOCAL_GL_COLOR_ATTACHMENT0,
                                      mFBOTextureTarget,
                                      tex,
                                      0);

    // Making this call to fCheckFramebufferStatus prevents a crash on
    // PowerVR. See bug 695246.
    GLenum result = mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
        nsCAutoString msg;
        msg.Append("Framebuffer not complete -- error 0x");
        msg.AppendInt(result, 16);
        msg.Append(", mFBOTextureTarget 0x");
        msg.AppendInt(mFBOTextureTarget, 16);
        msg.Append(", aRect.width ");
        msg.AppendInt(aRect.width);
        msg.Append(", aRect.height ");
        msg.AppendInt(aRect.height);
        NS_RUNTIMEABORT(msg.get());
    }

    SetupPipeline(aRect.width, aRect.height, DontApplyWorldTransform);
    mGLContext->fScissor(0, 0, aRect.width, aRect.height);

    if (aInit == InitModeClear) {
        mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
        mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
    }

    *aFBO = fbo;
    *aTexture = tex;
}
void
CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, SurfaceInitMode aInit,
                                    GLuint aSourceFrameBuffer,
                                    GLuint *aFBO, GLuint *aTexture)
{
  GLuint tex, fbo;

  mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
  mGLContext->fGenTextures(1, &tex);
  mGLContext->fBindTexture(mFBOTextureTarget, tex);

  if (aInit == INIT_MODE_COPY) {
    GLuint curFBO = mCurrentRenderTarget->GetFBO();
    if (curFBO != aSourceFrameBuffer) {
      mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aSourceFrameBuffer);
    }

    // We're going to create an RGBA temporary fbo.  But to
    // CopyTexImage() from the current framebuffer, the framebuffer's
    // format has to be compatible with the new texture's.  So we
    // check the format of the framebuffer here and take a slow path
    // if it's incompatible.
    GLenum format =
      GetFrameBufferInternalFormat(gl(), aSourceFrameBuffer, mWidget);

    bool isFormatCompatibleWithRGBA
        = gl()->IsGLES2() ? (format == LOCAL_GL_RGBA)
                          : true;

    if (isFormatCompatibleWithRGBA) {
      mGLContext->fCopyTexImage2D(mFBOTextureTarget,
                                  0,
                                  LOCAL_GL_RGBA,
                                  aRect.x, aRect.y,
                                  aRect.width, aRect.height,
                                  0);
    } else {
      // Curses, incompatible formats.  Take a slow path.

      // RGBA
      size_t bufferSize = aRect.width * aRect.height * 4;
      nsAutoArrayPtr<uint8_t> buf(new uint8_t[bufferSize]);

      mGLContext->fReadPixels(aRect.x, aRect.y,
                              aRect.width, aRect.height,
                              LOCAL_GL_RGBA,
                              LOCAL_GL_UNSIGNED_BYTE,
                              buf);
      mGLContext->fTexImage2D(mFBOTextureTarget,
                              0,
                              LOCAL_GL_RGBA,
                              aRect.width, aRect.height,
                              0,
                              LOCAL_GL_RGBA,
                              LOCAL_GL_UNSIGNED_BYTE,
                              buf);
    }
    GLenum error = mGLContext->GetAndClearError();
    if (error != LOCAL_GL_NO_ERROR) {
      nsAutoCString msg;
      msg.AppendPrintf("Texture initialization failed! -- error 0x%x, Source %d, Source format %d,  RGBA Compat %d",
                       error, aSourceFrameBuffer, format, isFormatCompatibleWithRGBA);
      NS_ERROR(msg.get());
    }
  } else {
    mGLContext->fTexImage2D(mFBOTextureTarget,
                            0,
                            LOCAL_GL_RGBA,
                            aRect.width, aRect.height,
                            0,
                            LOCAL_GL_RGBA,
                            LOCAL_GL_UNSIGNED_BYTE,
                            nullptr);
  }
  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MIN_FILTER,
                             LOCAL_GL_LINEAR);
  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER,
                             LOCAL_GL_LINEAR);
  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S,
                             LOCAL_GL_CLAMP_TO_EDGE);
  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T,
                             LOCAL_GL_CLAMP_TO_EDGE);
  mGLContext->fBindTexture(mFBOTextureTarget, 0);

  mGLContext->fGenFramebuffers(1, &fbo);

  *aFBO = fbo;
  *aTexture = tex;
}