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

This commit is contained in:
Mathias Agopian 2013-07-08 22:50:01 +00:00 committed by Android (Google) Code Review
commit 547e98f33c
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
/*
@ -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;
}

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