Example #1
0
void
DrawBlitProg::Draw(const BaseArgs& args, const YUVArgs* const argsYUV) const
{
    const auto& gl = mParent.mGL;

    const SaveRestoreCurrentProgram oldProg(gl);
    gl->fUseProgram(mProg);

    // --

    Mat3 destMatrix;
    if (args.destRect) {
        const auto& destRect = args.destRect.value();
        destMatrix = SubRectMat3(destRect.X() / args.destSize.width,
                                 destRect.Y() / args.destSize.height,
                                 destRect.Width() / args.destSize.width,
                                 destRect.Height() / args.destSize.height);
    } else {
        destMatrix = Mat3::I();
    }

    if (args.yFlip) {
        // Apply the y-flip matrix before the destMatrix.
        // That is, flip y=[0-1] to y=[1-0] before we restrict to the destRect.
        destMatrix.at(2,1) += destMatrix.at(1,1);
        destMatrix.at(1,1) *= -1.0f;
    }

    gl->fUniformMatrix3fv(mLoc_uDestMatrix, 1, false, destMatrix.m);
    gl->fUniformMatrix3fv(mLoc_uTexMatrix0, 1, false, args.texMatrix0.m);

    MOZ_ASSERT(bool(argsYUV) == (mLoc_uColorMatrix != -1));
    if (argsYUV) {
        gl->fUniformMatrix3fv(mLoc_uTexMatrix1, 1, false, argsYUV->texMatrix1.m);

        const auto& colorMatrix = gfxUtils::YuvToRgbMatrix4x4ColumnMajor(argsYUV->colorSpace);
        float mat4x3[4*3];
        switch (mType_uColorMatrix) {
        case LOCAL_GL_FLOAT_MAT4:
            gl->fUniformMatrix4fv(mLoc_uColorMatrix, 1, false, colorMatrix);
            break;
        case LOCAL_GL_FLOAT_MAT4x3:
            for (int x = 0; x < 4; x++) {
                for (int y = 0; y < 3; y++) {
                    mat4x3[3*x+y] = colorMatrix[4*x+y];
                }
            }
            gl->fUniformMatrix4x3fv(mLoc_uColorMatrix, 1, false, mat4x3);
            break;
        default:
            gfxCriticalError() << "Bad mType_uColorMatrix: "
                               << gfx::hexa(mType_uColorMatrix);
        }
    }

    // --

    const ScopedDrawBlitState drawState(gl, args.destSize);

    GLuint oldVAO;
    GLint vaa0Enabled;
    GLint vaa0Size;
    GLenum vaa0Type;
    GLint vaa0Normalized;
    GLsizei vaa0Stride;
    GLvoid* vaa0Pointer;
    if (mParent.mQuadVAO) {
        oldVAO = gl->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
        gl->fBindVertexArray(mParent.mQuadVAO);
    } else {
        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vaa0Enabled);
        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &vaa0Size);
        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint*)&vaa0Type);
        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vaa0Normalized);
        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, (GLint*)&vaa0Stride);
        gl->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &vaa0Pointer);

        gl->fEnableVertexAttribArray(0);
        const ScopedBindArrayBuffer bindVBO(gl, mParent.mQuadVBO);
        gl->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
    }

    gl->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);

    if (mParent.mQuadVAO) {
        gl->fBindVertexArray(oldVAO);
    } else {
        if (vaa0Enabled) {
            gl->fEnableVertexAttribArray(0);
        } else {
            gl->fDisableVertexAttribArray(0);
        }
        gl->fVertexAttribPointer(0, vaa0Size, vaa0Type, bool(vaa0Normalized), vaa0Stride,
                                 vaa0Pointer);
    }
}