Skip to content

Commit

Permalink
gl: refine GeometryRenderer. no qopenglshaderprogram
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Jul 23, 2016
1 parent b377fbe commit 07d63bc
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 76 deletions.
104 changes: 55 additions & 49 deletions src/opengl/GeometryRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,40 @@
namespace QtAV {

GeometryRenderer::GeometryRenderer()
: program(NULL)
, g(NULL)
, try_vbo(true)
, try_vao(true)
, try_ibo(true)
: g(NULL)
, features_(kVBO|kIBO|kVAO)
, ibo(QOpenGLBuffer::IndexBuffer)
{
static bool disable_vbo = qgetenv("QTAV_NO_VBO").toInt() > 0;
try_vbo = !disable_vbo;
setFeature(kVBO, !disable_vbo);
static bool disable_vao = qgetenv("QTAV_NO_VAO").toInt() > 0;
try_vao = !disable_vao;
setFeature(kVAO, !disable_vao);
}

void GeometryRenderer::setShaderProgram(QOpenGLShaderProgram *sp)
void GeometryRenderer::setFeature(int f, bool on)
{
program = sp;
if (on)
features_ |= f;
else
features_ ^= f;
}

bool GeometryRenderer::updateBuffers(Geometry *geo)
void GeometryRenderer::setFeatures(int value)
{
features_ = value;
}

int GeometryRenderer::features() const
{
return features_;
}

bool GeometryRenderer::testFeatures(int value) const
{
return !!(features() & value);
}

bool GeometryRenderer::updateGeometry(Geometry *geo)
{
g = geo;
if (!g) {
Expand All @@ -52,10 +67,10 @@ bool GeometryRenderer::updateBuffers(Geometry *geo)
ibo.destroy();
return true;
}
if (try_ibo && g->indexCount() > 0) {
if (testFeatures(kIBO) && g->indexCount() > 0) {
if (!ibo.isCreated()) {
if (!ibo.create()) {
try_ibo = false;
setFeature(kIBO, false);
qDebug("IBO is not supported");
}
}
Expand All @@ -65,14 +80,14 @@ bool GeometryRenderer::updateBuffers(Geometry *geo)
ibo.release();
}
}
if (!try_vbo)
if (!testFeatures(kVBO))
return false;
#if QT_VAO
if (try_vao) {
qDebug("updating vao...");
if (testFeatures(kVAO)) {
//qDebug("updating vao...");
if (!vao.isCreated()) {
if (!vao.create()) {
try_vao = false;
setFeature(kVAO, false);
qDebug("VAO is not supported");
}
}
Expand All @@ -82,8 +97,8 @@ bool GeometryRenderer::updateBuffers(Geometry *geo)
#endif
if (!vbo.isCreated()) {
if (!vbo.create()) {
try_vbo = false; // not supported by OpenGL
try_vao = false; // also disable VAO. destroy?
setFeature(kVBO, false);
setFeature(kVAO, false);// also disable Vao_. destroy?
qWarning("VBO is not supported");
return false;
}
Expand All @@ -93,15 +108,13 @@ bool GeometryRenderer::updateBuffers(Geometry *geo)
vbo.allocate(g->vertexData(), g->vertexCount()*g->stride());
//qDebug("allocate(%p, %d*%d)", g->vertexData(), g->vertexCount(), g->stride());
#if QT_VAO
if (try_vao) {
if (testFeatures(kVAO)) {
for (int an = 0; an < g->attributes().size(); ++an) {
// FIXME: assume bind order is 0,1,2...
const Attribute& a = g->attributes().at(an);
//DYGL(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), reinterpret_cast<const void *>(qptrdiff(a.offset()))));
/// FIXME: why qopengl function crash?
program->enableAttributeArray(an); //TODO: in setActiveShader
program->setAttributeBuffer(an, a.type(), a.offset(), a.tupleSize(), g->stride());
//DYGL(glEnableVertexAttribArray(an));
DYGL(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), reinterpret_cast<const void *>(qptrdiff(a.offset())))); //TODO: in setActiveShader
/// FIXME: why QOpenGLShaderProgram function crash?
DYGL(glEnableVertexAttribArray(an));
}
}
#endif
Expand All @@ -113,64 +126,57 @@ void GeometryRenderer::bindBuffers()
{
if (!g)
return;
if (try_ibo && ibo.isCreated())
if (testFeatures(kIBO) && ibo.isCreated())
ibo.bind();
#if QT_VAO
if (try_vao && vao.isCreated()) {
if (testFeatures(kVAO) && vao.isCreated()) {
vao.bind();
return;
}
#endif
if (try_vbo && vbo.isCreated()) {
const char* vdata = static_cast<const char*>(g->vertexData());
if (testFeatures(kVBO) && vbo.isCreated()) {
vbo.bind();
// normalized
for (int an = 0; an < g->attributes().size(); ++an) {
const Attribute& a = g->attributes().at(an);
//DYGL(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), reinterpret_cast<const void *>(qptrdiff(a.offset()))));
program->setAttributeBuffer(an, a.type(), a.offset(), a.tupleSize(), g->stride());
program->enableAttributeArray(an); //TODO: in setActiveShader
//DYGL(glEnableVertexAttribArray(an));
}
} else {
for (int an = 0; an < g->attributes().size(); ++an) {
const Attribute& a = g->attributes().at(an);
program->setAttributeArray(an, a.type(), (const char*)g->vertexData() + a.offset(), a.tupleSize(), g->stride());
//DYGL(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), (const char*)g->vertexData() + a.offset()));
program->enableAttributeArray(an); //TODO: in setActiveShader
//DYGL(glEnableVertexAttribArray(an));
}
vdata = NULL;
}
for (int an = 0; an < g->attributes().size(); ++an) {
const Attribute& a = g->attributes().at(an);
DYGL(glVertexAttribPointer(an, a.tupleSize(), a.type(), a.normalize(), g->stride(), vdata + a.offset()));
DYGL(glEnableVertexAttribArray(an)); //TODO: in setActiveShader
}
}

void GeometryRenderer::unbindBuffers()
{
if (!g)
return;
if (try_ibo && ibo.isCreated())
if (testFeatures(kIBO) && ibo.isCreated())
ibo.release();
#if QT_VAO
if (try_vao && vao.isCreated()) {
if (testFeatures(kVAO) && vao.isCreated()) {
vao.release();
return;
}
#endif //QT_VAO
for (int an = 0; an < g->attributes().size(); ++an) {
DYGL(glDisableVertexAttribArray(an));
}
// release vbo. qpainter is affected if vbo is bound
if (try_vbo && vbo.isCreated()) {
if (testFeatures(kVBO) && vbo.isCreated()) {
vbo.release();
}
for (int an = 0; an < g->attributes().size(); ++an) {
program->disableAttributeArray(an); //TODO: in setActiveShader
}
}

void GeometryRenderer::render()
{
if (!g)
return;
bindBuffers();
if (g->indexCount() > 0) {
DYGL(glDrawElements(g->primitive(), g->indexCount(), g->indexType(), g->indexData()));
} else {
DYGL(glDrawArrays(g->primitive(), 0, g->vertexCount()));
}
unbindBuffers();
}
} //namespace QtAV
22 changes: 14 additions & 8 deletions src/opengl/GeometryRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,27 @@ namespace QtAV {
class GeometryRenderer
{
public:
// rendering features. Use all possible features as the default.
static const int kVBO = 0x01;
static const int kIBO = 0x02;
static const int kVAO = 0x04;

GeometryRenderer();
void setShaderProgram(QOpenGLShaderProgram *sp); // TODO: remove this if use gl api directly
// call updateBuffer internally in bindBuffer if feature is changed
void setFeature(int f, bool on);
void setFeatures(int value);
int features() const;
bool testFeatures(int value) const;
/// assume attributes are bound in the order 0, 1, 2,....
/// null geometry: release vao/vbo
bool updateBuffers(Geometry* geo = NULL);
void bindBuffers();
bool updateGeometry(Geometry* geo = NULL);
void render();
protected:
void bindBuffers();
void unbindBuffers();
private:
QOpenGLShaderProgram *program;
Geometry *g;
// TODO: setFeatures(VAO|VBO)
bool try_vbo; // check environment var and opengl support
bool try_vao;
bool try_ibo;
int features_;
QOpenGLBuffer vbo; //VertexBuffer
#if QT_VAO
QOpenGLVertexArrayObject vao;
Expand Down
20 changes: 6 additions & 14 deletions src/opengl/OpenGLVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class OpenGLVideoPrivate : public DPtrPrivate<OpenGLVideo>

void resetGL() {
ctx = 0;
gr.updateBuffers(NULL);
gr.updateGeometry(NULL);
if (!manager)
return;
manager->setParent(0);
Expand All @@ -71,10 +71,7 @@ class OpenGLVideoPrivate : public DPtrPrivate<OpenGLVideo>
}
}
// update geometry(vertex array) set attributes or bind VAO/VBO.
void bindAttributes(VideoShader* shader, const QRectF& t, const QRectF& r);
void unbindAttributes(VideoShader*) {
gr.unbindBuffers();
}
void updateGeometry(VideoShader* shader, const QRectF& t, const QRectF& r);
public:
QOpenGLContext *ctx;
ShaderManager *manager;
Expand All @@ -93,7 +90,7 @@ class OpenGLVideoPrivate : public DPtrPrivate<OpenGLVideo>
VideoShader *user_shader;
};

void OpenGLVideoPrivate::bindAttributes(VideoShader* shader, const QRectF &t, const QRectF &r)
void OpenGLVideoPrivate::updateGeometry(VideoShader* shader, const QRectF &t, const QRectF &r)
{
// also check size change for normalizedROI computation if roi is not normalized
const bool roi_changed = valiad_tex_width != material->validTextureWidth() || roi != r || video_size != material->frameSize();
Expand All @@ -119,10 +116,8 @@ void OpenGLVideoPrivate::bindAttributes(VideoShader* shader, const QRectF &t, co
update_geo = true;
}
}
if (!update_geo) {
gr.bindBuffers();
if (!update_geo)
return;
}
//qDebug("updating geometry...");
// setTextureCount may change the vertex data. Call it before setRect()
geometry.setTextureCount(shader->textureTarget() == GL_TEXTURE_RECTANGLE ? tc : 1);
Expand All @@ -134,8 +129,7 @@ void OpenGLVideoPrivate::bindAttributes(VideoShader* shader, const QRectF &t, co
}
}
update_geo = false;
gr.updateBuffers(&geometry);
gr.bindBuffers();
gr.updateGeometry(&geometry);
}

OpenGLVideo::OpenGLVideo() {}
Expand Down Expand Up @@ -296,9 +290,8 @@ void OpenGLVideo::render(const QRectF &target, const QRectF& roi, const QMatrix4
shader->update(d.material);
d.material->setDirty(false); //
shader->program()->setUniformValue(shader->matrixLocation(), transform*d.matrix);
d.gr.setShaderProgram(shader->program());
// uniform end. attribute begin
d.bindAttributes(shader, target, roi);
d.updateGeometry(shader, target, roi);
// normalize?
const bool blending = d.material->hasAlpha();
if (blending) {
Expand All @@ -309,7 +302,6 @@ void OpenGLVideo::render(const QRectF &target, const QRectF& roi, const QMatrix4
if (blending)
DYGL(glDisable(GL_BLEND));
// d.shader->program()->release(); //glUseProgram(0)
d.unbindAttributes(shader);
d.material->unbind();

Q_EMIT afterRendering();
Expand Down
7 changes: 2 additions & 5 deletions src/opengl/SubImagesRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ void SubImagesRenderer::render(const SubImageSet &ass, const QRect &target, cons
{
if (m_geometry->setSubImages(ass) || m_rect != target) {
m_rect = target;
if (!m_geometry->generateVertexData(m_rect, true))
if (!m_geometry->generateVertexData(m_rect, true)) // FIXME: IBO + VAO works, IBO only crash, IBO +VBO nothing
return;

uploadTexture(m_geometry);
m_renderer->updateBuffers(m_geometry);
m_renderer->updateGeometry(m_geometry);
}
if (!m_program.isLinked()) {
m_program.removeAllShaders();
Expand All @@ -71,8 +71,6 @@ void SubImagesRenderer::render(const SubImageSet &ass, const QRect &target, cons
DYGL(glBindTexture(GL_TEXTURE_2D, m_tex));
m_program.setUniformValue("u_Texture", 0);
m_program.setUniformValue("u_Matrix", transform*m_mat);
m_renderer->setShaderProgram(&m_program);
m_renderer->bindBuffers();
DYGL(glEnable(GL_BLEND));
if (m_geometry->images().format() == SubImageSet::ASS)
gl().BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Expand All @@ -82,7 +80,6 @@ void SubImagesRenderer::render(const SubImageSet &ass, const QRect &target, cons
m_renderer->render();

DYGL(glDisable(GL_BLEND));
m_renderer->unbindBuffers();
}

void SubImagesRenderer::setProjectionMatrixToRect(const QRectF &v)
Expand Down

0 comments on commit 07d63bc

Please sign in to comment.