Пример #1
0
void
GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest)
{
    MOZ_ASSERT(src && dest);
    MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size());
    MOZ_ASSERT(dest->Format() == (src->HasAlpha() ? gfxImageFormat::ARGB32
                                                  : gfxImageFormat::RGB24));

    mGL->MakeCurrent();

    bool needsSwap = src != SharedSurf();
    if (needsSwap) {
        SharedSurf()->UnlockProd();
        src->LockProd();
    }

    ReadBuffer* buffer = CreateRead(src);
    MOZ_ASSERT(buffer);

    ScopedBindFramebuffer autoFB(mGL, buffer->FB());
    ReadPixelsIntoImageSurface(mGL, dest);

    delete buffer;

    if (needsSwap) {
        src->UnlockProd();
        SharedSurf()->LockProd();
    }
}
Пример #2
0
SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
                                         const IntSize& size,
                                         bool hasAlpha,
                                         SurfaceFormat format,
                                         GLuint tex)
    : SharedSurface_GL(SharedSurfaceType::Basic,
                       AttachmentType::GLTexture,
                       gl,
                       size,
                       hasAlpha)
    , mTex(tex), mFB(0)
{
    mGL->MakeCurrent();
    mGL->fGenFramebuffers(1, &mFB);

    ScopedBindFramebuffer autoFB(mGL, mFB);
    mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
                              LOCAL_GL_COLOR_ATTACHMENT0,
                              LOCAL_GL_TEXTURE_2D,
                              mTex,
                              0);

    GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
        mGL->fDeleteFramebuffers(1, &mFB);
        mFB = 0;
    }

    mData = Factory::CreateDataSourceSurfaceWithStride(size, format,
              GetAlignedStride<4>(size.width * BytesPerPixel(format)));
}
Пример #3
0
void
SharedSurface_Basic::Fence()
{
    mGL->MakeCurrent();
    ScopedBindFramebuffer autoFB(mGL, mFB);
    ReadPixelsIntoDataSurface(mGL, mData);
}
Пример #4
0
void
SharedSurface_Basic::Fence()
{
    mGL->MakeCurrent();

    ScopedBindFramebuffer autoFB(mGL, mFB);

    DataSourceSurface::MappedSurface map;
    mData->Map(DataSourceSurface::MapType::WRITE, &map);
    nsRefPtr<gfxImageSurface> wrappedData =
      new gfxImageSurface(map.mData,
                          ThebesIntSize(mData->GetSize()),
                          map.mStride,
                          SurfaceFormatToImageFormat(mData->GetFormat()));
    ReadPixelsIntoImageSurface(mGL, wrappedData);
    mData->Unmap();
}
Пример #5
0
ScopedFramebufferForRenderbuffer::ScopedFramebufferForRenderbuffer(GLContext* aGL,
                                                                   GLuint aRB)
    : ScopedGLWrapper<ScopedFramebufferForRenderbuffer>(aGL)
    , mComplete(false)
    , mFB(0)
{
    mGL->fGenFramebuffers(1, &mFB);
    ScopedBindFramebuffer autoFB(aGL, mFB);
    mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
                                  LOCAL_GL_COLOR_ATTACHMENT0,
                                  LOCAL_GL_RENDERBUFFER,
                                  aRB);

    GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
        mComplete = true;
    } else {
        mGL->fDeleteFramebuffers(1, &mFB);
        mFB = 0;
    }
}
Пример #6
0
/* ScopedFramebufferForTexture ************************************************/
ScopedFramebufferForTexture::ScopedFramebufferForTexture(GLContext* aGL,
                                                         GLuint aTexture,
                                                         GLenum aTarget)
    : ScopedGLWrapper<ScopedFramebufferForTexture>(aGL)
    , mComplete(false)
    , mFB(0)
{
    mGL->fGenFramebuffers(1, &mFB);
    ScopedBindFramebuffer autoFB(aGL, mFB);
    mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
                               LOCAL_GL_COLOR_ATTACHMENT0,
                               aTarget,
                               aTexture,
                               0);

    GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
        mComplete = true;
    } else {
        mGL->fDeleteFramebuffers(1, &mFB);
        mFB = 0;
    }
}
Пример #7
0
void
GLScreenBuffer::Attach(SharedSurface* surface, const gfx::IntSize& size)
{
    ScopedBindFramebuffer autoFB(mGL);

    SharedSurface_GL* surf = SharedSurface_GL::Cast(surface);
    if (mRead && SharedSurf())
        SharedSurf()->UnlockProd();

    surf->LockProd();

    if (mRead &&
        surf->AttachType() == SharedSurf()->AttachType() &&
        size == Size())
    {
        // Same size, same type, ready for reuse!
        mRead->Attach(surf);
    } else {
        // Else something changed, so resize:
        DrawBuffer* draw = CreateDraw(size);  // Can be null.
        ReadBuffer* read = CreateRead(surf);
        MOZ_ASSERT(read); // Should never fail if SwapProd succeeded.

        delete mDraw;
        delete mRead;

        mDraw = draw;
        mRead = read;
    }

    // Check that we're all set up.
    MOZ_ASSERT(SharedSurf() == surf);

    if (!PreserveBuffer()) {
        // DiscardFramebuffer here could help perf on some mobile platforms.
    }
}
Пример #8
0
bool
WebGLFramebuffer::ValidateAndInitAttachments(const char* funcName)
{
    MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
               mContext->mBoundReadFramebuffer == this);

    nsCString fbStatusInfo;
    const auto fbStatus = CheckFramebufferStatus(&fbStatusInfo);
    if (fbStatus != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
        nsCString errorText = nsPrintfCString("Incomplete framebuffer: Status 0x%04x",
                                              fbStatus.get());
        if (fbStatusInfo.Length()) {
            errorText += ": ";
            errorText += fbStatusInfo;
        }

        mContext->ErrorInvalidFramebufferOperation("%s: %s.", funcName,
                                                   errorText.BeginReading());
        return false;
    }

    // Cool! We've checked out ok. Just need to initialize.

    // Check if we need to initialize anything
    {
        bool hasUninitializedAttachments = false;

        if (mColorAttachment0.HasImage() && IsDrawBuffer(0))
            hasUninitializedAttachments |= mColorAttachment0.HasUninitializedImageData();

        size_t i = 1;
        for (const auto& cur : mMoreColorAttachments) {
            if (cur.HasImage() && IsDrawBuffer(i))
                hasUninitializedAttachments |= cur.HasUninitializedImageData();

            ++i;
        }

        if (mDepthAttachment.HasImage())
            hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
        if (mStencilAttachment.HasImage())
            hasUninitializedAttachments |= mStencilAttachment.HasUninitializedImageData();
        if (mDepthStencilAttachment.HasImage())
            hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();

        if (!hasUninitializedAttachments)
            return true;
    }

    // Get buffer-bit-mask and color-attachment-mask-list
    uint32_t clearBits = 0;
    std::vector<GLenum> tempDrawBuffers(1 + mMoreColorAttachments.Size(), LOCAL_GL_NONE);

    if (mColorAttachment0.HasUninitializedImageData() && IsDrawBuffer(0)) {
        clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
        tempDrawBuffers[0] = LOCAL_GL_COLOR_ATTACHMENT0;
    }

    size_t i = 1;
    for (const auto& cur : mMoreColorAttachments) {
        if (cur.HasUninitializedImageData() && IsDrawBuffer(i)) {
            clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
            tempDrawBuffers[i] = LOCAL_GL_COLOR_ATTACHMENT0 + i;
        }

        ++i;
    }

    if (mDepthAttachment.HasUninitializedImageData() ||
        mDepthStencilAttachment.HasUninitializedImageData())
    {
        clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
    }

    if (mStencilAttachment.HasUninitializedImageData() ||
        mDepthStencilAttachment.HasUninitializedImageData())
    {
        clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
    }

    mContext->MakeContextCurrent();

    const auto fnDrawBuffers = [this](const std::vector<GLenum>& list) {
        const GLenum* ptr = nullptr;
        if (list.size()) {
            ptr = &(list[0]);
        }
        this->mContext->gl->fDrawBuffers(list.size(), ptr);
    };

    const auto drawBufferExt = WebGLExtensionID::WEBGL_draw_buffers;
    const bool hasDrawBuffers = (mContext->IsWebGL2() ||
                                 mContext->IsExtensionEnabled(drawBufferExt));

    if (hasDrawBuffers) {
        fnDrawBuffers(tempDrawBuffers);
    }

    // Clear!
    {
        // This FB maybe bind to GL_READ_FRAMEBUFFER and glClear only
        // clear GL_DRAW_FRAMEBUFFER. So bind FB to GL_DRAW_FRAMEBUFFER
        // here.
        gl::ScopedBindFramebuffer autoFB(mContext->gl, mGLName);
        mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
    }

    if (hasDrawBuffers) {
        fnDrawBuffers(mDrawBuffers);
    }

    // Mark all the uninitialized images as initialized.
    if (mDepthAttachment.HasUninitializedImageData())
        mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
    if (mStencilAttachment.HasUninitializedImageData())
        mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
    if (mDepthStencilAttachment.HasUninitializedImageData())
        mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);

    if (mColorAttachment0.HasUninitializedImageData() && IsDrawBuffer(0)) {
        mColorAttachment0.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
    }

    i = 1;
    for (auto& cur : mMoreColorAttachments) {
        if (cur.HasUninitializedImageData() && IsDrawBuffer(i))
            cur.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);

        ++i;
    }

    return true;
}
void
ReadScreenIntoImageSurface(GLContext* gl, gfxImageSurface* dest)
{
    ScopedBindFramebuffer autoFB(gl, 0);
    ReadPixelsIntoImageSurface(gl, dest);
}
Пример #10
0
// `mask` from glClear.
static bool
ClearWithTempFB(WebGLContext* webgl, GLuint tex,
                TexImageTarget texImageTarget, GLint level,
                TexInternalFormat baseInternalFormat,
                GLsizei width, GLsizei height)
{
    MOZ_ASSERT(texImageTarget == LOCAL_GL_TEXTURE_2D);

    gl::GLContext* gl = webgl->GL();
    MOZ_ASSERT(gl->IsCurrent());

    gl::ScopedFramebuffer fb(gl);
    gl::ScopedBindFramebuffer autoFB(gl, fb.FB());
    GLbitfield mask = 0;

    switch (baseInternalFormat.get()) {
    case LOCAL_GL_LUMINANCE:
    case LOCAL_GL_LUMINANCE_ALPHA:
    case LOCAL_GL_ALPHA:
    case LOCAL_GL_RGB:
    case LOCAL_GL_RGBA:
    case LOCAL_GL_BGR:
    case LOCAL_GL_BGRA:
        mask = LOCAL_GL_COLOR_BUFFER_BIT;
        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
                                  texImageTarget.get(), tex, level);
        break;
    case LOCAL_GL_DEPTH_COMPONENT32_OES:
    case LOCAL_GL_DEPTH_COMPONENT24_OES:
    case LOCAL_GL_DEPTH_COMPONENT16:
    case LOCAL_GL_DEPTH_COMPONENT:
        mask = LOCAL_GL_DEPTH_BUFFER_BIT;
        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
                                  texImageTarget.get(), tex, level);
        break;

    case LOCAL_GL_DEPTH24_STENCIL8:
    case LOCAL_GL_DEPTH_STENCIL:
        mask = LOCAL_GL_DEPTH_BUFFER_BIT |
               LOCAL_GL_STENCIL_BUFFER_BIT;
        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
                                  texImageTarget.get(), tex, level);
        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
                                  texImageTarget.get(), tex, level);
        break;

    default:
        return false;
    }
    MOZ_ASSERT(mask);

    if (ClearByMask(webgl, mask))
        return true;

    // Failed to simply build an FB from the tex, but maybe it needs a
    // color buffer to be complete.

    if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
        // Nope, it already had one.
        return false;
    }

    gl::ScopedRenderbuffer rb(gl);
    {
        // Only GLES guarantees RGBA4.
        GLenum format = gl->IsGLES() ? LOCAL_GL_RGBA4 : LOCAL_GL_RGBA8;
        gl::ScopedBindRenderbuffer rbBinding(gl, rb.RB());
        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, width, height);
    }

    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
                                 LOCAL_GL_RENDERBUFFER, rb.RB());
    mask |= LOCAL_GL_COLOR_BUFFER_BIT;

    // Last chance!
    return ClearByMask(webgl, mask);
}