1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdlib.h> 18 #include <stdint.h> 19 #include <sys/types.h> 20 21 #include <utils/Errors.h> 22 #include <utils/Log.h> 23 24 #include <ui/GraphicBuffer.h> 25 26 #include "LayerDim.h" 27 #include "SurfaceFlinger.h" 28 #include "DisplayHardware/DisplayHardware.h" 29 30 namespace android { 31 // --------------------------------------------------------------------------- 32 33 const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; 34 const char* const LayerDim::typeID = "LayerDim"; 35 36 bool LayerDim::sUseTexture; 37 GLuint LayerDim::sTexId; 38 EGLImageKHR LayerDim::sImage; 39 int32_t LayerDim::sWidth; 40 int32_t LayerDim::sHeight; 41 42 // --------------------------------------------------------------------------- 43 44 LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, 45 const sp<Client>& client, int32_t i) 46 : LayerBaseClient(flinger, display, client, i) 47 { 48 } 49 50 void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) 51 { 52 sTexId = -1; 53 sImage = EGL_NO_IMAGE_KHR; 54 sWidth = w; 55 sHeight = h; 56 sUseTexture = false; 57 58 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer) 59 60 #warning "using a texture to implement LayerDim" 61 62 /* On some h/w like msm7K, it is faster to use a texture because the 63 * software renderer will defer to copybit, for this to work we need to 64 * use an EGLImage texture so copybit can actually make use of it. 65 * This burns a full-screen worth of graphic memory. 66 */ 67 68 const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); 69 uint32_t flags = hw.getFlags(); 70 71 if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) { 72 sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565, 73 GraphicBuffer::USAGE_SW_WRITE_OFTEN | 74 GraphicBuffer::USAGE_HW_TEXTURE); 75 76 android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); 77 78 glGenTextures(1, &sTexId); 79 glBindTexture(GL_TEXTURE_2D, sTexId); 80 81 EGLDisplay dpy = eglGetCurrentDisplay(); 82 sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 83 EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0); 84 if (sImage == EGL_NO_IMAGE_KHR) { 85 LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError()); 86 return; 87 } 88 89 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage); 90 GLint error = glGetError(); 91 if (error != GL_NO_ERROR) { 92 eglDestroyImageKHR(dpy, sImage); 93 LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error); 94 return; 95 } 96 97 // initialize the texture with zeros 98 GGLSurface t; 99 buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN); 100 memset(t.data, 0, t.stride * t.height * 2); 101 buffer->unlock(); 102 sUseTexture = true; 103 } 104 #endif 105 } 106 107 LayerDim::~LayerDim() 108 { 109 } 110 111 void LayerDim::onDraw(const Region& clip) const 112 { 113 const State& s(drawingState()); 114 Region::const_iterator it = clip.begin(); 115 Region::const_iterator const end = clip.end(); 116 if (s.alpha>0 && (it != end)) { 117 const DisplayHardware& hw(graphicPlane(0).displayHardware()); 118 const GGLfixed alpha = (s.alpha << 16)/255; 119 const uint32_t fbHeight = hw.getHeight(); 120 glDisable(GL_DITHER); 121 glEnable(GL_BLEND); 122 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 123 glColor4x(0, 0, 0, alpha); 124 125 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer) 126 if (sUseTexture) { 127 glBindTexture(GL_TEXTURE_2D, sTexId); 128 glEnable(GL_TEXTURE_2D); 129 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 130 const GLshort texCoords[4][2] = { 131 { 0, 0 }, 132 { 0, 1 }, 133 { 1, 1 }, 134 { 1, 0 } 135 }; 136 glMatrixMode(GL_TEXTURE); 137 glLoadIdentity(); 138 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 139 glTexCoordPointer(2, GL_SHORT, 0, texCoords); 140 } else 141 #endif 142 { 143 glDisable(GL_TEXTURE_2D); 144 } 145 146 GLshort w = sWidth; 147 GLshort h = sHeight; 148 const GLshort vertices[4][2] = { 149 { 0, 0 }, 150 { 0, h }, 151 { w, h }, 152 { w, 0 } 153 }; 154 glVertexPointer(2, GL_SHORT, 0, vertices); 155 156 while (it != end) { 157 const Rect& r = *it++; 158 const GLint sy = fbHeight - (r.top + r.height()); 159 glScissor(r.left, sy, r.width(), r.height()); 160 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 161 } 162 } 163 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 164 } 165 166 // --------------------------------------------------------------------------- 167 168 }; // namespace android 169