Noesis Integration with cocos2dx?

Thank you!
On the error, it may be because of the way im saving and trying to restore the open GL state, there might be something ive missed when im doing this.

Ive used the code @jsantos pointed me to and have made slight changed to that to save and restore my openGL state. Like so…

Here the struct render states captures all the openGL parameters i am trying to save and restore. The save() and restore() functions actually perform the operation and are called once each every draw loop.

struct RenderStates
{
int frameBuffer;
int viewport[4];
float clearColors[4];
float clearDepth;
int clearStencil;
unsigned char alphaTest;
unsigned char depthTest;
unsigned char depthWrite;
int depthFunc;
unsigned char stencilTest;
int stencilTestFailOp;
int stencilTestSPDF;
int stencilTestSPDP;
int stencilFunc;
int stencilRef;
unsigned int stencilMask;
unsigned int stencilWriteMask;
unsigned char scissorTest;
unsigned char cullFaceEnabled;
int cullFaceMode;
unsigned char dither;
unsigned char sampleAlphaToCoverage;
unsigned char sampleCoverage;
unsigned char blendEnabled;
int blendEquation;
int blendSource;
int blendDestination;
unsigned char colorWriteMask[4];
unsigned int arrayBuffer;
int vertexAttribsEnabled[6];
int activeTexture;
unsigned int elementArrayBuffer;
unsigned int vertexArrayBuffer;
int boundTexture[4];
int currentProgram;
int unpackAlignment;
};

void OpenGLState::Store()
{
glGetIntegerv(GL_UNPACK_ALIGNMENT, &renderStates.unpackAlignment);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &renderStates.frameBuffer);
glGetIntegerv(GL_VIEWPORT, renderStates.viewport);

glGetFloatv(GL_COLOR_CLEAR_VALUE, renderStates.clearColors);
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &renderStates.clearDepth);
glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &renderStates.clearStencil);

glGetBooleanv(GL_COLOR_WRITEMASK, renderStates.colorWriteMask);

