1/* 2 * Copyright (C) 2011 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 <GLES/gl.h> 22#include <GLES/glext.h> 23 24#include <utils/Errors.h> 25#include <utils/Log.h> 26 27#include <ui/GraphicBuffer.h> 28 29#include "LayerScreenshot.h" 30#include "SurfaceFlinger.h" 31#include "DisplayDevice.h" 32 33 34namespace android { 35// --------------------------------------------------------------------------- 36 37LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, 38 const sp<Client>& client) 39 : LayerBaseClient(flinger, client), 40 mTextureName(0), mFlinger(flinger), mIsSecure(false) 41{ 42} 43 44LayerScreenshot::~LayerScreenshot() 45{ 46 if (mTextureName) { 47 mFlinger->deleteTextureAsync(mTextureName); 48 } 49} 50 51status_t LayerScreenshot::captureLocked(int32_t layerStack) { 52 GLfloat u, v; 53 status_t result = mFlinger->renderScreenToTextureLocked(layerStack, 54 &mTextureName, &u, &v); 55 if (result != NO_ERROR) { 56 return result; 57 } 58 initTexture(u, v); 59 60 // Currently screenshot always comes from the default display 61 mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); 62 63 return NO_ERROR; 64} 65 66status_t LayerScreenshot::capture() { 67 GLfloat u, v; 68 status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v); 69 if (result != NO_ERROR) { 70 return result; 71 } 72 initTexture(u, v); 73 74 // Currently screenshot always comes from the default display 75 mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); 76 77 return NO_ERROR; 78} 79 80void LayerScreenshot::initTexture(GLfloat u, GLfloat v) { 81 glBindTexture(GL_TEXTURE_2D, mTextureName); 82 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 83 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 84 mTexCoords[0] = 0; mTexCoords[1] = v; 85 mTexCoords[2] = 0; mTexCoords[3] = 0; 86 mTexCoords[4] = u; mTexCoords[5] = 0; 87 mTexCoords[6] = u; mTexCoords[7] = v; 88} 89 90void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) { 91 LayerBaseClient::initStates(w, h, flags); 92 if (!(flags & ISurfaceComposerClient::eHidden)) { 93 capture(); 94 } 95 if (flags & ISurfaceComposerClient::eSecure) { 96 ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered " 97 "secure iff it captures the contents of a secure surface."); 98 } 99} 100 101uint32_t LayerScreenshot::doTransaction(uint32_t flags) 102{ 103 const LayerBase::State& draw(drawingState()); 104 const LayerBase::State& curr(currentState()); 105 106 if (draw.flags & layer_state_t::eLayerHidden) { 107 if (!(curr.flags & layer_state_t::eLayerHidden)) { 108 // we're going from hidden to visible 109 status_t err = captureLocked(curr.layerStack); 110 if (err != NO_ERROR) { 111 ALOGW("createScreenshotSurface failed (%s)", strerror(-err)); 112 } 113 } 114 } else if (curr.flags & layer_state_t::eLayerHidden) { 115 // we're going from visible to hidden 116 if (mTextureName) { 117 glDeleteTextures(1, &mTextureName); 118 mTextureName = 0; 119 } 120 } 121 return LayerBaseClient::doTransaction(flags); 122} 123 124void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const 125{ 126 const State& s(drawingState()); 127 if (s.alpha>0) { 128 const GLfloat alpha = s.alpha/255.0f; 129 const uint32_t fbHeight = hw->getHeight(); 130 131 if (s.alpha == 0xFF) { 132 glDisable(GL_BLEND); 133 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 134 } else { 135 glEnable(GL_BLEND); 136 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 137 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 138 } 139 140 GLuint texName = mTextureName; 141 if (isSecure() && !hw->isSecure()) { 142 texName = mFlinger->getProtectedTexName(); 143 } 144 145 LayerMesh mesh; 146 computeGeometry(hw, &mesh); 147 148 glColor4f(alpha, alpha, alpha, alpha); 149 150 glDisable(GL_TEXTURE_EXTERNAL_OES); 151 glEnable(GL_TEXTURE_2D); 152 153 glBindTexture(GL_TEXTURE_2D, texName); 154 glMatrixMode(GL_TEXTURE); 155 glLoadIdentity(); 156 glMatrixMode(GL_MODELVIEW); 157 158 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 159 glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); 160 glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); 161 glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); 162 163 glDisable(GL_BLEND); 164 glDisable(GL_TEXTURE_2D); 165 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 166 } 167} 168 169// --------------------------------------------------------------------------- 170 171}; // namespace android 172