void djvOpenGlImageShader::init(
    const QString & vertex,
    const QString & fragment) throw (djvError)
{
    if (vertex == _vertex && fragment == _fragment)
        return;

    //DJV_DEBUG("djvOpenGlImageShader::init");
    //DJV_DEBUG_PRINT("fragment = " << fragment);

    del();

    _vertex   = vertex;
    _fragment = fragment;

    GLint error = GL_FALSE;

    _vertexId   = shaderCreate(GL_VERTEX_SHADER);
    _fragmentId = shaderCreate(GL_FRAGMENT_SHADER);

    shaderCompile(_vertexId,   _vertex);
    shaderCompile(_fragmentId, _fragment);

    DJV_DEBUG_OPEN_GL(_program = glCreateProgram());

    if (! _program)
    {
        throw djvError(
            "djvOpenGlImageShader",
            djvOpenGlImage::errorLabels()[djvOpenGlImage::ERROR_CREATE_PROGRAM]);
    }

    DJV_DEBUG_OPEN_GL(glAttachShader(_program, _vertexId));
    DJV_DEBUG_OPEN_GL(glAttachShader(_program, _fragmentId));
    DJV_DEBUG_OPEN_GL(glLinkProgram (_program));

    glGetProgramiv(_program, GL_LINK_STATUS, &error);

    char log [4096] = "";
    GLsizei logSize = 0;
    glGetProgramInfoLog(_program, 4096, &logSize, log);

    //DJV_DEBUG_PRINT("log = " << QString(log));

    if (error != GL_TRUE)
    {
        throw djvError(
            "djvOpenGlImageShader",
            djvOpenGlImage::errorLabels()[djvOpenGlImage::ERROR_CREATE_PROGRAM].
            arg(log));
    }
}
void djvOpenGlImageTexture::copy(const djvVector2i & in)
{
    //DJV_DEBUG("djvOpenGlImageTexture::copy");
    //DJV_DEBUG_PRINT("in = " << in);

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, _id));

    DJV_DEBUG_OPEN_GL(
        glCopyTexSubImage2D(
            GL_TEXTURE_2D,
            0,
            0,
            0,
            0,
            0,
            in.x,
            in.y));
}
void djvGlslTestAbstractOp::begin()
{
    //DJV_DEBUG("djvGlslTestAbstractOp::begin");

    DJV_DEBUG_OPEN_GL(glPushAttrib(
        GL_VIEWPORT_BIT |
        GL_CURRENT_BIT |
        GL_ENABLE_BIT |
        GL_TRANSFORM_BIT |
        GL_PIXEL_MODE_BIT |
        GL_TEXTURE_BIT));
}
Exemple #4
0
void djvGlslTestOffscreen::init() throw (djvError)
{
    if (_id)
        return;

    //DJV_DEBUG("djvGlslTestOffscreen::init");

    DJV_DEBUG_OPEN_GL(glGenFramebuffers(1, &_id));

    if (! _id)
        throw djvError("glGenFramebuffers");
}
Exemple #5
0
void djvGlslTestOffscreen::set(const djvOpenGlTexture & in)
{
    //DJV_DEBUG("djvGlslTestOffscreen::set");

    fboCheck();

    DJV_DEBUG_OPEN_GL(glFramebufferTexture2D(
        GL_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_RECTANGLE,
        in.id(),
        0));
}
void djvOpenGlImageTexture::copy(const djvPixelData & in)
{
    //DJV_DEBUG("djvOpenGlImageTexture::copy");
    //DJV_DEBUG_PRINT("in = " << in);

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, _id));

    const djvPixelDataInfo & info = in.info();

    djvOpenGlImage::stateUnpack(in.info());

    DJV_DEBUG_OPEN_GL(
        glTexSubImage2D(
            GL_TEXTURE_2D,
            0,
            0,
            0,
            info.size.x,
            info.size.y,
            djvOpenGlUtil::format(info.pixel, info.bgr),
            djvOpenGlUtil::type(info.pixel),
            in.data()));
}
Exemple #7
0
void djvOpenGlLut::init(const djvPixelDataInfo & info) throw (djvError)
{
    if (info == _info)
        return;

    //DJV_DEBUG("djvOpenGlLut::init");
    //DJV_DEBUG_PRINT("info = " << info);

    del();

    _info = info;
    _size = djvMath::toPow2(_info.size.x);

    //DJV_DEBUG_PRINT("size = " << _size);

    DJV_DEBUG_OPEN_GL(glGenTextures(1, &_id));

    if (! _id)
    {
        throw djvError(
            "djvOpenGlLut",
            qApp->translate("djvOpenGlLut", "Cannot create texture"));
    }

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_1D, _id));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));

    GLenum format = GL_RGBA;

    if (djvPixel::F16 == djvPixel::type(_info.pixel))
    {
        format = GL_RGBA16F;
    }
    else if (djvPixel::F32 == djvPixel::type(_info.pixel))
    {
        format = GL_RGBA32F;
    }

    DJV_DEBUG_OPEN_GL(
        glTexImage1D(
            GL_TEXTURE_1D,
            0,
            format,
            _size,
            0,
            djvOpenGlUtil::format(_info.pixel, _info.bgr),
            djvOpenGlUtil::type(_info.pixel),
            0));
}
Exemple #8
0
void djvGlslTestOffscreen::bind()
{
    //DJV_DEBUG("djvGlslTestOffscreen::bind");

    DJV_DEBUG_OPEN_GL(glBindFramebuffer(GL_FRAMEBUFFER, _id));
}
Exemple #9
0
void djvOpenGlLut::bind()
{
    //DJV_DEBUG("djvOpenGlLut::bind");

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_1D, _id));
}
void djvOpenGlImageShader::bind()
{
    //DJV_DEBUG("djvOpenGlImageShader::bind");

    DJV_DEBUG_OPEN_GL(glUseProgram(_program));
}
void djvOpenGlImageTexture::bind()
{
    //DJV_DEBUG("djvOpenGlImageTexture::bind");

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, _id));
}
void djvOpenGlImageTexture::init(
    const djvPixelDataInfo & info,
    GLenum                   min,
    GLenum                   mag) throw (djvError)
{
    if (info == _info && min == _min && mag == _mag)
        return;

    del();

    //DJV_DEBUG("djvOpenGlImageTexture::init");
    //DJV_DEBUG_PRINT("info = " << info);

    _info = info;
    _min  = min;
    _mag  = mag;

    DJV_DEBUG_OPEN_GL(glGenTextures(1, &_id));

    //DJV_DEBUG_PRINT("id = " << int(_id));

    if (! _id)
    {
        throw djvError(
            "djvOpenGlImageTexture",
            djvOpenGlImage::errorLabels()[djvOpenGlImage::ERROR_CREATE_TEXTURE]);
    }

    DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, _id));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min));
    DJV_DEBUG_OPEN_GL(
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag));

    GLenum format = GL_RGBA;

    if (djvPixel::F16 == djvPixel::type(_info.pixel))
    {
        format = GL_RGBA16F;
    }
    else if (djvPixel::F32 == djvPixel::type(_info.pixel))
    {
        format = GL_RGBA32F;
    }

    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        format,
        _info.size.x,
        _info.size.y,
        0,
        djvOpenGlUtil::format(_info.pixel, _info.bgr),
        djvOpenGlUtil::type(_info.pixel),
        0);
    
    GLenum error = glGetError();
    
