Move scissor state to RenderState
Change-Id: I1227a3886fb24e4d9fad79fca469794f06cfb15e
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
new file mode 100644
index 0000000..3a9a92e
--- /dev/null
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 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 "RenderState.h"
+
+#include "renderthread/CanvasContext.h"
+#include "renderthread/EglManager.h"
+
+namespace android {
+namespace uirenderer {
+
+RenderState::RenderState(renderthread::RenderThread& thread)
+ : mRenderThread(thread)
+ , mCaches(nullptr)
+ , mViewportWidth(0)
+ , mViewportHeight(0)
+ , mFramebuffer(0) {
+ mThreadId = pthread_self();
+}
+
+RenderState::~RenderState() {
+}
+
+void RenderState::onGLContextCreated() {
+ // This is delayed because the first access of Caches makes GL calls
+ mCaches = &Caches::getInstance();
+ mCaches->init();
+ mCaches->setRenderState(this);
+ mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
+
+ LOG_ALWAYS_FATAL_IF(scissor().isEnabled(), "scissor used before GL context created");
+ glDisable(GL_SCISSOR_TEST);
+}
+
+void RenderState::onGLContextDestroyed() {
+/*
+ size_t size = mActiveLayers.size();
+ if (CC_UNLIKELY(size != 0)) {
+ ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
+ mRegisteredContexts.size(), size, mActiveLayers.empty());
+ mCaches->dumpMemoryUsage();
+ for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
+ cit != mRegisteredContexts.end(); cit++) {
+ renderthread::CanvasContext* context = *cit;
+ ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get());
+ ALOGE(" Prefeteched layers: %zu", context->mPrefetechedLayers.size());
+ for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
+ pit != context->mPrefetechedLayers.end(); pit++) {
+ (*pit)->debugDumpLayers(" ");
+ }
+ context->mRootRenderNode->debugDumpLayers(" ");
+ }
+
+
+ if (mActiveLayers.begin() == mActiveLayers.end()) {
+ ALOGE("set has become empty. wat.");
+ }
+ for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
+ lit != mActiveLayers.end(); lit++) {
+ const Layer* layer = *(lit);
+ ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d",
+ layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered);
+ }
+ LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
+ }
+*/
+ mAssetAtlas.terminate();
+}
+
+void RenderState::setViewport(GLsizei width, GLsizei height) {
+ mViewportWidth = width;
+ mViewportHeight = height;
+ glViewport(0, 0, mViewportWidth, mViewportHeight);
+}
+
+
+void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
+ *outWidth = mViewportWidth;
+ *outHeight = mViewportHeight;
+}
+
+void RenderState::bindFramebuffer(GLuint fbo) {
+ if (mFramebuffer != fbo) {
+ mFramebuffer = fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ }
+}
+
+void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
+ interruptForFunctorInvoke();
+ (*functor)(mode, info);
+ resumeFromFunctorInvoke();
+}
+
+void RenderState::interruptForFunctorInvoke() {
+ if (mCaches->currentProgram) {
+ if (mCaches->currentProgram->isInUse()) {
+ mCaches->currentProgram->remove();
+ mCaches->currentProgram = nullptr;
+ }
+ }
+ mCaches->resetActiveTexture();
+ mCaches->unbindMeshBuffer();
+ mCaches->unbindIndicesBuffer();
+ mCaches->resetVertexPointers();
+ mCaches->disableTexCoordsVertexArray();
+ debugOverdraw(false, false);
+}
+
+void RenderState::resumeFromFunctorInvoke() {
+ glViewport(0, 0, mViewportWidth, mViewportHeight);
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ debugOverdraw(false, false);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ scissor().invalidate();
+
+ mCaches->activeTexture(0);
+ mCaches->resetBoundTextures();
+
+ mCaches->blend = true;
+ glEnable(GL_BLEND);
+ glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode);
+ glBlendEquation(GL_FUNC_ADD);
+}
+
+void RenderState::debugOverdraw(bool enable, bool clear) {
+ if (mCaches->debugOverdraw && mFramebuffer == 0) {
+ if (clear) {
+ scissor().setEnabled(false);
+ mCaches->stencil.clear();
+ }
+ if (enable) {
+ mCaches->stencil.enableDebugWrite();
+ } else {
+ mCaches->stencil.disable();
+ }
+ }
+}
+
+void RenderState::requireGLContext() {
+ assertOnGLThread();
+ mRenderThread.eglManager().requireGlContext();
+}
+
+void RenderState::assertOnGLThread() {
+ pthread_t curr = pthread_self();
+ LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!");
+}
+
+
+class DecStrongTask : public renderthread::RenderTask {
+public:
+ DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
+
+ virtual void run() override {
+ mObject->decStrong(nullptr);
+ mObject = nullptr;
+ delete this;
+ }
+
+private:
+ VirtualLightRefBase* mObject;
+};
+
+void RenderState::postDecStrong(VirtualLightRefBase* object) {
+ mRenderThread.queue(new DecStrongTask(object));
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
new file mode 100644
index 0000000..b2d5cc5
--- /dev/null
+++ b/libs/hwui/renderstate/RenderState.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 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 RENDERSTATE_H
+#define RENDERSTATE_H
+
+#include <set>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <utils/Mutex.h>
+#include <utils/Functor.h>
+#include <utils/RefBase.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
+#include "AssetAtlas.h"
+#include "Caches.h"
+#include "Scissor.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+class Caches;
+class Layer;
+
+namespace renderthread {
+class CanvasContext;
+class RenderThread;
+}
+
+// TODO: Replace Cache's GL state tracking with this. For now it's more a thin
+// wrapper of Caches for users to migrate to.
+class RenderState {
+ PREVENT_COPY_AND_ASSIGN(RenderState);
+public:
+ void onGLContextCreated();
+ void onGLContextDestroyed();
+
+ void setViewport(GLsizei width, GLsizei height);
+ void getViewport(GLsizei* outWidth, GLsizei* outHeight);
+
+ void bindFramebuffer(GLuint fbo);
+ GLint getFramebuffer() { return mFramebuffer; }
+
+ void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info);
+
+ void debugOverdraw(bool enable, bool clear);
+
+ void registerLayer(const Layer* layer) {
+ mActiveLayers.insert(layer);
+ }
+ void unregisterLayer(const Layer* layer) {
+ mActiveLayers.erase(layer);
+ }
+
+ void registerCanvasContext(renderthread::CanvasContext* context) {
+ mRegisteredContexts.insert(context);
+ }
+
+ void unregisterCanvasContext(renderthread::CanvasContext* context) {
+ mRegisteredContexts.erase(context);
+ }
+
+ void requireGLContext();
+
+ // TODO: This system is a little clunky feeling, this could use some
+ // more thinking...
+ void postDecStrong(VirtualLightRefBase* object);
+
+ AssetAtlas& assetAtlas() { return mAssetAtlas; }
+
+ Scissor& scissor() { return mScissor; }
+private:
+ friend class renderthread::RenderThread;
+ friend class Caches;
+
+ void interruptForFunctorInvoke();
+ void resumeFromFunctorInvoke();
+ void assertOnGLThread();
+
+ RenderState(renderthread::RenderThread& thread);
+ ~RenderState();
+
+ Scissor mScissor;
+
+ renderthread::RenderThread& mRenderThread;
+ Caches* mCaches;
+ AssetAtlas mAssetAtlas;
+ std::set<const Layer*> mActiveLayers;
+ std::set<renderthread::CanvasContext*> mRegisteredContexts;
+
+ GLsizei mViewportWidth;
+ GLsizei mViewportHeight;
+ GLuint mFramebuffer;
+
+ pthread_t mThreadId;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* RENDERSTATE_H */
diff --git a/libs/hwui/renderstate/Scissor.cpp b/libs/hwui/renderstate/Scissor.cpp
new file mode 100644
index 0000000..ede57be
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 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 "Scissor.h"
+
+namespace android {
+namespace uirenderer {
+
+Scissor::Scissor()
+ : mEnabled(false)
+ , mScissorX(0)
+ , mScissorY(0)
+ , mScissorWidth(0)
+ , mScissorHeight(0) {
+}
+
+bool Scissor::setEnabled(bool enabled) {
+ if (mEnabled != enabled) {
+ if (enabled) {
+ glEnable(GL_SCISSOR_TEST);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+ mEnabled = enabled;
+ return true;
+ }
+ return false;
+}
+
+bool Scissor::set(GLint x, GLint y, GLint width, GLint height) {
+ if (mEnabled && (x != mScissorX || y != mScissorY
+ || width != mScissorWidth || height != mScissorHeight)) {
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (width < 0) {
+ width = 0;
+ }
+ if (height < 0) {
+ height = 0;
+ }
+ glScissor(x, y, width, height);
+
+ mScissorX = x;
+ mScissorY = y;
+ mScissorWidth = width;
+ mScissorHeight = height;
+
+ return true;
+ }
+ return false;
+}
+
+void Scissor::reset() {
+ mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
+}
+
+void Scissor::invalidate() {
+ mEnabled = glIsEnabled(GL_SCISSOR_TEST);
+ setEnabled(true);
+ reset();
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/Scissor.h b/libs/hwui/renderstate/Scissor.h
new file mode 100644
index 0000000..eabf3a77
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 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 RENDERSTATE_SCISSOR_H
+#define RENDERSTATE_SCISSOR_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace android {
+namespace uirenderer {
+
+class Scissor {
+ friend class RenderState;
+public:
+ Scissor();
+ bool setEnabled(bool enabled);
+ bool set(GLint x, GLint y, GLint width, GLint height);
+ void reset();
+ bool isEnabled() { return mEnabled; }
+private:
+ void invalidate();
+ bool mEnabled;
+ GLint mScissorX;
+ GLint mScissorY;
+ GLint mScissorWidth;
+ GLint mScissorHeight;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_SCISSOR_H