renderStates.dither = glIsEnabled(GL_DITHER);
renderStates.sampleAlphaToCoverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
renderStates.sampleCoverage = glIsEnabled(/*#ifndef LEADWERKS_3_1
renderStates.alphaTest = glIsEnabled(GL_ALPHA_TEST);

renderStates.depthTest = glIsEnabled(GL_DEPTH_TEST);
glGetBooleanv(GL_DEPTH_WRITEMASK, &renderStates.depthWrite);
glGetIntegerv(GL_DEPTH_FUNC, &renderStates.depthFunc);

renderStates.stencilTest = glIsEnabled(GL_STENCIL_TEST);
glGetIntegerv(GL_STENCIL_FAIL, &renderStates.stencilTestFailOp);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &renderStates.stencilTestSPDF);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &renderStates.stencilTestSPDP);
glGetIntegerv(GL_STENCIL_FUNC, &renderStates.stencilFunc);
glGetIntegerv(GL_STENCIL_REF, &renderStates.stencilRef);
glGetIntegerv(GL_STENCIL_VALUE_MASK, (int*)&renderStates.stencilMask);
glGetIntegerv(GL_STENCIL_WRITEMASK, (int*)&renderStates.stencilWriteMask);

renderStates.scissorTest = glIsEnabled(GL_SCISSOR_TEST);
renderStates.cullFaceEnabled = glIsEnabled(GL_CULL_FACE);
glGetIntegerv(GL_CULL_FACE_MODE, &renderStates.cullFaceMode);

renderStates.blendEnabled = glIsEnabled(GL_BLEND);
glGetIntegerv(GL_BLEND_EQUATION_RGB, &renderStates.blendEquation);
glGetIntegerv(GL_BLEND_SRC_RGB, &renderStates.blendSource);
glGetIntegerv(GL_BLEND_DST_RGB, &renderStates.blendDestination);

glGetIntegerv(GL_ACTIVE_TEXTURE, &renderStates.activeTexture);

for (NsSize i = 0; i < 4; i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &(renderStates.boundTexture[i]));
}

glGetIntegerv(GL_CURRENT_PROGRAM, &renderStates.currentProgram);

glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (int*)&renderStates.arrayBuffer);
for (NsSize i = 0; i < 6; i++)
{
glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED,
&(renderStates.vertexAttribsEnabled[i]));
}

glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, (int*)&renderStates.elementArrayBuffer);
glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (int*)&renderStates.vertexArrayBuffer);
}

void OpenGLState::Restore()
{

glPixelStorei(GL_UNPACK_ALIGNMENT, renderStates.unpackAlignment);

glBindFramebuffer(GL_FRAMEBUFFER, renderStates.frameBuffer);
glViewport(renderStates.viewport[0], renderStates.viewport[1], renderStates.viewport[2],
renderStates.viewport[3]);

glClearColor(renderStates.clearColors[0], renderStates.clearColors[1],
renderStates.clearColors[2], renderStates.clearColors[3]);
glClearDepthf(renderStates.clearDepth);

glClearStencil(renderStates.clearStencil);
glColorMask(renderStates.colorWriteMask[0], renderStates.colorWriteMask[1],
renderStates.colorWriteMask[2], renderStates.colorWriteMask[3]);

renderStates.dither ? glEnable(GL_DITHER) : glDisable(GL_DITHER);
renderStates.sampleAlphaToCoverage ? glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE) :
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);

renderStates.sampleCoverage ? glEnable(GL_SAMPLE_COVERAGE) : glDisable(GL_SAMPLE_COVERAGE);

renderStates.depthTest ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);

glDepthMask(renderStates.depthWrite);
glDepthFunc(renderStates.depthFunc);
renderStates.stencilTest ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST);
glStencilOp(renderStates.stencilTestFailOp, renderStates.stencilTestSPDF,
renderStates.stencilTestSPDP);
glStencilFunc(renderStates.stencilFunc, renderStates.stencilRef, renderStates.stencilMask);
glStencilMask(renderStates.stencilWriteMask);
renderStates.scissorTest ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
renderStates.cullFaceEnabled ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
glCullFace(renderStates.cullFaceMode);
renderStates.blendEnabled ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glBlendEquation(renderStates.blendEquation);
glBlendFunc(renderStates.blendSource, renderStates.blendDestination);
for (NsSize i = 0; i < 4; i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, renderStates.boundTexture[i]);
}

glActiveTexture(renderStates.activeTexture);

glUseProgram(renderStates.currentProgram);

glBindBuffer(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, renderStates.vertexArrayBuffer);

//glBindVertexArray(renderStates.vertexArrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, renderStates.arrayBuffer);
for (NsSize i = 0; i < 6; i++)
{
renderStates.vertexAttribsEnabled[i] ?
glEnableVertexAttribArray(i) : glDisableVertexAttribArray(i);
}

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderStates.elementArrayBuffer);

I may be doing something wrong here which causes the error. Im not sure exactly ow cocos2dx works underneath so i may be doing something wrong here!

It is difficult to tell where is the error.
The error appears because the cocos2d-x code call glGetError (only in debug mode) before rendering some stuff.

But in order to know where is the error, you have to call getGetError after each gl call that you are making.

Ok will try this out. Thank you @ricardo

Hi @alias1234, is there any news :slight_smile:

Im still looking into it…Its like looking for a needle in a haystack and have had no luck! I recently got busy with something else will try and look at this over the next few days!

Ok, good luck.

There is an easy (hacky) way to solve this problem. At the end of the functions that Push and Pop the GL state just doing:

while (glGetError() != GL_NO_ERROR);

will clear the error state and CHECK_GL_ERROR_DEBUG() no longer will give error.

@jsantos will try this. But this only silences the error, am i right?

Yes, correct. At least it will allow you having an application that not longer crash and interact with the GUI.

It is not a final solution, it is only a workaround to go on.

any news about this?

Ive silenced the error for now, i could not resolve it. Trying to mock up some sample xaml to see how it runs on cocos2dx!

Cool! Remember to activate again the offscreen.

any news? :slight_smile:

Here is a link to a test project i have created on github.

https://github.com/xmarklabs/Cocos2dx-Noesis-Test

It is by no means final, as the open GL bug still persists. I have managed to isolate the possible cause of the bug (documented in the readme.md), and i am fairly confident that it is happening due to the i am saving and restoring the openGL state.

I still have no solution for this and i would urge someone who knows the inner workings of cocos2dx better to try and resolve this!

Thanks @alias1234, i’m trying to run the test, but i have a problem, this is my Log

–START–
GLERR: 0
GLERR: 0
–END–
(lldb)

Is it crashing? Are you seeing anything drawing on screen?

it is crashing at the beginning, there is nothing in the screen :frowning:

Hi Ricardo,

I have a doubt regarding this. In NoesisGUi we need two different entry points for rendering:

  • Normal Pass: following your explanation I will use a CustomCommand to dispatch GL commands. After that I will manually restore the changed GL state.
  • Offscreen Pass: this pass is needed before the main scene is render. So, before the main framebuffer is bound. At this pass we generate the needed textures needed by the Normal Pass. Here we use render to texture and need to bind our own framebuffers. This step cannot be done in the Normal pass because in Tiled Architectures (all mobiles) changing the framebuffer in the middle of the rendering is very inefficient.

So, my question is, what is the proper place to implement the offscreen pass?

Thanks!

@jsantos

We don’t have the concept of “offscreen pass” in cocos2d-x yet.
But, is this something that you need to do every frame, or is this just a one-time only?

In any case, one thing that you can do, kind of hackish, is to register for the update() callback, and do the offscreen thing there.
update() will be called before the rendering starts, so potentially you can do all your offscreen stuff there, create your textures, and then use them in your CustomCommand code.

Will that work for you?

Thanks for the quick answer. Yes, I will try that today.

By the way, is there a list or something commenting about the GL states that must be restored if I change them (from the update callback or from a CustomCommand)?

For example do I need to restore the main framebuffer or the viewport? Today I am going to analyze it carefully, but you know, having an official answer is always better.