PageRenderTime 30ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/hwui/OpenGLRenderer.cpp

https://gitlab.com/AvayKumar/android_frameworks_base
C++ | 1400 lines | 957 code | 233 blank | 210 comment | 160 complexity | 447763f97167f7b018135ce01fd768e1 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 <SkColor.h>
  22. #include <SkShader.h>
  23. #include <SkTypeface.h>
  24. #include <utils/Log.h>
  25. #include <utils/StopWatch.h>
  26. #include <private/hwui/DrawGlInfo.h>
  27. #include <ui/Rect.h>
  28. #include "OpenGLRenderer.h"
  29. #include "DeferredDisplayList.h"
  30. #include "DisplayListRenderer.h"
  31. #include "Fence.h"
  32. #include "RenderState.h"
  33. #include "PathTessellator.h"
  34. #include "Properties.h"
  35. #include "ShadowTessellator.h"
  36. #include "SkiaShader.h"
  37. #include "utils/GLUtils.h"
  38. #include "utils/TraceUtils.h"
  39. #include "Vector.h"
  40. #include "VertexBuffer.h"
  41. #if DEBUG_DETAILED_EVENTS
  42. #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
  43. #else
  44. #define EVENT_LOGD(...)
  45. #endif
  46. namespace android {
  47. namespace uirenderer {
  48. static GLenum getFilter(const SkPaint* paint) {
  49. if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
  50. return GL_LINEAR;
  51. }
  52. return GL_NEAREST;
  53. }
  54. ///////////////////////////////////////////////////////////////////////////////
  55. // Globals
  56. ///////////////////////////////////////////////////////////////////////////////
  57. /**
  58. * Structure mapping Skia xfermodes to OpenGL blending factors.
  59. */
  60. struct Blender {
  61. SkXfermode::Mode mode;
  62. GLenum src;
  63. GLenum dst;
  64. }; // struct Blender
  65. // In this array, the index of each Blender equals the value of the first
  66. // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
  67. static const Blender gBlends[] = {
  68. { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  69. { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
  70. { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
  71. { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
  72. { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
  73. { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
  74. { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
  75. { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  76. { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  77. { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  78. { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
  79. { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  80. { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
  81. { SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
  82. { SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
  83. };
  84. // This array contains the swapped version of each SkXfermode. For instance
  85. // this array's SrcOver blending mode is actually DstOver. You can refer to
  86. // createLayer() for more information on the purpose of this array.
  87. static const Blender gBlendsSwap[] = {
  88. { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  89. { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
  90. { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
  91. { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
  92. { SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
  93. { SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
  94. { SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
  95. { SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
  96. { SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
  97. { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
  98. { SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  99. { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
  100. { SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
  101. { SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
  102. { SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
  103. };
  104. ///////////////////////////////////////////////////////////////////////////////
  105. // Functions
  106. ///////////////////////////////////////////////////////////////////////////////
  107. template<typename T>
  108. static inline T min(T a, T b) {
  109. return a < b ? a : b;
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////
  112. // Constructors/destructor
  113. ///////////////////////////////////////////////////////////////////////////////
  114. OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
  115. : mFrameStarted(false)
  116. , mCaches(Caches::getInstance())
  117. , mExtensions(Extensions::getInstance())
  118. , mRenderState(renderState)
  119. , mScissorOptimizationDisabled(false)
  120. , mSuppressTiling(false)
  121. , mFirstFrameAfterResize(true)
  122. , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN})
  123. , mLightRadius(FLT_MIN)
  124. , mAmbientShadowAlpha(0)
  125. , mSpotShadowAlpha(0) {
  126. // *set* draw modifiers to be 0
  127. memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
  128. mDrawModifiers.mOverrideLayerAlpha = 1.0f;
  129. memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
  130. }
  131. OpenGLRenderer::~OpenGLRenderer() {
  132. // The context has already been destroyed at this point, do not call
  133. // GL APIs. All GL state should be kept in Caches.h
  134. }
  135. void OpenGLRenderer::initProperties() {
  136. char property[PROPERTY_VALUE_MAX];
  137. if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
  138. mScissorOptimizationDisabled = !strcasecmp(property, "true");
  139. INIT_LOGD(" Scissor optimization %s",
  140. mScissorOptimizationDisabled ? "disabled" : "enabled");
  141. } else {
  142. INIT_LOGD(" Scissor optimization enabled");
  143. }
  144. }
  145. void OpenGLRenderer::initLight(const Vector3& lightCenter, float lightRadius,
  146. uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
  147. mLightCenter = lightCenter;
  148. mLightRadius = lightRadius;
  149. mAmbientShadowAlpha = ambientShadowAlpha;
  150. mSpotShadowAlpha = spotShadowAlpha;
  151. }
  152. ///////////////////////////////////////////////////////////////////////////////
  153. // Setup
  154. ///////////////////////////////////////////////////////////////////////////////
  155. void OpenGLRenderer::onViewportInitialized() {
  156. glDisable(GL_DITHER);
  157. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  158. glEnableVertexAttribArray(Program::kBindingPosition);
  159. mFirstFrameAfterResize = true;
  160. }
  161. void OpenGLRenderer::setupFrameState(float left, float top,
  162. float right, float bottom, bool opaque) {
  163. mCaches.clearGarbage();
  164. initializeSaveStack(left, top, right, bottom, mLightCenter);
  165. mOpaque = opaque;
  166. mTilingClip.set(left, top, right, bottom);
  167. }
  168. status_t OpenGLRenderer::startFrame() {
  169. if (mFrameStarted) return DrawGlInfo::kStatusDone;
  170. mFrameStarted = true;
  171. mDirtyClip = true;
  172. discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
  173. mRenderState.setViewport(getWidth(), getHeight());
  174. // Functors break the tiling extension in pretty spectacular ways
  175. // This ensures we don't use tiling when a functor is going to be
  176. // invoked during the frame
  177. mSuppressTiling = mCaches.hasRegisteredFunctors()
  178. || mFirstFrameAfterResize;
  179. mFirstFrameAfterResize = false;
  180. startTilingCurrentClip(true);
  181. debugOverdraw(true, true);
  182. return clear(mTilingClip.left, mTilingClip.top,
  183. mTilingClip.right, mTilingClip.bottom, mOpaque);
  184. }
  185. status_t OpenGLRenderer::prepareDirty(float left, float top,
  186. float right, float bottom, bool opaque) {
  187. setupFrameState(left, top, right, bottom, opaque);
  188. // Layer renderers will start the frame immediately
  189. // The framebuffer renderer will first defer the display list
  190. // for each layer and wait until the first drawing command
  191. // to start the frame
  192. if (currentSnapshot()->fbo == 0) {
  193. syncState();
  194. updateLayers();
  195. } else {
  196. return startFrame();
  197. }
  198. return DrawGlInfo::kStatusDone;
  199. }
  200. void OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
  201. // If we know that we are going to redraw the entire framebuffer,
  202. // perform a discard to let the driver know we don't need to preserve
  203. // the back buffer for this frame.
  204. if (mExtensions.hasDiscardFramebuffer() &&
  205. left <= 0.0f && top <= 0.0f && right >= getWidth() && bottom >= getHeight()) {
  206. const bool isFbo = getTargetFbo() == 0;
  207. const GLenum attachments[] = {
  208. isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
  209. isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
  210. glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
  211. }
  212. }
  213. status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
  214. #ifdef QCOM_HARDWARE
  215. mCaches.enableScissor();
  216. mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top);
  217. glClear(GL_COLOR_BUFFER_BIT);
  218. if (opaque) {
  219. mCaches.resetScissor();
  220. return DrawGlInfo::kStatusDone;
  221. }
  222. #else
  223. if (!opaque) {
  224. mCaches.enableScissor();
  225. mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top);
  226. glClear(GL_COLOR_BUFFER_BIT);
  227. return DrawGlInfo::kStatusDrew;
  228. }
  229. #endif
  230. return DrawGlInfo::kStatusDrew;
  231. }
  232. void OpenGLRenderer::syncState() {
  233. if (mCaches.blend) {
  234. glEnable(GL_BLEND);
  235. } else {
  236. glDisable(GL_BLEND);
  237. }
  238. }
  239. void OpenGLRenderer::startTilingCurrentClip(bool opaque, bool expand) {
  240. if (!mSuppressTiling) {
  241. const Snapshot* snapshot = currentSnapshot();
  242. const Rect* clip = &mTilingClip;
  243. if (snapshot->flags & Snapshot::kFlagFboTarget) {
  244. clip = &(snapshot->layer->clipRect);
  245. }
  246. startTiling(*clip, getViewportHeight(), opaque, expand);
  247. }
  248. }
  249. void OpenGLRenderer::startTiling(const Rect& clip, int windowHeight, bool opaque, bool expand) {
  250. if (!mSuppressTiling) {
  251. if(expand) {
  252. // Expand the startTiling region by 1
  253. int leftNotZero = (clip.left > 0) ? 1 : 0;
  254. int topNotZero = (windowHeight - clip.bottom > 0) ? 1 : 0;
  255. mCaches.startTiling(
  256. clip.left - leftNotZero,
  257. windowHeight - clip.bottom - topNotZero,
  258. clip.right - clip.left + leftNotZero + 1,
  259. clip.bottom - clip.top + topNotZero + 1,
  260. opaque);
  261. } else {
  262. mCaches.startTiling(clip.left, windowHeight - clip.bottom,
  263. clip.right - clip.left, clip.bottom - clip.top, opaque);
  264. }
  265. }
  266. }
  267. void OpenGLRenderer::endTiling() {
  268. if (!mSuppressTiling) mCaches.endTiling();
  269. }
  270. void OpenGLRenderer::finish() {
  271. renderOverdraw();
  272. endTiling();
  273. for (size_t i = 0; i < mTempPaths.size(); i++) {
  274. delete mTempPaths[i];
  275. }
  276. mTempPaths.clear();
  277. // When finish() is invoked on FBO 0 we've reached the end
  278. // of the current frame
  279. if (getTargetFbo() == 0) {
  280. mCaches.pathCache.trim();
  281. mCaches.tessellationCache.trim();
  282. }
  283. if (!suppressErrorChecks()) {
  284. #if DEBUG_OPENGL
  285. GLUtils::dumpGLErrors();
  286. #endif
  287. #if DEBUG_MEMORY_USAGE
  288. mCaches.dumpMemoryUsage();
  289. #else
  290. if (mCaches.getDebugLevel() & kDebugMemory) {
  291. mCaches.dumpMemoryUsage();
  292. }
  293. #endif
  294. }
  295. mFrameStarted = false;
  296. }
  297. void OpenGLRenderer::resumeAfterLayer() {
  298. mRenderState.setViewport(getViewportWidth(), getViewportHeight());
  299. mRenderState.bindFramebuffer(currentSnapshot()->fbo);
  300. debugOverdraw(true, false);
  301. mCaches.resetScissor();
  302. dirtyClip();
  303. }
  304. status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
  305. if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
  306. Rect clip(*currentClipRect());
  307. clip.snapToPixelBoundaries();
  308. // Since we don't know what the functor will draw, let's dirty
  309. // the entire clip region
  310. if (hasLayer()) {
  311. dirtyLayerUnchecked(clip, getRegion());
  312. }
  313. DrawGlInfo info;
  314. info.clipLeft = clip.left;
  315. info.clipTop = clip.top;
  316. info.clipRight = clip.right;
  317. info.clipBottom = clip.bottom;
  318. info.isLayer = hasLayer();
  319. info.width = getViewportWidth();
  320. info.height = getViewportHeight();
  321. currentTransform()->copyTo(&info.transform[0]);
  322. bool prevDirtyClip = mDirtyClip;
  323. // setup GL state for functor
  324. if (mDirtyClip) {
  325. setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
  326. }
  327. if (mCaches.enableScissor() || prevDirtyClip) {
  328. setScissorFromClip();
  329. }
  330. mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
  331. // Scissor may have been modified, reset dirty clip
  332. dirtyClip();
  333. return DrawGlInfo::kStatusDrew;
  334. }
  335. ///////////////////////////////////////////////////////////////////////////////
  336. // Debug
  337. ///////////////////////////////////////////////////////////////////////////////
  338. void OpenGLRenderer::eventMarkDEBUG(const char* fmt, ...) const {
  339. #if DEBUG_DETAILED_EVENTS
  340. const int BUFFER_SIZE = 256;
  341. va_list ap;
  342. char buf[BUFFER_SIZE];
  343. va_start(ap, fmt);
  344. vsnprintf(buf, BUFFER_SIZE, fmt, ap);
  345. va_end(ap);
  346. eventMark(buf);
  347. #endif
  348. }
  349. void OpenGLRenderer::eventMark(const char* name) const {
  350. mCaches.eventMark(0, name);
  351. }
  352. void OpenGLRenderer::startMark(const char* name) const {
  353. mCaches.startMark(0, name);
  354. }
  355. void OpenGLRenderer::endMark() const {
  356. mCaches.endMark();
  357. }
  358. void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
  359. mRenderState.debugOverdraw(enable, clear);
  360. }
  361. void OpenGLRenderer::renderOverdraw() {
  362. if (mCaches.debugOverdraw && getTargetFbo() == 0) {
  363. const Rect* clip = &mTilingClip;
  364. mCaches.enableScissor();
  365. mCaches.setScissor(clip->left, firstSnapshot()->getViewportHeight() - clip->bottom,
  366. clip->right - clip->left, clip->bottom - clip->top);
  367. // 1x overdraw
  368. mCaches.stencil.enableDebugTest(2);
  369. drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
  370. // 2x overdraw
  371. mCaches.stencil.enableDebugTest(3);
  372. drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
  373. // 3x overdraw
  374. mCaches.stencil.enableDebugTest(4);
  375. drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
  376. // 4x overdraw and higher
  377. mCaches.stencil.enableDebugTest(4, true);
  378. drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
  379. mCaches.stencil.disable();
  380. }
  381. }
  382. ///////////////////////////////////////////////////////////////////////////////
  383. // Layers
  384. ///////////////////////////////////////////////////////////////////////////////
  385. bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
  386. if (layer->deferredUpdateScheduled && layer->renderer
  387. && layer->renderNode.get() && layer->renderNode->isRenderable()) {
  388. Rect& dirty = layer->dirtyRect;
  389. if (inFrame) {
  390. endTiling();
  391. debugOverdraw(false, false);
  392. }
  393. if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
  394. layer->render(*this);
  395. } else {
  396. layer->defer(*this);
  397. }
  398. if (inFrame) {
  399. resumeAfterLayer();
  400. startTilingCurrentClip();
  401. }
  402. layer->debugDrawUpdate = mCaches.debugLayersUpdates;
  403. layer->hasDrawnSinceUpdate = false;
  404. return true;
  405. }
  406. return false;
  407. }
  408. void OpenGLRenderer::updateLayers() {
  409. // If draw deferring is enabled this method will simply defer
  410. // the display list of each individual layer. The layers remain
  411. // in the layer updates list which will be cleared by flushLayers().
  412. int count = mLayerUpdates.size();
  413. if (count > 0) {
  414. if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
  415. startMark("Layer Updates");
  416. } else {
  417. startMark("Defer Layer Updates");
  418. }
  419. // Note: it is very important to update the layers in order
  420. for (int i = 0; i < count; i++) {
  421. Layer* layer = mLayerUpdates.itemAt(i).get();
  422. updateLayer(layer, false);
  423. }
  424. if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
  425. mLayerUpdates.clear();
  426. mRenderState.bindFramebuffer(getTargetFbo());
  427. }
  428. endMark();
  429. }
  430. }
  431. void OpenGLRenderer::flushLayers() {
  432. int count = mLayerUpdates.size();
  433. if (count > 0) {
  434. startMark("Apply Layer Updates");
  435. // Note: it is very important to update the layers in order
  436. for (int i = 0; i < count; i++) {
  437. mLayerUpdates.itemAt(i)->flush();
  438. }
  439. mLayerUpdates.clear();
  440. mRenderState.bindFramebuffer(getTargetFbo());
  441. endMark();
  442. }
  443. }
  444. void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
  445. if (layer) {
  446. // Make sure we don't introduce duplicates.
  447. // SortedVector would do this automatically but we need to respect
  448. // the insertion order. The linear search is not an issue since
  449. // this list is usually very short (typically one item, at most a few)
  450. for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
  451. if (mLayerUpdates.itemAt(i) == layer) {
  452. return;
  453. }
  454. }
  455. mLayerUpdates.push_back(layer);
  456. }
  457. }
  458. void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
  459. if (layer) {
  460. for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
  461. if (mLayerUpdates.itemAt(i) == layer) {
  462. mLayerUpdates.removeAt(i);
  463. break;
  464. }
  465. }
  466. }
  467. }
  468. void OpenGLRenderer::flushLayerUpdates() {
  469. ATRACE_NAME("Update HW Layers");
  470. syncState();
  471. updateLayers();
  472. flushLayers();
  473. // Wait for all the layer updates to be executed
  474. AutoFence fence;
  475. }
  476. void OpenGLRenderer::markLayersAsBuildLayers() {
  477. for (size_t i = 0; i < mLayerUpdates.size(); i++) {
  478. mLayerUpdates[i]->wasBuildLayered = true;
  479. }
  480. }
  481. ///////////////////////////////////////////////////////////////////////////////
  482. // State management
  483. ///////////////////////////////////////////////////////////////////////////////
  484. void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
  485. bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer;
  486. bool restoreClip = removed.flags & Snapshot::kFlagClipSet;
  487. bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
  488. if (restoreViewport) {
  489. mRenderState.setViewport(getViewportWidth(), getViewportHeight());
  490. }
  491. if (restoreClip) {
  492. dirtyClip();
  493. }
  494. if (restoreLayer) {
  495. endMark(); // Savelayer
  496. ATRACE_END(); // SaveLayer
  497. startMark("ComposeLayer");
  498. composeLayer(removed, restored);
  499. endMark();
  500. }
  501. }
  502. ///////////////////////////////////////////////////////////////////////////////
  503. // Layers
  504. ///////////////////////////////////////////////////////////////////////////////
  505. int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
  506. const SkPaint* paint, int flags, const SkPath* convexMask) {
  507. // force matrix/clip isolation for layer
  508. flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
  509. const int count = saveSnapshot(flags);
  510. if (!currentSnapshot()->isIgnored()) {
  511. createLayer(left, top, right, bottom, paint, flags, convexMask);
  512. }
  513. return count;
  514. }
  515. void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
  516. const Rect untransformedBounds(bounds);
  517. currentTransform()->mapRect(bounds);
  518. // Layers only make sense if they are in the framebuffer's bounds
  519. if (bounds.intersect(*currentClipRect())) {
  520. // We cannot work with sub-pixels in this case
  521. bounds.snapToPixelBoundaries();
  522. // When the layer is not an FBO, we may use glCopyTexImage so we
  523. // need to make sure the layer does not extend outside the bounds
  524. // of the framebuffer
  525. const Snapshot& previous = *(currentSnapshot()->previous);
  526. Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
  527. if (!bounds.intersect(previousViewport)) {
  528. bounds.setEmpty();
  529. } else if (fboLayer) {
  530. clip.set(bounds);
  531. mat4 inverse;
  532. inverse.loadInverse(*currentTransform());
  533. inverse.mapRect(clip);
  534. clip.snapToPixelBoundaries();
  535. if (clip.intersect(untransformedBounds)) {
  536. clip.translate(-untransformedBounds.left, -untransformedBounds.top);
  537. bounds.set(untransformedBounds);
  538. } else {
  539. clip.setEmpty();
  540. }
  541. }
  542. } else {
  543. bounds.setEmpty();
  544. }
  545. }
  546. void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
  547. bool fboLayer, int alpha) {
  548. if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
  549. bounds.getHeight() > mCaches.maxTextureSize ||
  550. (fboLayer && clip.isEmpty())) {
  551. mSnapshot->empty = fboLayer;
  552. } else {
  553. mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer);
  554. }
  555. }
  556. int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
  557. const SkPaint* paint, int flags) {
  558. const int count = saveSnapshot(flags);
  559. if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
  560. // initialize the snapshot as though it almost represents an FBO layer so deferred draw
  561. // operations will be able to store and restore the current clip and transform info, and
  562. // quick rejection will be correct (for display lists)
  563. Rect bounds(left, top, right, bottom);
  564. Rect clip;
  565. calculateLayerBoundsAndClip(bounds, clip, true);
  566. updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
  567. if (!currentSnapshot()->isIgnored()) {
  568. mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
  569. mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
  570. mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight());
  571. mSnapshot->roundRectClipState = NULL;
  572. }
  573. }
  574. return count;
  575. }
  576. /**
  577. * Layers are viewed by Skia are slightly different than layers in image editing
  578. * programs (for instance.) When a layer is created, previously created layers
  579. * and the frame buffer still receive every drawing command. For instance, if a
  580. * layer is created and a shape intersecting the bounds of the layers and the
  581. * framebuffer is draw, the shape will be drawn on both (unless the layer was
  582. * created with the SkCanvas::kClipToLayer_SaveFlag flag.)
  583. *
  584. * A way to implement layers is to create an FBO for each layer, backed by an RGBA
  585. * texture. Unfortunately, this is inefficient as it requires every primitive to
  586. * be drawn n + 1 times, where n is the number of active layers. In practice this
  587. * means, for every primitive:
  588. * - Switch active frame buffer
  589. * - Change viewport, clip and projection matrix
  590. * - Issue the drawing
  591. *
  592. * Switching rendering target n + 1 times per drawn primitive is extremely costly.
  593. * To avoid this, layers are implemented in a different way here, at least in the
  594. * general case. FBOs are used, as an optimization, when the "clip to layer" flag
  595. * is set. When this flag is set we can redirect all drawing operations into a
  596. * single FBO.
  597. *
  598. * This implementation relies on the frame buffer being at least RGBA 8888. When
  599. * a layer is created, only a texture is created, not an FBO. The content of the
  600. * frame buffer contained within the layer's bounds is copied into this texture
  601. * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
  602. * buffer and drawing continues as normal. This technique therefore treats the
  603. * frame buffer as a scratch buffer for the layers.
  604. *
  605. * To compose the layers back onto the frame buffer, each layer texture
  606. * (containing the original frame buffer data) is drawn as a simple quad over
  607. * the frame buffer. The trick is that the quad is set as the composition
  608. * destination in the blending equation, and the frame buffer becomes the source
  609. * of the composition.
  610. *
  611. * Drawing layers with an alpha value requires an extra step before composition.
  612. * An empty quad is drawn over the layer's region in the frame buffer. This quad
  613. * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
  614. * quad is used to multiply the colors in the frame buffer. This is achieved by
  615. * changing the GL blend functions for the GL_FUNC_ADD blend equation to
  616. * GL_ZERO, GL_SRC_ALPHA.
  617. *
  618. * Because glCopyTexImage2D() can be slow, an alternative implementation might
  619. * be use to draw a single clipped layer. The implementation described above
  620. * is correct in every case.
  621. *
  622. * (1) The frame buffer is actually not cleared right away. To allow the GPU
  623. * to potentially optimize series of calls to glCopyTexImage2D, the frame
  624. * buffer is left untouched until the first drawing operation. Only when
  625. * something actually gets drawn are the layers regions cleared.
  626. */
  627. bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
  628. const SkPaint* paint, int flags, const SkPath* convexMask) {
  629. LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
  630. LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
  631. const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
  632. // Window coordinates of the layer
  633. Rect clip;
  634. Rect bounds(left, top, right, bottom);
  635. calculateLayerBoundsAndClip(bounds, clip, fboLayer);
  636. updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint));
  637. // Bail out if we won't draw in this snapshot
  638. if (currentSnapshot()->isIgnored()) {
  639. return false;
  640. }
  641. mCaches.activeTexture(0);
  642. Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
  643. if (!layer) {
  644. return false;
  645. }
  646. layer->setPaint(paint);
  647. layer->layer.set(bounds);
  648. layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
  649. bounds.getWidth() / float(layer->getWidth()), 0.0f);
  650. layer->setBlend(true);
  651. layer->setDirty(false);
  652. layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
  653. // Save the layer in the snapshot
  654. mSnapshot->flags |= Snapshot::kFlagIsLayer;
  655. mSnapshot->layer = layer;
  656. ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u",
  657. fboLayer ? "" : "unclipped ",
  658. layer->getWidth(), layer->getHeight());
  659. startMark("SaveLayer");
  660. if (fboLayer) {
  661. return createFboLayer(layer, bounds, clip);
  662. } else {
  663. // Copy the framebuffer into the layer
  664. layer->bindTexture();
  665. if (!bounds.isEmpty()) {
  666. if (layer->isEmpty()) {
  667. // Workaround for some GL drivers. When reading pixels lying outside
  668. // of the window we should get undefined values for those pixels.
  669. // Unfortunately some drivers will turn the entire target texture black
  670. // when reading outside of the window.
  671. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->getWidth(), layer->getHeight(),
  672. 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  673. layer->setEmpty(false);
  674. }
  675. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
  676. bounds.left, getViewportHeight() - bounds.bottom,
  677. bounds.getWidth(), bounds.getHeight());
  678. // Enqueue the buffer coordinates to clear the corresponding region later
  679. mLayers.push(new Rect(bounds));
  680. }
  681. }
  682. return true;
  683. }
  684. bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
  685. layer->clipRect.set(clip);
  686. layer->setFbo(mCaches.fboCache.get());
  687. mSnapshot->region = &mSnapshot->layer->region;
  688. mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
  689. mSnapshot->fbo = layer->getFbo();
  690. mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
  691. mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
  692. mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight());
  693. mSnapshot->roundRectClipState = NULL;
  694. endTiling();
  695. debugOverdraw(false, false);
  696. // Bind texture to FBO
  697. mRenderState.bindFramebuffer(layer->getFbo());
  698. layer->bindTexture();
  699. // Initialize the texture if needed
  700. if (layer->isEmpty()) {
  701. layer->allocateTexture();
  702. layer->setEmpty(false);
  703. }
  704. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
  705. layer->getTexture(), 0);
  706. // Expand the startTiling region by 1
  707. startTilingCurrentClip(true, true);
  708. // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
  709. mCaches.enableScissor();
  710. mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
  711. clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
  712. glClear(GL_COLOR_BUFFER_BIT);
  713. dirtyClip();
  714. // Change the ortho projection
  715. mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
  716. return true;
  717. }
  718. /**
  719. * Read the documentation of createLayer() before doing anything in this method.
  720. */
  721. void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& restored) {
  722. if (!removed.layer) {
  723. ALOGE("Attempting to compose a layer that does not exist");
  724. return;
  725. }
  726. Layer* layer = removed.layer;
  727. const Rect& rect = layer->layer;
  728. const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer;
  729. bool clipRequired = false;
  730. calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
  731. &clipRequired, NULL, false); // safely ignore return, should never be rejected
  732. mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
  733. if (fboLayer) {
  734. endTiling();
  735. // Detach the texture from the FBO
  736. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
  737. layer->removeFbo(false);
  738. // Unbind current FBO and restore previous one
  739. mRenderState.bindFramebuffer(restored.fbo);
  740. debugOverdraw(true, false);
  741. startTilingCurrentClip();
  742. }
  743. if (!fboLayer && layer->getAlpha() < 255) {
  744. SkPaint layerPaint;
  745. layerPaint.setAlpha(layer->getAlpha());
  746. layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
  747. layerPaint.setColorFilter(layer->getColorFilter());
  748. drawColorRect(rect.left, rect.top, rect.right, rect.bottom, &layerPaint, true);
  749. // Required below, composeLayerRect() will divide by 255
  750. layer->setAlpha(255);
  751. }
  752. mCaches.unbindMeshBuffer();
  753. mCaches.activeTexture(0);
  754. // When the layer is stored in an FBO, we can save a bit of fillrate by
  755. // drawing only the dirty region
  756. if (fboLayer) {
  757. dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *restored.transform);
  758. composeLayerRegion(layer, rect);
  759. } else if (!rect.isEmpty()) {
  760. dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
  761. save(0);
  762. // the layer contains screen buffer content that shouldn't be alpha modulated
  763. // (and any necessary alpha modulation was handled drawing into the layer)
  764. mSnapshot->alpha = 1.0f;
  765. composeLayerRect(layer, rect, true);
  766. restore();
  767. }
  768. dirtyClip();
  769. // Failing to add the layer to the cache should happen only if the layer is too large
  770. layer->setConvexMask(NULL);
  771. if (!mCaches.layerCache.put(layer)) {
  772. LAYER_LOGD("Deleting layer");
  773. layer->decStrong(0);
  774. }
  775. }
  776. void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
  777. float alpha = getLayerAlpha(layer);
  778. setupDraw();
  779. if (layer->getRenderTarget() == GL_TEXTURE_2D) {
  780. setupDrawWithTexture();
  781. } else {
  782. setupDrawWithExternalTexture();
  783. }
  784. setupDrawTextureTransform();
  785. setupDrawColor(alpha, alpha, alpha, alpha);
  786. setupDrawColorFilter(layer->getColorFilter());
  787. setupDrawBlending(layer);
  788. setupDrawProgram();
  789. setupDrawPureColorUniforms();
  790. setupDrawColorFilterUniforms(layer->getColorFilter());
  791. if (layer->getRenderTarget() == GL_TEXTURE_2D) {
  792. setupDrawTexture(layer->getTexture());
  793. } else {
  794. setupDrawExternalTexture(layer->getTexture());
  795. }
  796. if (currentTransform()->isPureTranslate() &&
  797. !layer->getForceFilter() &&
  798. layer->getWidth() == (uint32_t) rect.getWidth() &&
  799. layer->getHeight() == (uint32_t) rect.getHeight()) {
  800. const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
  801. const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
  802. layer->setFilter(GL_NEAREST);
  803. setupDrawModelView(kModelViewMode_TranslateAndScale, false,
  804. x, y, x + rect.getWidth(), y + rect.getHeight(), true);
  805. } else {
  806. layer->setFilter(GL_LINEAR);
  807. setupDrawModelView(kModelViewMode_TranslateAndScale, false,
  808. rect.left, rect.top, rect.right, rect.bottom);
  809. }
  810. setupDrawTextureTransformUniforms(layer->getTexTransform());
  811. setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
  812. glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
  813. }
  814. void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
  815. if (layer->isTextureLayer()) {
  816. EVENT_LOGD("composeTextureLayerRect");
  817. resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
  818. drawTextureLayer(layer, rect);
  819. resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
  820. } else {
  821. EVENT_LOGD("composeHardwareLayerRect");
  822. const Rect& texCoords = layer->texCoords;
  823. resetDrawTextureTexCoords(texCoords.left, texCoords.top,
  824. texCoords.right, texCoords.bottom);
  825. float x = rect.left;
  826. float y = rect.top;
  827. bool simpleTransform = currentTransform()->isPureTranslate() &&
  828. layer->getWidth() == (uint32_t) rect.getWidth() &&
  829. layer->getHeight() == (uint32_t) rect.getHeight();
  830. if (simpleTransform) {
  831. // When we're swapping, the layer is already in screen coordinates
  832. if (!swap) {
  833. x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
  834. y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
  835. }
  836. layer->setFilter(GL_NEAREST, true);
  837. } else {
  838. layer->setFilter(GL_LINEAR, true);
  839. }
  840. SkPaint layerPaint;
  841. layerPaint.setAlpha(getLayerAlpha(layer) * 255);
  842. layerPaint.setXfermodeMode(layer->getMode());
  843. layerPaint.setColorFilter(layer->getColorFilter());
  844. bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f;
  845. drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
  846. layer->getTexture(), &layerPaint, blend,
  847. &mMeshVertices[0].x, &mMeshVertices[0].u,
  848. GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
  849. resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
  850. }
  851. }
  852. /**
  853. * Issues the command X, and if we're composing a save layer to the fbo or drawing a newly updated
  854. * hardware layer with overdraw debug on, draws again to the stencil only, so that these draw
  855. * operations are correctly counted twice for overdraw. NOTE: assumes composeLayerRegion only used
  856. * by saveLayer's restore
  857. */
  858. #define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \
  859. DRAW_COMMAND; \
  860. if (CC_UNLIKELY(mCaches.debugOverdraw && getTargetFbo() == 0 && COND)) { \
  861. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
  862. DRAW_COMMAND; \
  863. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
  864. } \
  865. }
  866. #define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
  867. // This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
  868. // use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
  869. class LayerShader : public SkShader {
  870. public:
  871. LayerShader(Layer* layer, const SkMatrix* localMatrix)
  872. : INHERITED(localMatrix)
  873. , mLayer(layer) {
  874. }
  875. virtual bool asACustomShader(void** data) const {
  876. if (data) {
  877. *data = static_cast<void*>(mLayer);
  878. }
  879. return true;
  880. }
  881. virtual bool isOpaque() const {
  882. return !mLayer->isBlend();
  883. }
  884. protected:
  885. virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
  886. LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
  887. }
  888. virtual void flatten(SkWriteBuffer&) const {
  889. LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
  890. }
  891. virtual Factory getFactory() const {
  892. LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
  893. return NULL;
  894. }
  895. private:
  896. // Unowned.
  897. Layer* mLayer;
  898. typedef SkShader INHERITED;
  899. };
  900. void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
  901. if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
  902. if (layer->getConvexMask()) {
  903. save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
  904. // clip to the area of the layer the mask can be larger
  905. clipRect(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kIntersect_Op);
  906. SkPaint paint;
  907. paint.setAntiAlias(true);
  908. paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
  909. // create LayerShader to map SaveLayer content into subsequent draw
  910. SkMatrix shaderMatrix;
  911. shaderMatrix.setTranslate(rect.left, rect.bottom);
  912. shaderMatrix.preScale(1, -1);
  913. LayerShader layerShader(layer, &shaderMatrix);
  914. paint.setShader(&layerShader);
  915. // Since the drawing primitive is defined in local drawing space,
  916. // we don't need to modify the draw matrix
  917. const SkPath* maskPath = layer->getConvexMask();
  918. DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
  919. paint.setShader(NULL);
  920. restore();
  921. return;
  922. }
  923. if (layer->region.isRect()) {
  924. layer->setRegionAsRect();
  925. DRAW_DOUBLE_STENCIL(composeLayerRect(layer, layer->regionRect));
  926. layer->region.clear();
  927. return;
  928. }
  929. EVENT_LOGD("composeLayerRegion");
  930. // standard Region based draw
  931. size_t count;
  932. const android::Rect* rects;
  933. Region safeRegion;
  934. if (CC_LIKELY(hasRectToRectTransform())) {
  935. rects = layer->region.getArray(&count);
  936. } else {
  937. safeRegion = Region::createTJunctionFreeRegion(layer->region);
  938. rects = safeRegion.getArray(&count);
  939. }
  940. const float alpha = getLayerAlpha(layer);
  941. const float texX = 1.0f / float(layer->getWidth());
  942. const float texY = 1.0f / float(layer->getHeight());
  943. const float height = rect.getHeight();
  944. setupDraw();
  945. // We must get (and therefore bind) the region mesh buffer
  946. // after we setup drawing in case we need to mess with the
  947. // stencil buffer in setupDraw()
  948. TextureVertex* mesh = mCaches.getRegionMesh();
  949. uint32_t numQuads = 0;
  950. setupDrawWithTexture();
  951. setupDrawColor(alpha, alpha, alpha, alpha);
  952. setupDrawColorFilter(layer->getColorFilter());
  953. setupDrawBlending(layer);
  954. setupDrawProgram();
  955. setupDrawDirtyRegionsDisabled();
  956. setupDrawPureColorUniforms();
  957. setupDrawColorFilterUniforms(layer->getColorFilter());
  958. setupDrawTexture(layer->getTexture());
  959. if (currentTransform()->isPureTranslate()) {
  960. const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
  961. const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
  962. layer->setFilter(GL_NEAREST);
  963. setupDrawModelView(kModelViewMode_Translate, false,
  964. x, y, x + rect.getWidth(), y + rect.getHeight(), true);
  965. } else {
  966. layer->setFilter(GL_LINEAR);
  967. setupDrawModelView(kModelViewMode_Translate, false,
  968. rect.left, rect.top, rect.right, rect.bottom);
  969. }
  970. setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
  971. for (size_t i = 0; i < count; i++) {
  972. const android::Rect* r = &rects[i];
  973. const float u1 = r->left * texX;
  974. const float v1 = (height - r->top) * texY;
  975. const float u2 = r->right * texX;
  976. const float v2 = (height - r->bottom) * texY;
  977. // TODO: Reject quads outside of the clip
  978. TextureVertex::set(mesh++, r->left, r->top, u1, v1);
  979. TextureVertex::set(mesh++, r->right, r->top, u2, v1);
  980. TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
  981. TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
  982. numQuads++;
  983. if (numQuads >= gMaxNumberOfQuads) {
  984. DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
  985. GL_UNSIGNED_SHORT, NULL));
  986. numQuads = 0;
  987. mesh = mCaches.getRegionMesh();
  988. }
  989. }
  990. if (numQuads > 0) {
  991. DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
  992. GL_UNSIGNED_SHORT, NULL));
  993. }
  994. #if DEBUG_LAYERS_AS_REGIONS
  995. drawRegionRectsDebug(layer->region);
  996. #endif
  997. layer->region.clear();
  998. }
  999. #if DEBUG_LAYERS_AS_REGIONS
  1000. void OpenGLRenderer::drawRegionRectsDebug(const Region& region) {
  1001. size_t count;
  1002. const android::Rect* rects = region.getArray(&count);
  1003. uint32_t colors[] = {
  1004. 0x7fff0000, 0x7f00ff00,
  1005. 0x7f0000ff, 0x7fff00ff,
  1006. };
  1007. int offset = 0;
  1008. int32_t top = rects[0].top;
  1009. for (size_t i = 0; i < count; i++) {
  1010. if (top != rects[i].top) {
  1011. offset ^= 0x2;
  1012. top = rects[i].top;
  1013. }
  1014. SkPaint paint;
  1015. paint.setColor(colors[offset + (i & 0x1)]);
  1016. Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
  1017. drawColorRect(r.left, r.top, r.right, r.bottom, paint);
  1018. }
  1019. }
  1020. #endif
  1021. void OpenGLRenderer::drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty) {
  1022. Vector<float> rects;
  1023. SkRegion::Iterator it(region);
  1024. while (!it.done()) {
  1025. const SkIRect& r = it.rect();
  1026. rects.push(r.fLeft);
  1027. rects.push(r.fTop);
  1028. rects.push(r.fRight);
  1029. rects.push(r.fBottom);
  1030. it.next();
  1031. }
  1032. drawColorRects(rects.array(), rects.size(), &paint, true, dirty, false);
  1033. }
  1034. void OpenGLRenderer::dirtyLayer(const float left, const float top,
  1035. const float right, const float bottom, const mat4 transform) {
  1036. if (hasLayer()) {
  1037. Rect bounds(left, top, right, bottom);
  1038. transform.mapRect(bounds);
  1039. dirtyLayerUnchecked(bounds, getRegion());
  1040. }
  1041. }
  1042. void OpenGLRenderer::dirtyLayer(const float left, const float top,
  1043. const float right, const float bottom) {
  1044. if (hasLayer()) {
  1045. Rect bounds(left, top, right, bottom);
  1046. dirtyLayerUnchecked(bounds, getRegion());
  1047. }
  1048. }
  1049. void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
  1050. if (bounds.intersect(*currentClipRect())) {
  1051. bounds.snapToPixelBoundaries();
  1052. android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
  1053. if (!dirty.isEmpty()) {
  1054. region->orSelf(dirty);
  1055. }
  1056. }
  1057. }
  1058. void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
  1059. GLsizei elementsCount = quadsCount * 6;
  1060. while (elementsCount > 0) {
  1061. GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6);
  1062. setupDrawIndexedVertices(&mesh[0].x);
  1063. glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, NULL);
  1064. elementsCount -= drawCount;
  1065. // Though there are 4 vertices in a quad, we use 6 indices per
  1066. // quad to draw with GL_TRIANGLES
  1067. mesh += (drawCount / 6) * 4;
  1068. }
  1069. }
  1070. void OpenGLRenderer::clearLayerRegions() {
  1071. const size_t count = mLayers.size();
  1072. if (count == 0) return;
  1073. if (!currentSnapshot()->isIgnored()) {
  1074. EVENT_LOGD("clearLayerRegions");
  1075. // Doing several glScissor/glClear here can negatively impact
  1076. // GPUs with a tiler architecture, instead we draw quads with
  1077. // the Clear blending mode
  1078. // The list contains bounds that have already been clipped
  1079. // against their initial clip rect, and the current clip
  1080. // is likely different so we need to disable clipping here
  1081. bool scissorChanged = mCaches.disableScissor();
  1082. Vertex mesh[count * 4];
  1083. Vertex* vertex = mesh;
  1084. for (uint32_t i = 0; i < count; i++) {
  1085. Rect* bounds = mLayers.itemAt(i);
  1086. Vertex::set(vertex++, bounds->left, bounds->top);
  1087. Vertex::set(vertex++, bounds->right, bounds->top);
  1088. Vertex::set(vertex++, bounds->left, bounds->bottom);
  1089. Vertex::set(vertex++, bounds->right, bounds->bottom);
  1090. delete bounds;
  1091. }
  1092. // We must clear the list of dirty rects before we
  1093. // call setupDraw() to prevent stencil setup to do
  1094. // the same thing again
  1095. mLayers.clear();
  1096. SkPaint clearPaint;
  1097. clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
  1098. setupDraw(false);
  1099. setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
  1100. setupDrawBlending(&clearPaint, true);
  1101. setupDrawProgram();
  1102. setupDrawPureColorUniforms();
  1103. setupDrawModelView(kModelViewMode_Translate, false,
  1104. 0.0f, 0.0f, 0.0f, 0.0f, true);
  1105. issueIndexedQuadDraw(&mesh[0], count);
  1106. if (scissorChanged) mCaches.enableScissor();
  1107. } else {
  1108. for (uint32_t i = 0; i < count; i++) {
  1109. delete mLayers.itemAt(i);
  1110. }
  1111. mLayers.clear();
  1112. }
  1113. }
  1114. ///////////////////////////////////////////////////////////////////////////////
  1115. // State Deferral
  1116. ///////////////////////////////////////////////////////////////////////////////
  1117. bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
  1118. const Rect* currentClip = currentClipRect();
  1119. const mat4* currentMatrix = currentTransform();
  1120. if (stateDeferFlags & kStateDeferFlag_Draw) {
  1121. // state has bounds initialized in local coordinates
  1122. if (!state.mBounds.isEmpty()) {
  1123. currentMatrix->mapRect(state.mBounds);
  1124. Rect clippedBounds(state.mBounds);
  1125. // NOTE: if we ever want to use this clipping info to drive whether the scissor
  1126. // is used, it should more closely duplicate the quickReject logic (in how it uses
  1127. // snapToPixelBoundaries)
  1128. if(!clippedBounds.intersect(*currentClip)) {
  1129. // quick rejected
  1130. return true;
  1131. }
  1132. state.mClipSideFlags = kClipSide_None;
  1133. if (!currentClip->contains(state.mBounds)) {
  1134. int& flags = state.mClipSideFlags;
  1135. // op partially clipped, so record which sides are clipped for clip-aware merging
  1136. if (currentClip->left > state.mBounds.left) flags |= kClipSide_Left;
  1137. if (currentClip->top > state.mBounds.top) flags |= kClipSide_Top;
  1138. if (currentClip->right < state.mBounds.right) flags |= kClipSide_Right;
  1139. if (currentClip->bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
  1140. }
  1141. state.mBounds.set(clippedBounds);
  1142. } else {
  1143. // Empty bounds implies size unknown. Label op as conservatively clipped to disable
  1144. // overdraw avoidance (since we don't know what it overlaps)
  1145. state.mClipSideFlags = kClipSide_ConservativeFull;
  1146. state.mBounds.set(*currentClip);
  1147. }
  1148. }
  1149. state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
  1150. if (state.mClipValid) {
  1151. state.mClip.set(*currentClip);
  1152. }
  1153. // Transform, drawModifiers, and alpha always deferred, since they are used by state operations
  1154. // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
  1155. state.mMatrix.load(*currentMatrix);
  1156. state.mDrawModifiers = mDrawModifiers;
  1157. state.mAlpha = currentSnapshot()->alpha;
  1158. // always store/restore, since it's just a pointer
  1159. state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
  1160. return false;
  1161. }
  1162. void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
  1163. setMatrix(state.mMatrix);
  1164. mSnapshot->alpha = state.mAlpha;
  1165. mDrawModifiers = state.mDrawModifiers;
  1166. mSnapshot->roundRectClipState = state.mRoundRectClipState;
  1167. if (state.mClipV