Moves fbo support in renderscript behind the hal

Change-Id: I26a857586f5f0b47df4c1f4589d2023e70481ec7
diff --git a/Android.mk b/Android.mk
index ef00b30..29c1447 100644
--- a/Android.mk
+++ b/Android.mk
@@ -117,6 +117,7 @@
 	rsType.cpp \
 	driver/rsdBcc.cpp \
 	driver/rsdCore.cpp \
+	driver/rsdFrameBuffer.cpp \
 	driver/rsdGL.cpp \
 	driver/rsdMesh.cpp \
 	driver/rsdMeshObj.cpp \
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 0a5f2ec..7ef9c30 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -23,6 +23,7 @@
 #include "rsdProgramFragment.h"
 #include "rsdMesh.h"
 #include "rsdSampler.h"
+#include "rsdFrameBuffer.h"
 
 #include <malloc.h>
 #include "rsContext.h"
@@ -98,6 +99,12 @@
         rsdSamplerDestroy
     },
 
+    {
+        rsdFrameBufferInit,
+        rsdFrameBufferSetActive,
+        rsdFrameBufferDestroy
+    },
+
 };
 
 pthread_key_t rsdgThreadTLSKey = 0;
diff --git a/driver/rsdFrameBuffer.cpp b/driver/rsdFrameBuffer.cpp
new file mode 100644
index 0000000..6a7dac4
--- /dev/null
+++ b/driver/rsdFrameBuffer.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdFrameBuffer.h"
+
+#include "rsContext.h"
+#include "rsFBOCache.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+struct DrvFrameBuffer {
+    GLuint mFBOId;
+};
+
+void checkError(const Context *rsc) {
+    GLenum status;
+    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    switch (status) {
+    case GL_FRAMEBUFFER_COMPLETE:
+        break;
+    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+        rsc->setError(RS_ERROR_BAD_VALUE,
+                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
+        break;
+    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+        rsc->setError(RS_ERROR_BAD_VALUE,
+                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
+        break;
+    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+        rsc->setError(RS_ERROR_BAD_VALUE,
+                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
+        break;
+    case GL_FRAMEBUFFER_UNSUPPORTED:
+        rsc->setError(RS_ERROR_BAD_VALUE,
+                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
+        break;
+    }
+}
+
+
+void setDepthAttachment(const Context *rsc, const FBOCache *fb) {
+    if (fb->mHal.state.depthTarget.get() != NULL) {
+        if (fb->mHal.state.depthTarget->getIsTexture()) {
+            uint32_t texID = fb->mHal.state.depthTarget->getTextureID();
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                   GL_TEXTURE_2D, texID, 0);
+        } else {
+            uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID();
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                      GL_RENDERBUFFER, texID);
+        }
+    } else {
+        // Reset last attachment
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                  GL_RENDERBUFFER, 0);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                               GL_TEXTURE_2D, 0, 0);
+    }
+}
+
+void setColorAttachment(const Context *rsc, const FBOCache *fb) {
+    // Now attach color targets
+    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
+        uint32_t texID = 0;
+        if (fb->mHal.state.colorTargets[i].get() != NULL) {
+            if (fb->mHal.state.colorTargets[i]->getIsTexture()) {
+                uint32_t texID = fb->mHal.state.colorTargets[i]->getTextureID();
+                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+                                       GL_TEXTURE_2D, texID, 0);
+            } else {
+                uint32_t texID = fb->mHal.state.depthTarget->getRenderTargetID();
+                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+                                          GL_RENDERBUFFER, texID);
+            }
+        } else {
+            // Reset last attachment
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+                                      GL_RENDERBUFFER, 0);
+            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+                                   GL_TEXTURE_2D, 0, 0);
+        }
+    }
+}
+
+bool renderToFramebuffer(const FBOCache *fb) {
+    if (fb->mHal.state.depthTarget.get() != NULL) {
+        return false;
+    }
+
+    for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) {
+        if (fb->mHal.state.colorTargets[i].get() != NULL) {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+bool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) {
+    DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer));
+    if (drv == NULL) {
+        return false;
+    }
+    fb->mHal.drv = drv;
+    drv->mFBOId = 0;
+
+    return true;
+}
+
+void rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) {
+    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
+
+    bool framebuffer = renderToFramebuffer(fb);
+    if (!framebuffer) {
+        if(drv->mFBOId == 0) {
+            glGenFramebuffers(1, &drv->mFBOId);
+        }
+        glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId);
+
+        setDepthAttachment(rsc, fb);
+        setColorAttachment(rsc, fb);
+
+        glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(),
+                         fb->mHal.state.colorTargets[0]->getType()->getDimY());
+
+        checkError(rsc);
+    } else {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+    }
+}
+
+void rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) {
+    DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv;
+    if(drv->mFBOId != 0) {
+        glDeleteFramebuffers(1, &drv->mFBOId);
+    }
+
+    free(fb->mHal.drv);
+    fb->mHal.drv = NULL;
+}
+
+
diff --git a/driver/rsdFrameBuffer.h b/driver/rsdFrameBuffer.h
new file mode 100644
index 0000000..dec59fc
--- /dev/null
+++ b/driver/rsdFrameBuffer.h
@@ -0,0 +1,30 @@
+/*
+ * 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 RSD_FRAME_BUFFER_H
+#define RSD_FRAME_BUFFER_H
+
+#include <rs_hal.h>
+
+bool rsdFrameBufferInit(const android::renderscript::Context *rsc,
+                         const android::renderscript::FBOCache *fb);
+void rsdFrameBufferSetActive(const android::renderscript::Context *rsc,
+                              const android::renderscript::FBOCache *fb);
+void rsdFrameBufferDestroy(const android::renderscript::Context *rsc,
+                            const android::renderscript::FBOCache *fb);
+
+
+#endif // RSD_FRAME_BUFFER_H
diff --git a/rsContext.cpp b/rsContext.cpp
index 98adabc..532b1a2 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -238,6 +238,7 @@
         rsc->setProgramStore(NULL);
         rsc->mStateFont.init(rsc);
         rsc->setFont(NULL);
+        rsc->mFBOCache.init(rsc);
     }
 
     rsc->mRunning = true;
@@ -298,6 +299,7 @@
          mStateFragment.deinit(this);
          mStateFragmentStore.deinit(this);
          mStateFont.deinit(this);
+         mFBOCache.deinit(this);
     }
     //LOGV("destroyWorkerThreadResources 2");
     mExit = true;
diff --git a/rsFBOCache.cpp b/rsFBOCache.cpp
index 0f33f67..31a51b7 100644
--- a/rsFBOCache.cpp
+++ b/rsFBOCache.cpp
@@ -19,33 +19,30 @@
 #include "rsContext.h"
 #include "rsAllocation.h"
 
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES2/gl2.h>
-#endif //ANDROID_RS_SERIALIZE
-
 using namespace android;
 using namespace android::renderscript;
 
 
 FBOCache::FBOCache() {
-    mFBOId = 0;
     mDirty = true;
-    mMaxTargets = 1;
-    mColorTargets = new ObjectBaseRef<Allocation>[mMaxTargets];
+    mHal.state.colorTargetsCount = 1;
+    mHal.state.colorTargets = new ObjectBaseRef<Allocation>[mHal.state.colorTargetsCount];
 }
 
 FBOCache::~FBOCache() {
-    delete[] mColorTargets;
-#ifndef ANDROID_RS_SERIALIZE
-    if(mFBOId != 0) {
-        glDeleteFramebuffers(1, &mFBOId);
-    }
-#endif //ANDROID_RS_SERIALIZE
+    delete[] mHal.state.colorTargets;
+}
+
+void FBOCache::init(Context *rsc) {
+    rsc->mHal.funcs.framebuffer.init(rsc, this);
+}
+
+void FBOCache::deinit(Context *rsc) {
+    rsc->mHal.funcs.framebuffer.destroy(rsc, this);
 }
 
 void FBOCache::bindColorTarget(Context *rsc, Allocation *a, uint32_t slot) {
-    if (slot >= mMaxTargets) {
+    if (slot >= mHal.state.colorTargetsCount) {
         LOGE("Invalid render target index");
         return;
     }
@@ -62,7 +59,7 @@
             a->deferredAllocateRenderTarget(rsc);
         }
     }
-    mColorTargets[slot].set(a);
+    mHal.state.colorTargets[slot].set(a);
     mDirty = true;
 }
 
@@ -80,131 +77,34 @@
             a->deferredAllocateRenderTarget(rsc);
         }
     }
-    mDepthTarget.set(a);
+    mHal.state.depthTarget.set(a);
     mDirty = true;
 }
 
 void FBOCache::resetAll(Context *) {
-    for (uint32_t i = 0; i < mMaxTargets; i ++) {
-        mColorTargets[i].set(NULL);
+    for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
+        mHal.state.colorTargets[i].set(NULL);
     }
-    mDepthTarget.set(NULL);
+    mHal.state.depthTarget.set(NULL);
     mDirty = true;
 }
 
-bool FBOCache::renderToFramebuffer() {
-    if (mDepthTarget.get() != NULL) {
-        return false;
-    }
-
-    for (uint32_t i = 0; i < mMaxTargets; i ++) {
-        if (mColorTargets[i].get() != NULL) {
-            return false;
-        }
-    }
-    return true;
-}
-
-void FBOCache::checkError(Context *rsc) {
-    GLenum status;
-    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    switch (status) {
-    case GL_FRAMEBUFFER_COMPLETE:
-        break;
-    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
-        rsc->setError(RS_ERROR_BAD_VALUE,
-                      "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT");
-        break;
-    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
-        rsc->setError(RS_ERROR_BAD_VALUE,
-                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
-        break;
-    case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
-        rsc->setError(RS_ERROR_BAD_VALUE,
-                      "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
-        break;
-    case GL_FRAMEBUFFER_UNSUPPORTED:
-        rsc->setError(RS_ERROR_BAD_VALUE,
-                      "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED");
-        break;
-    }
-}
-
-void FBOCache::setDepthAttachment(Context *rsc) {
-#ifndef ANDROID_RS_SERIALIZE
-    if (mDepthTarget.get() != NULL) {
-        mDepthTarget->uploadCheck(rsc);
-        if (mDepthTarget->getIsTexture()) {
-            uint32_t texID = mDepthTarget->getTextureID();
-            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                                   GL_TEXTURE_2D, texID, 0);
-        } else {
-            uint32_t texID = mDepthTarget->getRenderTargetID();
-            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                                      GL_RENDERBUFFER, texID);
-        }
-    } else {
-        // Reset last attachment
-        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                                  GL_RENDERBUFFER, 0);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                               GL_TEXTURE_2D, 0, 0);
-    }
-#endif //ANDROID_RS_SERIALIZE
-}
-
-void FBOCache::setColorAttachment(Context *rsc) {
-#ifndef ANDROID_RS_SERIALIZE
-    // Now attach color targets
-    for (uint32_t i = 0; i < mMaxTargets; i ++) {
-        uint32_t texID = 0;
-        if (mColorTargets[i].get() != NULL) {
-            mColorTargets[i]->uploadCheck(rsc);
-            if (mColorTargets[i]->getIsTexture()) {
-                uint32_t texID = mColorTargets[i]->getTextureID();
-                glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-                                       GL_TEXTURE_2D, texID, 0);
-            } else {
-                uint32_t texID = mDepthTarget->getRenderTargetID();
-                glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-                                          GL_RENDERBUFFER, texID);
-            }
-        } else {
-            // Reset last attachment
-            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-                                      GL_RENDERBUFFER, 0);
-            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
-                                   GL_TEXTURE_2D, 0, 0);
-        }
-    }
-#endif //ANDROID_RS_SERIALIZE
-}
-
 void FBOCache::setup(Context *rsc) {
-#ifndef ANDROID_RS_SERIALIZE
     if (!mDirty) {
         return;
     }
 
-    bool framebuffer = renderToFramebuffer();
-
-    if (!framebuffer) {
-        if(mFBOId == 0) {
-            glGenFramebuffers(1, &mFBOId);
-        }
-        glBindFramebuffer(GL_FRAMEBUFFER, mFBOId);
-
-        setDepthAttachment(rsc);
-        setColorAttachment(rsc);
-
-        glViewport(0, 0, mColorTargets[0]->getType()->getDimX(),
-                         mColorTargets[0]->getType()->getDimY());
-
-        checkError(rsc);
-    } else {
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
-        glViewport(0, 0, rsc->getWidth(), rsc->getHeight());
+    if (mHal.state.depthTarget.get() != NULL) {
+        mHal.state.depthTarget->uploadCheck(rsc);
     }
+
+    for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) {
+        if (mHal.state.colorTargets[i].get() != NULL) {
+            mHal.state.colorTargets[i]->uploadCheck(rsc);
+        }
+    }
+
+    rsc->mHal.funcs.framebuffer.setActive(rsc, this);
+
     mDirty = false;
-#endif //ANDROID_RS_SERIALIZE
 }
diff --git a/rsFBOCache.h b/rsFBOCache.h
index c9ae1dc..f42e1f3 100644
--- a/rsFBOCache.h
+++ b/rsFBOCache.h
@@ -30,24 +30,33 @@
     FBOCache();
     ~FBOCache();
 
+    void init(Context *rsc);
+    void deinit(Context *rsc);
+
     void bindColorTarget(Context *rsc, Allocation *a, uint32_t slot);
     void bindDepthTarget(Context *, Allocation *a);
     void resetAll(Context *);
 
     void setup(Context *);
 
-protected:
+    struct Hal {
+        mutable void *drv;
 
+        struct State {
+            ObjectBaseRef<Allocation> *colorTargets;
+            uint32_t colorTargetsCount;
+            ObjectBaseRef<Allocation> depthTarget;
+        };
+        State state;
+    };
+    Hal mHal;
+
+protected:
     bool mDirty;
-    uint32_t mMaxTargets;
     void checkError(Context *);
     void setColorAttachment(Context *rsc);
     void setDepthAttachment(Context *rsc);
     bool renderToFramebuffer();
-    ObjectBaseRef<Allocation> *mColorTargets;
-    ObjectBaseRef<Allocation> mDepthTarget;
-
-    uint32_t mFBOId;
 
 };
 
diff --git a/rs_hal.h b/rs_hal.h
index 4cc2abf..cfa4e74 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -37,6 +37,7 @@
 class ProgramFragment;
 class Mesh;
 class Sampler;
+class FBOCache;
 
 typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName);
 
@@ -128,6 +129,12 @@
         void (*destroy)(const Context *rsc, const Sampler *m);
     } sampler;
 
+    struct {
+        bool (*init)(const Context *rsc, const FBOCache *fb);
+        void (*setActive)(const Context *rsc, const FBOCache *fb);
+        void (*destroy)(const Context *rsc, const FBOCache *fb);
+    } framebuffer;
+
 } RsdHalFunctions;