diff options
author | Mathias Agopian <mathias@google.com> | 2013-07-08 22:50:01 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-07-08 22:50:01 +0000 |
commit | 547e98f33c829eb2e3948a57e491a9106afa1f5e (patch) | |
tree | 2b15d4d670e31263502098c639c644e173460023 /services | |
parent | ba02cd2f6cc3f59adf66cb2b9176bfe6c9e382d1 (diff) | |
parent | 875d8e1323536e16dcfc90c9674d7ad32116a69a (diff) | |
download | frameworks_native-547e98f33c829eb2e3948a57e491a9106afa1f5e.zip frameworks_native-547e98f33c829eb2e3948a57e491a9106afa1f5e.tar.gz frameworks_native-547e98f33c829eb2e3948a57e491a9106afa1f5e.tar.bz2 |
Merge "Refactor SF. Move all GL operations in their own class."
Diffstat (limited to 'services')
17 files changed, 714 insertions, 476 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index f2051dd..2ec575e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -6,7 +6,6 @@ LOCAL_SRC_FILES:= \ DisplayDevice.cpp \ EventThread.cpp \ FrameTracker.cpp \ - GLExtensions.cpp \ Layer.cpp \ LayerDim.cpp \ MessageQueue.cpp \ @@ -19,7 +18,12 @@ LOCAL_SRC_FILES:= \ DisplayHardware/PowerHAL.cpp \ DisplayHardware/VirtualDisplaySurface.cpp \ EventLog/EventLogTags.logtags \ - EventLog/EventLog.cpp + EventLog/EventLog.cpp \ + RenderEngine/GLExtensions.cpp \ + RenderEngine/RenderEngine.cpp \ + RenderEngine/GLES10RenderEngine.cpp \ + RenderEngine/GLES11RenderEngine.cpp + LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index b001bdb..2eae9c2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -29,18 +29,14 @@ #include <gui/Surface.h> -#include <GLES/gl.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - #include <hardware/gralloc.h> #include "DisplayHardware/DisplaySurface.h" #include "DisplayHardware/HWComposer.h" +#include "RenderEngine/RenderEngine.h" #include "clz.h" #include "DisplayDevice.h" -#include "GLExtensions.h" #include "SurfaceFlinger.h" #include "Layer.h" @@ -48,20 +44,6 @@ using namespace android; // ---------------------------------------------------------------------------- -static __attribute__((noinline)) -void checkGLErrors() -{ - do { - // there could be more than one error flag - GLenum error = glGetError(); - if (error == GL_NO_ERROR) - break; - ALOGE("GL error 0x%04x", int(error)); - } while(true); -} - -// ---------------------------------------------------------------------------- - /* * Initialize the display to the specified values. * @@ -189,7 +171,7 @@ status_t DisplayDevice::compositionComplete() const { void DisplayDevice::flip(const Region& dirty) const { - checkGLErrors(); + mFlinger->getRenderEngine().checkErrors(); EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; @@ -246,28 +228,22 @@ uint32_t DisplayDevice::getFlags() const return mFlags; } -EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, - const sp<const DisplayDevice>& hw, EGLContext ctx) { +EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const { EGLBoolean result = EGL_TRUE; EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); - if (sur != hw->mSurface) { - result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx); + if (sur != mSurface) { + result = eglMakeCurrent(dpy, mSurface, mSurface, ctx); if (result == EGL_TRUE) { - setViewportAndProjection(hw); + setViewportAndProjection(); } } return result; } -void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) { - GLsizei w = hw->mDisplayWidth; - GLsizei h = hw->mDisplayHeight; - glViewport(0, 0, w, h); - 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 - glMatrixMode(GL_MODELVIEW); +void DisplayDevice::setViewportAndProjection() const { + size_t w = mDisplayWidth; + size_t h = mDisplayHeight; + mFlinger->getRenderEngine().setViewportAndProjection(w, h); } // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 047eecd..eefc107 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -133,10 +133,8 @@ public: void setDisplayName(const String8& displayName); const String8& getDisplayName() const { return mDisplayName; } - static EGLBoolean makeCurrent(EGLDisplay dpy, - const sp<const DisplayDevice>& hw, EGLContext ctx); - - static void setViewportAndProjection(const sp<const DisplayDevice>& hw); + EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const; + void setViewportAndProjection() const; /* ------------------------------------------------------------------------ * blank / unblank management diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b08b8d1..3605dd4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -38,13 +38,14 @@ #include "clz.h" #include "Colorizer.h" #include "DisplayDevice.h" -#include "GLExtensions.h" #include "Layer.h" #include "SurfaceFlinger.h" #include "SurfaceTextureLayer.h" #include "DisplayHardware/HWComposer.h" +#include "RenderEngine/RenderEngine.h" + #define DEBUG_RESIZE 0 namespace android { @@ -63,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mName("unnamed"), mDebug(false), mFormat(PIXEL_FORMAT_NONE), - mGLExtensions(GLExtensions::getInstance()), mOpaqueLayer(true), mTransactionFlags(0), mQueuedFrames(0), @@ -236,15 +236,6 @@ sp<BufferQueue> Layer::getBufferQueue() const { return mSurfaceFlingerConsumer->getBufferQueue(); } -//virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { -// sp<IGraphicBufferProducer> res; -// sp<const Layer> that( mOwner.promote() ); -// if (that != NULL) { -// res = that->mSurfaceFlingerConsumer->getBufferQueue(); -// } -// return res; -//} - // --------------------------------------------------------------------------- // h/w composer set-up // --------------------------------------------------------------------------- @@ -499,6 +490,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); + RenderEngine& engine(mFlinger->getRenderEngine()); + if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); @@ -509,49 +502,24 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); // Set things up for texturing. - glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName); - GLenum filter = GL_NEAREST; - if (useFiltering) { - filter = GL_LINEAR; - } - glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter); - glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(textureMatrix); - glMatrixMode(GL_MODELVIEW); - glDisable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_EXTERNAL_OES); + engine.setupLayerTexturing(mTextureName, useFiltering, textureMatrix); } else { - glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName()); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glDisable(GL_TEXTURE_EXTERNAL_OES); - glEnable(GL_TEXTURE_2D); + engine.setupLayerBlackedOut(); } - drawWithOpenGL(hw, clip); - - glDisable(GL_TEXTURE_EXTERNAL_OES); - glDisable(GL_TEXTURE_2D); + engine.disableTexturing(); } void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const { - const uint32_t fbHeight = hw->getHeight(); - glColor4f(red,green,blue,alpha); - - glDisable(GL_TEXTURE_EXTERNAL_OES); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - LayerMesh mesh; computeGeometry(hw, &mesh); - glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); - glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); + mFlinger->getRenderEngine().clearWithColor( + mesh.getVertices(), mesh.getVertexCount(), + red, green, blue, alpha); } void Layer::clearWithOpenGL( @@ -559,102 +527,14 @@ void Layer::clearWithOpenGL( clearWithOpenGL(hw, clip, 0,0,0,0); } -static void setupOpenGL10(bool premultipliedAlpha, bool opaque, int alpha) { - // OpenGL ES 1.0 doesn't support texture combiners. - // This path doesn't properly handle opaque layers that have non-opaque - // alpha values. The alpha channel will be copied into the framebuffer or - // screenshot, so if the framebuffer or screenshot is blended on top of - // something else, whatever is below the window will incorrectly show - // through. - if (CC_UNLIKELY(alpha < 0xFF)) { - GLfloat floatAlpha = alpha * (1.0f / 255.0f); - if (premultipliedAlpha) { - glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha); - } else { - glColor4f(1.0f, 1.0f, 1.0f, floatAlpha); - } - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } else { - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } -} - -static void setupOpenGL11(bool premultipliedAlpha, bool opaque, int alpha) { - GLenum combineRGB; - GLenum combineAlpha; - GLenum src0Alpha; - GLfloat envColor[4]; - - if (CC_UNLIKELY(alpha < 0xFF)) { - // Cv = premultiplied ? Cs*alpha : Cs - // Av = !opaque ? alpha*As : 1.0 - combineRGB = premultipliedAlpha ? GL_MODULATE : GL_REPLACE; - combineAlpha = !opaque ? GL_MODULATE : GL_REPLACE; - src0Alpha = GL_CONSTANT; - envColor[0] = alpha * (1.0f / 255.0f); - } else { - // Cv = Cs - // Av = opaque ? 1.0 : As - combineRGB = GL_REPLACE; - combineAlpha = GL_REPLACE; - src0Alpha = opaque ? GL_CONSTANT : GL_TEXTURE; - envColor[0] = 1.0f; - } - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - if (combineRGB == GL_MODULATE) { - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - } - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - if (combineAlpha == GL_MODULATE) { - glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - } - if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) { - envColor[1] = envColor[0]; - envColor[2] = envColor[0]; - envColor[3] = envColor[0]; - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor); - } -} - void Layer::drawWithOpenGL( const sp<const DisplayDevice>& hw, const Region& clip) const { const uint32_t fbHeight = hw->getHeight(); const State& s(getDrawingState()); - if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) { - setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha); - } else { - setupOpenGL11(mPremultipliedAlpha, isOpaque(), s.alpha); - } - - if (s.alpha < 0xFF || !isOpaque()) { - glEnable(GL_BLEND); - glBlendFunc(mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA); - } else { - glDisable(GL_BLEND); - } - LayerMesh mesh; computeGeometry(hw, &mesh); - // TODO: we probably want to generate the texture coords with the mesh - // here we assume that we only have 4 vertices - - struct TexCoords { - GLfloat u; - GLfloat v; - }; - - /* * NOTE: the way we compute the texture coordinates here produces * different results than when we take the HWC path -- in the later case @@ -676,26 +556,25 @@ void Layer::drawWithOpenGL( GLfloat right = GLfloat(win.right) / GLfloat(s.active.w); GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h); - TexCoords texCoords[4]; - texCoords[0].u = left; - texCoords[0].v = top; - texCoords[1].u = left; - texCoords[1].v = bottom; - texCoords[2].u = right; - texCoords[2].v = bottom; - texCoords[3].u = right; - texCoords[3].v = top; + // TODO: we probably want to generate the texture coords with the mesh + // here we assume that we only have 4 vertices + float texCoords[4][2]; + texCoords[0][0] = left; + texCoords[0][1] = top; + texCoords[1][0] = left; + texCoords[1][1] = bottom; + texCoords[2][0] = right; + texCoords[2][1] = bottom; + texCoords[3][0] = right; + texCoords[3][1] = top; for (int i = 0; i < 4; i++) { - texCoords[i].v = 1.0f - texCoords[i].v; + texCoords[i][1] = 1.0f - texCoords[i][1]; } - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, texCoords); - glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); - glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_BLEND); + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); + engine.drawMesh2D(mesh.getVertices(), texCoords, mesh.getVertexCount()); + engine.disableBlending(); } void Layer::setFiltering(bool filtering) { @@ -1209,9 +1088,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) recomputeVisibleRegions = true; } - glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // FIXME: postedRegion should be dirty & bounds const Layer::State& s(getDrawingState()); Region dirtyRegion(Rect(s.active.w, s.active.h)); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f79bf2d..e7e9585 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -22,8 +22,6 @@ #include <EGL/egl.h> #include <EGL/eglext.h> -#include <GLES/gl.h> -#include <GLES/glext.h> #include <utils/RefBase.h> #include <utils/String8.h> @@ -55,7 +53,6 @@ class Colorizer; class DisplayDevice; class GraphicBuffer; class SurfaceFlinger; -class GLExtensions; // --------------------------------------------------------------------------- @@ -113,14 +110,15 @@ public: class LayerMesh { friend class Layer; - GLfloat mVertices[4][2]; + typedef GLfloat float2[2]; + float2 mVertices[4]; size_t mNumVertices; public: LayerMesh() : mNumVertices(4) { } - GLfloat const* getVertices() const { - return &mVertices[0][0]; + float2 const* getVertices() const { + return mVertices; } size_t getVertexCount() const { return mNumVertices; @@ -355,7 +353,6 @@ private: String8 mName; mutable bool mDebug; PixelFormat mFormat; - const GLExtensions& mGLExtensions; bool mOpaqueLayer; // these are protected by an external lock diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index f4adeeb..062ad46 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -18,9 +18,6 @@ #include <stdint.h> #include <sys/types.h> -#include <GLES/gl.h> -#include <GLES/glext.h> - #include <utils/Errors.h> #include <utils/Log.h> @@ -29,6 +26,7 @@ #include "LayerDim.h" #include "SurfaceFlinger.h" #include "DisplayDevice.h" +#include "RenderEngine/RenderEngine.h" namespace android { // --------------------------------------------------------------------------- @@ -45,28 +43,12 @@ void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) con { const State& s(getDrawingState()); if (s.alpha>0) { - const GLfloat alpha = s.alpha/255.0f; - const uint32_t fbHeight = hw->getHeight(); - glDisable(GL_TEXTURE_EXTERNAL_OES); - glDisable(GL_TEXTURE_2D); - - if (s.alpha == 0xFF) { - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - - glColor4f(0, 0, 0, alpha); - LayerMesh mesh; computeGeometry(hw, &mesh); - - glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); - glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); - - glDisable(GL_BLEND); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupDimLayerBlending(s.alpha); + engine.drawMesh2D(mesh.getVertices(), NULL, mesh.getVertexCount()); + engine.disableBlending(); } } diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index 2a96149..6561d7f 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -20,9 +20,6 @@ #include <stdint.h> #include <sys/types.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - #include "Layer.h" // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp new file mode 100644 index 0000000..9a47568 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp @@ -0,0 +1,61 @@ +/* + * 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 <GLES/gl.h> + +#include <cutils/compiler.h> + +#include "GLES10RenderEngine.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +GLES10RenderEngine::~GLES10RenderEngine() { +} + +void GLES10RenderEngine::setupLayerBlending( + bool premultipliedAlpha, bool opaque, int alpha) { + // OpenGL ES 1.0 doesn't support texture combiners. + // This path doesn't properly handle opaque layers that have non-opaque + // alpha values. The alpha channel will be copied into the framebuffer or + // screenshot, so if the framebuffer or screenshot is blended on top of + // something else, whatever is below the window will incorrectly show + // through. + if (CC_UNLIKELY(alpha < 0xFF)) { + GLfloat floatAlpha = alpha * (1.0f / 255.0f); + if (premultipliedAlpha) { + glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha); + } else { + glColor4f(1.0f, 1.0f, 1.0f, floatAlpha); + } + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } else { + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } + + if (alpha < 0xFF || !opaque) { + glEnable(GL_BLEND); + glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } +} + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h new file mode 100644 index 0000000..f9c7c04 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h @@ -0,0 +1,40 @@ +/* + * 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_GLES10RENDERENGINE_H_ +#define SF_GLES10RENDERENGINE_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include "GLES11RenderEngine.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class GLES10RenderEngine : public GLES11RenderEngine { + virtual ~GLES10RenderEngine(); +protected: + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha); +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif /* SF_GLES10RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp new file mode 100644 index 0000000..19499c9 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp @@ -0,0 +1,217 @@ +/* + * 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 <GLES/gl.h> + +#include <utils/String8.h> +#include <cutils/compiler.h> + +#include "GLES11RenderEngine.h" +#include "GLExtensions.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +GLES11RenderEngine::GLES11RenderEngine() { + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glEnableClientState(GL_VERTEX_ARRAY); + glShadeModel(GL_FLAT); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + + 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); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(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); +} + +GLES11RenderEngine::~GLES11RenderEngine() { +} + + +size_t GLES11RenderEngine::getMaxTextureSize() const { + return mMaxTextureSize; +} + +size_t GLES11RenderEngine::getMaxViewportDims() const { + return + mMaxViewportDims[0] < mMaxViewportDims[1] ? + mMaxViewportDims[0] : mMaxViewportDims[1]; +} + +void GLES11RenderEngine::setViewportAndProjection(size_t w, size_t h) { + glViewport(0, 0, w, h); + 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 + glMatrixMode(GL_MODELVIEW); +} + +void GLES11RenderEngine::setupLayerBlending( + bool premultipliedAlpha, bool opaque, int alpha) { + GLenum combineRGB; + GLenum combineAlpha; + GLenum src0Alpha; + GLfloat envColor[4]; + + if (CC_UNLIKELY(alpha < 0xFF)) { + // Cv = premultiplied ? Cs*alpha : Cs + // Av = !opaque ? alpha*As : 1.0 + combineRGB = premultipliedAlpha ? GL_MODULATE : GL_REPLACE; + combineAlpha = !opaque ? GL_MODULATE : GL_REPLACE; + src0Alpha = GL_CONSTANT; + envColor[0] = alpha * (1.0f / 255.0f); + } else { + // Cv = Cs + // Av = opaque ? 1.0 : As + combineRGB = GL_REPLACE; + combineAlpha = GL_REPLACE; + src0Alpha = opaque ? GL_CONSTANT : GL_TEXTURE; + envColor[0] = 1.0f; + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + if (combineRGB == GL_MODULATE) { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + } + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + if (combineAlpha == GL_MODULATE) { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + } + if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) { + envColor[1] = envColor[0]; + envColor[2] = envColor[0]; + envColor[3] = envColor[0]; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor); + } + + if (alpha < 0xFF || !opaque) { + glEnable(GL_BLEND); + glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } +} + +void GLES11RenderEngine::setupDimLayerBlending(int alpha) { + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); + if (alpha == 0xFF) { + glDisable(GL_BLEND); + } else { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + glColor4f(0, 0, 0, alpha/255.0f); +} + +void GLES11RenderEngine::setupLayerTexturing(size_t textureName, + bool useFiltering, const float* textureMatrix) { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName); + GLenum filter = GL_NEAREST; + if (useFiltering) { + filter = GL_LINEAR; + } + glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter); + glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(textureMatrix); + glMatrixMode(GL_MODELVIEW); + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_EXTERNAL_OES); +} + +void GLES11RenderEngine::setupLayerBlackedOut() { + glBindTexture(GL_TEXTURE_2D, mProtectedTexName); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glDisable(GL_TEXTURE_EXTERNAL_OES); + glEnable(GL_TEXTURE_2D); +} + +void GLES11RenderEngine::disableTexturing() { + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); +} + +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); + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glVertexPointer(2, GL_FLOAT, 0, vertices); + glDrawArrays(GL_TRIANGLE_FAN, 0, count); +} + +void GLES11RenderEngine::drawMesh2D( + const float vertices[][2], const float texCoords[][2], size_t count) { + if (texCoords) { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + } + glVertexPointer(2, GL_FLOAT, 0, vertices); + glDrawArrays(GL_TRIANGLE_FAN, 0, count); + if (texCoords) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +void GLES11RenderEngine::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/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h new file mode 100644 index 0000000..15054bd --- /dev/null +++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h @@ -0,0 +1,67 @@ +/* + * 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_GLES11RENDERENGINE_H_ +#define SF_GLES11RENDERENGINE_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include <GLES/gl.h> + +#include "RenderEngine.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class String8; + +class GLES11RenderEngine : public RenderEngine { + GLuint mProtectedTexName; + GLint mMaxViewportDims[2]; + GLint mMaxTextureSize; + +public: + GLES11RenderEngine(); + +protected: + virtual ~GLES11RenderEngine(); + + virtual void dump(String8& result); + virtual void setViewportAndProjection(size_t w, size_t h); + 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 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 size_t getMaxTextureSize() const; + virtual size_t getMaxViewportDims() const; +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif /* SF_GLES11RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp index e5fb083..76bbcc1 100644 --- a/services/surfaceflinger/GLExtensions.cpp +++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp @@ -26,10 +26,7 @@ namespace android { ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions ) GLExtensions::GLExtensions() - : mHaveTextureExternal(false), - mHaveNpot(false), - mHaveDirectTexture(false), - mHaveFramebufferObject(false) + : mHaveFramebufferObject(false) { } @@ -37,18 +34,12 @@ void GLExtensions::initWithGLStrings( GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, - GLubyte const* extensions, - char const* egl_vendor, - char const* egl_version, - char const* egl_extensions) + GLubyte const* extensions) { mVendor = (char const*)vendor; mRenderer = (char const*)renderer; mVersion = (char const*)version; mExtensions = (char const*)extensions; - mEglVendor = egl_vendor; - mEglVersion = egl_version; - mEglExtensions = egl_extensions; char const* curr = (char const*)extensions; char const* head = curr; @@ -61,39 +52,6 @@ void GLExtensions::initWithGLStrings( curr = head+1; } while (head); - curr = egl_extensions; - head = curr; - do { - head = strchr(curr, ' '); - String8 s(curr, head ? head-curr : strlen(curr)); - if (s.length()) { - mExtensionList.add(s); - } - curr = head+1; - } while (head); - -#ifdef EGL_ANDROID_image_native_buffer - if (hasExtension("GL_OES_EGL_image") && - (hasExtension("EGL_KHR_image_base") || hasExtension("EGL_KHR_image")) && - hasExtension("EGL_ANDROID_image_native_buffer")) - { - mHaveDirectTexture = true; - } -#else -#error "EGL_ANDROID_image_native_buffer not supported" -#endif - - if (hasExtension("GL_ARB_texture_non_power_of_two")) { - mHaveNpot = true; - } - - if (hasExtension("GL_OES_EGL_image_external")) { - mHaveTextureExternal = true; - } else if (strstr(mRenderer.string(), "Adreno")) { - // hack for Adreno 200 - mHaveTextureExternal = true; - } - if (hasExtension("GL_OES_framebuffer_object")) { mHaveFramebufferObject = true; } @@ -121,18 +79,5 @@ char const* GLExtensions::getExtension() const { return mExtensions.string(); } -char const* GLExtensions::getEglVendor() const { - return mEglVendor.string(); -} - -char const* GLExtensions::getEglVersion() const { - return mEglVersion.string(); -} - -char const* GLExtensions::getEglExtension() const { - return mEglExtensions.string(); -} - - // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h index c86c66a..d81ed2a 100644 --- a/services/surfaceflinger/GLExtensions.h +++ b/services/surfaceflinger/RenderEngine/GLExtensions.h @@ -36,18 +36,12 @@ class GLExtensions : public Singleton<GLExtensions> { friend class Singleton<GLExtensions>; - bool mHaveTextureExternal : 1; - bool mHaveNpot : 1; - bool mHaveDirectTexture : 1; bool mHaveFramebufferObject : 1; String8 mVendor; String8 mRenderer; String8 mVersion; String8 mExtensions; - String8 mEglVendor; - String8 mEglVersion; - String8 mEglExtensions; SortedVector<String8> mExtensionList; GLExtensions(const GLExtensions&); @@ -57,15 +51,6 @@ protected: GLExtensions(); public: - inline bool haveTextureExternal() const { - return mHaveTextureExternal; - } - inline bool haveNpot() const { - return mHaveNpot; - } - inline bool haveDirectTexture() const { - return mHaveDirectTexture; - } inline bool haveFramebufferObject() const { return mHaveFramebufferObject; @@ -75,20 +60,13 @@ public: GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, - GLubyte const* extensions, - char const* egl_vendor, - char const* egl_version, - char const* egl_extensions); + GLubyte const* extensions); char const* getVendor() const; char const* getRenderer() const; char const* getVersion() const; char const* getExtension() const; - char const* getEglVendor() const; - char const* getEglVersion() const; - char const* getEglExtension() const; - bool hasExtension(char const* extension) const; }; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp new file mode 100644 index 0000000..cb77e38 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -0,0 +1,145 @@ +/* + * 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 <cutils/log.h> + +#include "RenderEngine.h" +#include "GLES10RenderEngine.h" +#include "GLES11RenderEngine.h" +#include "GLExtensions.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { + // Also create our EGLContext + EGLint contextAttributes[] = { +// EGL_CONTEXT_CLIENT_VERSION, 2, +#ifdef EGL_IMG_context_priority +#ifdef HAS_CONTEXT_PRIORITY +#warning "using EGL_IMG_context_priority" + EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, +#endif +#endif + EGL_NONE, EGL_NONE + }; + + EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); + if (ctxt == EGL_NO_CONTEXT) { + // maybe ES 2.x is not supported + ALOGW("can't create an ES 2.x context, trying 1.x"); + ctxt = eglCreateContext(display, config, NULL, contextAttributes + 2); + } + + // if can't create a GL context, we can only abort. + LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); + + + // now figure out what version of GL did we actually get + // NOTE: a dummy surface is not needed if KHR_create_context is supported + + EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; + EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs); + LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); + EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); + LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); + + GLExtensions& extensions(GLExtensions::getInstance()); + extensions.initWithGLStrings( + glGetString(GL_VENDOR), + glGetString(GL_RENDERER), + glGetString(GL_VERSION), + glGetString(GL_EXTENSIONS)); + + GlesVersion version = parseGlesVersion( extensions.getVersion() ); + + // initialize the renderer while GL is current + + RenderEngine* engine = NULL; + switch (version) { + case GLES_VERSION_1_0: + engine = new GLES10RenderEngine(); + break; + case GLES_VERSION_1_1: + engine = new GLES11RenderEngine(); + break; + case GLES_VERSION_2_0: + case GLES_VERSION_3_0: + //engine = new GLES20RenderEngine(); + break; + } + engine->setEGLContext(ctxt); + + ALOGI("OpenGL ES informations:"); + ALOGI("vendor : %s", extensions.getVendor()); + ALOGI("renderer : %s", extensions.getRenderer()); + ALOGI("version : %s", extensions.getVersion()); + ALOGI("extensions: %s", extensions.getExtension()); + ALOGI("GL_MAX_TEXTURE_SIZE = %d", engine->getMaxTextureSize()); + ALOGI("GL_MAX_VIEWPORT_DIMS = %d", engine->getMaxViewportDims()); + + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(display, dummy); + + return engine; +} + +RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) { +} + +RenderEngine::~RenderEngine() { +} + +void RenderEngine::setEGLContext(EGLContext ctxt) { + mEGLContext = ctxt; +} + +EGLContext RenderEngine::getEGLContext() const { + return mEGLContext; +} + +void RenderEngine::checkErrors() const { + do { + // there could be more than one error flag + GLenum error = glGetError(); + if (error == GL_NO_ERROR) + break; + ALOGE("GL error 0x%04x", int(error)); + } while (true); +} + +RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) { + int major, minor; + if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) { + if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) { + ALOGW("Unable to parse GL_VERSION string: \"%s\"", str); + return GLES_VERSION_1_0; + } + } + + if (major == 1 && minor == 0) return GLES_VERSION_1_0; + if (major == 1 && minor >= 1) return GLES_VERSION_1_1; + if (major == 2 && minor >= 0) return GLES_VERSION_2_0; + if (major == 3 && minor >= 0) return GLES_VERSION_3_0; + + ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor); + return GLES_VERSION_1_0; +} + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h new file mode 100644 index 0000000..e43bfa4 --- /dev/null +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -0,0 +1,78 @@ +/* + * 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_RENDERENGINE_H_ +#define SF_RENDERENGINE_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include <EGL/egl.h> + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class String8; + +class RenderEngine { + enum GlesVersion { + GLES_VERSION_1_0 = 0x10000, + GLES_VERSION_1_1 = 0x10001, + GLES_VERSION_2_0 = 0x20000, + GLES_VERSION_3_0 = 0x30000, + }; + static GlesVersion parseGlesVersion(const char* str); + + EGLContext mEGLContext; + void setEGLContext(EGLContext ctxt); + +protected: + RenderEngine(); + virtual ~RenderEngine() = 0; + +public: + static RenderEngine* create(EGLDisplay display, EGLConfig config); + + virtual void checkErrors() const; + + virtual void dump(String8& result) = 0; + virtual void setViewportAndProjection(size_t w, size_t h) = 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; + virtual void setupLayerBlackedOut() = 0; + + 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; + + virtual size_t getMaxTextureSize() const = 0; + virtual size_t getMaxViewportDims() const = 0; + + EGLContext getEGLContext() const; +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif /* SF_RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c789941..c6feee1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -24,6 +24,7 @@ #include <EGL/egl.h> #include <GLES/gl.h> +#include <GLES/glext.h> #include <cutils/log.h> #include <cutils/properties.h> @@ -61,7 +62,6 @@ #include "DdmConnection.h" #include "DisplayDevice.h" #include "EventThread.h" -#include "GLExtensions.h" #include "Layer.h" #include "LayerDim.h" #include "SurfaceFlinger.h" @@ -70,6 +70,8 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" +#include "RenderEngine/RenderEngine.h" + #define DISPLAY_COUNT 1 /* @@ -97,6 +99,7 @@ SurfaceFlinger::SurfaceFlinger() mAnimTransactionPending(false), mLayersRemoved(false), mRepaintEverything(0), + mRenderEngine(NULL), mBootTime(systemTime()), mVisibleRegionsDirty(false), mHwWorkListDirty(false), @@ -355,7 +358,9 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua status_t err; EGLAttributeVector attribs; - attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT; + // TODO: enable ES2 + //attribs[EGL_RENDERABLE_TYPE] = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; + attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; attribs[EGL_RED_SIZE] = 8; @@ -366,25 +371,12 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua if (!err) goto success; - // maybe we failed because of EGL_FRAMEBUFFER_TARGET_ANDROID - ALOGW("no suitable EGLConfig found, trying without EGL_FRAMEBUFFER_TARGET_ANDROID"); + // this didn't work, probably because we're on the emulator... + // try a simplified query + ALOGW("no suitable EGLConfig found, trying a simpler query"); + attribs.remove(EGL_RENDERABLE_TYPE); attribs.remove(EGL_FRAMEBUFFER_TARGET_ANDROID); - err = selectConfigForAttribute(display, attribs, - EGL_NATIVE_VISUAL_ID, nativeVisualId, &config); - if (!err) - goto success; - - // maybe we failed because of EGL_RECORDABLE_ANDROID - ALOGW("no suitable EGLConfig found, trying without EGL_RECORDABLE_ANDROID"); attribs.remove(EGL_RECORDABLE_ANDROID); - err = selectConfigForAttribute(display, attribs, - EGL_NATIVE_VISUAL_ID, nativeVisualId, &config); - if (!err) - goto success; - - // allow less than 24-bit color; the non-gpu-accelerated emulator only - // supports 16-bit color - ALOGW("no suitable EGLConfig found, trying with 16-bit color allowed"); attribs.remove(EGL_RED_SIZE); attribs.remove(EGL_GREEN_SIZE); attribs.remove(EGL_BLUE_SIZE); @@ -394,8 +386,7 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua goto success; // this EGL is too lame for Android - ALOGE("no suitable EGLConfig found, giving up"); - + LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); return 0; success: @@ -404,97 +395,6 @@ success: return config; } -EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config) { - // Also create our EGLContext - EGLint contextAttributes[] = { -#ifdef EGL_IMG_context_priority -#ifdef HAS_CONTEXT_PRIORITY -#warning "using EGL_IMG_context_priority" - EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, -#endif -#endif - EGL_NONE, EGL_NONE - }; - EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); - ALOGE_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); - return ctxt; -} - -static GlesVersion parseGlesVersion(const char* str) { - int major, minor; - if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) { - ALOGW("Unable to parse GL_VERSION string: \"%s\"", str); - return GLES_VERSION_1_0; - } - - if (major == 1 && minor == 0) return GLES_VERSION_1_0; - if (major == 1 && minor >= 1) return GLES_VERSION_1_1; - if (major == 2 && minor >= 0) return GLES_VERSION_2_0; - if (major == 3 && minor >= 0) return GLES_VERSION_3_0; - - ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor); - return GLES_VERSION_1_0; -} - -void SurfaceFlinger::initializeGL(EGLDisplay display) { - GLExtensions& extensions(GLExtensions::getInstance()); - extensions.initWithGLStrings( - glGetString(GL_VENDOR), - glGetString(GL_RENDERER), - glGetString(GL_VERSION), - glGetString(GL_EXTENSIONS), - eglQueryString(display, EGL_VENDOR), - eglQueryString(display, EGL_VERSION), - eglQueryString(display, EGL_EXTENSIONS)); - - mGlesVersion = parseGlesVersion(extensions.getVersion()); - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); - glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glEnableClientState(GL_VERTEX_ARRAY); - glShadeModel(GL_FLAT); - glDisable(GL_DITHER); - glDisable(GL_CULL_FACE); - - 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); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterx(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); - - // print some debugging info - EGLint r,g,b,a; - eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE, &r); - eglGetConfigAttrib(display, mEGLConfig, EGL_GREEN_SIZE, &g); - eglGetConfigAttrib(display, mEGLConfig, EGL_BLUE_SIZE, &b); - eglGetConfigAttrib(display, mEGLConfig, EGL_ALPHA_SIZE, &a); - ALOGI("EGL informations:"); - ALOGI("vendor : %s", extensions.getEglVendor()); - ALOGI("version : %s", extensions.getEglVersion()); - ALOGI("extensions: %s", extensions.getEglExtension()); - ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); - ALOGI("OpenGL ES informations:"); - ALOGI("vendor : %s", extensions.getVendor()); - ALOGI("renderer : %s", extensions.getRenderer()); - ALOGI("version : %s", extensions.getVersion()); - ALOGI("extensions: %s", extensions.getExtension()); - ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize); - ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]); -} status_t SurfaceFlinger::readyToRun() { @@ -512,10 +412,27 @@ status_t SurfaceFlinger::readyToRun() mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this)); - // initialize the config and context - EGLint format = mHwc->getVisualID(); - mEGLConfig = selectEGLConfig(mEGLDisplay, format); - mEGLContext = createGLContext(mEGLDisplay, mEGLConfig); + // initialize the config and context (can't fail) + mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID()); + + // print some debugging info + EGLint r,g,b,a; + eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r); + eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a); + ALOGI("EGL informations:"); + ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR)); + ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION)); + ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS)); + ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported"); + ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); + + // get a RenderEngine for the given display / config (can't fail) + mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig); + + // retrieve the EGL context that was selected/created + mEGLContext = mRenderEngine->getEGLContext(); // figure out which format we got eglGetConfigAttrib(mEGLDisplay, mEGLConfig, @@ -549,17 +466,6 @@ status_t SurfaceFlinger::readyToRun() } } - // we need a GL context current in a few places, when initializing - // OpenGL ES (see below), or creating a layer, - // or when a texture is (asynchronously) destroyed, and for that - // we need a valid surface, so it's convenient to use the main display - // for that. - sp<const DisplayDevice> hw(getDefaultDisplayDevice()); - - // initialize OpenGL ES - DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext); - initializeGL(mEGLDisplay); - // start the EventThread mEventThread = new EventThread(this); mEventQueue.setEventThread(mEventThread); @@ -567,7 +473,6 @@ status_t SurfaceFlinger::readyToRun() // initialize our drawing state mDrawingState = mCurrentState; - // We're now ready to accept clients... mReadyToRunBarrier.open(); @@ -591,13 +496,12 @@ void SurfaceFlinger::startBootAnim() { property_set("ctl.start", "bootanim"); } -uint32_t SurfaceFlinger::getMaxTextureSize() const { - return mMaxTextureSize; +size_t SurfaceFlinger::getMaxTextureSize() const { + return mRenderEngine->getMaxTextureSize(); } -uint32_t SurfaceFlinger::getMaxViewportDims() const { - return mMaxViewportDims[0] < mMaxViewportDims[1] ? - mMaxViewportDims[0] : mMaxViewportDims[1]; +size_t SurfaceFlinger::getMaxViewportDims() const { + return mRenderEngine->getMaxViewportDims(); } // ---------------------------------------------------------------------------- @@ -1029,8 +933,7 @@ void SurfaceFlinger::postFramebuffer() // EGL spec says: // "surface must be bound to the calling thread's current context, // for the current rendering API." - DisplayDevice::makeCurrent(mEGLDisplay, - getDefaultDisplayDevice(), mEGLContext); + getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); } hwc.commit(); } @@ -1137,7 +1040,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // be sure that nothing associated with this display // is current. const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice()); - DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext); + defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext); sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i))); if (hw != NULL) hw->disconnect(getHwComposer()); @@ -1568,7 +1471,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end); if (hasGlesComposition) { - if (!DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext)) { + if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", hw->getDisplayName().string()); return; @@ -2389,7 +2292,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, HWComposer& hwc(getHwComposer()); sp<const DisplayDevice> hw(getDefaultDisplayDevice()); - const GLExtensions& extensions(GLExtensions::getInstance()); colorizer.bold(result); result.appendFormat("EGL implementation : %s\n", @@ -2398,13 +2300,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.appendFormat("%s\n", eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS)); - colorizer.bold(result); - result.appendFormat("GLES: %s, %s, %s\n", - extensions.getVendor(), - extensions.getRenderer(), - extensions.getVersion()); - colorizer.reset(result); - result.appendFormat("%s\n", extensions.getExtension()); + mRenderEngine->dump(result); hw->undefinedRegion.dump(result, "undefinedRegion"); result.appendFormat(" orientation=%d, canDraw=%d\n", @@ -2737,10 +2633,6 @@ status_t SurfaceFlinger::captureScreenImplLocked( { ATRACE_CALL(); - if (!GLExtensions::getInstance().haveFramebufferObject()) { - return INVALID_OPERATION; - } - // get screen geometry const uint32_t hw_w = hw->getWidth(); const uint32_t hw_h = hw->getHeight(); @@ -2799,7 +2691,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, - GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0); + GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); } else { // since we're going to use glReadPixels() anyways, // use an intermediate renderbuffer instead @@ -2858,7 +2750,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); } - DisplayDevice::setViewportAndProjection(hw); + hw->setViewportAndProjection(); return result; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index cbedda7..21d523b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -21,7 +21,7 @@ #include <sys/types.h> #include <EGL/egl.h> -#include <GLES/gl.h> +#include <GLES/gl.h> // needed for GLuint #include <cutils/compiler.h> @@ -62,6 +62,7 @@ class IGraphicBufferAlloc; class Layer; class LayerDim; class Surface; +class RenderEngine; // --------------------------------------------------------------------------- @@ -72,13 +73,6 @@ enum { eTransactionMask = 0x07 }; -enum GlesVersion { - GLES_VERSION_1_0 = 0x10000, - GLES_VERSION_1_1 = 0x10001, - GLES_VERSION_2_0 = 0x20000, - GLES_VERSION_3_0 = 0x30000, -}; - class SurfaceFlinger : public BinderService<SurfaceFlinger>, public BnSurfaceComposer, private IBinder::DeathRecipient, @@ -128,9 +122,8 @@ public: // TODO: this should be made accessible only to HWComposer const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id); - // return the version of the OpenGL ES composition context - GlesVersion getGlesVersion() const { - return mGlesVersion; + RenderEngine& getRenderEngine() const { + return *mRenderEngine; } private: @@ -319,10 +312,8 @@ private: static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig); static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId); - static EGLContext createGLContext(EGLDisplay disp, EGLConfig config); - void initializeGL(EGLDisplay display); - uint32_t getMaxTextureSize() const; - uint32_t getMaxViewportDims() const; + size_t getMaxTextureSize() const; + size_t getMaxViewportDims() const; /* ------------------------------------------------------------------------ * Display and layer stack management @@ -378,9 +369,6 @@ private: void postFramebuffer(); void drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const; - GLuint getProtectedTexName() const { - return mProtectedTexName; - } /* ------------------------------------------------------------------------ * Display management @@ -426,17 +414,14 @@ private: // constant members (no synchronization needed for access) HWComposer* mHwc; - GLuint mProtectedTexName; + RenderEngine* mRenderEngine; nsecs_t mBootTime; bool mGpuToCpuSupported; sp<EventThread> mEventThread; - GLint mMaxViewportDims[2]; - GLint mMaxTextureSize; EGLContext mEGLContext; EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; EGLint mEGLNativeVisualId; - GlesVersion mGlesVersion; sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES]; // Can only accessed from the main thread, these members |