summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/RenderEngine
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/RenderEngine')
-rw-r--r--services/surfaceflinger/RenderEngine/Description.cpp99
-rw-r--r--services/surfaceflinger/RenderEngine/Description.h74
-rw-r--r--services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp47
-rw-r--r--services/surfaceflinger/RenderEngine/GLES11RenderEngine.h9
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp213
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.h70
-rw-r--r--services/surfaceflinger/RenderEngine/Mesh.cpp81
-rw-r--r--services/surfaceflinger/RenderEngine/Mesh.h65
-rw-r--r--services/surfaceflinger/RenderEngine/Program.cpp144
-rw-r--r--services/surfaceflinger/RenderEngine/Program.h89
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.cpp206
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.h127
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.cpp87
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.h39
14 files changed, 1321 insertions, 29 deletions
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
new file mode 100644
index 0000000..9611b02
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 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 <stdint.h>
+#include <string.h>
+
+#include <utils/TypeHelpers.h>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include "Description.h"
+
+namespace android {
+
+Description::Description() :
+ mUniformsDirty(true) {
+ mPlaneAlpha = 1.0f;
+ mPremultipliedAlpha = true;
+ mOpaque = true;
+ mTextureTarget = GL_TEXTURE_EXTERNAL_OES;
+
+ const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
+ memset(mColor, 0, sizeof(mColor));
+ memcpy(mProjectionMatrix, m, sizeof(mProjectionMatrix));
+ memcpy(mTextureMatrix, m, sizeof(mTextureMatrix));
+}
+
+Description::~Description() {
+}
+
+void Description::setPlaneAlpha(GLclampf planeAlpha) {
+ if (planeAlpha != mPlaneAlpha) {
+ mUniformsDirty = true;
+ mPlaneAlpha = planeAlpha;
+ }
+}
+
+void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
+ if (premultipliedAlpha != mPremultipliedAlpha) {
+ mPremultipliedAlpha = premultipliedAlpha;
+ }
+}
+
+void Description::setOpaque(bool opaque) {
+ if (opaque != mOpaque) {
+ mOpaque = opaque;
+ }
+}
+
+void Description::setTextureName(GLenum target, GLuint tname) {
+ if (target != mTextureTarget) {
+ mTextureTarget = target;
+ }
+ if (tname != mTextureName) {
+ mTextureName = tname;
+ mUniformsDirty = true;
+ }
+}
+
+void Description::disableTexture() {
+ if (mTextureTarget != 0) {
+ mTextureTarget = 0;
+ }
+ mTextureName = 0;
+}
+
+void Description::setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ mColor[0] = red;
+ mColor[1] = green;
+ mColor[2] = blue;
+ mColor[3] = alpha;
+ mUniformsDirty = true;
+}
+
+void Description::setProjectionMatrix(GLfloat const* mtx) {
+ memcpy(mProjectionMatrix, mtx, sizeof(mProjectionMatrix));
+ mUniformsDirty = true;
+}
+
+void Description::setTextureMatrix(GLfloat const* mtx) {
+ memcpy(mTextureMatrix, mtx, sizeof(mTextureMatrix));
+ mUniformsDirty = true;
+}
+
+} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
new file mode 100644
index 0000000..47b0d8e
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2013 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 <GLES2/gl2.h>
+
+#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_
+#define SF_RENDER_ENGINE_DESCRIPTION_H_
+
+namespace android {
+
+class Program;
+
+/*
+ * This holds the state of the rendering engine. This class is used
+ * to generate a corresponding GLSL program and set the appropriate
+ * uniform.
+ *
+ * Program and ProgramCache are friends and access the state directly
+ */
+class Description {
+ friend class Program;
+ friend class ProgramCache;
+
+ // value of the plane-alpha, between 0 and 1
+ GLclampf mPlaneAlpha;
+ // whether textures are premultiplied
+ bool mPremultipliedAlpha;
+ // whether this layer is marked as opaque
+ bool mOpaque;
+ // texture target, TEXTURE_2D or TEXTURE_EXTERNAL
+ GLenum mTextureTarget;
+
+ // name of the texture
+ GLuint mTextureName;
+ // color used when texturing is disabled
+ GLclampf mColor[4];
+ // projection matrix
+ GLfloat mProjectionMatrix[16];
+ // texture matrix
+ GLfloat mTextureMatrix[16];
+
+public:
+ Description();
+ ~Description();
+
+ void setPlaneAlpha(GLclampf planeAlpha);
+ void setPremultipliedAlpha(bool premultipliedAlpha);
+ void setOpaque(bool opaque);
+ void setTextureName(GLenum target, GLuint tname);
+ void disableTexture();
+ void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void setProjectionMatrix(GLfloat const* mtx);
+ void setTextureMatrix(GLfloat const* mtx);
+
+private:
+ bool mUniformsDirty;
+};
+
+} /* namespace android */
+
+#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index 19499c9..27105a2 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -21,6 +21,7 @@
#include "GLES11RenderEngine.h"
#include "GLExtensions.h"
+#include "Mesh.h"
// ---------------------------------------------------------------------------
namespace android {
@@ -69,12 +70,14 @@ size_t GLES11RenderEngine::getMaxViewportDims() const {
mMaxViewportDims[0] : mMaxViewportDims[1];
}
-void GLES11RenderEngine::setViewportAndProjection(size_t w, size_t h) {
- glViewport(0, 0, w, h);
+void GLES11RenderEngine::setViewportAndProjection(
+ size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
+ glViewport(0, 0, vpw, vph);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// put the origin in the left-bottom corner
- glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
+ if (yswap) glOrthof(0, w, h, 0, 0, 1);
+ else glOrthof(0, w, 0, h, 0, 1);
glMatrixMode(GL_MODELVIEW);
}
@@ -87,7 +90,7 @@ void GLES11RenderEngine::setupLayerBlending(
if (CC_UNLIKELY(alpha < 0xFF)) {
// Cv = premultiplied ? Cs*alpha : Cs
- // Av = !opaque ? alpha*As : 1.0
+ // Av = !opaque ? As*alpha : As
combineRGB = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
combineAlpha = !opaque ? GL_MODULATE : GL_REPLACE;
src0Alpha = GL_CONSTANT;
@@ -180,25 +183,37 @@ void GLES11RenderEngine::disableBlending() {
glDisable(GL_BLEND);
}
-void GLES11RenderEngine::clearWithColor(const float vertices[][2] , size_t count,
- float red, float green, float blue, float alpha) {
- glColor4f(red, green, blue, alpha);
+void GLES11RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float b, float a) {
+ glColor4f(r, g, b, a);
glDisable(GL_TEXTURE_EXTERNAL_OES);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- glVertexPointer(2, GL_FLOAT, 0, vertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, count);
+
+ glVertexPointer(mesh.getVertexSize(),
+ GL_FLOAT,
+ mesh.getByteStride(),
+ mesh.getVertices());
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
}
-void GLES11RenderEngine::drawMesh2D(
- const float vertices[][2], const float texCoords[][2], size_t count) {
- if (texCoords) {
+void GLES11RenderEngine::drawMesh(const Mesh& mesh) {
+ if (mesh.getTexCoordsSize()) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glTexCoordPointer(mesh.getTexCoordsSize(),
+ GL_FLOAT,
+ mesh.getByteStride(),
+ mesh.getTexCoords());
}
- glVertexPointer(2, GL_FLOAT, 0, vertices);
- glDrawArrays(GL_TRIANGLE_FAN, 0, count);
- if (texCoords) {
+
+ glVertexPointer(mesh.getVertexSize(),
+ GL_FLOAT,
+ mesh.getByteStride(),
+ mesh.getVertices());
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+ if (mesh.getTexCoordsSize()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 15054bd..8bb7ed1 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -30,6 +30,7 @@ namespace android {
// ---------------------------------------------------------------------------
class String8;
+class Mesh;
class GLES11RenderEngine : public RenderEngine {
GLuint mProtectedTexName;
@@ -43,7 +44,7 @@ protected:
virtual ~GLES11RenderEngine();
virtual void dump(String8& result);
- virtual void setViewportAndProjection(size_t w, size_t h);
+ virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
virtual void setupDimLayerBlending(int alpha);
virtual void setupLayerTexturing(size_t textureName, bool useFiltering, const float* textureMatrix);
@@ -51,10 +52,8 @@ protected:
virtual void disableTexturing();
virtual void disableBlending();
- virtual void clearWithColor(const float vertices[][2], size_t count,
- float red, float green, float blue, float alpha);
-
- virtual void drawMesh2D(const float vertices[][2], const float texCoords[][2], size_t count);
+ virtual void fillWithColor(const Mesh& mesh, float r, float g, float b, float a) ;
+ virtual void drawMesh(const Mesh& mesh);
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
new file mode 100644
index 0000000..6786065
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <GLES2/gl2.h>
+
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+#include <cutils/compiler.h>
+
+#include "GLES20RenderEngine.h"
+#include "GLExtensions.h"
+#include "Program.h"
+#include "ProgramCache.h"
+#include "Description.h"
+#include "Mesh.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+GLES20RenderEngine::GLES20RenderEngine() {
+
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
+ struct pack565 {
+ inline uint16_t operator() (int r, int g, int b) const {
+ return (r<<11)|(g<<5)|b;
+ }
+ } pack565;
+
+ const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
+ glGenTextures(1, &mProtectedTexName);
+ glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
+}
+
+GLES20RenderEngine::~GLES20RenderEngine() {
+}
+
+
+size_t GLES20RenderEngine::getMaxTextureSize() const {
+ return mMaxTextureSize;
+}
+
+size_t GLES20RenderEngine::getMaxViewportDims() const {
+ return
+ mMaxViewportDims[0] < mMaxViewportDims[1] ?
+ mMaxViewportDims[0] : mMaxViewportDims[1];
+}
+
+void GLES20RenderEngine::setViewportAndProjection(
+ size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
+
+ struct ortho {
+ inline void operator() (GLfloat *m,
+ GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
+ GLfloat near, GLfloat far) const {
+ memset(m, 0, 16*sizeof(GLfloat));
+ m[ 0] = 2.0f / (right - left);
+ m[ 5] = 2.0f / (top - bottom);
+ m[10] =-2.0f / (far - near);
+ m[15] = 1.0f;
+ m[12] = -(right + left) / (right - left);
+ m[13] = -(top + bottom) / (top - bottom);
+ m[14] = -(far + near) / (far - near);
+ }
+ } ortho;
+
+ GLfloat m[16];
+ if (yswap) ortho(m, 0, w, h, 0, 0, 1);
+ else ortho(m, 0, w, 0, h, 0, 1);
+
+ glViewport(0, 0, vpw, vph);
+ mState.setProjectionMatrix(m);
+}
+
+void GLES20RenderEngine::setupLayerBlending(
+ bool premultipliedAlpha, bool opaque, int alpha) {
+
+ mState.setPremultipliedAlpha(premultipliedAlpha);
+ mState.setOpaque(opaque);
+ mState.setPlaneAlpha(alpha / 255.0f);
+
+ if (alpha < 0xFF || !opaque) {
+ glEnable(GL_BLEND);
+ glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glDisable(GL_BLEND);
+ }
+}
+
+void GLES20RenderEngine::setupDimLayerBlending(int alpha) {
+ mState.setPlaneAlpha(alpha / 255.0f);
+
+ if (alpha == 0xFF) {
+ glDisable(GL_BLEND);
+ } else {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ disableTexturing();
+}
+
+void GLES20RenderEngine::setupLayerTexturing(size_t textureName,
+ bool useFiltering, const float* textureMatrix) {
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName);
+ GLenum filter = GL_NEAREST;
+ if (useFiltering) {
+ filter = GL_LINEAR;
+ }
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
+
+ mState.setTextureName(GL_TEXTURE_EXTERNAL_OES, textureName);
+ mState.setTextureMatrix(textureMatrix);
+}
+
+void GLES20RenderEngine::setupLayerBlackedOut() {
+ const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
+ glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
+ mState.setTextureName(GL_TEXTURE_2D, mProtectedTexName);
+ mState.setTextureMatrix(m);
+}
+
+void GLES20RenderEngine::disableTexturing() {
+ mState.disableTexture();
+}
+
+void GLES20RenderEngine::disableBlending() {
+ glDisable(GL_BLEND);
+}
+
+void GLES20RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float b, float a) {
+ mState.setColor(r, g, b, a);
+ disableTexturing();
+ glDisable(GL_BLEND);
+
+ ProgramCache::getInstance().useProgram(mState);
+
+ glVertexAttribPointer(Program::position,
+ mesh.getVertexSize(),
+ GL_FLOAT, GL_FALSE,
+ mesh.getByteStride(),
+ mesh.getVertices());
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+}
+
+void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
+
+ ProgramCache::getInstance().useProgram(mState);
+
+ if (mesh.getTexCoordsSize()) {
+ glEnableVertexAttribArray(Program::texCoords);
+ glVertexAttribPointer(Program::texCoords,
+ mesh.getTexCoordsSize(),
+ GL_FLOAT, GL_FALSE,
+ mesh.getByteStride(),
+ mesh.getTexCoords());
+ }
+
+ glVertexAttribPointer(Program::position,
+ mesh.getVertexSize(),
+ GL_FLOAT, GL_FALSE,
+ mesh.getByteStride(),
+ mesh.getVertices());
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+ if (mesh.getTexCoordsSize()) {
+ glDisableVertexAttribArray(Program::texCoords);
+ }
+}
+
+void GLES20RenderEngine::dump(String8& result) {
+ const GLExtensions& extensions(GLExtensions::getInstance());
+ result.appendFormat("GLES: %s, %s, %s\n",
+ extensions.getVendor(),
+ extensions.getRenderer(),
+ extensions.getVersion());
+ result.appendFormat("%s\n", extensions.getExtension());
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
new file mode 100644
index 0000000..873a643
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 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 SF_GLES20RENDERENGINE_H_
+#define SF_GLES20RENDERENGINE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <GLES2/gl2.h>
+
+#include "RenderEngine.h"
+#include "ProgramCache.h"
+#include "Description.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+class Mesh;
+
+class GLES20RenderEngine : public RenderEngine {
+ GLuint mProtectedTexName;
+ GLint mMaxViewportDims[2];
+ GLint mMaxTextureSize;
+
+ Description mState;
+
+public:
+ GLES20RenderEngine();
+
+protected:
+ virtual ~GLES20RenderEngine();
+
+ virtual void dump(String8& result);
+ virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
+ virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+ virtual void setupDimLayerBlending(int alpha);
+ virtual void setupLayerTexturing(size_t textureName, bool useFiltering, const float* textureMatrix);
+ virtual void setupLayerBlackedOut();
+ virtual void disableTexturing();
+ virtual void disableBlending();
+
+ virtual void fillWithColor(const Mesh& mesh, float r, float g, float b, float a);
+ virtual void drawMesh(const Mesh& mesh);
+
+ virtual size_t getMaxTextureSize() const;
+ virtual size_t getMaxViewportDims() const;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif /* SF_GLES20RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
new file mode 100644
index 0000000..a08eea6
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 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 "Mesh.h"
+
+namespace android {
+
+Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
+ : mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize),
+ mPrimitive(primitive)
+{
+ mVertices = new float[(vertexSize + texCoordSize) * vertexCount];
+ mStride = mVertexSize + mTexCoordsSize;
+}
+
+Mesh::~Mesh() {
+ delete [] mVertices;
+}
+
+float const* Mesh::operator[](size_t index) const {
+ return &mVertices[index * mStride];
+}
+
+float* Mesh::operator[](size_t index) {
+ return &mVertices[index * mStride];
+}
+
+Mesh::Primitive Mesh::getPrimitive() const {
+ return mPrimitive;
+}
+
+
+float const* Mesh::getVertices() const {
+ return mVertices;
+}
+float* Mesh::getVertices() {
+ return mVertices;
+}
+
+float const* Mesh::getTexCoords() const {
+ return mVertices + mVertexSize;
+}
+float* Mesh::getTexCoords() {
+ return mVertices + mVertexSize;
+}
+
+
+size_t Mesh::getVertexCount() const {
+ return mVertexCount;
+}
+
+size_t Mesh::getVertexSize() const {
+ return mVertexSize;
+}
+
+size_t Mesh::getTexCoordsSize() const {
+ return mTexCoordsSize;
+}
+
+size_t Mesh::getByteStride() const {
+ return mStride*sizeof(float);
+}
+
+size_t Mesh::getStride() const {
+ return mStride;
+}
+
+} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Mesh.h b/services/surfaceflinger/RenderEngine/Mesh.h
new file mode 100644
index 0000000..599a150
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Mesh.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 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 SF_RENDER_ENGINE_MESH_H
+#define SF_RENDER_ENGINE_MESH_H
+
+#include <stdint.h>
+
+namespace android {
+
+class Mesh {
+public:
+ enum Primitive {
+ TRIANGLES = 0x0004,
+ TRIANGLE_STRIP = 0x0005,
+ TRIANGLE_FAN = 0x0006
+ };
+
+ Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0);
+ ~Mesh();
+
+ float const* operator[](size_t index) const;
+ float* operator[](size_t index);
+
+
+ Primitive getPrimitive() const;
+
+ float const* getVertices() const;
+ float* getVertices();
+
+ float const* getTexCoords() const;
+ float* getTexCoords();
+
+ size_t getVertexCount() const;
+ size_t getVertexSize() const;
+ size_t getTexCoordsSize() const;
+
+ size_t getByteStride() const;
+ size_t getStride() const;
+
+private:
+ float* mVertices;
+ size_t mVertexCount;
+ size_t mVertexSize;
+ size_t mTexCoordsSize;
+ size_t mStride;
+ Primitive mPrimitive;
+};
+
+
+} /* namespace android */
+#endif /* SF_RENDER_ENGINE_MESH_H */
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
new file mode 100644
index 0000000..586d1ad
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -0,0 +1,144 @@
+/*Gluint
+ * Copyright 2013 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 <stdint.h>
+
+#include <log/log.h>
+
+#include "Program.h"
+#include "ProgramCache.h"
+#include "Description.h"
+#include <utils/String8.h>
+
+namespace android {
+
+Program::Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment)
+ : mInitialized(false) {
+ GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
+ GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
+ GLuint programId = glCreateProgram();
+ glAttachShader(programId, vertexId);
+ glAttachShader(programId, fragmentId);
+ glBindAttribLocation(programId, position, "position");
+ glBindAttribLocation(programId, texCoords, "texCoords");
+ glLinkProgram(programId);
+
+ GLint status;
+ glGetProgramiv(programId, GL_LINK_STATUS, &status);
+ if (status != GL_TRUE) {
+ ALOGE("Error while linking shaders:");
+ GLint infoLen = 0;
+ glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1) {
+ GLchar log[infoLen];
+ glGetProgramInfoLog(programId, infoLen, 0, &log[0]);
+ ALOGE("%s", log);
+ }
+ glDetachShader(programId, vertexId);
+ glDetachShader(programId, fragmentId);
+ glDeleteShader(vertexId);
+ glDeleteShader(fragmentId);
+ glDeleteProgram(programId);
+ } else {
+ mProgram = programId;
+ mVertexShader = vertexId;
+ mFragmentShader = fragmentId;
+ mInitialized = true;
+
+ mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
+ mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
+ mSamplerLoc = glGetUniformLocation(programId, "sampler");
+ mColorLoc = glGetUniformLocation(programId, "color");
+ mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
+
+ // set-up the default values for our uniforms
+ glUseProgram(programId);
+ const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
+ glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, m);
+ glEnableVertexAttribArray(0);
+ }
+}
+
+Program::~Program() {
+}
+
+bool Program::isValid() const {
+ return mInitialized;
+}
+
+void Program::use() {
+ glUseProgram(mProgram);
+}
+
+GLuint Program::getAttrib(const char* name) const {
+ // TODO: maybe use a local cache
+ return glGetAttribLocation(mProgram, name);
+}
+
+GLint Program::getUniform(const char* name) const {
+ // TODO: maybe use a local cache
+ return glGetUniformLocation(mProgram, name);
+}
+
+GLuint Program::buildShader(const char* source, GLenum type) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &source, 0);
+ glCompileShader(shader);
+ GLint status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status != GL_TRUE) {
+ // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+ // use a fixed size instead
+ GLchar log[512];
+ glGetShaderInfoLog(shader, sizeof(log), 0, log);
+ ALOGE("Error while compiling shader: \n%s\n%s", source, log);
+ glDeleteShader(shader);
+ return 0;
+ }
+ return shader;
+}
+
+String8& Program::dumpShader(String8& result, GLenum type) {
+ GLuint shader = GL_FRAGMENT_SHADER ? mFragmentShader : mVertexShader;
+ GLint l;
+ glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l);
+ char* src = new char[l];
+ glGetShaderSource(shader, l, NULL, src);
+ result.append(src);
+ delete [] src;
+ return result;
+}
+
+void Program::setUniforms(const Description& desc) {
+
+ // TODO: we should have a mechanism here to not always reset uniforms that
+ // didn't change for this program.
+
+ if (mSamplerLoc >= 0) {
+ glUniform1i(mSamplerLoc, 0);
+ glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTextureMatrix);
+ }
+ if (mAlphaPlaneLoc >= 0) {
+ glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha);
+ }
+ if (mColorLoc >= 0) {
+ glUniform4fv(mColorLoc, 1, desc.mColor);
+ }
+ // these uniforms are always present
+ glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix);
+}
+
+} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h
new file mode 100644
index 0000000..91bb3db
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2013 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 SF_RENDER_ENGINE_PROGRAM_H
+#define SF_RENDER_ENGINE_PROGRAM_H
+
+#include <stdint.h>
+
+#include <GLES2/gl2.h>
+
+#include "Description.h"
+#include "ProgramCache.h"
+
+namespace android {
+
+class String8;
+
+/*
+ * Abstracts a GLSL program comprising a vertex and fragment shader
+ */
+class Program {
+public:
+ // known locations for position and texture coordinates
+ enum { position=0, texCoords=1 };
+
+ Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
+ ~Program();
+
+ /* whether this object is usable */
+ bool isValid() const;
+
+ /* Binds this program to the GLES context */
+ void use();
+
+ /* Returns the location of the specified attribute */
+ GLuint getAttrib(const char* name) const;
+
+ /* Returns the location of the specified uniform */
+ GLint getUniform(const char* name) const;
+
+ /* set-up uniforms from the description */
+ void setUniforms(const Description& desc);
+
+
+private:
+ GLuint buildShader(const char* source, GLenum type);
+ String8& dumpShader(String8& result, GLenum type);
+
+ // whether the initialization succeeded
+ bool mInitialized;
+
+ // Name of the OpenGL program and shaders
+ GLuint mProgram;
+ GLuint mVertexShader;
+ GLuint mFragmentShader;
+
+ /* location of the projection matrix uniform */
+ GLint mProjectionMatrixLoc;
+
+ /* location of the texture matrix uniform */
+ GLint mTextureMatrixLoc;
+
+ /* location of the sampler uniform */
+ GLint mSamplerLoc;
+
+ /* location of the alpha plane uniform */
+ GLint mAlphaPlaneLoc;
+
+ /* location of the color uniform */
+ GLint mColorLoc;
+};
+
+
+} /* namespace android */
+
+#endif /* SF_RENDER_ENGINE_PROGRAM_H */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
new file mode 100644
index 0000000..835ed8a
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2013 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 <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/String8.h>
+
+#include "ProgramCache.h"
+#include "Program.h"
+#include "Description.h"
+
+namespace android {
+// -----------------------------------------------------------------------------------------------
+
+
+/*
+ * A simple formatter class to automatically add the endl and
+ * manage the indentation.
+ */
+
+class Formatter;
+static Formatter& indent(Formatter& f);
+static Formatter& dedent(Formatter& f);
+
+class Formatter {
+ String8 mString;
+ int mIndent;
+ typedef Formatter& (*FormaterManipFunc)(Formatter&);
+ friend Formatter& indent(Formatter& f);
+ friend Formatter& dedent(Formatter& f);
+public:
+ String8 getString() const {
+ return mString;
+ }
+
+ friend Formatter& operator << (Formatter& out, const char* in) {
+ for (int i=0 ; i<out.mIndent ; i++) {
+ out.mString.append(" ");
+ }
+ out.mString.append(in);
+ out.mString.append("\n");
+ return out;
+ }
+ friend inline Formatter& operator << (Formatter& out, const String8& in) {
+ return operator << (out, in.string());
+ }
+ friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
+ return (*func)(to);
+ }
+};
+Formatter& indent(Formatter& f) {
+ f.mIndent++;
+ return f;
+}
+Formatter& dedent(Formatter& f) {
+ f.mIndent--;
+ return f;
+}
+
+// -----------------------------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(ProgramCache)
+
+
+ProgramCache::ProgramCache() {
+}
+
+ProgramCache::~ProgramCache() {
+}
+
+ProgramCache::Key ProgramCache::computeKey(const Description& description) {
+ Key needs;
+ needs.set(Key::TEXTURE_MASK,
+ (description.mTextureTarget == GL_TEXTURE_EXTERNAL_OES) ? Key::TEXTURE_EXT :
+ (description.mTextureTarget == GL_TEXTURE_2D) ? Key::TEXTURE_2D :
+ Key::TEXTURE_OFF)
+ .set(Key::PLANE_ALPHA_MASK,
+ (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE)
+ .set(Key::BLEND_MASK,
+ description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
+ .set(Key::OPACITY_MASK,
+ description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
+ return needs;
+}
+
+String8 ProgramCache::generateVertexShader(const Key& needs) {
+ Formatter vs;
+ if (needs.isTexturing()) {
+ vs << "attribute vec4 texCoords;"
+ << "varying vec2 outTexCoords;";
+ }
+ vs << "attribute vec4 position;"
+ << "uniform mat4 projection;"
+ << "uniform mat4 texture;"
+ << "void main(void) {" << indent
+ << "gl_Position = projection * position;";
+ if (needs.isTexturing()) {
+ vs << "outTexCoords = (texture * texCoords).st;";
+ }
+ vs << dedent << "}";
+ return vs.getString();
+}
+
+String8 ProgramCache::generateFragmentShader(const Key& needs) {
+ Formatter fs;
+ if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
+ fs << "#extension GL_OES_EGL_image_external : require";
+ }
+ if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
+ fs << "uniform samplerExternalOES sampler;"
+ << "varying vec2 outTexCoords;";
+ } else if (needs.getTextureTarget() == Key::TEXTURE_2D) {
+ fs << "uniform sampler2D sampler;"
+ << "varying vec2 outTexCoords;";
+ } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
+ fs << "uniform vec4 color;";
+ }
+ if (needs.hasPlaneAlpha()) {
+ fs << "uniform float alphaPlane;";
+ }
+ fs << "void main(void) {" << indent;
+ if (needs.isTexturing()) {
+ fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
+ } else {
+ fs << "gl_FragColor = color;";
+ }
+ if (needs.hasPlaneAlpha()) {
+ // modulate the alpha value with planeAlpha
+ if (needs.isPremultiplied()) {
+ // ... and the color too if we're premultiplied
+ if (needs.isOpaque()) {
+ // ... we're opaque, only premultiply the color component
+ fs << "gl_FragColor.rgb *= alphaPlane;"
+ << "gl_FragColor.a = alphaPlane;";
+ } else {
+ fs << "gl_FragColor *= alphaPlane;";
+ }
+ } else {
+ // not premultiplied
+ if (needs.isOpaque()) {
+ fs << "gl_FragColor.a = alphaPlane;";
+ } else {
+ fs << "gl_FragColor.a *= alphaPlane;";
+ }
+ }
+ } else {
+ if (needs.isOpaque()) {
+ fs << "gl_FragColor.a = 1.0;";
+ }
+ }
+ fs << dedent << "}";
+ return fs.getString();
+}
+
+Program* ProgramCache::generateProgram(const Key& needs) {
+ // vertex shader
+ String8 vs = generateVertexShader(needs);
+
+ // fragment shader
+ String8 fs = generateFragmentShader(needs);
+
+ Program* program = new Program(needs, vs.string(), fs.string());
+ return program;
+}
+
+void ProgramCache::useProgram(const Description& description) {
+
+ // generate the key for the shader based on the description
+ Key needs(computeKey(description));
+
+ // look-up the program in the cache
+ Program* program = mCache.valueFor(needs);
+ if (program == NULL) {
+ // we didn't find our program, so generate one...
+ nsecs_t time = -systemTime();
+ program = generateProgram(needs);
+ mCache.add(needs, program);
+ time += systemTime();
+
+ //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
+ // needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
+ }
+
+ // here we have a suitable program for this description
+ if (program->isValid()) {
+ program->use();
+ program->setUniforms(description);
+ }
+}
+
+
+} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
new file mode 100644
index 0000000..fcbeffd
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013 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 SF_RENDER_ENGINE_PROGRAMCACHE_H
+#define SF_RENDER_ENGINE_PROGRAMCACHE_H
+
+#include <GLES2/gl2.h>
+
+#include <utils/Singleton.h>
+#include <utils/KeyedVector.h>
+#include <utils/TypeHelpers.h>
+
+#include "Description.h"
+
+namespace android {
+
+class Description;
+class Program;
+class String8;
+
+/*
+ * This class generates GLSL programs suitable to handle a given
+ * Description. It's responsible for figuring out what to
+ * generate from a Description.
+ * It also maintains a cache of these Programs.
+ */
+class ProgramCache : public Singleton<ProgramCache> {
+public:
+ /*
+ * Key is used to retrieve a Program in the cache.
+ * A Key is generated from a Description.
+ */
+ class Key {
+ friend class ProgramCache;
+ typedef uint32_t key_t;
+ key_t mKey;
+ public:
+ enum {
+ BLEND_PREMULT = 0x00000001,
+ BLEND_NORMAL = 0x00000000,
+ BLEND_MASK = 0x00000001,
+
+ OPACITY_OPAQUE = 0x00000002,
+ OPACITY_TRANSLUCENT = 0x00000000,
+ OPACITY_MASK = 0x00000002,
+
+ PLANE_ALPHA_LT_ONE = 0x00000004,
+ PLANE_ALPHA_EQ_ONE = 0x00000000,
+ PLANE_ALPHA_MASK = 0x00000004,
+
+ TEXTURE_OFF = 0x00000000,
+ TEXTURE_EXT = 0x00000008,
+ TEXTURE_2D = 0x00000010,
+ TEXTURE_MASK = 0x00000018,
+ };
+
+ inline Key() : mKey(0) { }
+ inline Key(const Key& rhs) : mKey(rhs.mKey) { }
+
+ inline Key& set(key_t mask, key_t value) {
+ mKey = (mKey & ~mask) | value;
+ return *this;
+ }
+
+ inline bool isTexturing() const {
+ return (mKey & TEXTURE_MASK) != TEXTURE_OFF;
+ }
+ inline int getTextureTarget() const {
+ return (mKey & TEXTURE_MASK);
+ }
+ inline bool isPremultiplied() const {
+ return (mKey & BLEND_MASK) == BLEND_PREMULT;
+ }
+ inline bool isOpaque() const {
+ return (mKey & OPACITY_MASK) == OPACITY_OPAQUE;
+ }
+ inline bool hasPlaneAlpha() const {
+ return (mKey & PLANE_ALPHA_MASK) == PLANE_ALPHA_LT_ONE;
+ }
+
+ // this is the definition of a friend function -- not a method of class Needs
+ friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
+ return (lhs.mKey < rhs.mKey) ? 1 : 0;
+ }
+ };
+
+ ProgramCache();
+ ~ProgramCache();
+
+ // useProgram lookup a suitable program in the cache or generates one
+ // if none can be found.
+ void useProgram(const Description& description);
+
+private:
+ // compute a cache Key from a Description
+ static Key computeKey(const Description& description);
+ // generates a program from the Key
+ static Program* generateProgram(const Key& needs);
+ // generates the vertex shader from the Key
+ static String8 generateVertexShader(const Key& needs);
+ // generates the fragment shader from the Key
+ static String8 generateFragmentShader(const Key& needs);
+
+ // Key/Value map used for caching Programs. Currently the cache
+ // is never shrunk.
+ DefaultKeyedVector<Key, Program*> mCache;
+};
+
+
+ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key)
+
+} /* namespace android */
+
+#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index cb77e38..e8016ee 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -15,11 +15,15 @@
*/
#include <cutils/log.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
#include "RenderEngine.h"
#include "GLES10RenderEngine.h"
#include "GLES11RenderEngine.h"
+#include "GLES20RenderEngine.h"
#include "GLExtensions.h"
+#include "Mesh.h"
// ---------------------------------------------------------------------------
namespace android {
@@ -28,7 +32,7 @@ namespace android {
RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
// Also create our EGLContext
EGLint contextAttributes[] = {
-// EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_CONTEXT_CLIENT_VERSION, 2, // MUST be first
#ifdef EGL_IMG_context_priority
#ifdef HAS_CONTEXT_PRIORITY
#warning "using EGL_IMG_context_priority"
@@ -79,7 +83,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- //engine = new GLES20RenderEngine();
+ engine = new GLES20RenderEngine();
break;
}
engine->setEGLContext(ctxt);
@@ -140,6 +144,85 @@ RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
return GLES_VERSION_1_0;
}
+void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
+ float red, float green, float blue, float alpha) {
+ size_t c;
+ Rect const* r = region.getArray(&c);
+ Mesh mesh(Mesh::TRIANGLES, c*6, 2);
+ for (size_t i=0 ; i<c ; i++, r++) {
+ mesh[i*6 + 0][0] = r->left;
+ mesh[i*6 + 0][1] = height - r->top;
+ mesh[i*6 + 1][0] = r->left;
+ mesh[i*6 + 1][1] = height - r->bottom;
+ mesh[i*6 + 2][0] = r->right;
+ mesh[i*6 + 2][1] = height - r->bottom;
+ mesh[i*6 + 3][0] = r->left;
+ mesh[i*6 + 3][1] = height - r->top;
+ mesh[i*6 + 4][0] = r->right;
+ mesh[i*6 + 4][1] = height - r->bottom;
+ mesh[i*6 + 5][0] = r->right;
+ mesh[i*6 + 5][1] = height - r->top;
+ }
+ fillWithColor(mesh, red, green, blue, alpha);
+}
+
+void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+ glClearColor(red, green, blue, alpha);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void RenderEngine::setScissor(
+ uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
+ glScissor(left, bottom, right, top);
+ glEnable(GL_SCISSOR_TEST);
+}
+
+void RenderEngine::disableScissor() {
+ glDisable(GL_SCISSOR_TEST);
+}
+
+void RenderEngine::genTextures(size_t count, uint32_t* names) {
+ glGenTextures(count, names);
+}
+
+void RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+ glDeleteTextures(count, names);
+}
+
+// ---------------------------------------------------------------------------
+
+RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
+ RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
+{
+ GLuint tname, name;
+ // turn our EGLImage into a texture
+ glGenTextures(1, &tname);
+ glBindTexture(GL_TEXTURE_2D, tname);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+ // create a Framebuffer Object to render into
+ glGenFramebuffersOES(1, &name);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+ glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+ GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+ mStatus = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+ ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
+ "glCheckFramebufferStatusOES error %d", mStatus);
+ mTexName = tname;
+ mFbName = name;
+}
+
+RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
+ // back to main framebuffer
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+ glDeleteFramebuffersOES(1, &mFbName);
+ glDeleteTextures(1, &mTexName);
+
+}
+
+status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
+ return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index e43bfa4..f4fa30b 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -22,12 +22,16 @@
#include <sys/types.h>
#include <EGL/egl.h>
+#include <EGL/eglext.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class String8;
+class Rect;
+class Region;
+class Mesh;
class RenderEngine {
enum GlesVersion {
@@ -48,10 +52,31 @@ protected:
public:
static RenderEngine* create(EGLDisplay display, EGLConfig config);
- virtual void checkErrors() const;
+ // helpers
+ void clearWithColor(float red, float green, float blue, float alpha);
+ void fillRegionWithColor(const Region& region, uint32_t height,
+ float red, float green, float blue, float alpha);
+
+ // common to all GL versions
+ void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top);
+ void disableScissor();
+ void genTextures(size_t count, uint32_t* names);
+ void deleteTextures(size_t count, uint32_t const* names);
+
+ class BindImageAsFramebuffer {
+ RenderEngine& mEngine;
+ unsigned int mTexName, mFbName;
+ unsigned int mStatus;
+ public:
+ BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
+ ~BindImageAsFramebuffer();
+ int getStatus() const;
+ };
+ // set-up
+ virtual void checkErrors() const;
virtual void dump(String8& result) = 0;
- virtual void setViewportAndProjection(size_t w, size_t h) = 0;
+ virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap) = 0;
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
virtual void setupDimLayerBlending(int alpha) = 0;
virtual void setupLayerTexturing(size_t textureName, bool useFiltering, const float* textureMatrix) = 0;
@@ -60,14 +85,16 @@ public:
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
- virtual void clearWithColor(const float vertices[][2], size_t count,
- float red, float green, float blue, float alpha) = 0;
-
- virtual void drawMesh2D(const float vertices[][2], const float texCoords[][2], size_t count) = 0;
+ // drawing
+ virtual void fillWithColor(const Mesh& mesh, float r, float g, float b, float a) = 0;
+ virtual void drawMesh(const Mesh& mesh) = 0;
+ // queries
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
+
+
EGLContext getEGLContext() const;
};