Create shared contexts.

TRAC #12498

Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch

Author:    Andrew Lewycky

git-svn-id: https://angleproject.googlecode.com/svn/trunk@363 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 2c59bb3..ac12499 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -378,11 +378,11 @@
     return surface;
 }
 
-EGLContext Display::createContext(EGLConfig configHandle)
+EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
 {
     const egl::Config *config = mConfigSet.get(configHandle);
 
-    gl::Context *context = glCreateContext(config);
+    gl::Context *context = glCreateContext(config, shareContext);
     mContextSet.insert(context);
 
     return context;
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index 02c9fde..8f3aea3 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -43,7 +43,7 @@
     bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
 
     egl::Surface *createWindowSurface(HWND window, EGLConfig config);
-    EGLContext createContext(EGLConfig configHandle);
+    EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext);
 
     void destroySurface(egl::Surface *surface);
     void destroyContext(gl::Context *context);
diff --git a/src/libEGL/libEGL.cpp b/src/libEGL/libEGL.cpp
index 4396b02..5ceb6ef 100644
--- a/src/libEGL/libEGL.cpp
+++ b/src/libEGL/libEGL.cpp
@@ -772,7 +772,7 @@
             return EGL_NO_CONTEXT;
         }
 
-        EGLContext context = display->createContext(config);
+        EGLContext context = display->createContext(config, static_cast<gl::Context*>(share_context));
 
         return success(context);
     }
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index c619ec6..eab929e 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -34,7 +34,7 @@
 
 namespace gl
 {
-Context::Context(const egl::Config *config)
+Context::Context(const egl::Config *config, const gl::Context *shareContext)
     : mConfig(config)
 {
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -104,8 +104,15 @@
     mState.colorMaskAlpha = true;
     mState.depthMask = true;
 
-    // FIXME: Resource managers should get managed with context sharing
-    mResourceManager = new ResourceManager();
+    if (shareContext != NULL)
+    {
+        mResourceManager = shareContext->mResourceManager;
+        mResourceManager->addRef();
+    }
+    else
+    {
+        mResourceManager = new ResourceManager();
+    }
 
     // [OpenGL ES 2.0.24] section 3.7 page 83:
     // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
@@ -200,8 +207,7 @@
         mMaskedClearSavedState->Release();
     }
 
-    // FIXME: Context should not be responsible for resource manager deallocation
-    delete mResourceManager;
+    mResourceManager->release();
 }
 
 void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
@@ -277,6 +283,12 @@
     mScissorStateDirty = true;
     mSampleStateDirty = true;
     mDitherStateDirty = true;
+    mFrontFaceDirty = true;
+
+    if (mBufferBackEnd != NULL)
+    {
+        mBufferBackEnd->invalidate();
+    }
 }
 
 void Context::setClearColor(float red, float green, float blue, float alpha)
@@ -2803,9 +2815,9 @@
 
 extern "C"
 {
-gl::Context *glCreateContext(const egl::Config *config)
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
 {
-    return new gl::Context(config);
+    return new gl::Context(config, shareContext);
 }
 
 void glDestroyContext(gl::Context *context)
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index ec14b98..cc52878 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -193,7 +193,7 @@
 class Context
 {
   public:
-    Context(const egl::Config *config);
+    Context(const egl::Config *config, const gl::Context *shareContext);
 
     ~Context();
 
@@ -459,7 +459,7 @@
 extern "C"
 {
 // Exported functions for use by EGL
-gl::Context *glCreateContext(const egl::Config *config);
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext);
 void glDestroyContext(gl::Context *context);
 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
 gl::Context *glGetCurrentContext();
diff --git a/src/libGLESv2/ResourceManager.cpp b/src/libGLESv2/ResourceManager.cpp
index 6b4deb1..8fa2a65 100644
--- a/src/libGLESv2/ResourceManager.cpp
+++ b/src/libGLESv2/ResourceManager.cpp
@@ -19,6 +19,7 @@
 {
 ResourceManager::ResourceManager()
 {
+    mRefCount = 1;
 }
 
 ResourceManager::~ResourceManager()
@@ -49,6 +50,19 @@
     }
 }
 
+void ResourceManager::addRef()
+{
+    mRefCount++;
+}
+
+void ResourceManager::release()
+{
+    if (--mRefCount == 0)
+    {
+        delete this;
+    }
+}
+
 // Returns an unused buffer name
 GLuint ResourceManager::createBuffer()
 {
diff --git a/src/libGLESv2/ResourceManager.h b/src/libGLESv2/ResourceManager.h
index 8563367..346e51f 100644
--- a/src/libGLESv2/ResourceManager.h
+++ b/src/libGLESv2/ResourceManager.h
@@ -39,6 +39,9 @@
     ResourceManager();
     ~ResourceManager();
 
+    void addRef();
+    void release();
+
     GLuint createBuffer();
     GLuint createShader(GLenum type);
     GLuint createProgram();
@@ -66,6 +69,8 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(ResourceManager);
 
+    std::size_t mRefCount;
+
     typedef std::map<GLuint, Buffer*> BufferMap;
     BufferMap mBufferMap;
 
diff --git a/src/libGLESv2/geometry/backend.h b/src/libGLESv2/geometry/backend.h
index d18a908..1457f33 100644
--- a/src/libGLESv2/geometry/backend.h
+++ b/src/libGLESv2/geometry/backend.h
@@ -65,6 +65,8 @@
 
     virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo) = 0;
     virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes) = 0;
+
+    virtual void invalidate() = 0;
 };
 
 class TranslatedBuffer
diff --git a/src/libGLESv2/geometry/dx9.cpp b/src/libGLESv2/geometry/dx9.cpp
index e51befb..3a935d5 100644
--- a/src/libGLESv2/geometry/dx9.cpp
+++ b/src/libGLESv2/geometry/dx9.cpp
@@ -471,6 +471,14 @@
     return GL_NO_ERROR;
 }
 
+void Dx9BackEnd::invalidate()
+{
+    for (int i = 0; i < MAX_VERTEX_ATTRIBS + 1; i++)
+    {
+        mStreamFrequency[i] = STREAM_FREQUENCY_DIRTY;
+    }
+}
+
 Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size)
     : TranslatedVertexBuffer(size)
 {
diff --git a/src/libGLESv2/geometry/dx9.h b/src/libGLESv2/geometry/dx9.h
index 6068dd6..fd5964c 100644
--- a/src/libGLESv2/geometry/dx9.h
+++ b/src/libGLESv2/geometry/dx9.h
@@ -35,6 +35,8 @@
     virtual GLenum setupIndicesPreDraw(const TranslatedIndexData &indexInfo);
     virtual GLenum setupAttributesPreDraw(const TranslatedAttribute *attributes);
 
+    void invalidate();
+
   private:
     IDirect3DDevice9 *mDevice;
 
@@ -47,10 +49,11 @@
     {
         STREAM_FREQUENCY_UNINSTANCED = 0,
         STREAM_FREQUENCY_INDEXED,
-        STREAM_FREQUENCY_INSTANCED
+        STREAM_FREQUENCY_INSTANCED,
+        STREAM_FREQUENCY_DIRTY
     };
 
-    StreamFrequency mStreamFrequency[MAX_VERTEX_ATTRIBS+1];
+    StreamFrequency mStreamFrequency[MAX_VERTEX_ATTRIBS+1]; // Stream frequencies as last set.
 
     struct TranslationInfo
     {