#if ! defined(DJV_OSX)

    //! \todo On OS X this error is triggered the first time djv_view is
    //! started, though it doesn't actually seem to be a problem? If we
    //! throw here the image is not displayed (start djv_view from the
    //! command line with an image), but if we igore the error the image is
    //! displayed OK? Is this related to the "invalid drawable" message we
    //! are also getting on start up?
    
    if (error != GL_NO_ERROR)
    {
        throw djvError(
            "djvOpenGlImageTexture",
            djvOpenGlImage::errorLabels()[djvOpenGlImage::ERROR_CREATE_TEXTURE2].
            arg((char *)gluErrorString(error)));
    }
    
#endif // DJV_OSX
}
void djvOpenGlImage::draw(
    const djvPixelData &          data,
    const djvOpenGlImageOptions & options,
    djvOpenGlImageState *         state) throw (djvError)
{
    //DJV_DEBUG("djvOpenGlImage::draw");
    //DJV_DEBUG_PRINT("data = " << data);
    //DJV_DEBUG_PRINT("color profile = " << options.colorProfile);
    
    RestoreState restoreState;

    djvOpenGlImageState defaultState;

    if (! state)
    {
        state = &defaultState;
    }

    const djvPixelDataInfo & info = data.info();

    const int proxyScale =
        options.proxyScale ?
        djvPixelDataUtil::proxyScale(info.proxy) :
        1;

    const djvVector2i scale = djvVectorUtil::ceil<double, int>(
        options.xform.scale * djvVector2f(info.size * proxyScale));

    const djvVector2i scaleTmp(scale.x, data.h());

    //DJV_DEBUG_PRINT("scale = " << scale);
    //DJV_DEBUG_PRINT("scale tmp = " << scaleTmp);

    // Initialize.

    const djvOpenGlImageFilter::FILTER filter =
        info.size == scale ? djvOpenGlImageFilter::NEAREST :
        (djvVectorUtil::area(scale) < djvVectorUtil::area(info.size) ?
         options.filter.min : options.filter.mag);

    //DJV_DEBUG_PRINT("filter min = " << options.filter.min);
    //DJV_DEBUG_PRINT("filter mag = " << options.filter.mag);
    //DJV_DEBUG_PRINT("filter = " << filter);

    if (! state->_init || state->_info != info || state->_options != options)
    {
        switch (filter)
        {
            case djvOpenGlImageFilter::NEAREST:
            case djvOpenGlImageFilter::LINEAR:
            {
                //DJV_DEBUG_PRINT("init single pass");

                state->_texture->init(
                    data.info(),
                    djvOpenGlImageFilter::toGl(filter),
                    djvOpenGlImageFilter::toGl(filter));

                state->_shader->init(
                    sourceVertex,
                    sourceFragment(
                        options.colorProfile.type,
                        options.displayProfile,
                        options.channel,
                        false,
                        0,
                        false));
            }
            break;

            case djvOpenGlImageFilter::BOX:
            case djvOpenGlImageFilter::TRIANGLE:
            case djvOpenGlImageFilter::BELL:
            case djvOpenGlImageFilter::BSPLINE:
            case djvOpenGlImageFilter::LANCZOS3:
            case djvOpenGlImageFilter::CUBIC:
            case djvOpenGlImageFilter::MITCHELL:
            {
                //DJV_DEBUG_PRINT("init two pass");

                state->_texture->init(
                    data.info(),
                    GL_NEAREST,
                    GL_NEAREST);

                // Initialize horizontal pass.

                djvPixelData contrib;

                scaleContrib(
                    data.w(),
                    scale.x,
                    filter,
                    contrib);

                state->_scaleXContrib->init(
                    contrib,
                    GL_NEAREST,
                    GL_NEAREST);

                state->_scaleXShader->init(
                    sourceVertex,
                    sourceFragment(
                        options.colorProfile.type,
                        djvOpenGlImageDisplayProfile(),
                        static_cast<djvOpenGlImageOptions::CHANNEL>(0),
                        true,
                        contrib.h(),
                        true));

                // Initialize vertical pass.

                scaleContrib(
                    data.h(),
                    scale.y,
                    filter,
                    contrib);

                state->_scaleYContrib->init(
                    contrib,
                    GL_NEAREST,
                    GL_NEAREST);

                state->_scaleYShader->init(
                    sourceVertex,
                    sourceFragment(
                        static_cast<djvColorProfile::PROFILE>(0),
                        options.displayProfile,
                        options.channel,
                        true,
                        contrib.h(),
                        false));
            }
            break;

            default: break;
        }

        state->_init    = true;
        state->_info    = info;
        state->_options = options;
    }

    // Render.

    const djvPixelDataInfo::Mirror mirror(
        info.mirror.x ? (! options.xform.mirror.x) : options.xform.mirror.x,
        info.mirror.y ? (! options.xform.mirror.y) : options.xform.mirror.y);

    //DJV_DEBUG_PRINT("mirror = " << mirror.x << " " << mirror.y);

    switch (filter)
    {
        case djvOpenGlImageFilter::NEAREST:
        case djvOpenGlImageFilter::LINEAR:
        {
            //DJV_DEBUG_PRINT("draw single pass");

            state->_shader->bind();

            // Initialize color and display profiles.

            colorProfileInit(
                options,
                state->_shader->program(),
                *state->_lutColorProfile);

            displayProfileInit(
                options,
                state->_shader->program(),
                *state->_lutDisplayProfile);

            // Draw.

            activeTexture(GL_TEXTURE0);

            uniform1i(state->_shader->program(), "inTexture", 0);

            state->_texture->copy(data);
            state->_texture->bind();

            DJV_DEBUG_OPEN_GL(glPushMatrix());
            const djvMatrix3f m = djvOpenGlImageXform::xformMatrix(options.xform);
            //DJV_DEBUG_PRINT("m = " << m);
            DJV_DEBUG_OPEN_GL(glLoadMatrixd(djvMatrixUtil::matrix4(m).e));

            quad(info.size, mirror, proxyScale);

            DJV_DEBUG_OPEN_GL(glPopMatrix());
        }
        break;

        case djvOpenGlImageFilter::BOX:
        case djvOpenGlImageFilter::TRIANGLE:
        case djvOpenGlImageFilter::BELL:
        case djvOpenGlImageFilter::BSPLINE:
        case djvOpenGlImageFilter::LANCZOS3:
        case djvOpenGlImageFilter::CUBIC:
        case djvOpenGlImageFilter::MITCHELL:
        {
            //DJV_DEBUG_PRINT("draw two pass");

            // Horizontal pass.

            djvOpenGlOffscreenBuffer buffer(
                djvPixelDataInfo(scaleTmp, data.pixel()));

            {
                djvOpenGlOffscreenBufferScope bufferScope(&buffer);

                state->_scaleXShader->bind();

                colorProfileInit(
                    options,
                    state->_scaleXShader->program(),
                    *state->_lutColorProfile);

                activeTexture(GL_TEXTURE0);

                uniform1i(state->_scaleXShader->program(), "inTexture", 0);

                state->_texture->copy(data);
                state->_texture->bind();

                activeTexture(GL_TEXTURE1);

                uniform1i(
                    state->_scaleXShader->program(), "inScaleContrib", 1);

                state->_scaleXContrib->bind();

                glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT);
                glMatrixMode(GL_PROJECTION);
                glPushMatrix();
                glMatrixMode(GL_MODELVIEW);
                glPushMatrix();

                djvOpenGlUtil::ortho(scaleTmp);
                glViewport(0, 0, scaleTmp.x, scaleTmp.y);
                quad(scaleTmp, mirror);

                glMatrixMode(GL_PROJECTION);
                glPopMatrix();
                glMatrixMode(GL_MODELVIEW);
                glPopMatrix();
                glPopAttrib();
            }

            // Vertical pass.

            state->_scaleYShader->bind();

            displayProfileInit(
                options,
                state->_scaleYShader->program(),
                *state->_lutDisplayProfile);

            activeTexture(GL_TEXTURE0);

            uniform1i(state->_scaleYShader->program(), "inTexture", 0);

            DJV_DEBUG_OPEN_GL(glBindTexture(GL_TEXTURE_2D, buffer.texture()));

            activeTexture(GL_TEXTURE1);

            uniform1i(state->_scaleYShader->program(), "inScaleContrib", 1);

            state->_scaleYContrib->bind();

            djvOpenGlImageXform xform = options.xform;
            xform.scale = djvVector2f(1.0);
            const djvMatrix3f m = djvOpenGlImageXform::xformMatrix(xform);

            DJV_DEBUG_OPEN_GL(glPushMatrix());
            DJV_DEBUG_OPEN_GL(glLoadMatrixd(djvMatrixUtil::matrix4(m).e));

            quad(scale);

            DJV_DEBUG_OPEN_GL(glPopMatrix());
        }
        break;

        default: break;
    }
}