Refactor SF. Move all GL operations in their own class.

this is the first step to add support for GLES 2.x, this
change breaks the dependency of SF on GLES 1.x by moving
all operation into their own class.

Bug: 8679321

Change-Id: I0d2741eca2cefe67dfd9cf837cac10c4d126928b
This commit is contained in:
Mathias Agopian 2013-06-07 15:35:48 -07:00
parent 9c3e2dd97e
commit 875d8e1323
17 changed files with 714 additions and 476 deletions

View File

@ -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

View File

@ -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);
}
// ----------------------------------------------------------------------------

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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();
}
}

View File

@ -20,9 +20,6 @@
#include <stdint.h>
#include <sys/types.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "Layer.h"
// ---------------------------------------------------------------------------

View File

@ -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
// ---------------------------------------------------------------------------

View File

@ -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_ */

View File

@ -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
// ---------------------------------------------------------------------------

View File

@ -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_ */

View File

@ -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

View File

@ -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;
};

View File

@ -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
// ---------------------------------------------------------------------------

View File

@ -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_ */

View File

@ -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
EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
@ -91,6 +93,7 @@ SurfaceFlinger::SurfaceFlinger()
mAnimTransactionPending(false),
mLayersRemoved(false),
mRepaintEverything(0),
mRenderEngine(NULL),
mBootTime(systemTime()),
mVisibleRegionsDirty(false),
mHwWorkListDirty(false),
@ -349,7 +352,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;
@ -360,25 +365,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);
@ -388,8 +380,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:
@ -398,97 +389,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()
{
@ -506,10 +406,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,
@ -543,17 +460,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);
@ -561,7 +467,6 @@ status_t SurfaceFlinger::readyToRun()
// initialize our drawing state
mDrawingState = mCurrentState;
// We're now ready to accept clients...
mReadyToRunBarrier.open();
@ -585,13 +490,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();
}
// ----------------------------------------------------------------------------
@ -1023,8 +927,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();
}
@ -1131,7 +1034,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());
@ -1562,7 +1465,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;
@ -2383,7 +2286,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",
@ -2392,13 +2294,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",
@ -2731,10 +2627,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();
@ -2793,7 +2685,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
@ -2851,7 +2743,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(
native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
}
DisplayDevice::setViewportAndProjection(hw);
hw->setViewportAndProjection();
return result;
}

View File

@ -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
@ -423,17 +411,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