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; }
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"); }