PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/frameworks/base/libs/hwui/OpenGLRenderer.cpp

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
C++ | 1516 lines | 1088 code | 260 blank | 168 comment | 186 complexity | 6efd5a1a2190706eae066af5d15ea33d MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 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. #define LOG_TAG "OpenGLRenderer"
  17. #include <stdlib.h>
  18. #include <stdint.h>
  19. #include <sys/types.h>
  20. #include <SkCanvas.h>
  21. #include <SkPathMeasure.h>
  22. #include <SkTypeface.h>
  23. #include <utils/Log.h>
  24. #include <utils/StopWatch.h>
  25. #include <private/hwui/DrawGlInfo.h>
  26. #include <ui/Rect.h>
  27. #include "OpenGLRenderer.h"
  28. #include "DisplayListRenderer.h"
  29. #include "PathRenderer.h"
  30. #include "Properties.h"
  31. #include "Vector.h"
  32. namespace android {
  33. namespace uirenderer {
  34. ///////////////////////////////////////////////////////////////////////////////
  35. // Defines
  36. ///////////////////////////////////////////////////////////////////////////////
  37. #define RAD_TO_DEG (180.0f / 3.14159265f)
  38. #define MIN_ANGLE 0.001f
  39. #define ALPHA_THRESHOLD 0
  40. #define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // Globals
  43. ///////////////////////////////////////////////////////////////////////////////
  44. /**
  45. * Structure mapping Skia xfermodes to OpenGL blending factors.
  46. */
  47. struct Blender {
  48. SkXfermode::Mode mode;
  49. GLenum src;
  50. GLenum dst;
  51. }; // struct Blender
  52. // In this array, the index of each Blender equals the value of the first
  53. // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
  54. static const Blender gBlends[] = {
  55. { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  56. { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
  57. { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
  58. { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
  59. { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
  60. { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
  61. { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
  62. { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  63. { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  64. { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  65. { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
  66. { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  67. { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
  68. { SkXfermode::kMultiply_Mode, GL_ZERO, GL_SRC_COLOR },
  69. { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
  70. };
  71. // This array contains the swapped version of each SkXfermode. For instance
  72. // this array's SrcOver blending mode is actually DstOver. You can refer to
  73. // createLayer() for more information on the purpose of this array.
  74. static const Blender gBlendsSwap[] = {
  75. { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  76. { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
  77. { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
  78. { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
  79. { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
  80. { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
  81. { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
  82. { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  83. { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  84. { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
  85. { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  86. { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  87. { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
  88. { SkXfermode::kMultiply_Mode, GL_DST_COLOR, GL_ZERO },
  89. { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
  90. };
  91. ///////////////////////////////////////////////////////////////////////////////
  92. // Constructors/destructor
  93. ///////////////////////////////////////////////////////////////////////////////
  94. static int EnableDither = 0;
  95. char* GetProgramName(char* buf, int size)
  96. {
  97. char procName[64];
  98. pid_t pid = getpid();
  99. FILE* fp = NULL;
  100. snprintf(procName, sizeof(procName), "/proc/%i/cmdline", pid);
  101. fp = fopen(procName, "r");
  102. if(fp)
  103. {
  104. fread(buf, 1, size, fp);
  105. fclose(fp);
  106. fp = NULL;
  107. }
  108. else
  109. {
  110. ALOGD("%s : %d : open file %s failed \n", __FUNCTION__, __LINE__, procName);
  111. }
  112. return buf;
  113. }
  114. OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) {
  115. mShader = NULL;
  116. mColorFilter = NULL;
  117. mHasShadow = false;
  118. mHasDrawFilter = false;
  119. mOrientation = -1;
  120. memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
  121. mFirstSnapshot = new Snapshot;
  122. mScissorOptimizationDisabled = false;
  123. char property[PROPERTY_VALUE_MAX];
  124. property_get("ro.sf.lcdc_composer", property, NULL) > 0;
  125. char exeName[64] = {0};
  126. GetProgramName(exeName, 64 - 1);
  127. if( ((0 == strcmp("com.android.browser", exeName)) ||
  128. (0 == strcmp("com.android.launcher", exeName))) &&
  129. !strcmp(property, "1"))
  130. {
  131. EnableDither = 1;
  132. } else {
  133. EnableDither = 0;
  134. }
  135. }
  136. OpenGLRenderer::~OpenGLRenderer() {
  137. // The context has already been destroyed at this point, do not call
  138. // GL APIs. All GL state should be kept in Caches.h
  139. }
  140. void OpenGLRenderer::initProperties() {
  141. char property[PROPERTY_VALUE_MAX];
  142. if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
  143. mScissorOptimizationDisabled = !strcasecmp(property, "true");
  144. INIT_LOGD(" Scissor optimization %s",
  145. mScissorOptimizationDisabled ? "disabled" : "enabled");
  146. } else {
  147. INIT_LOGD(" Scissor optimization enabled");
  148. }
  149. }
  150. ///////////////////////////////////////////////////////////////////////////////
  151. // Setup
  152. ///////////////////////////////////////////////////////////////////////////////
  153. bool OpenGLRenderer::isDeferred() {
  154. return false;
  155. }
  156. bool OpenGLRenderer::queryHWRenderEngine(const char* property) {
  157. //get gpu renderer, make sure gl context has created.
  158. const char *renderer = (const char *)glGetString(GL_RENDERER);
  159. if (renderer != NULL) {
  160. if (!strcmp(property, "debug.hwui.render_dirty_regions")) {
  161. if (!strcmp(renderer, "Mali-400 MP")) {
  162. return false;
  163. } else if (!strcmp(renderer, "PowerVR SGX 540")) {
  164. return true;
  165. }
  166. }
  167. }
  168. return false;
  169. }
  170. void OpenGLRenderer::setOrientation(int orientation) {
  171. //ALOGD("setOrientation: %d", orientation);
  172. mOrientation = orientation;
  173. }
  174. void OpenGLRenderer::setViewport(int width, int height) {
  175. initViewport(width, height);
  176. if(EnableDither)
  177. glEnable(GL_DITHER);
  178. else
  179. glDisable(GL_DITHER);
  180. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  181. glEnableVertexAttribArray(Program::kBindingPosition);
  182. }
  183. void OpenGLRenderer::initViewport(int width, int height) {
  184. mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
  185. mWidth = width;
  186. mHeight = height;
  187. mFirstSnapshot->height = height;
  188. mFirstSnapshot->viewport.set(0, 0, width, height);
  189. }
  190. status_t OpenGLRenderer::prepare(bool opaque) {
  191. if (mOrientation != -1 && mOrientation % 2 == 1) {
  192. return prepareDirty(0.0f, 0.0f, mHeight, mWidth, opaque);
  193. } else {
  194. return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
  195. }
  196. }
  197. status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
  198. bool opaque) {
  199. mCaches.clearGarbage();
  200. mSnapshot = new Snapshot(mFirstSnapshot,
  201. SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
  202. mSnapshot->fbo = getTargetFbo();
  203. int convertLeft = left;
  204. int convertTop = top;
  205. int convertRight = right;
  206. int convertBottom = bottom;
  207. switch (mOrientation) {
  208. case 3:
  209. rotate(-90);
  210. translate(-mHeight, 0);
  211. left = convertTop;
  212. bottom = mHeight - convertLeft;
  213. right = convertBottom;
  214. top = mHeight - convertRight;
  215. break;
  216. case 1:
  217. rotate(90);
  218. translate(0, -mWidth);
  219. left = mWidth - convertBottom;
  220. bottom = convertRight;
  221. right = mWidth - convertTop;
  222. top = convertLeft;
  223. break;
  224. case 2:
  225. rotate(180);
  226. translate(-mWidth, -mHeight);
  227. left = mWidth - convertRight;
  228. bottom = mHeight - convertTop;
  229. right = mWidth - convertLeft;
  230. top = mHeight - convertBottom;
  231. break;
  232. }
  233. mSaveCount = 1;
  234. mSnapshot->setClip(left, top, right, bottom);
  235. mDirtyClip = true;
  236. updateLayers();
  237. // If we know that we are going to redraw the entire framebuffer,
  238. // perform a discard to let the driver know we don't need to preserve
  239. // the back buffer for this frame.
  240. if (mCaches.extensions.hasDiscardFramebuffer() &&
  241. left <= 0.0f && top <= 0.0f && right >= mWidth && bottom >= mHeight) {
  242. const GLenum attachments[] = { getTargetFbo() == 0 ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0 };
  243. glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
  244. }
  245. syncState();
  246. // Functors break the tiling extension in pretty spectacular ways
  247. // This ensures we don't use tiling when a functor is going to be
  248. // invoked during the frame
  249. mSuppressTiling = mCaches.hasRegisteredFunctors();
  250. mTilingSnapshot = mSnapshot;
  251. startTiling(mTilingSnapshot, true);
  252. debugOverdraw(true, true);
  253. return clear(left, top, right, bottom, opaque);
  254. }
  255. status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
  256. if (!opaque) {
  257. mCaches.enableScissor();
  258. mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
  259. glClear(GL_COLOR_BUFFER_BIT);
  260. return DrawGlInfo::kStatusDrew;
  261. }
  262. mCaches.resetScissor();
  263. return DrawGlInfo::kStatusDone;
  264. }
  265. void OpenGLRenderer::syncState() {
  266. glViewport(0, 0, mWidth, mHeight);
  267. if (mCaches.blend) {
  268. glEnable(GL_BLEND);
  269. } else {
  270. glDisable(GL_BLEND);
  271. }
  272. }
  273. void OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) {
  274. if (!mSuppressTiling) {
  275. Rect* clip = mTilingSnapshot->clipRect;
  276. if (s->flags & Snapshot::kFlagIsFboLayer) {
  277. clip = s->clipRect;
  278. }
  279. mCaches.startTiling(clip->left, s->height - clip->bottom,
  280. clip->right - clip->left, clip->bottom - clip->top, opaque);
  281. }
  282. }
  283. void OpenGLRenderer::endTiling() {
  284. if (!mSuppressTiling) mCaches.endTiling();
  285. }
  286. void OpenGLRenderer::finish() {
  287. renderOverdraw();
  288. endTiling();
  289. if (!suppressErrorChecks()) {
  290. #if DEBUG_OPENGL
  291. GLenum status = GL_NO_ERROR;
  292. while ((status = glGetError()) != GL_NO_ERROR) {
  293. ALOGD("GL error from OpenGLRenderer: 0x%x", status);
  294. switch (status) {
  295. case GL_INVALID_ENUM:
  296. ALOGE(" GL_INVALID_ENUM");
  297. break;
  298. case GL_INVALID_VALUE:
  299. ALOGE(" GL_INVALID_VALUE");
  300. break;
  301. case GL_INVALID_OPERATION:
  302. ALOGE(" GL_INVALID_OPERATION");
  303. break;
  304. case GL_OUT_OF_MEMORY:
  305. ALOGE(" Out of memory!");
  306. break;
  307. }
  308. }
  309. #endif
  310. #if DEBUG_MEMORY_USAGE
  311. mCaches.dumpMemoryUsage();
  312. #else
  313. if (mCaches.getDebugLevel() & kDebugMemory) {
  314. mCaches.dumpMemoryUsage();
  315. }
  316. #endif
  317. }
  318. }
  319. void OpenGLRenderer::interrupt() {
  320. if (mCaches.currentProgram) {
  321. if (mCaches.currentProgram->isInUse()) {
  322. mCaches.currentProgram->remove();
  323. mCaches.currentProgram = NULL;
  324. }
  325. }
  326. mCaches.unbindMeshBuffer();
  327. mCaches.unbindIndicesBuffer();
  328. mCaches.resetVertexPointers();
  329. mCaches.disbaleTexCoordsVertexArray();
  330. debugOverdraw(false, false);
  331. }
  332. void OpenGLRenderer::resume() {
  333. sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
  334. glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
  335. glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
  336. debugOverdraw(true, false);
  337. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  338. mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
  339. mCaches.enableScissor();
  340. mCaches.resetScissor();
  341. dirtyClip();
  342. mCaches.activeTexture(0);
  343. mCaches.blend = true;
  344. glEnable(GL_BLEND);
  345. glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
  346. glBlendEquation(GL_FUNC_ADD);
  347. }
  348. void OpenGLRenderer::resumeAfterLayer() {
  349. sp<Snapshot> snapshot = (mSnapshot != NULL) ? mSnapshot : mFirstSnapshot;
  350. glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
  351. glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
  352. debugOverdraw(true, false);
  353. mCaches.resetScissor();
  354. dirtyClip();
  355. }
  356. void OpenGLRenderer::detachFunctor(Functor* functor) {
  357. mFunctors.remove(functor);
  358. }
  359. void OpenGLRenderer::attachFunctor(Functor* functor) {
  360. mFunctors.add(functor);
  361. }
  362. status_t OpenGLRenderer::invokeFunctors(Rect& dirty) {
  363. status_t result = DrawGlInfo::kStatusDone;
  364. size_t count = mFunctors.size();
  365. if (count > 0) {
  366. interrupt();
  367. SortedVector<Functor*> functors(mFunctors);
  368. mFunctors.clear();
  369. DrawGlInfo info;
  370. info.clipLeft = 0;
  371. info.clipTop = 0;
  372. info.clipRight = 0;
  373. info.clipBottom = 0;
  374. info.isLayer = false;
  375. info.width = 0;
  376. info.height = 0;
  377. memset(info.transform, 0, sizeof(float) * 16);
  378. for (size_t i = 0; i < count; i++) {
  379. Functor* f = functors.itemAt(i);
  380. result |= (*f)(DrawGlInfo::kModeProcess, &info);
  381. if (result & DrawGlInfo::kStatusDraw) {
  382. Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
  383. dirty.unionWith(localDirty);
  384. }
  385. if (result & DrawGlInfo::kStatusInvoke) {
  386. mFunctors.add(f);
  387. }
  388. }
  389. resume();
  390. }
  391. return result;
  392. }
  393. status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
  394. interrupt();
  395. detachFunctor(functor);
  396. mCaches.enableScissor();
  397. if (mDirtyClip) {
  398. setScissorFromClip();
  399. }
  400. Rect clip(*mSnapshot->clipRect);
  401. clip.snapToPixelBoundaries();
  402. // Since we don't know what the functor will draw, let's dirty
  403. // tne entire clip region
  404. if (hasLayer()) {
  405. dirtyLayerUnchecked(clip, getRegion());
  406. }
  407. DrawGlInfo info;
  408. info.clipLeft = clip.left;
  409. info.clipTop = clip.top;
  410. info.clipRight = clip.right;
  411. info.clipBottom = clip.bottom;
  412. info.isLayer = hasLayer();
  413. info.width = getSnapshot()->viewport.getWidth();
  414. info.height = getSnapshot()->height;
  415. getSnapshot()->transform->copyTo(&info.transform[0]);
  416. status_t result = (*functor)(DrawGlInfo::kModeDraw, &info) | DrawGlInfo::kStatusDrew;
  417. if (result != DrawGlInfo::kStatusDone) {
  418. Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
  419. dirty.unionWith(localDirty);
  420. if (result & DrawGlInfo::kStatusInvoke) {
  421. mFunctors.add(functor);
  422. }
  423. }
  424. resume();
  425. return result;
  426. }
  427. ///////////////////////////////////////////////////////////////////////////////
  428. // Debug
  429. ///////////////////////////////////////////////////////////////////////////////
  430. void OpenGLRenderer::startMark(const char* name) const {
  431. mCaches.startMark(0, name);
  432. }
  433. void OpenGLRenderer::endMark() const {
  434. mCaches.endMark();
  435. }
  436. void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
  437. if (mCaches.debugOverdraw && getTargetFbo() == 0) {
  438. if (clear) {
  439. mCaches.disableScissor();
  440. mCaches.stencil.clear();
  441. }
  442. if (enable) {
  443. mCaches.stencil.enableDebugWrite();
  444. } else {
  445. mCaches.stencil.disable();
  446. }
  447. }
  448. }
  449. void OpenGLRenderer::renderOverdraw() {
  450. if (mCaches.debugOverdraw && getTargetFbo() == 0) {
  451. const Rect* clip = mTilingSnapshot->clipRect;
  452. mCaches.enableScissor();
  453. mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
  454. clip->right - clip->left, clip->bottom - clip->top);
  455. mCaches.stencil.enableDebugTest(2);
  456. drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
  457. mCaches.stencil.enableDebugTest(3);
  458. drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
  459. mCaches.stencil.enableDebugTest(4);
  460. drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
  461. mCaches.stencil.enableDebugTest(4, true);
  462. drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
  463. mCaches.stencil.disable();
  464. }
  465. }
  466. ///////////////////////////////////////////////////////////////////////////////
  467. // Layers
  468. ///////////////////////////////////////////////////////////////////////////////
  469. bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
  470. if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
  471. OpenGLRenderer* renderer = layer->renderer;
  472. Rect& dirty = layer->dirtyRect;
  473. if (inFrame) {
  474. endTiling();
  475. debugOverdraw(false, false);
  476. }
  477. int ori = mOrientation;
  478. if (mOrientation != -1) {
  479. renderer->setOrientation(0);
  480. }
  481. renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
  482. renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
  483. renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
  484. renderer->finish();
  485. renderer->setOrientation(ori);
  486. if (inFrame) {
  487. resumeAfterLayer();
  488. startTiling(mSnapshot);
  489. }
  490. dirty.setEmpty();
  491. layer->deferredUpdateScheduled = false;
  492. layer->renderer = NULL;
  493. layer->displayList = NULL;
  494. return true;
  495. }
  496. return false;
  497. }
  498. void OpenGLRenderer::updateLayers() {
  499. int count = mLayerUpdates.size();
  500. if (count > 0) {
  501. startMark("Layer Updates");
  502. // Note: it is very important to update the layers in reverse order
  503. for (int i = count - 1; i >= 0; i--) {
  504. Layer* layer = mLayerUpdates.itemAt(i);
  505. updateLayer(layer, false);
  506. mCaches.resourceCache.decrementRefcount(layer);
  507. }
  508. mLayerUpdates.clear();
  509. glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
  510. endMark();
  511. }
  512. }
  513. void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
  514. if (layer) {
  515. mLayerUpdates.push_back(layer);
  516. mCaches.resourceCache.incrementRefcount(layer);
  517. }
  518. }
  519. void OpenGLRenderer::clearLayerUpdates() {
  520. size_t count = mLayerUpdates.size();
  521. if (count > 0) {
  522. mCaches.resourceCache.lock();
  523. for (size_t i = 0; i < count; i++) {
  524. mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i));
  525. }
  526. mCaches.resourceCache.unlock();
  527. mLayerUpdates.clear();
  528. }
  529. }
  530. ///////////////////////////////////////////////////////////////////////////////
  531. // State management
  532. ///////////////////////////////////////////////////////////////////////////////
  533. int OpenGLRenderer::getSaveCount() const {
  534. return mSaveCount;
  535. }
  536. int OpenGLRenderer::save(int flags) {
  537. return saveSnapshot(flags);
  538. }
  539. void OpenGLRenderer::restore() {
  540. if (mSaveCount > 1) {
  541. restoreSnapshot();
  542. }
  543. }
  544. void OpenGLRenderer::restoreToCount(int saveCount) {
  545. if (saveCount < 1) saveCount = 1;
  546. while (mSaveCount > saveCount) {
  547. restoreSnapshot();
  548. }
  549. }
  550. int OpenGLRenderer::saveSnapshot(int flags) {
  551. mSnapshot = new Snapshot(mSnapshot, flags);
  552. return mSaveCount++;
  553. }
  554. bool OpenGLRenderer::restoreSnapshot() {
  555. bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
  556. bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
  557. bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho;
  558. sp<Snapshot> current = mSnapshot;
  559. sp<Snapshot> previous = mSnapshot->previous;
  560. if (restoreOrtho) {
  561. Rect& r = previous->viewport;
  562. glViewport(r.left, r.top, r.right, r.bottom);
  563. mOrthoMatrix.load(current->orthoMatrix);
  564. }
  565. mSaveCount--;
  566. mSnapshot = previous;
  567. if (restoreClip) {
  568. dirtyClip();
  569. }
  570. if (restoreLayer) {
  571. composeLayer(current, previous);
  572. }
  573. return restoreClip;
  574. }
  575. ///////////////////////////////////////////////////////////////////////////////
  576. // Layers
  577. ///////////////////////////////////////////////////////////////////////////////
  578. int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
  579. SkPaint* p, int flags) {
  580. const GLuint previousFbo = mSnapshot->fbo;
  581. const int count = saveSnapshot(flags);
  582. if (!mSnapshot->isIgnored()) {
  583. int alpha = 255;
  584. SkXfermode::Mode mode;
  585. if (p) {
  586. alpha = p->getAlpha();
  587. mode = getXfermode(p->getXfermode());
  588. } else {
  589. mode = SkXfermode::kSrcOver_Mode;
  590. }
  591. createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo);
  592. }
  593. return count;
  594. }
  595. int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
  596. int alpha, int flags) {
  597. if (alpha >= 255) {
  598. return saveLayer(left, top, right, bottom, NULL, flags);
  599. } else {
  600. SkPaint paint;
  601. paint.setAlpha(alpha);
  602. return saveLayer(left, top, right, bottom, &paint, flags);
  603. }
  604. }
  605. /**
  606. * Layers are viewed by Skia are slightly different than layers in image editing
  607. * programs (for instance.) When a layer is created, previously created layers
  608. * and the frame buffer still receive every drawing command. For instance, if a
  609. * layer is created and a shape intersecting the bounds of the layers and the
  610. * framebuffer is draw, the shape will be drawn on both (unless the layer was
  611. * created with the SkCanvas::kClipToLayer_SaveFlag flag.)
  612. *
  613. * A way to implement layers is to create an FBO for each layer, backed by an RGBA
  614. * texture. Unfortunately, this is inefficient as it requires every primitive to
  615. * be drawn n + 1 times, where n is the number of active layers. In practice this
  616. * means, for every primitive:
  617. * - Switch active frame buffer
  618. * - Change viewport, clip and projection matrix
  619. * - Issue the drawing
  620. *
  621. * Switching rendering target n + 1 times per drawn primitive is extremely costly.
  622. * To avoid this, layers are implemented in a different way here, at least in the
  623. * general case. FBOs are used, as an optimization, when the "clip to layer" flag
  624. * is set. When this flag is set we can redirect all drawing operations into a
  625. * single FBO.
  626. *
  627. * This implementation relies on the frame buffer being at least RGBA 8888. When
  628. * a layer is created, only a texture is created, not an FBO. The content of the
  629. * frame buffer contained within the layer's bounds is copied into this texture
  630. * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
  631. * buffer and drawing continues as normal. This technique therefore treats the
  632. * frame buffer as a scratch buffer for the layers.
  633. *
  634. * To compose the layers back onto the frame buffer, each layer texture
  635. * (containing the original frame buffer data) is drawn as a simple quad over
  636. * the frame buffer. The trick is that the quad is set as the composition
  637. * destination in the blending equation, and the frame buffer becomes the source
  638. * of the composition.
  639. *
  640. * Drawing layers with an alpha value requires an extra step before composition.
  641. * An empty quad is drawn over the layer's region in the frame buffer. This quad
  642. * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
  643. * quad is used to multiply the colors in the frame buffer. This is achieved by
  644. * changing the GL blend functions for the GL_FUNC_ADD blend equation to
  645. * GL_ZERO, GL_SRC_ALPHA.
  646. *
  647. * Because glCopyTexImage2D() can be slow, an alternative implementation might
  648. * be use to draw a single clipped layer. The implementation described above
  649. * is correct in every case.
  650. *
  651. * (1) The frame buffer is actually not cleared right away. To allow the GPU
  652. * to potentially optimize series of calls to glCopyTexImage2D, the frame
  653. * buffer is left untouched until the first drawing operation. Only when
  654. * something actually gets drawn are the layers regions cleared.
  655. */
  656. bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
  657. int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo) {
  658. LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
  659. LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
  660. const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
  661. // Window coordinates of the layer
  662. Rect clip;
  663. Rect bounds(left, top, right, bottom);
  664. Rect untransformedBounds(bounds);
  665. mSnapshot->transform->mapRect(bounds);
  666. // Layers only make sense if they are in the framebuffer's bounds
  667. if (bounds.intersect(*mSnapshot->clipRect)) {
  668. // We cannot work with sub-pixels in this case
  669. bounds.snapToPixelBoundaries();
  670. // When the layer is not an FBO, we may use glCopyTexImage so we
  671. // need to make sure the layer does not extend outside the bounds
  672. // of the framebuffer
  673. if (!bounds.intersect(mSnapshot->previous->viewport)) {
  674. bounds.setEmpty();
  675. } else if (fboLayer) {
  676. clip.set(bounds);
  677. mat4 inverse;
  678. inverse.loadInverse(*mSnapshot->transform);
  679. inverse.mapRect(clip);
  680. clip.snapToPixelBoundaries();
  681. if (clip.intersect(untransformedBounds)) {
  682. clip.translate(-left, -top);
  683. bounds.set(untransformedBounds);
  684. } else {
  685. clip.setEmpty();
  686. }
  687. }
  688. } else {
  689. bounds.setEmpty();
  690. }
  691. if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
  692. bounds.getHeight() > mCaches.maxTextureSize ||
  693. (fboLayer && clip.isEmpty())) {
  694. mSnapshot->empty = fboLayer;
  695. } else {
  696. mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
  697. }
  698. // Bail out if we won't draw in this snapshot
  699. if (mSnapshot->invisible || mSnapshot->empty) {
  700. return false;
  701. }
  702. mCaches.activeTexture(0);
  703. Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight());
  704. if (!layer) {
  705. return false;
  706. }
  707. layer->setAlpha(alpha, mode);
  708. layer->layer.set(bounds);
  709. layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
  710. bounds.getWidth() / float(layer->getWidth()), 0.0f);
  711. layer->setColorFilter(mColorFilter);
  712. layer->setBlend(true);
  713. layer->setDirty(false);
  714. // Save the layer in the snapshot
  715. mSnapshot->flags |= Snapshot::kFlagIsLayer;
  716. mSnapshot->layer = layer;
  717. if (fboLayer) {
  718. return createFboLayer(layer, bounds, clip, previousFbo);
  719. } else {
  720. // Copy the framebuffer into the layer
  721. layer->bindTexture();
  722. if (!bounds.isEmpty()) {
  723. if (layer->isEmpty()) {
  724. glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
  725. bounds.left, mSnapshot->height - bounds.bottom,
  726. layer->getWidth(), layer->getHeight(), 0);
  727. layer->setEmpty(false);
  728. } else {
  729. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
  730. mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
  731. }
  732. // Enqueue the buffer coordinates to clear the corresponding region later
  733. mLayers.push(new Rect(bounds));
  734. }
  735. }
  736. return true;
  737. }
  738. bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo) {
  739. layer->setFbo(mCaches.fboCache.get());
  740. mSnapshot->region = &mSnapshot->layer->region;
  741. mSnapshot->flags |= Snapshot::kFlagFboTarget;
  742. mSnapshot->flags |= Snapshot::kFlagIsFboLayer;
  743. mSnapshot->fbo = layer->getFbo();
  744. mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
  745. mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
  746. mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
  747. mSnapshot->height = bounds.getHeight();
  748. mSnapshot->flags |= Snapshot::kFlagDirtyOrtho;
  749. mSnapshot->orthoMatrix.load(mOrthoMatrix);
  750. endTiling();
  751. debugOverdraw(false, false);
  752. // Bind texture to FBO
  753. glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
  754. layer->bindTexture();
  755. // Initialize the texture if needed
  756. if (layer->isEmpty()) {
  757. layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
  758. layer->setEmpty(false);
  759. }
  760. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
  761. layer->getTexture(), 0);
  762. startTiling(mSnapshot);
  763. // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
  764. mCaches.enableScissor();
  765. mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
  766. clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
  767. glClear(GL_COLOR_BUFFER_BIT);
  768. dirtyClip();
  769. // Change the ortho projection
  770. glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
  771. mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
  772. return true;
  773. }
  774. /**
  775. * Read the documentation of createLayer() before doing anything in this method.
  776. */
  777. void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
  778. if (!current->layer) {
  779. ALOGE("Attempting to compose a layer that does not exist");
  780. return;
  781. }
  782. const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
  783. if (fboLayer) {
  784. endTiling();
  785. // Detach the texture from the FBO
  786. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
  787. // Unbind current FBO and restore previous one
  788. glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
  789. debugOverdraw(true, false);
  790. startTiling(previous);
  791. }
  792. Layer* layer = current->layer;
  793. const Rect& rect = layer->layer;
  794. if (!fboLayer && layer->getAlpha() < 255) {
  795. drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
  796. layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true);
  797. // Required below, composeLayerRect() will divide by 255
  798. layer->setAlpha(255);
  799. }
  800. mCaches.unbindMeshBuffer();
  801. mCaches.activeTexture(0);
  802. // When the layer is stored in an FBO, we can save a bit of fillrate by
  803. // drawing only the dirty region
  804. if (fboLayer) {
  805. dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
  806. if (layer->getColorFilter()) {
  807. setupColorFilter(layer->getColorFilter());
  808. }
  809. composeLayerRegion(layer, rect);
  810. if (layer->getColorFilter()) {
  811. resetColorFilter();
  812. }
  813. } else if (!rect.isEmpty()) {
  814. dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
  815. composeLayerRect(layer, rect, true);
  816. }
  817. if (fboLayer) {
  818. // Note: No need to use glDiscardFramebufferEXT() since we never
  819. // create/compose layers that are not on screen with this
  820. // code path
  821. // See LayerRenderer::destroyLayer(Layer*)
  822. // Put the FBO name back in the cache, if it doesn't fit, it will be destroyed
  823. mCaches.fboCache.put(current->fbo);
  824. layer->setFbo(0);
  825. }
  826. dirtyClip();
  827. // Failing to add the layer to the cache should happen only if the layer is too large
  828. if (!mCaches.layerCache.put(layer)) {
  829. LAYER_LOGD("Deleting layer");
  830. Caches::getInstance().resourceCache.decrementRefcount(layer);
  831. }
  832. }
  833. void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
  834. float alpha = layer->getAlpha() / 255.0f;
  835. setupDraw();
  836. if (layer->getRenderTarget() == GL_TEXTURE_2D) {
  837. setupDrawWithTexture();
  838. } else {
  839. setupDrawWithExternalTexture();
  840. }
  841. setupDrawTextureTransform();
  842. setupDrawColor(alpha, alpha, alpha, alpha);
  843. setupDrawColorFilter();
  844. setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode());
  845. setupDrawProgram();
  846. setupDrawPureColorUniforms();
  847. setupDrawColorFilterUniforms();
  848. if (layer->getRenderTarget() == GL_TEXTURE_2D) {
  849. setupDrawTexture(layer->getTexture());
  850. } else {
  851. setupDrawExternalTexture(layer->getTexture());
  852. }
  853. if (mSnapshot->transform->isPureTranslate() &&
  854. layer->getWidth() == (uint32_t) rect.getWidth() &&
  855. layer->getHeight() == (uint32_t) rect.getHeight()) {
  856. const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
  857. const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
  858. layer->setFilter(GL_NEAREST);
  859. setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
  860. } else {
  861. layer->setFilter(GL_LINEAR);
  862. setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
  863. }
  864. setupDrawTextureTransformUniforms(layer->getTexTransform());
  865. setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
  866. glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
  867. finishDrawTexture();
  868. }
  869. void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
  870. if (!layer->isTextureLayer()) {
  871. const Rect& texCoords = layer->texCoords;
  872. resetDrawTextureTexCoords(texCoords.left, texCoords.top,
  873. texCoords.right, texCoords.bottom);
  874. float x = rect.left;
  875. float y = rect.top;
  876. bool simpleTransform = mSnapshot->transform->isPureTranslate() &&
  877. layer->getWidth() == (uint32_t) rect.getWidth() &&
  878. layer->getHeight() == (uint32_t) rect.getHeight();
  879. if (simpleTransform) {
  880. // When we're swapping, the layer is already in screen coordinates
  881. if (!swap) {
  882. x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
  883. y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
  884. }
  885. layer->setFilter(GL_NEAREST, true);
  886. } else {
  887. layer->setFilter(GL_LINEAR, true);
  888. }
  889. drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
  890. layer->getTexture(), layer->getAlpha() / 255.0f,
  891. layer->getMode(), layer->isBlend(),
  892. &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
  893. GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
  894. resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
  895. } else {
  896. resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
  897. drawTextureLayer(layer, rect);
  898. resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
  899. }
  900. }
  901. void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
  902. if (layer->region.isRect()) {
  903. layer->setRegionAsRect();
  904. composeLayerRect(layer, layer->regionRect);
  905. layer->region.clear();
  906. return;
  907. }
  908. // TODO: See LayerRenderer.cpp::generateMesh() for important
  909. // information about this implementation
  910. if (CC_LIKELY(!layer->region.isEmpty())) {
  911. size_t count;
  912. const android::Rect* rects = layer->region.getArray(&count);
  913. const float alpha = layer->getAlpha() / 255.0f;
  914. const float texX = 1.0f / float(layer->getWidth());
  915. const float texY = 1.0f / float(layer->getHeight());
  916. const float height = rect.getHeight();
  917. TextureVertex* mesh = mCaches.getRegionMesh();
  918. GLsizei numQuads = 0;
  919. setupDraw();
  920. setupDrawWithTexture();
  921. setupDrawColor(alpha, alpha, alpha, alpha);
  922. setupDrawColorFilter();
  923. setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false);
  924. setupDrawProgram();
  925. setupDrawDirtyRegionsDisabled();
  926. setupDrawPureColorUniforms();
  927. setupDrawColorFilterUniforms();
  928. setupDrawTexture(layer->getTexture());
  929. if (mSnapshot->transform->isPureTranslate()) {
  930. const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
  931. const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
  932. layer->setFilter(GL_NEAREST);
  933. setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
  934. } else {
  935. layer->setFilter(GL_LINEAR);
  936. setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
  937. }
  938. setupDrawMeshIndices(&mesh[0].position[0], &mesh[0].texture[0]);
  939. for (size_t i = 0; i < count; i++) {
  940. const android::Rect* r = &rects[i];
  941. const float u1 = r->left * texX;
  942. const float v1 = (height - r->top) * texY;
  943. const float u2 = r->right * texX;
  944. const float v2 = (height - r->bottom) * texY;
  945. // TODO: Reject quads outside of the clip
  946. TextureVertex::set(mesh++, r->left, r->top, u1, v1);
  947. TextureVertex::set(mesh++, r->right, r->top, u2, v1);
  948. TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
  949. TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
  950. numQuads++;
  951. if (numQuads >= REGION_MESH_QUAD_COUNT) {
  952. glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL);
  953. numQuads = 0;
  954. mesh = mCaches.getRegionMesh();
  955. }
  956. }
  957. if (numQuads > 0) {
  958. glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, NULL);
  959. }
  960. finishDrawTexture();
  961. #if DEBUG_LAYERS_AS_REGIONS
  962. drawRegionRects(layer->region);
  963. #endif
  964. layer->region.clear();
  965. }
  966. }
  967. void OpenGLRenderer::drawRegionRects(const Region& region) {
  968. #if DEBUG_LAYERS_AS_REGIONS
  969. size_t count;
  970. const android::Rect* rects = region.getArray(&count);
  971. uint32_t colors[] = {
  972. 0x7fff0000, 0x7f00ff00,
  973. 0x7f0000ff, 0x7fff00ff,
  974. };
  975. int offset = 0;
  976. int32_t top = rects[0].top;
  977. for (size_t i = 0; i < count; i++) {
  978. if (top != rects[i].top) {
  979. offset ^= 0x2;
  980. top = rects[i].top;
  981. }
  982. Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
  983. drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
  984. SkXfermode::kSrcOver_Mode);
  985. }
  986. #endif
  987. }
  988. void OpenGLRenderer::dirtyLayer(const float left, const float top,
  989. const float right, const float bottom, const mat4 transform) {
  990. if (hasLayer()) {
  991. Rect bounds(left, top, right, bottom);
  992. transform.mapRect(bounds);
  993. dirtyLayerUnchecked(bounds, getRegion());
  994. }
  995. }
  996. void OpenGLRenderer::dirtyLayer(const float left, const float top,
  997. const float right, const float bottom) {
  998. if (hasLayer()) {
  999. Rect bounds(left, top, right, bottom);
  1000. dirtyLayerUnchecked(bounds, getRegion());
  1001. }
  1002. }
  1003. void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
  1004. if (bounds.intersect(*mSnapshot->clipRect)) {
  1005. bounds.snapToPixelBoundaries();
  1006. android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
  1007. if (!dirty.isEmpty()) {
  1008. region->orSelf(dirty);
  1009. }
  1010. }
  1011. }
  1012. void OpenGLRenderer::clearLayerRegions() {
  1013. const size_t count = mLayers.size();
  1014. if (count == 0) return;
  1015. if (!mSnapshot->isIgnored()) {
  1016. // Doing several glScissor/glClear here can negatively impact
  1017. // GPUs with a tiler architecture, instead we draw quads with
  1018. // the Clear blending mode
  1019. // The list contains bounds that have already been clipped
  1020. // against their initial clip rect, and the current clip
  1021. // is likely different so we need to disable clipping here
  1022. bool scissorChanged = mCaches.disableScissor();
  1023. Vertex mesh[count * 6];
  1024. Vertex* vertex = mesh;
  1025. for (uint32_t i = 0; i < count; i++) {
  1026. Rect* bounds = mLayers.itemAt(i);
  1027. Vertex::set(vertex++, bounds->left, bounds->bottom);
  1028. Vertex::set(vertex++, bounds->left, bounds->top);
  1029. Vertex::set(vertex++, bounds->right, bounds->top);
  1030. Vertex::set(vertex++, bounds->left, bounds->bottom);
  1031. Vertex::set(vertex++, bounds->right, bounds->top);
  1032. Vertex::set(vertex++, bounds->right, bounds->bottom);
  1033. delete bounds;
  1034. }
  1035. setupDraw(false);
  1036. setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
  1037. setupDrawBlending(true, SkXfermode::kClear_Mode);
  1038. setupDrawProgram();
  1039. setupDrawPureColorUniforms();
  1040. setupDrawModelViewTranslate(0.0f, 0.0f, 0.0f, 0.0f, true);
  1041. setupDrawVertices(&mesh[0].position[0]);
  1042. glDrawArrays(GL_TRIANGLES, 0, count * 6);
  1043. if (scissorChanged) mCaches.enableScissor();
  1044. } else {
  1045. for (uint32_t i = 0; i < count; i++) {
  1046. delete mLayers.itemAt(i);
  1047. }
  1048. }
  1049. mLayers.clear();
  1050. }
  1051. ///////////////////////////////////////////////////////////////////////////////
  1052. // Transforms
  1053. ///////////////////////////////////////////////////////////////////////////////
  1054. void OpenGLRenderer::translate(float dx, float dy) {
  1055. mSnapshot->transform->translate(dx, dy, 0.0f);
  1056. }
  1057. void OpenGLRenderer::rotate(float degrees) {
  1058. mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
  1059. }
  1060. void OpenGLRenderer::scale(float sx, float sy) {
  1061. mSnapshot->transform->scale(sx, sy, 1.0f);
  1062. }
  1063. void OpenGLRenderer::skew(float sx, float sy) {
  1064. mSnapshot->transform->skew(sx, sy);
  1065. }
  1066. void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
  1067. if (matrix) {
  1068. mSnapshot->transform->load(*matrix);
  1069. } else {
  1070. mSnapshot->transform->loadIdentity();
  1071. }
  1072. }
  1073. void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
  1074. mSnapshot->transform->copyTo(*matrix);
  1075. }
  1076. void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
  1077. SkMatrix transform;
  1078. mSnapshot->transform->copyTo(transform);
  1079. transform.preConcat(*matrix);
  1080. mSnapshot->transform->load(transform);
  1081. }
  1082. ///////////////////////////////////////////////////////////////////////////////
  1083. // Clipping
  1084. ///////////////////////////////////////////////////////////////////////////////
  1085. void OpenGLRenderer::setScissorFromClip() {
  1086. Rect clip(*mSnapshot->clipRect);
  1087. clip.snapToPixelBoundaries();
  1088. if (mCaches.setScissor(clip.left, mSnapshot->height - clip.bottom,
  1089. clip.getWidth(), clip.getHeight())) {
  1090. mDirtyClip = false;
  1091. }
  1092. }
  1093. const Rect& OpenGLRenderer::getClipBounds() {
  1094. return mSnapshot->getLocalClip();
  1095. }
  1096. bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom) {
  1097. if (mSnapshot->isIgnored()) {
  1098. return true;
  1099. }
  1100. Rect r(left, top, right, bottom);
  1101. mSnapshot->transform->mapRect(r);
  1102. r.snapToPixelBoundaries();
  1103. Rect clipRect(*mSnapshot->clipRect);
  1104. clipRect.snapToPixelBoundaries();
  1105. return !clipRect.intersects(r);
  1106. }
  1107. bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
  1108. Rect& transformed, Rect& clip) {
  1109. if (mSnapshot->isIgnored()) {
  1110. return true;
  1111. }
  1112. transformed.set(left, top, right, bottom);
  1113. mSnapshot->transform->mapRect(transformed);
  1114. transformed.snapToPixelBoundaries();
  1115. clip.set(*mSnapshot->clipRect);
  1116. clip.snapToPixelBoundaries();
  1117. return !clip.intersects(transformed);
  1118. }
  1119. bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint) {
  1120. if (paint->getStyle() != SkPaint::kFill_Style) {
  1121. float outset = paint->getStrokeWidth() * 0.5f;
  1122. return quickReject(left - outset, top - outset, right + outset, bottom + outset);
  1123. } else {
  1124. return quickReject(left, top, right, bottom);
  1125. }
  1126. }
  1127. bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
  1128. if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
  1129. return true;
  1130. }
  1131. Rect r(left, top, right, bottom);
  1132. mSnapshot->transform->mapRect(r);
  1133. r.snapToPixelBoundaries();
  1134. Rect clipRect(*mSnapshot->clipRect);
  1135. clipRect.snapToPixelBoundaries();
  1136. bool rejected = !clipRect.intersects(r);
  1137. if (!isDeferred() && !rejected) {
  1138. mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clipRect.contains(r));
  1139. }
  1140. return rejected;
  1141. }
  1142. bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
  1143. bool clipped = mSnapshot->clip(left, top, right, bottom, op);
  1144. if (clipped) {
  1145. dirtyClip();
  1146. }
  1147. return !mSnapshot->clipRect->isEmpty();
  1148. }
  1149. Rect* OpenGLRenderer::getClipRect() {
  1150. return mSnapshot->clipRect;
  1151. }
  1152. ///////////////////////////////////////////////////////////////////////////////
  1153. // Drawing commands
  1154. ///////////////////////////////////////////////////////////////////////////////
  1155. void OpenGLRenderer::setupDraw(bool clear) {
  1156. // TODO: It would be best if we could do this before quickReject()
  1157. // changes the scissor test state
  1158. if (clear) clearLayerRegions();
  1159. if (mDirtyClip) {
  1160. setScissorFromClip();
  1161. }
  1162. mDescription.reset();
  1163. mSetShaderColor = false;
  1164. mColorSet = false;
  1165. mColorA = mColorR = mColorG = mColorB = 0.0f;
  1166. mTextureUnit = 0;
  1167. mTrackDirtyRegions = true;
  1168. }
  1169. void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
  1170. mDescription.hasTexture = true;
  1171. mDescription.hasAlpha8Texture = isAlpha8;
  1172. }
  1173. void OpenGLRenderer::setupDrawWithExternalTexture() {
  1174. mDescription.hasExternalTexture = true;
  1175. }
  1176. void OpenGLRenderer::setupDrawNoTexture() {
  1177. mCaches.disbaleTexCoordsVertexArray();
  1178. }
  1179. void OpenGLRenderer::setupDrawAA() {
  1180. mDescription.isAA = true;
  1181. }
  1182. void OpenGLRenderer::setupDrawVertexShape() {
  1183. mDescription.isVertexShape = true;
  1184. }
  1185. void OpenGLRenderer::setupDrawPoint(float pointSize) {
  1186. mDescription.isPoint = true;
  1187. mDescription.pointSize = pointSize;
  1188. }
  1189. void OpenGLRenderer::setupDrawColor(int color) {
  1190. setupDrawColor(color, (color >> 24) & 0xFF);
  1191. }
  1192. void OpenGLRenderer::setupDrawColor(int color, int alpha) {
  1193. mColorA = alpha / 255.0f;
  1194. // Second divide of a by 255 is an optimization, allowing us to simply multiply
  1195. // the rgb values by a instead of also dividing by 255
  1196. const float a = mColorA / 255.0f;
  1197. mColorR = a * ((color >> 16) & 0xFF);
  1198. mColorG = a * ((color >> 8) & 0xFF);
  1199. mColorB = a * ((color ) & 0xFF);
  1200. mColorSet = true;
  1201. mSetShaderColor = mDescription.setColor(mColorR, mColorG, mColorB, mColorA);
  1202. }
  1203. void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
  1204. mColorA = alpha / 255.0f;
  1205. // Double-divide of a by 255 is an optimization, allowing us to simply multiply
  1206. // the rgb values by a instead of also dividing by 255
  1207. const float a = mColorA / 255.0f;
  1208. mColorR = a * ((color >> 16) & 0xFF);
  1209. mColorG = a * ((color >> 8) & 0xFF);
  1210. mColorB = a * ((color ) & 0xFF);
  1211. mColorSet = true;
  1212. mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
  1213. }
  1214. void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
  1215. mCaches.fontRenderer->describe(mDescription, paint);
  1216. }
  1217. void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
  1218. mColorA = a;
  1219. mColorR = r;
  1220. mColorG = g;
  1221. mColorB = b;
  1222. mColorSet = true;
  1223. mSetShaderColor = mDescription.setColor(r, g, b, a);
  1224. }
  1225. void OpenGLRenderer::setupDrawShader() {
  1226. if (mShader) {
  1227. mShader->describe(mDescription, mCaches.extensions);
  1228. }
  1229. }
  1230. void OpenGLRenderer::setupDrawColorFilter() {
  1231. if (mColorFilter) {
  1232. mColorFilter->describe(mDescription, mCaches.extensions);
  1233. }
  1234. }
  1235. void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
  1236. if (mColorSet && mode == SkXfermode::kClear_Mode) {
  1237. mColorA = 1.0f;
  1238. mColorR = mColorG = mColorB = 0.0f;
  1239. mSetShaderColor = mDescription.modulate = true;
  1240. }
  1241. }
  1242. void OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) {
  1243. // When the blending mode is kClear_Mode, we need to use a modulate color
  1244. // argb=1,0,0,0
  1245. accountForClear(mode);
  1246. chooseBlending((mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
  1247. mDescription, swapSrcDst);
  1248. }
  1249. void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) {
  1250. // When the blending mode is kClear_Mode, we need to use a modulate color
  1251. // argb=1,0,0,0
  1252. accountForClear(mode);
  1253. chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()) ||
  1254. (mColorFilter && mColorFilter->blend()), mode, mDescription, swapSrcDst);
  1255. }
  1256. void OpenGLRenderer::setupDrawP