From af4f66be50b17c8b8fce1dda53389bb0a10968ba Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Tue, 15 Nov 2011 16:14:11 -0800 Subject: [PATCH] EmuGL: implement OES_EGL_image_external for GLESv1 GLESv2 support will come in a followup change but will take advantage of the GLClientState changes. Change-Id: Ib6cbb4dafbd071e3b59b1e5d808b3e23656ada92 --- .../OpenglCodecCommon/GLClientState.cpp | 180 ++++++++ .../shared/OpenglCodecCommon/GLClientState.h | 77 ++++ tools/emulator/opengl/system/GLESv1/gl.cpp | 21 +- .../opengl/system/GLESv1_enc/GLEncoder.cpp | 417 ++++++++++++++++-- .../opengl/system/GLESv1_enc/GLEncoder.h | 34 +- tools/emulator/opengl/system/GLESv2/gl2.cpp | 4 +- 6 files changed, 697 insertions(+), 36 deletions(-) diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp index f8820d23f..c689f83a3 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.cpp @@ -21,6 +21,10 @@ #include "glUtils.h" #include +#ifndef MAX +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif + GLClientState::GLClientState(int nLocations) { if (nLocations < LAST_LOCATION) { @@ -54,6 +58,12 @@ GLClientState::GLClientState(int nLocations) m_pixelStore.unpack_alignment = 4; m_pixelStore.pack_alignment = 4; + + memset(m_tex.unit, 0, sizeof(m_tex.unit)); + m_tex.activeUnit = &m_tex.unit[0]; + m_tex.textures = NULL; + m_tex.numTextures = 0; + m_tex.allocTextures = 0; } GLClientState::~GLClientState() @@ -230,3 +240,173 @@ size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLenum format return aligned_linesize * height; } +GLenum GLClientState::setActiveTextureUnit(GLenum texture) +{ + GLuint unit = texture - GL_TEXTURE0; + if (unit >= MAX_TEXTURE_UNITS) { + return GL_INVALID_OPERATION; + } + m_tex.activeUnit = &m_tex.unit[unit]; + return GL_NO_ERROR; +} + +void GLClientState::enableTextureTarget(GLenum target) +{ + switch (target) { + case GL_TEXTURE_2D: + m_tex.activeUnit->enables |= (1u << TEXTURE_2D); + break; + case GL_TEXTURE_EXTERNAL_OES: + m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL); + break; + } +} + +void GLClientState::disableTextureTarget(GLenum target) +{ + switch (target) { + case GL_TEXTURE_2D: + m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D); + break; + case GL_TEXTURE_EXTERNAL_OES: + m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL); + break; + } +} + +GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const +{ + unsigned int enables = m_tex.activeUnit->enables; + if (enables & (1u << TEXTURE_EXTERNAL)) { + return GL_TEXTURE_EXTERNAL_OES; + } else if (enables & (1u << TEXTURE_2D)) { + return GL_TEXTURE_2D; + } else { + return allDisabled; + } +} + +int GLClientState::compareTexId(const void* pid, const void* prec) +{ + const GLuint* id = (const GLuint*)pid; + const TextureRec* rec = (const TextureRec*)prec; + return (GLint)(*id) - (GLint)rec->id; +} + +GLenum GLClientState::bindTexture(GLenum target, GLuint texture, + GLboolean* firstUse) +{ + GLboolean first = GL_FALSE; + TextureRec* texrec = NULL; + if (texture != 0) { + if (m_tex.textures) { + texrec = (TextureRec*)bsearch(&texture, m_tex.textures, + m_tex.numTextures, sizeof(TextureRec), compareTexId); + } + if (!texrec) { + if (!(texrec = addTextureRec(texture, target))) { + return GL_OUT_OF_MEMORY; + } + first = GL_TRUE; + } + if (target != texrec->target) { + return GL_INVALID_OPERATION; + } + } + + switch (target) { + case GL_TEXTURE_2D: + m_tex.activeUnit->texture[TEXTURE_2D] = texture; + break; + case GL_TEXTURE_EXTERNAL_OES: + m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture; + break; + } + + if (firstUse) { + *firstUse = first; + } + + return GL_NO_ERROR; +} + +GLClientState::TextureRec* GLClientState::addTextureRec(GLuint id, + GLenum target) +{ + if (m_tex.numTextures == m_tex.allocTextures) { + const GLuint MAX_TEXTURES = 0xFFFFFFFFu; + + GLuint newAlloc; + if (MAX_TEXTURES - m_tex.allocTextures >= m_tex.allocTextures) { + newAlloc = MAX(4, 2 * m_tex.allocTextures); + } else { + if (m_tex.allocTextures == MAX_TEXTURES) { + return NULL; + } + newAlloc = MAX_TEXTURES; + } + + TextureRec* newTextures = (TextureRec*)realloc(m_tex.textures, + newAlloc * sizeof(TextureRec)); + if (!newTextures) { + return NULL; + } + + m_tex.textures = newTextures; + m_tex.allocTextures = newAlloc; + } + + TextureRec* tex = m_tex.textures + m_tex.numTextures; + TextureRec* prev = tex - 1; + while (tex != m_tex.textures && id < prev->id) { + *tex-- = *prev--; + } + tex->id = id; + tex->target = target; + m_tex.numTextures++; + + return tex; +} + +GLuint GLClientState::getBoundTexture(GLenum target) const +{ + switch (target) { + case GL_TEXTURE_2D: + return m_tex.activeUnit->texture[TEXTURE_2D]; + case GL_TEXTURE_EXTERNAL_OES: + return m_tex.activeUnit->texture[TEXTURE_EXTERNAL]; + default: + return 0; + } +} + +void GLClientState::deleteTextures(GLsizei n, const GLuint* textures) +{ + // Updating the textures array could be made more efficient when deleting + // several textures: + // - compacting the array could be done in a single pass once the deleted + // textures are marked, or + // - could swap deleted textures to the end and re-sort. + TextureRec* texrec; + for (const GLuint* texture = textures; texture != textures + n; texture++) { + texrec = (TextureRec*)bsearch(texture, m_tex.textures, + m_tex.numTextures, sizeof(TextureRec), compareTexId); + if (texrec) { + const TextureRec* end = m_tex.textures + m_tex.numTextures; + memmove(texrec, texrec + 1, + (end - texrec + 1) * sizeof(TextureRec)); + m_tex.numTextures--; + + for (TextureUnit* unit = m_tex.unit; + unit != m_tex.unit + MAX_TEXTURE_UNITS; + unit++) + { + if (unit->texture[TEXTURE_2D] == *texture) { + unit->texture[TEXTURE_2D] = 0; + } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) { + unit->texture[TEXTURE_EXTERNAL] = 0; + } + } + } + } +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.h b/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.h index 6b12f6871..be66d6828 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.h +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/GLClientState.h @@ -70,6 +70,10 @@ public: int pack_alignment; } PixelStoreState; + enum { + MAX_TEXTURE_UNITS = 32, + }; + public: GLClientState(int nLocations = CODEC_MAX_VERTEX_ATTRIBUTES); ~GLClientState(); @@ -123,6 +127,53 @@ public: void setCurrentProgram(GLint program) { m_currentProgram = program; } GLint currentProgram() const { return m_currentProgram; } + /* OES_EGL_image_external + * + * These functions manipulate GL state which interacts with the + * OES_EGL_image_external extension, to support client-side emulation on + * top of host implementations that don't have it. + * + * Most of these calls should only be used with TEXTURE_2D or + * TEXTURE_EXTERNAL_OES texture targets; TEXTURE_CUBE_MAP or other extension + * targets should bypass this. An exception is bindTexture(), which should + * see all glBindTexture() calls for any target. + */ + + // glActiveTexture(GL_TEXTURE0 + i) + // Sets the active texture unit. Up to MAX_TEXTURE_UNITS are supported. + GLenum setActiveTextureUnit(GLenum texture); + + // glEnable(GL_TEXTURE_(2D|EXTERNAL_OES)) + void enableTextureTarget(GLenum target); + + // glDisable(GL_TEXTURE_(2D|EXTERNAL_OES)) + void disableTextureTarget(GLenum target); + + // Implements the target priority logic: + // * Return GL_TEXTURE_EXTERNAL_OES if enabled, else + // * Return GL_TEXTURE_2D if enabled, else + // * Return the allDisabled value. + // For some cases passing GL_TEXTURE_2D for allDisabled makes callee code + // simpler; for other cases passing a recognizable enum like GL_ZERO or + // GL_INVALID_ENUM is appropriate. + GLenum getPriorityEnabledTarget(GLenum allDisabled) const; + + // glBindTexture(GL_TEXTURE_*, ...) + // Set the target binding of the active texture unit to texture. Returns + // GL_NO_ERROR on success or GL_INVALID_OPERATION if the texture has + // previously been bound to a different target. If firstUse is not NULL, + // it is set to indicate whether this is the first use of the texture. + // For accurate error detection, bindTexture should be called for *all* + // targets, not just 2D and EXTERNAL_OES. + GLenum bindTexture(GLenum target, GLuint texture, GLboolean* firstUse); + + // Return the texture currently bound to GL_TEXTURE_(2D|EXTERNAL_OES). + GLuint getBoundTexture(GLenum target) const; + + // glDeleteTextures(...) + // Remove references to the to-be-deleted textures. + void deleteTextures(GLsizei n, const GLuint* textures); + private: PixelStoreState m_pixelStore; VertexAttribState *m_states; @@ -133,6 +184,32 @@ private: GLint m_currentProgram; bool validLocation(int location) { return (location >= 0 && location < m_nLocations); } + + enum TextureTarget { + TEXTURE_2D = 0, + TEXTURE_EXTERNAL = 1, + TEXTURE_TARGET_COUNT + }; + struct TextureUnit { + unsigned int enables; + GLuint texture[TEXTURE_TARGET_COUNT]; + }; + struct TextureRec { + GLuint id; + GLenum target; + }; + struct TextureState { + TextureUnit unit[MAX_TEXTURE_UNITS]; + TextureUnit* activeUnit; + TextureRec* textures; + GLuint numTextures; + GLuint allocTextures; + }; + TextureState m_tex; + + static int compareTexId(const void* pid, const void* prec); + TextureRec* addTextureRec(GLuint id, GLenum target); + public: void getClientStatePointer(GLenum pname, GLvoid** params); diff --git a/tools/emulator/opengl/system/GLESv1/gl.cpp b/tools/emulator/opengl/system/GLESv1/gl.cpp index 142c21823..07afade96 100644 --- a/tools/emulator/opengl/system/GLESv1/gl.cpp +++ b/tools/emulator/opengl/system/GLESv1/gl.cpp @@ -10,7 +10,7 @@ //XXX: fix this macro to get the context from fast tls path -#define GET_CONTEXT gl_client_context_t * ctx = getEGLThreadInfo()->hostConn->glEncoder(); +#define GET_CONTEXT GLEncoder * ctx = getEGLThreadInfo()->hostConn->glEncoder(); #include "gl_entry.cpp" @@ -35,7 +35,7 @@ static EGLClient_glesInterface * s_gl = NULL; //GL extensions void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetTexture2DOES v1 image=0x%x", image); + DBG("glEGLImageTargetTexture2DOES v1 target=%#x image=%p", target, image); //TODO: check error - we don't have a way to set gl error android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; @@ -47,15 +47,21 @@ void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES imag return; } + GET_CONTEXT; DEFINE_AND_VALIDATE_HOST_CONNECTION(); - rcEnc->rcBindTexture(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle); + + ctx->override2DTextureTarget(target); + rcEnc->rcBindTexture(rcEnc, + ((cb_handle_t *)(native_buffer->handle))->hostHandle); + ctx->restore2DTextureTarget(); return; } void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetRenderbufferStorageOES v1 image=0x%x", image); + DBG("glEGLImageTargetRenderbufferStorageOES v1 target=%#x image=%p", + target, image); //TODO: check error - we don't have a way to set gl error android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; @@ -67,8 +73,13 @@ void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImag return; } + GET_CONTEXT; DEFINE_AND_VALIDATE_HOST_CONNECTION(); - rcEnc->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle); + + ctx->override2DTextureTarget(target); + rcEnc->rcBindRenderbuffer(rcEnc, + ((cb_handle_t *)(native_buffer->handle))->hostHandle); + ctx->restore2DTextureTarget(); return; } diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp index 43391f0f7..dc7c52735 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp @@ -16,26 +16,19 @@ #include "GLEncoder.h" #include "glUtils.h" #include "FixedBuffer.h" +#include #include #include +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + static GLubyte *gVendorString= (GLubyte *) "Android"; static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 1.0"; static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0"; static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point; -#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \ - HostConnection *hostCon = HostConnection::get(); \ - if (!hostCon) { \ - LOGE("egl: Failed to get host connection\n"); \ - return ret; \ - } \ - renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \ - if (!rcEnc) { \ - LOGE("egl: Failed to get renderControl encoder context\n"); \ - return ret; \ - } - #define SET_ERROR_IF(condition,err) if((condition)) { \ LOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ ctx->setError(err); \ @@ -80,14 +73,37 @@ void GLEncoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr) { GLEncoder *ctx = (GLEncoder *)self; assert(ctx->m_state != NULL); - if (param == GL_COMPRESSED_TEXTURE_FORMATS) { + GLClientState* state = ctx->m_state; + + switch (param) { + case GL_COMPRESSED_TEXTURE_FORMATS: { GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); - if (ctx->m_num_compressedTextureFormats > 0 && compressedTextureFormats != NULL) { - memcpy(ptr, compressedTextureFormats, ctx->m_num_compressedTextureFormats * sizeof(GLint)); + if (ctx->m_num_compressedTextureFormats > 0 && + compressedTextureFormats != NULL) { + memcpy(ptr, compressedTextureFormats, + ctx->m_num_compressedTextureFormats * sizeof(GLint)); } + break; } - else if (!ctx->m_state->getClientStateParameter(param,ptr)) { + + case GL_MAX_TEXTURE_UNITS: ctx->m_glGetIntegerv_enc(self, param, ptr); + *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS); + break; + + case GL_TEXTURE_BINDING_2D: + *ptr = state->getBoundTexture(GL_TEXTURE_2D); + break; + + case GL_TEXTURE_BINDING_EXTERNAL_OES: + *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); + break; + + default: + if (!state->getClientStateParameter(param,ptr)) { + ctx->m_glGetIntegerv_enc(self, param, ptr); + } + break; } } @@ -95,16 +111,38 @@ void GLEncoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr) { GLEncoder *ctx = (GLEncoder *)self; assert(ctx->m_state != NULL); - if (param == GL_COMPRESSED_TEXTURE_FORMATS) { + GLClientState* state = ctx->m_state; + + switch (param) { + case GL_COMPRESSED_TEXTURE_FORMATS: { GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); - if (ctx->m_num_compressedTextureFormats > 0 && compressedTextureFormats != NULL) { + if (ctx->m_num_compressedTextureFormats > 0 && + compressedTextureFormats != NULL) { for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { ptr[i] = (GLfloat) compressedTextureFormats[i]; } } + break; } - else if (!ctx->m_state->getClientStateParameter(param,ptr)) { + + case GL_MAX_TEXTURE_UNITS: ctx->m_glGetFloatv_enc(self, param, ptr); + *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS); + break; + + case GL_TEXTURE_BINDING_2D: + *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D); + break; + + case GL_TEXTURE_BINDING_EXTERNAL_OES: + *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); + break; + + default: + if (!state->getClientStateParameter(param,ptr)) { + ctx->m_glGetFloatv_enc(self, param, ptr); + } + break; } } @@ -112,16 +150,38 @@ void GLEncoder::s_glGetFixedv(void *self, GLenum param, GLfixed *ptr) { GLEncoder *ctx = (GLEncoder *)self; assert(ctx->m_state != NULL); - if (param == GL_COMPRESSED_TEXTURE_FORMATS) { + GLClientState* state = ctx->m_state; + + switch (param) { + case GL_COMPRESSED_TEXTURE_FORMATS: { GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); - if (ctx->m_num_compressedTextureFormats > 0 && compressedTextureFormats != NULL) { + if (ctx->m_num_compressedTextureFormats > 0 && + compressedTextureFormats != NULL) { for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { ptr[i] = compressedTextureFormats[i] << 16; } } + break; } - else if (!ctx->m_state->getClientStateParameter(param,ptr)) { + + case GL_MAX_TEXTURE_UNITS: ctx->m_glGetFixedv_enc(self, param, ptr); + *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS << 16); + break; + + case GL_TEXTURE_BINDING_2D: + *ptr = state->getBoundTexture(GL_TEXTURE_2D) << 16; + break; + + case GL_TEXTURE_BINDING_EXTERNAL_OES: + *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) << 16; + break; + + default: + if (!state->getClientStateParameter(param,ptr)) { + ctx->m_glGetFixedv_enc(self, param, ptr); + } + break; } } @@ -129,11 +189,34 @@ void GLEncoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr) { GLEncoder *ctx = (GLEncoder *)self; assert(ctx->m_state != NULL); - if (param == GL_COMPRESSED_TEXTURE_FORMATS) { - // ignore the command, although we should have generated a GLerror; + GLClientState* state = ctx->m_state; + + switch (param) { + case GL_COMPRESSED_TEXTURE_FORMATS: { + GLint* compressedTextureFormats = ctx->getCompressedTextureFormats(); + if (ctx->m_num_compressedTextureFormats > 0 && + compressedTextureFormats != NULL) { + for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { + ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE; + } + } + break; } - else if (!ctx->m_state->getClientStateParameter(param,ptr)) { - ctx->m_glGetBooleanv_enc(self, param, ptr); + + case GL_TEXTURE_BINDING_2D: + *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE; + break; + + case GL_TEXTURE_BINDING_EXTERNAL_OES: + *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0 + ? GL_TRUE : GL_FALSE; + break; + + default: + if (!state->getClientStateParameter(param,ptr)) { + ctx->m_glGetBooleanv_enc(self, param, ptr); + } + break; } } @@ -515,6 +598,273 @@ void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum } } +void GLEncoder::s_glActiveTexture(void* self, GLenum texture) +{ + GLEncoder* ctx = (GLEncoder*)self; + GLClientState* state = ctx->m_state; + GLenum err; + + if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) { + LOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); + ctx->setError(err); + return; + } + + ctx->m_glActiveTexture_enc(ctx, texture); +} + +void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture) +{ + GLEncoder* ctx = (GLEncoder*)self; + GLClientState* state = ctx->m_state; + GLenum err; + + GLboolean firstUse; + if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) { + LOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); + ctx->setError(err); + return; + } + + if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { + ctx->m_glBindTexture_enc(ctx, target, texture); + return; + } + + GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); + + if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { + ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); + ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if (target != priorityTarget) { + ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, + state->getBoundTexture(GL_TEXTURE_2D)); + } + } + + if (target == priorityTarget) { + ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); + } +} + +void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) +{ + GLEncoder* ctx = (GLEncoder*)self; + GLClientState* state = ctx->m_state; + + state->deleteTextures(n, textures); + ctx->m_glDeleteTextures_enc(ctx, n, textures); +} + +void GLEncoder::s_glDisable(void* self, GLenum cap) +{ + GLEncoder* ctx = (GLEncoder*)self; + GLClientState* state = ctx->m_state; + + if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { + GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); + state->disableTextureTarget(cap); + GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); + + if (prevTarget != currTarget) { + if (currTarget == GL_INVALID_ENUM) { + ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D); + currTarget = GL_TEXTURE_2D; + } + // maintain the invariant that when TEXTURE_EXTERNAL_OES is + // disabled, the TEXTURE_2D binding is active, even if + // TEXTURE_2D is also disabled. + ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, + state->getBoundTexture(currTarget)); + } + + } else { + ctx->m_glDisable_enc(ctx, cap); + } +} + +void GLEncoder::s_glEnable(void* self, GLenum cap) +{ + GLEncoder* ctx = (GLEncoder*)self; + GLClientState* state = ctx->m_state; + + if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { + GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); + state->enableTextureTarget(cap); + GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); + + if (prevTarget != currTarget) { + if (prevTarget == GL_INVALID_ENUM) { + ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D); + } + if (currTarget == GL_TEXTURE_EXTERNAL_OES) { + ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, + state->getBoundTexture(currTarget)); + } + } + + } else { + ctx->m_glEnable_enc(ctx, cap); + } +} + +void GLEncoder::s_glGetTexParameterfv(void* self, + GLenum target, GLenum pname, GLfloat* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::s_glGetTexParameteriv(void* self, + GLenum target, GLenum pname, GLint* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::s_glGetTexParameterxv(void* self, + GLenum target, GLenum pname, GLfixed* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::s_glTexParameterf(void* self, + GLenum target, GLenum pname, GLfloat param) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameterf_enc(ctx, target, pname, param); + } +} + +void GLEncoder::s_glTexParameterfv(void* self, + GLenum target, GLenum pname, const GLfloat* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameterfv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::s_glTexParameteri(void* self, + GLenum target, GLenum pname, GLint param) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameteri_enc(ctx, target, pname, param); + } +} + +void GLEncoder::s_glTexParameterx(void* self, + GLenum target, GLenum pname, GLfixed param) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameterx_enc(ctx, target, pname, param); + } +} + +void GLEncoder::s_glTexParameteriv(void* self, + GLenum target, GLenum pname, const GLint* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameteriv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::s_glTexParameterxv(void* self, + GLenum target, GLenum pname, const GLfixed* params) +{ + GLEncoder* ctx = (GLEncoder*)self; + const GLClientState* state = ctx->m_state; + + if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { + ctx->override2DTextureTarget(target); + ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); + ctx->restore2DTextureTarget(); + } else { + ctx->m_glTexParameterxv_enc(ctx, target, pname, params); + } +} + +void GLEncoder::override2DTextureTarget(GLenum target) +{ + if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && + target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) { + m_glBindTexture_enc(this, GL_TEXTURE_2D, + m_state->getBoundTexture(target)); + } +} + +void GLEncoder::restore2DTextureTarget() +{ + GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); + m_glBindTexture_enc(this, GL_TEXTURE_2D, + m_state->getBoundTexture(priorityTarget)); +} + GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) { m_initialized = false; @@ -554,6 +904,20 @@ GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) set_glFinish(s_glFinish); m_glGetError_enc = set_glGetError(s_glGetError); + m_glActiveTexture_enc = set_glActiveTexture(s_glActiveTexture); + m_glBindTexture_enc = set_glBindTexture(s_glBindTexture); + m_glDeleteTextures_enc = set_glDeleteTextures(s_glDeleteTextures); + m_glDisable_enc = set_glDisable(s_glDisable); + m_glEnable_enc = set_glEnable(s_glEnable); + m_glGetTexParameterfv_enc = set_glGetTexParameterfv(s_glGetTexParameterfv); + m_glGetTexParameteriv_enc = set_glGetTexParameteriv(s_glGetTexParameteriv); + m_glGetTexParameterxv_enc = set_glGetTexParameterxv(s_glGetTexParameterxv); + m_glTexParameterf_enc = set_glTexParameterf(s_glTexParameterf); + m_glTexParameterfv_enc = set_glTexParameterfv(s_glTexParameterfv); + m_glTexParameteri_enc = set_glTexParameteri(s_glTexParameteri); + m_glTexParameterx_enc = set_glTexParameterx(s_glTexParameterx); + m_glTexParameteriv_enc = set_glTexParameteriv(s_glTexParameteriv); + m_glTexParameterxv_enc = set_glTexParameterxv(s_glTexParameterxv); } GLEncoder::~GLEncoder() @@ -572,4 +936,3 @@ void GLEncoder::s_glFinish(void *self) GLEncoder *ctx = (GLEncoder *)self; ctx->glFinishRoundTrip(self); } - diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h index 2076cf45c..effc53fe7 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h @@ -39,6 +39,9 @@ public: virtual void setError(GLenum error){ m_error = error; }; virtual GLenum getError() { return m_error; }; + void override2DTextureTarget(GLenum target); + void restore2DTextureTarget(); + private: bool m_initialized; @@ -80,6 +83,21 @@ private: glDrawElements_client_proc_t m_glDrawElements_enc; glFlush_client_proc_t m_glFlush_enc; + glActiveTexture_client_proc_t m_glActiveTexture_enc; + glBindTexture_client_proc_t m_glBindTexture_enc; + glDeleteTextures_client_proc_t m_glDeleteTextures_enc; + glDisable_client_proc_t m_glDisable_enc; + glEnable_client_proc_t m_glEnable_enc; + glGetTexParameterfv_client_proc_t m_glGetTexParameterfv_enc; + glGetTexParameteriv_client_proc_t m_glGetTexParameteriv_enc; + glGetTexParameterxv_client_proc_t m_glGetTexParameterxv_enc; + glTexParameterf_client_proc_t m_glTexParameterf_enc; + glTexParameterfv_client_proc_t m_glTexParameterfv_enc; + glTexParameteri_client_proc_t m_glTexParameteri_enc; + glTexParameterx_client_proc_t m_glTexParameterx_enc; + glTexParameteriv_client_proc_t m_glTexParameteriv_enc; + glTexParameterxv_client_proc_t m_glTexParameterxv_enc; + // statics static GLenum s_glGetError(void * self); static void s_glGetIntegerv(void *self, GLenum pname, GLint *ptr); @@ -106,14 +124,26 @@ private: static void s_glBufferSubData(void *self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data); static void s_glDeleteBuffers(void *self, GLsizei n, const GLuint * buffers); - static void s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count); static void s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices); static void s_glPixelStorei(void *self, GLenum param, GLint value); static void s_glFinish(void *self); - static void s_glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image); void sendVertexData(unsigned first, unsigned count); + static void s_glActiveTexture(void* self, GLenum texture); + static void s_glBindTexture(void* self, GLenum target, GLuint texture); + static void s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures); + static void s_glDisable(void* self, GLenum cap); + static void s_glEnable(void* self, GLenum cap); + static void s_glGetTexParameterfv(void* self, GLenum target, GLenum pname, GLfloat* params); + static void s_glGetTexParameteriv(void* self, GLenum target, GLenum pname, GLint* params); + static void s_glGetTexParameterxv(void* self, GLenum target, GLenum pname, GLfixed* params); + static void s_glTexParameterf(void* self, GLenum target, GLenum pname, GLfloat param); + static void s_glTexParameterfv(void* self, GLenum target, GLenum pname, const GLfloat* params); + static void s_glTexParameteri(void* self, GLenum target, GLenum pname, GLint param); + static void s_glTexParameterx(void* self, GLenum target, GLenum pname, GLfixed param); + static void s_glTexParameteriv(void* self, GLenum target, GLenum pname, const GLint* params); + static void s_glTexParameterxv(void* self, GLenum target, GLenum pname, const GLfixed* params); }; #endif diff --git a/tools/emulator/opengl/system/GLESv2/gl2.cpp b/tools/emulator/opengl/system/GLESv2/gl2.cpp index 06db29668..a014c1a46 100644 --- a/tools/emulator/opengl/system/GLESv2/gl2.cpp +++ b/tools/emulator/opengl/system/GLESv2/gl2.cpp @@ -35,7 +35,7 @@ static EGLClient_glesInterface * s_gl = NULL; //GL extensions void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetTexture2DOES v2 img=0x%x\n", image); + DBG("glEGLImageTargetTexture2DOES v2 img=%p\n", image); //TODO: check error - we don't have a way to set gl error android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; @@ -55,7 +55,7 @@ void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES imag void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetRenderbufferStorageOES v2 image=0x%x\n", image); + DBG("glEGLImageTargetRenderbufferStorageOES v2 image=%p\n", image); //TODO: check error - we don't have a way to set gl error android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;