opengles emulator: cache all buffer on the guest
This is needed to support the rare, but still legal scenario, when glDrawElemets is used with some index array data is stored in VBO's while the actual attributes (vertices) data is in immediate mode. When in immediate mode, we need to process the incodes, in order to know which vertex data to send, which was impossible without the caching. This commit introduces a new class GLSharedGroup, which will hold all data that can be shared by shared contexts (buffers are such data). This also makes the "Jet Cars Stunts" app work properly. Change-Id: Ic937080dae461bc8cdf4d10cf37066a6e847f464
This commit is contained in:
committed by
David 'Digit' Turner
parent
6208854726
commit
e99305dd9f
@@ -7,6 +7,20 @@ static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0";
|
||||
static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0";
|
||||
static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
|
||||
|
||||
#define SET_ERROR_IF(condition,err) if((condition)) { \
|
||||
LOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
|
||||
ctx->setError(err); \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
#define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \
|
||||
LOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \
|
||||
ctx->setError(err); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
|
||||
GL2Encoder::GL2Encoder(IOStream *stream) : gl2_encoder_context_t(stream)
|
||||
{
|
||||
m_initialized = false;
|
||||
@@ -98,6 +112,39 @@ void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id)
|
||||
ctx->m_glBindBuffer_enc(self, target, id);
|
||||
}
|
||||
|
||||
void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
|
||||
{
|
||||
GL2Encoder *ctx = (GL2Encoder *) self;
|
||||
GLuint bufferId = ctx->m_state->getBuffer(target);
|
||||
SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
|
||||
SET_ERROR_IF(size<0, GL_INVALID_VALUE);
|
||||
|
||||
ctx->m_shared->updateBufferData(bufferId, size, (void*)data);
|
||||
ctx->m_glBufferData_enc(self, target, size, data, usage);
|
||||
}
|
||||
|
||||
void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
|
||||
{
|
||||
GL2Encoder *ctx = (GL2Encoder *) self;
|
||||
GLuint bufferId = ctx->m_state->getBuffer(target);
|
||||
SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION);
|
||||
|
||||
GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data);
|
||||
SET_ERROR_IF(res, res);
|
||||
|
||||
ctx->m_glBufferSubData_enc(self, target, offset, size, data);
|
||||
}
|
||||
|
||||
void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers)
|
||||
{
|
||||
GL2Encoder *ctx = (GL2Encoder *) self;
|
||||
SET_ERROR_IF(n<0, GL_INVALID_VALUE);
|
||||
for (int i=0; i<n; i++) {
|
||||
ctx->m_shared->deleteBufferData(buffers[i]);
|
||||
ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void GL2Encoder::s_glVertexAtrribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr)
|
||||
{
|
||||
GL2Encoder *ctx = (GL2Encoder *)self;
|
||||
@@ -234,9 +281,10 @@ void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count)
|
||||
this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride,
|
||||
(unsigned char *)state->data + firstIndex, datalen);
|
||||
} else {
|
||||
this->glBindBuffer(this, GL_ARRAY_BUFFER, state->bufferObject);
|
||||
this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject);
|
||||
this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride,
|
||||
(GLuint) state->data + firstIndex);
|
||||
this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo());
|
||||
}
|
||||
} else {
|
||||
this->m_glDisableVertexAttribArray_enc(this, i);
|
||||
@@ -257,6 +305,7 @@ void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum
|
||||
|
||||
GL2Encoder *ctx = (GL2Encoder *)self;
|
||||
assert(ctx->m_state != NULL);
|
||||
SET_ERROR_IF(count<0, GL_INVALID_VALUE);
|
||||
|
||||
bool has_immediate_arrays = false;
|
||||
bool has_indirect_arrays = false;
|
||||
@@ -278,14 +327,20 @@ void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum
|
||||
return;
|
||||
}
|
||||
|
||||
bool adjustIndices = true;
|
||||
if (ctx->m_state->currentIndexVbo() != 0) {
|
||||
if (!has_immediate_arrays) {
|
||||
ctx->sendVertexAttributes(0, count);
|
||||
ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo());
|
||||
ctx->glDrawElementsOffset(ctx, mode, count, type, (GLuint)indices);
|
||||
adjustIndices = false;
|
||||
} else {
|
||||
LOGE("glDrawElements: indirect index arrays, with immidate-mode data array is not supported\n");
|
||||
BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo());
|
||||
ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (adjustIndices) {
|
||||
void *adjustedIndices = (void*)indices;
|
||||
int minIndex = 0, maxIndex = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user