Beispiel #1
0
bool ImageConverter::prepareData()
{
    DPTR_D(ImageConverter);
    if (d.fmt_out == QTAV_PIX_FMT_C(NONE) || d.w_out <=0 || d.h_out <= 0)
        return false;
    AV_ENSURE(av_image_check_size(d.w_out, d.h_out, 0, NULL), false);
    const int nb_planes = qMax(av_pix_fmt_count_planes(d.fmt_out), 0);
    d.bits.resize(nb_planes);
    d.pitchs.resize(nb_planes);
    // alignment is 16. sws in ffmpeg is 16, libav10 is 8
    const int kAlign = 16;
    AV_ENSURE(av_image_fill_linesizes((int*)d.pitchs.constData(), d.fmt_out, kAlign > 7 ? FFALIGN(d.w_out, 8) : d.w_out), false);
    for (int i = 0; i < d.pitchs.size(); ++i)
        d.pitchs[i] = FFALIGN(d.pitchs[i], kAlign);
    int s = av_image_fill_pointers((uint8_t**)d.bits.constData(), d.fmt_out, d.h_out, NULL, d.pitchs.constData());
    if (s < 0)
        return false;
    d.data_out.resize(s + kAlign-1);
    const int offset = (kAlign - ((uintptr_t)d.data_out.constData() & (kAlign-1))) & (kAlign-1);
    AV_ENSURE(av_image_fill_pointers((uint8_t**)d.bits.constData(), d.fmt_out, d.h_out, (uint8_t*)d.data_out.constData()+offset, d.pitchs.constData()), false);
    // TODO: special formats
    //if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
       //    avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt);
    for (int i = 0; i < d.pitchs.size(); ++i) {
        Q_ASSERT(d.pitchs[i]%kAlign == 0);
        Q_ASSERT(qptrdiff(d.bits[i])%kAlign == 0);
    }
    return true;
}
Beispiel #2
0
void GeometryRenderer::updateGeometry(Geometry *geo)
{
    g = geo;
    if (!g) {
        ibo.destroy();
        vbo.destroy();
#if QT_VAO
        vao.destroy();
#endif
        vbo_size = 0;
        ibo_size = 0;
        return;
    }
    static int support_map = -1;
    if (support_map < 0) {
        static const char* ext[] = { "GL_OES_mapbuffer", NULL};
        if (OpenGLHelper::isOpenGLES()) {
            support_map = QOpenGLContext::currentContext()->format().majorVersion() > 2 ||
                    OpenGLHelper::hasExtension(ext);
        } else {
            support_map = 1;
        }
    }
    if (testFeatures(kIBO) && !ibo.isCreated()) {
        if (g->indexCount() > 0) {
            qDebug("creating IBO...");
            if (!ibo.create())
                qDebug("IBO create error");
        }
    }
    if (ibo.isCreated()) {
        ibo.bind();
        const int bs = g->indexDataSize();
        if (bs == ibo_size) {
            void * p = NULL;
            if (support_map && testFeatures(kMapBuffer))
                p = ibo.map(QOpenGLBuffer::WriteOnly);
            if (p) {
                memcpy(p, g->constIndexData(), bs);
                ibo.unmap();
            } else {
                ibo.write(0, g->constIndexData(), bs);
            }
        } else {
            ibo.allocate(g->indexData(), bs); // TODO: allocate NULL and then map or BufferSubData?
            ibo_size = bs;
        }
        ibo.release();
    }
    if (testFeatures(kVBO) && !vbo.isCreated()) {
        qDebug("creating VBO...");
        if (!vbo.create())
            qWarning("VBO create error");
    }
    if (vbo.isCreated()) {
        vbo.bind();
        const int bs = g->vertexCount()*g->stride();
        /* Notes from https://www.opengl.org/sdk/docs/man/html/glBufferSubData.xhtml
           When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.
         */
        if (bs == vbo_size) { // vbo.size() error 0x501 on rpi, and query gl value can be slow
            void* p = NULL;
            if (support_map && testFeatures(kMapBuffer))
                p = vbo.map(QOpenGLBuffer::WriteOnly);
            if (p) {
                memcpy(p, g->constVertexData(), bs);
                vbo.unmap();
            } else {
                vbo.write(0, g->constVertexData(), bs);
                vbo_size = bs;
            }
        } else {
            vbo.allocate(g->vertexData(), bs);
        }
        vbo.release();
    }
#if QT_VAO
    if (stride == g->stride() && attrib == g->attributes())
        return;
    stride = g->stride();
    attrib = g->attributes();

    if (testFeatures(kVAO) && !vao.isCreated()) {
        qDebug("creating VAO...");
        if (!vao.create())
            qDebug("VAO create error");
    }
    qDebug("vao updated");
    if (vao.isCreated()) // can not use vao binder because it will create a vao if necessary
        vao.bind();
// can set data before vao bind
    if (!vao.isCreated())
        return;
    qDebug("geometry attributes changed, rebind vao...");
    // call once is enough if no feature and no geometry attribute is changed
    if (vbo.isCreated()) {
        vbo.bind();
        for (int an = 0; an < g->attributes().size(); ++an) {
            // FIXME: assume bind order is 0,1,2...
            const Attribute& a = g->attributes().at(an);
            QGLF(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), reinterpret_cast<const void *>(qptrdiff(a.offset())))); //TODO: in setActiveShader
            QGLF(glEnableVertexAttribArray(an));
        }
        vbo.release(); // unbind after vao unbind? http://www.zwqxin.com/archives/opengl/vao-and-vbo-stuff.html
    } // TODO: bind pointers if vbo is disabled
    // bind ibo to vao thus no bind is required later
    if (ibo.isCreated())// if not bind here, glDrawElements(...,NULL) crashes and must use ibo data ptr, why?
        ibo.bind();
    vao.release();
    if (ibo.isCreated())
        ibo.release();
#endif
    qDebug("geometry updated");
}