LayerBlur.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. * Copyright (c) 2014, The Linux Foundation. All rights reserved.
  3. * Not a Contribution.
  4. *
  5. * Copyright (C) 2007 The Android Open Source Project
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. #define ATRACE_TAG ATRACE_TAG_GRAPHICS
  20. //#define LOG_NDEBUG 0
  21. #include <stdlib.h>
  22. #include <stdint.h>
  23. #include <sys/types.h>
  24. #include <time.h>
  25. #include <dlfcn.h>
  26. #include <utils/Errors.h>
  27. #include <utils/Log.h>
  28. #include <utils/Trace.h>
  29. #include <GLES/gl.h>
  30. #include <GLES2/gl2.h>
  31. #include "LayerBlur.h"
  32. #include "SurfaceFlinger.h"
  33. #include "DisplayDevice.h"
  34. #include "RenderEngine/RenderEngine.h"
  35. namespace android {
  36. // ---------------------------------------------------------------------------
  37. // Automatically disables scissor test and restores it when destroyed
  38. class ScopedScissorDisabler {
  39. bool scissorEnabled;
  40. public:
  41. ScopedScissorDisabler(bool enabled) : scissorEnabled(enabled) {
  42. if(scissorEnabled) {
  43. glDisable(GL_SCISSOR_TEST);
  44. }
  45. }
  46. ~ScopedScissorDisabler() {
  47. if(scissorEnabled) {
  48. glEnable(GL_SCISSOR_TEST);
  49. }
  50. };
  51. };
  52. static void setupMeshPartial(Mesh& mesh, Rect rcDraw, Rect rcTexture, int texWidth, int texHeight, int viewportHeight) {
  53. Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
  54. position[0] = vec2(rcDraw.left, rcDraw.top);
  55. position[1] = vec2(rcDraw.left, rcDraw.bottom);
  56. position[2] = vec2(rcDraw.right, rcDraw.bottom);
  57. position[3] = vec2(rcDraw.right, rcDraw.top);
  58. for(size_t i=0; i<4; ++i) {
  59. position[i].y = viewportHeight - position[i].y;
  60. }
  61. Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
  62. texCoords[0] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight);
  63. texCoords[1] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight);
  64. texCoords[2] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight);
  65. texCoords[3] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight);
  66. }
  67. static void setupMesh(Mesh& mesh, int width, int height, int viewportHeight) {
  68. Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
  69. position[0] = vec2(0, 0);
  70. position[1] = vec2(0, height);
  71. position[2] = vec2(width, height);
  72. position[3] = vec2(width, 0);
  73. for(size_t i=0; i<4; ++i) {
  74. position[i].y = viewportHeight - position[i].y;
  75. }
  76. Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
  77. texCoords[0] = vec2(0, 1.0f);
  78. texCoords[1] = vec2(0, 0);
  79. texCoords[2] = vec2(1.0f, 0);
  80. texCoords[3] = vec2(1.0f, 1.0f);
  81. }
  82. LayerBlur::LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client,
  83. const String8& name, uint32_t w, uint32_t h, uint32_t flags)
  84. : Layer(flinger, client, name, w, h, flags), mBlurMaskSampling(1),
  85. mBlurMaskAlphaThreshold(0.0f) ,mLastFrameSequence(0)
  86. {
  87. GLuint texnames[3];
  88. mFlinger->getRenderEngine().genTextures(3, texnames);
  89. mTextureCapture.init(Texture::TEXTURE_2D, texnames[0]);
  90. mTextureBlur.init(Texture::TEXTURE_2D, texnames[1]);
  91. mTextureMasking.init(Texture::TEXTURE_2D, texnames[2]);
  92. }
  93. LayerBlur::~LayerBlur() {
  94. releaseFbo(mFboCapture);
  95. releaseFbo(mFboMasking);
  96. mFlinger->deleteTextureAsync(mTextureCapture.getTextureName());
  97. mFlinger->deleteTextureAsync(mTextureBlur.getTextureName());
  98. mFlinger->deleteTextureAsync(mTextureMasking.getTextureName());
  99. }
  100. void LayerBlur::onDraw(const sp<const DisplayDevice>& hw, const Region& /*clip*/,
  101. bool useIdentityTransform)
  102. {
  103. clock_t t1 = clock();
  104. const ScopedTrace traceTotal(ATRACE_TAG, "Blur.onDraw");
  105. const Layer::State& s(getDrawingState());
  106. if (s.alpha==0) {
  107. return;
  108. }
  109. /////
  110. // NOTE:
  111. //
  112. // Scissor test has been turned on by SurfaceFlinger for NON-primary display
  113. // We need to turn off the scissor test during our fbo drawing
  114. GLboolean isScissorEnabled = false;
  115. glGetBooleanv(GL_SCISSOR_TEST, &isScissorEnabled);
  116. ScopedScissorDisabler _(isScissorEnabled);
  117. //
  118. /////
  119. int hwWidth = hw->getWidth();
  120. int hwHeight = hw->getHeight();
  121. RenderEngine& engine(mFlinger->getRenderEngine());
  122. bool savedProjectionYSwap = engine.getProjectionYSwap();
  123. Rect savedProjectionSourceCrop = engine.getProjectionSourceCrop();
  124. Transform::orientation_flags savedProjectionRotation = engine.getProjectionRotation();
  125. size_t savedViewportWidth = engine.getViewportWidth();
  126. size_t savedViewportHeight = engine.getViewportHeight();
  127. if (mLastFrameSequence != mFlinger->mActiveFrameSequence ||
  128. mTextureBlur.getWidth() == 0 || mTextureBlur.getHeight() == 0) {
  129. // full drawing needed.
  130. // capture
  131. if (!captureScreen(hw, mFboCapture, mTextureCapture, hwWidth, hwHeight)) {
  132. return;
  133. }
  134. // blur
  135. size_t outTexWidth = mTextureBlur.getWidth();
  136. size_t outTexHeight = mTextureBlur.getHeight();
  137. if (mBlurImpl.blur(s.blur,
  138. mTextureCapture.getTextureName(),
  139. mTextureCapture.getWidth(),
  140. mTextureCapture.getHeight(),
  141. mTextureBlur.getTextureName(),
  142. &outTexWidth,
  143. &outTexHeight) != OK) {
  144. return;
  145. }
  146. // mTextureBlur now has "Blurred image"
  147. mTextureBlur.setDimensions(outTexWidth, outTexHeight);
  148. } else {
  149. // We can just re-use mTextureBlur.
  150. // SurfaceFlinger or other LayerBlur object called my draw() multiple times
  151. // while making one frame.
  152. //
  153. // Fall through
  154. }
  155. // masking
  156. bool masking = false;
  157. sp<Layer> maskLayer = mBlurMaskLayer.promote();
  158. if (maskLayer != 0) {
  159. // The larger sampling, the faster drawing.
  160. // The smaller sampling, the prettier out line.
  161. int sampling = mBlurMaskSampling >= 1 ? mBlurMaskSampling : 1;
  162. //ALOGV("maskLayer available, sampling:%d", sampling);
  163. masking = drawMaskLayer(maskLayer, hw, mFboMasking, hwWidth, hwHeight, sampling, mTextureMasking);
  164. }
  165. // final draw
  166. doDrawFinal(hw,
  167. savedViewportWidth, savedViewportHeight,
  168. savedProjectionSourceCrop,
  169. savedProjectionYSwap,
  170. savedProjectionRotation,
  171. useIdentityTransform,
  172. masking ? &mTextureMasking : 0
  173. );
  174. mLastFrameSequence = mFlinger->mActiveFrameSequence;
  175. clock_t t2 = clock();
  176. ALOGV("onDraw took %d ms", (int)(1000*(t2-t1)/CLOCKS_PER_SEC));
  177. }
  178. bool LayerBlur::captureScreen(const sp<const DisplayDevice>& hw, FBO& fbo, Texture& texture, int width, int height) {
  179. ATRACE_CALL();
  180. ensureFbo(fbo, width, height, texture.getTextureName());
  181. Transform::orientation_flags rotation = Transform::ROT_0;
  182. if(fbo.fbo == 0) {
  183. ALOGE("captureScreen(). fbo.fbo == 0");
  184. return false;
  185. }
  186. GLint savedFramebuffer = 0;
  187. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
  188. glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo);
  189. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  190. texture.getTextureTarget(),
  191. texture.getTextureName(), 0);
  192. mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 1.0f);
  193. rotation = (Transform::orientation_flags)(rotation ^ hw->getPanelMountFlip());
  194. mFlinger->renderScreenImplLocked(
  195. hw,
  196. Rect(0,0,width,height),
  197. width, height,
  198. 0, getDrawingState().z-1,
  199. false,
  200. false,
  201. rotation);
  202. glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
  203. texture.setDimensions(width, height);
  204. return true;
  205. }
  206. bool LayerBlur::drawMaskLayer(sp<Layer>& maskLayer, const sp<const DisplayDevice>& hw,
  207. FBO& fbo, int width, int height, int sampling, Texture& texture) {
  208. // Draw maskLayer into fbo
  209. ATRACE_CALL();
  210. int maskWidth = width/sampling;
  211. int maskHeight = height/sampling;
  212. ensureFbo(fbo, maskWidth, maskHeight, texture.getTextureName());
  213. if(fbo.fbo == 0) {
  214. ALOGE("drawMaskLayer(). fbo.fbo == 0");
  215. return false;
  216. }
  217. GLint savedFramebuffer = 0;
  218. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
  219. glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo);
  220. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  221. texture.getTextureTarget(),
  222. texture.getTextureName(), 0);
  223. mFlinger->getRenderEngine().setViewportAndProjection(
  224. maskWidth, maskHeight,
  225. Rect(0,0,width,height),
  226. height,
  227. false,
  228. Transform::ROT_0
  229. );
  230. setupMesh(mMesh, width, height, height);
  231. mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 0.0f); // alpha must be ZERO
  232. maskLayer->draw(hw);
  233. glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
  234. texture.setDimensions(maskWidth, maskHeight);
  235. return true;
  236. }
  237. /*
  238. * draw final texture into outer framebuffer
  239. */
  240. void LayerBlur::doDrawFinal(const sp<const DisplayDevice>& hw,
  241. int savedViewportWidth, int savedViewportHeight,
  242. Rect savedProjectionSourceCrop,
  243. bool savedProjectionYSwap,
  244. Transform::orientation_flags savedRotation,
  245. bool useIdentityTransform,
  246. Texture* maskTexture
  247. ) {
  248. ATRACE_CALL();
  249. int hwWidth = hw->getWidth();
  250. int hwHeight = hw->getHeight();
  251. RenderEngine& engine(mFlinger->getRenderEngine());
  252. const Layer::State& s(getDrawingState());
  253. Transform trToDraw(useIdentityTransform ? hw->getTransform() : hw->getTransform() * s.transform);
  254. Transform trToMapTexture(hw->getTransform() * s.transform);
  255. Rect frameToDraw(trToDraw.transform(Rect(s.active.w, s.active.h)));
  256. Rect frameToMapTexture(trToMapTexture.transform(Rect(s.active.w, s.active.h)));
  257. engine.setViewportAndProjection(
  258. savedViewportWidth, savedViewportHeight,
  259. savedProjectionSourceCrop,
  260. hwHeight,
  261. savedProjectionYSwap,
  262. savedRotation
  263. );
  264. const mat4 identity;
  265. float textureMatrix[16];
  266. memcpy(textureMatrix, identity.asArray(), sizeof(textureMatrix));
  267. //mTextureBlur.setDimensions(hwWidth, hwHeight);
  268. mTextureBlur.setFiltering(true);
  269. mTextureBlur.setMatrix(textureMatrix);
  270. if (maskTexture != 0) {
  271. maskTexture->setFiltering(false);
  272. maskTexture->setMatrix(textureMatrix);
  273. }
  274. setupMeshPartial(mMesh, frameToDraw, frameToMapTexture, hwWidth, hwHeight,
  275. savedProjectionSourceCrop.height());
  276. engine.setupLayerTexturing(mTextureBlur);
  277. engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
  278. if (maskTexture) {
  279. engine.setupLayerMasking(*maskTexture, mBlurMaskAlphaThreshold);
  280. }
  281. engine.drawMesh(mMesh);
  282. engine.disableLayerMasking();
  283. engine.disableBlending();
  284. engine.disableTexturing();
  285. }
  286. bool LayerBlur::isVisible() const {
  287. const Layer::State& s(getDrawingState());
  288. return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
  289. }
  290. bool LayerBlur::setBlurMaskLayer(sp<Layer>& maskLayer) {
  291. if (maskLayer == mBlurMaskLayer) {
  292. return false;
  293. }
  294. mBlurMaskLayer = maskLayer;
  295. return true;
  296. }
  297. void LayerBlur::initFbo(FBO& fbobj, int width, int height, int textureName) {
  298. GLuint fbo=0;
  299. glGenFramebuffers(1, &fbo);
  300. glBindTexture(GL_TEXTURE_2D, textureName);
  301. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
  302. 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  303. glBindTexture(GL_TEXTURE_2D, 0);
  304. GLint savedFramebuffer = 0;
  305. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
  306. glBindFramebuffer(GL_FRAMEBUFFER, fbo);
  307. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  308. GL_TEXTURE_2D, textureName, 0);
  309. glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
  310. fbobj.fbo = fbo;
  311. fbobj.width = width;
  312. fbobj.height = height;
  313. }
  314. void LayerBlur::releaseFbo(FBO& fbo) {
  315. if(fbo.fbo != 0) {
  316. glDeleteFramebuffers(1, (GLuint*)&fbo.fbo);
  317. }
  318. fbo.fbo = 0;
  319. fbo.width = 0;
  320. fbo.height = 0;
  321. }
  322. void LayerBlur::ensureFbo(FBO& fbo, int width, int height, int textureName) {
  323. if(fbo.fbo != 0) {
  324. if(fbo.width != width || fbo.height != height) {
  325. releaseFbo(fbo);
  326. }
  327. }
  328. if(fbo.fbo == 0) {
  329. initFbo(fbo, width, height, textureName);
  330. }
  331. }
  332. // ---------------------------------------------------------------------------
  333. void* LayerBlur::BlurImpl::sLibHandle = NULL;
  334. bool LayerBlur::BlurImpl::sUnsupported = false;
  335. LayerBlur::BlurImpl::initBlurTokenFn LayerBlur::BlurImpl::initBlurToken = NULL;
  336. LayerBlur::BlurImpl::releaseBlurTokenFn LayerBlur::BlurImpl::releaseBlurToken = NULL;
  337. LayerBlur::BlurImpl::blurFn LayerBlur::BlurImpl::doBlur = NULL;
  338. Mutex LayerBlur::BlurImpl::sLock;
  339. void LayerBlur::BlurImpl::closeBlurImpl() {
  340. if (sLibHandle != NULL) {
  341. dlclose(sLibHandle);
  342. sLibHandle = NULL;
  343. }
  344. }
  345. status_t LayerBlur::BlurImpl::initBlurImpl() {
  346. if (sLibHandle != NULL) {
  347. return OK;
  348. }
  349. if (sUnsupported) {
  350. return NO_INIT;
  351. }
  352. sLibHandle = dlopen("libuiblur.so", RTLD_NOW);
  353. if (sLibHandle == NULL) {
  354. sUnsupported = true;
  355. return NO_INIT;
  356. }
  357. // happy happy joy joy!
  358. initBlurToken = (initBlurTokenFn)dlsym(sLibHandle,
  359. "_ZN7qtiblur13initBlurTokenEv");
  360. releaseBlurToken = (releaseBlurTokenFn)dlsym(sLibHandle,
  361. "_ZN7qtiblur16releaseBlurTokenEPv");
  362. if (sizeof(size_t) == 4) {
  363. doBlur = (blurFn)dlsym(sLibHandle,
  364. "_ZN7qtiblur4blurEPvijjjjPjS1_");
  365. } else if (sizeof(size_t) == 8) {
  366. doBlur = (blurFn)dlsym(sLibHandle,
  367. "_ZN7qtiblur4blurEPvijmmjPmS1_");
  368. }
  369. if (!initBlurToken || !releaseBlurToken || !doBlur) {
  370. ALOGE("dlsym failed for blur impl!: %s", dlerror());
  371. closeBlurImpl();
  372. sUnsupported = true;
  373. return NO_INIT;
  374. }
  375. return OK;
  376. }
  377. LayerBlur::BlurImpl::BlurImpl() : mToken(NULL) {
  378. Mutex::Autolock _l(sLock);
  379. if (initBlurImpl() == OK) {
  380. mToken = initBlurToken();
  381. }
  382. }
  383. LayerBlur::BlurImpl::~BlurImpl() {
  384. Mutex::Autolock _l(sLock);
  385. if (mToken != NULL) {
  386. releaseBlurToken(mToken);
  387. }
  388. }
  389. status_t LayerBlur::BlurImpl::blur(int level, uint32_t inId, size_t inWidth, size_t inHeight,
  390. uint32_t outId, size_t* outWidth, size_t* outHeight) {
  391. Mutex::Autolock _l(sLock);
  392. if (mToken == NULL) {
  393. return NO_INIT;
  394. }
  395. return doBlur(mToken, level, inId, inWidth, inHeight,
  396. outId, outWidth, outHeight) ? OK : NO_INIT;
  397. }
  398. // ---------------------------------------------------------------------------
  399. }; // namespace android