diff options
Diffstat (limited to 'services/surfaceflinger/RenderEngine')
-rw-r--r-- | services/surfaceflinger/RenderEngine/Description.cpp | 99 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Description.h | 74 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp | 47 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES11RenderEngine.h | 9 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp | 213 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/GLES20RenderEngine.h | 70 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Mesh.cpp | 81 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Mesh.h | 65 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Program.cpp | 144 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/Program.h | 89 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/ProgramCache.cpp | 206 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/ProgramCache.h | 127 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/RenderEngine.cpp | 87 | ||||
-rw-r--r-- | services/surfaceflinger/RenderEngine/RenderEngine.h | 39 |
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; }; |