diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk index 986f9c633..fa1b248ed 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/Android.mk @@ -8,13 +8,14 @@ $(call emugl-begin-static-library,libOpenglCodecCommon) LOCAL_SRC_FILES := \ GLClientState.cpp \ + GLSharedGroup.cpp \ glUtils.cpp \ TcpStream.cpp \ TimeUtils.cpp LOCAL_CFLAGS += -DLOG_TAG=\"eglCodecCommon\" -$(call emugl-export,SHARED_LIBRARIES,libcutils) +$(call emugl-export,SHARED_LIBRARIES,libcutils libutils) $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) $(call emugl-end-module) diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp new file mode 100644 index 000000000..84a73ef34 --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp @@ -0,0 +1,58 @@ +#include "GLSharedGroup.h" + +/**** BufferData ****/ + +BufferData::BufferData() : m_size(0) {}; +BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size) +{ + void * buffer = NULL; + if (size>0) buffer = m_fixedBuffer.alloc(size); + if (data) memcpy(buffer, data, size); +} + +/***** GLSharedGroup ****/ + +GLSharedGroup::GLSharedGroup() : + m_buffers(android::DefaultKeyedVector(NULL)) +{ +} + +GLSharedGroup::~GLSharedGroup() +{ + m_buffers.clear(); +} + +BufferData * GLSharedGroup::getBufferData(GLuint bufferId) +{ + android::AutoMutex _lock(m_lock); + return m_buffers.valueFor(bufferId); +} + +void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data) +{ + android::AutoMutex _lock(m_lock); + m_buffers.add(bufferId, new BufferData(size, data)); +} + +void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data) +{ + android::AutoMutex _lock(m_lock); + m_buffers.replaceValueFor(bufferId, new BufferData(size, data)); +} + +GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data) +{ + android::AutoMutex _lock(m_lock); + BufferData * buf = m_buffers.valueFor(bufferId); + if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE; + + //it's safe to update now + memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size); + return GL_NO_ERROR; +} + +void GLSharedGroup::deleteBufferData(GLuint bufferId) +{ + android::AutoMutex _lock(m_lock); + m_buffers.removeItem(bufferId); +} diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h new file mode 100644 index 000000000..0f07f47e0 --- /dev/null +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.h @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef _GL_SHARED_GROUP_H_ +#define _GL_SHARED_GROUP_H_ + +#define GL_API +#ifndef ANDROID +#define GL_APIENTRY +#define GL_APIENTRYP +#endif + +#include +#include +#include +#include + +#include +#include +#include "ErrorLog.h" +#include +#include +#include "FixedBuffer.h" +#include "SmartPtr.h" + +struct BufferData { + BufferData(); + BufferData(GLsizeiptr size, void * data); + GLsizeiptr m_size; + FixedBuffer m_fixedBuffer; +}; + + +class GLSharedGroup { +private: + android::DefaultKeyedVector m_buffers; + mutable android::Mutex m_lock; +public: + GLSharedGroup(); + ~GLSharedGroup(); + BufferData * getBufferData(GLuint bufferId); + void addBufferData(GLuint bufferId, GLsizeiptr size, void * data); + void updateBufferData(GLuint bufferId, GLsizeiptr size, void * data); + GLenum subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data); + void deleteBufferData(GLuint); +}; + +typedef SmartPtr GLSharedGroupPtr; + +#endif //_GL_SHARED_GROUP_H_ diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp index 653f71f1d..6d12fe365 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp @@ -36,6 +36,19 @@ static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this poin 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); \ + 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; \ + } + GLenum GLEncoder::s_glGetError(void * self) { GLEncoder *ctx = (GLEncoder *)self; @@ -263,6 +276,39 @@ void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id) ctx->m_glBindBuffer_enc(self, target, id); } +void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) +{ + GLEncoder *ctx = (GLEncoder *) 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 GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) +{ + GLEncoder *ctx = (GLEncoder *) 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 GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers) +{ + GLEncoder *ctx = (GLEncoder *) self; + SET_ERROR_IF(n<0, GL_INVALID_VALUE); + for (int i=0; im_shared->deleteBufferData(buffers[i]); + ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]); + } +} + void GLEncoder::sendVertexData(unsigned int first, unsigned int count) { assert(m_state != NULL); @@ -331,7 +377,7 @@ void GLEncoder::sendVertexData(unsigned int first, unsigned int count) break; } } else { - this->glBindBuffer(this, GL_ARRAY_BUFFER, state->bufferObject); + this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject); switch(i) { case GLClientState::VERTEX_LOCATION: @@ -369,7 +415,8 @@ void GLEncoder::sendVertexData(unsigned int first, unsigned int count) this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride, (GLuint)state->data+firstIndex); break; - } + } + this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); } } else { this->m_glDisableClientState_enc(this, state->glConst); @@ -390,6 +437,7 @@ void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum GLEncoder *ctx = (GLEncoder *)self; assert(ctx->m_state != NULL); + SET_ERROR_IF(count<0, GL_INVALID_VALUE); bool has_immediate_arrays = false; bool has_indirect_arrays = false; @@ -410,14 +458,20 @@ void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum return; } + bool adjustIndices = true; if (ctx->m_state->currentIndexVbo() != 0) { if (!has_immediate_arrays) { ctx->sendVertexData(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; @@ -487,6 +541,10 @@ GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) m_glGetPointerv_enc = set_glGetPointerv(s_glGetPointerv); m_glBindBuffer_enc = set_glBindBuffer(s_glBindBuffer); + m_glBufferData_enc = set_glBufferData(s_glBufferData); + m_glBufferSubData_enc = set_glBufferSubData(s_glBufferSubData); + m_glDeleteBuffers_enc = set_glDeleteBuffers(s_glDeleteBuffers); + m_glEnableClientState_enc = set_glEnableClientState(s_glEnableClientState); m_glDisableClientState_enc = set_glDisableClientState(s_glDisableClientState); m_glIsEnabled_enc = set_glIsEnabled(s_glIsEnabled); diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h index 7471bfb38..2076cf45c 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h @@ -18,6 +18,7 @@ #include "gl_enc.h" #include "GLClientState.h" +#include "GLSharedGroup.h" #include "FixedBuffer.h" class GLEncoder : public gl_encoder_context_t { @@ -28,6 +29,7 @@ public: void setClientState(GLClientState *state) { m_state = state; } + void setSharedGroup(GLSharedGroupPtr shared) { m_shared = shared; } void flush() { m_stream->flush(); } size_t pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack); @@ -41,6 +43,7 @@ private: bool m_initialized; GLClientState *m_state; + GLSharedGroupPtr m_shared; GLenum m_error; FixedBuffer m_fixedBuffer; GLint *m_compressedTextureFormats; @@ -66,6 +69,10 @@ private: glWeightPointerOES_client_proc_t m_glWeightPointerOES_enc; glBindBuffer_client_proc_t m_glBindBuffer_enc; + glBufferData_client_proc_t m_glBufferData_enc; + glBufferSubData_client_proc_t m_glBufferSubData_enc; + glDeleteBuffers_client_proc_t m_glDeleteBuffers_enc; + glEnableClientState_client_proc_t m_glEnableClientState_enc; glDisableClientState_client_proc_t m_glDisableClientState_enc; glIsEnabled_client_proc_t m_glIsEnabled_enc; @@ -95,6 +102,11 @@ private: static void s_glEnableClientState(void *self, GLenum state); static GLboolean s_glIsEnabled(void *self, GLenum cap); static void s_glBindBuffer(void *self, GLenum target, GLuint id); + static void s_glBufferData(void *self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + 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); diff --git a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp index 969c0c981..eda8f984e 100644 --- a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp +++ b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp @@ -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; im_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; diff --git a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h index bbe5659a7..d47ddcaad 100644 --- a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h +++ b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h @@ -19,6 +19,7 @@ #include "gl2_enc.h" #include "IOStream.h" #include "GLClientState.h" +#include "GLSharedGroup.h" #include "FixedBuffer.h" @@ -29,6 +30,7 @@ public: void setClientState(GLClientState *state) { m_state = state; } + void setSharedGroup(GLSharedGroupPtr shared){ m_shared = shared; } const GLClientState *state() { return m_state; } void flush() { gl2_encoder_context_t::m_stream->flush(); @@ -44,6 +46,7 @@ private: bool m_initialized; GLClientState *m_state; + GLSharedGroupPtr m_shared; GLenum m_error; GLint *m_compressedTextureFormats; @@ -69,6 +72,14 @@ private: glBindBuffer_client_proc_t m_glBindBuffer_enc; static void s_glBindBuffer(void *self, GLenum target, GLuint id); + + glBufferData_client_proc_t m_glBufferData_enc; + static void s_glBufferData(void *self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + glBufferSubData_client_proc_t m_glBufferSubData_enc; + static void s_glBufferSubData(void *self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data); + glDeleteBuffers_client_proc_t m_glDeleteBuffers_enc; + static void s_glDeleteBuffers(void *self, GLsizei n, const GLuint * buffers); + glDrawArrays_client_proc_t m_glDrawArrays_enc; static void s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count); diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp index fc99ff8ec..d0aa31fc9 100644 --- a/tools/emulator/opengl/system/egl/egl.cpp +++ b/tools/emulator/opengl/system/egl/egl.cpp @@ -20,6 +20,7 @@ #include #include "gralloc_cb.h" #include "GLClientState.h" +#include "GLSharedGroup.h" #include "GLEncoder.h" #ifdef WITH_GLES2 @@ -138,13 +139,14 @@ struct EGLContext_t { NEVER_CURRENT = 0x00020000 }; - EGLContext_t(EGLDisplay dpy, EGLConfig config); + EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx); ~EGLContext_t(); uint32_t flags; EGLDisplay dpy; EGLConfig config; EGLSurface read; EGLSurface draw; + EGLContext_t * shareCtx; EGLint version; uint32_t rcContext; const char* versionString; @@ -153,15 +155,18 @@ struct EGLContext_t { const char* extensionString; GLClientState * getClientState(){ return clientState; } + GLSharedGroupPtr getSharedGroup(){ return sharedGroup; } private: GLClientState * clientState; + GLSharedGroupPtr sharedGroup; }; -EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config) : +EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) : dpy(dpy), config(config), read(EGL_NO_SURFACE), draw(EGL_NO_SURFACE), + shareCtx(shareCtx), rcContext(0), versionString(NULL), vendorString(NULL), @@ -171,6 +176,8 @@ EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config) : flags = 0; version = 1; clientState = new GLClientState(); + if (shareCtx) sharedGroup = shareCtx->getSharedGroup(); + else sharedGroup = GLSharedGroupPtr(new GLSharedGroup()); }; EGLContext_t::~EGLContext_t() @@ -931,8 +938,9 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_c } uint32_t rcShareCtx = 0; + EGLContext_t * shareCtx = NULL; if (share_context) { - EGLContext_t * shareCtx = static_cast(share_context); + shareCtx = static_cast(share_context); rcShareCtx = shareCtx->rcContext; if (shareCtx->dpy != dpy) setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT); @@ -945,7 +953,7 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_c setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } - EGLContext_t * context = new EGLContext_t(dpy, config); + EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx); if (!context) setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT); @@ -1033,10 +1041,24 @@ EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLC //set the client state if (context->version == 2) { hostCon->gl2Encoder()->setClientState(context->getClientState()); + hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup()); } else { hostCon->glEncoder()->setClientState(context->getClientState()); + hostCon->glEncoder()->setSharedGroup(context->getSharedGroup()); } + } + else { + //release ClientState & SharedGroup + if (tInfo->currentContext->version == 2) { + hostCon->gl2Encoder()->setClientState(NULL); + hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL)); + } + else { + hostCon->glEncoder()->setClientState(NULL); + hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr(NULL)); + } + } if (tInfo->currentContext)