diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 16936e300a9e5..29b88e9f56404 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -21,6 +21,10 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES +ifeq ($(TARGET_BOARD_PLATFORM), msm7k) + LOCAL_CFLAGS += -DDIM_WITH_TEXTURE +endif + # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) ifeq ($(HOST_OS),linux) diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index c1e8ad63cdf94..b95e1844fe684 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -31,16 +31,73 @@ namespace android { const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; const char* const LayerDim::typeID = "LayerDim"; +bool LayerDim::sUseTexture; +GLuint LayerDim::sTexId; +EGLImageKHR LayerDim::sImage; +int32_t LayerDim::sWidth; +int32_t LayerDim::sHeight; + // --------------------------------------------------------------------------- LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, Client* client, int32_t i) - : LayerBaseClient(flinger, display, client, i) + : LayerBaseClient(flinger, display, client, i) { } void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) { + sTexId = -1; + sImage = EGL_NO_IMAGE_KHR; + sWidth = w; + sHeight = h; + sUseTexture = false; + +#ifdef DIM_WITH_TEXTURE + +#warning "using a texture to implement LayerDim" + + /* On some h/w like msm7K, it is faster to use a texture because the + * software renderer will defer to copybit, for this to work we need to + * use an EGLImage texture so copybit can actually make use of it. + * This burns a full-screen worth of graphic memory. + */ + + const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); + uint32_t flags = hw.getFlags(); + + if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) { + // TODO: api to pass the usage flags + sp buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565); + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + glGenTextures(1, &sTexId); + glBindTexture(GL_TEXTURE_2D, sTexId); + + EGLDisplay dpy = eglGetCurrentDisplay(); + sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, + EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0); + if (sImage == EGL_NO_IMAGE_KHR) { + LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError()); + return; + } + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage); + GLint error = glGetError(); + if (error != GL_NO_ERROR) { + eglDestroyImageKHR(dpy, sImage); + LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error); + return; + } + + // initialize the texture with zeros + GGLSurface t; + buffer->lock(&t, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN); + memset(t.data, 0, t.width * t.stride * 2); + buffer->unlock(); + sUseTexture = true; + } +#endif } LayerDim::~LayerDim() @@ -49,8 +106,6 @@ LayerDim::~LayerDim() void LayerDim::onDraw(const Region& clip) const { - // FIXME: on some h/w (like msm7K, it will be faster to use a texture) - const State& s(drawingState()); Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); @@ -58,12 +113,42 @@ void LayerDim::onDraw(const Region& clip) const const DisplayHardware& hw(graphicPlane(0).displayHardware()); const GGLfixed alpha = (s.alpha << 16)/255; const uint32_t fbHeight = hw.getHeight(); - glDisable(GL_TEXTURE_2D); glDisable(GL_DITHER); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColor4x(0, 0, 0, alpha); - glVertexPointer(2, GL_FIXED, 0, mVertices); + +#ifdef DIM_WITH_TEXTURE + if (sUseTexture) { + glBindTexture(GL_TEXTURE_2D, sTexId); + glEnable(GL_TEXTURE_2D); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + const GLshort texCoords[4][2] = { + { 0, 0 }, + { 0, 1 }, + { 1, 1 }, + { 1, 0 } + }; + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_SHORT, 0, texCoords); + } else +#endif + { + glDisable(GL_TEXTURE_2D); + } + + GLshort w = sWidth; + GLshort h = sHeight; + const GLshort vertices[4][2] = { + { 0, 0 }, + { 0, h }, + { w, h }, + { w, 0 } + }; + glVertexPointer(2, GL_SHORT, 0, vertices); + while (it != end) { const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); @@ -71,6 +156,7 @@ void LayerDim::onDraw(const Region& clip) const glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index 0d5bb986cf099..d9b70b4ea83d9 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -20,6 +20,9 @@ #include #include +#include +#include + #include "LayerBase.h" #include "LayerBitmap.h" @@ -29,6 +32,11 @@ namespace android { class LayerDim : public LayerBaseClient { + static bool sUseTexture; + static GLuint sTexId; + static EGLImageKHR sImage; + static int32_t sWidth; + static int32_t sHeight; public: static const uint32_t typeInfo; static const char* const typeID; diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index ebe315a450f74..ac133402788f1 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -180,6 +180,7 @@ private: friend class LayerBaseClient; friend class Layer; friend class LayerBlur; + friend class LayerDim; sp createSurface(ClientID client, int pid, ISurfaceFlingerClient::surface_data_t* params,