diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 20b038d..7993c0f 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -162,7 +162,7 @@ void OpenGLRenderer::initProperties() { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setViewport(int width, int height) { - initViewport(width, height); + initializeViewport(width, height); glDisable(GL_DITHER); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -170,12 +170,6 @@ void OpenGLRenderer::setViewport(int width, int height) { glEnableVertexAttribArray(Program::kBindingPosition); } -void OpenGLRenderer::initViewport(int width, int height) { - mProjectionMatrix.loadOrtho(0, width, height, 0, -1, 1); - - initializeViewport(width, height); -} - void OpenGLRenderer::setupFrameState(float left, float top, float right, float bottom, bool opaque) { mCaches.clearGarbage(); @@ -244,7 +238,7 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) { if (!opaque || mCountOverdraw) { mCaches.enableScissor(); - mCaches.setScissor(left, currentSnapshot()->height - bottom, right - left, bottom - top); + mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top); glClear(GL_COLOR_BUFFER_BIT); return DrawGlInfo::kStatusDrew; } @@ -270,7 +264,7 @@ void OpenGLRenderer::startTilingCurrentClip(bool opaque) { clip = &(snapshot->layer->clipRect); } - startTiling(*clip, snapshot->height, opaque); + startTiling(*clip, getViewportHeight(), opaque); } } @@ -333,7 +327,7 @@ void OpenGLRenderer::interrupt() { void OpenGLRenderer::resume() { const Snapshot* snapshot = currentSnapshot(); - glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); + glViewport(0, 0, getViewportWidth(), getViewportHeight()); glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); debugOverdraw(true, false); @@ -354,9 +348,8 @@ void OpenGLRenderer::resume() { } void OpenGLRenderer::resumeAfterLayer() { - const Snapshot* snapshot = currentSnapshot(); - glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight()); - glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); + glViewport(0, 0, getViewportWidth(), getViewportHeight()); + glBindFramebuffer(GL_FRAMEBUFFER, currentSnapshot()->fbo); debugOverdraw(true, false); mCaches.resetScissor(); @@ -381,8 +374,8 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { info.clipRight = clip.right; info.clipBottom = clip.bottom; info.isLayer = hasLayer(); - info.width = currentSnapshot()->viewport.getWidth(); - info.height = currentSnapshot()->height; + info.width = getViewportWidth(); + info.height = getViewportHeight(); currentTransform()->copyTo(&info.transform[0]); bool dirtyClip = mDirtyClip; @@ -437,7 +430,7 @@ void OpenGLRenderer::renderOverdraw() { const Rect* clip = &mTilingClip; mCaches.enableScissor(); - mCaches.setScissor(clip->left, firstSnapshot()->height - clip->bottom, + mCaches.setScissor(clip->left, firstSnapshot()->getViewportHeight() - clip->bottom, clip->right - clip->left, clip->bottom - clip->top); // 1x overdraw @@ -621,14 +614,12 @@ void OpenGLRenderer::flushLayerUpdates() { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) { - bool restoreOrtho = removed.flags & Snapshot::kFlagDirtyOrtho; + bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer; bool restoreClip = removed.flags & Snapshot::kFlagClipSet; bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer; - if (restoreOrtho) { - const Rect& r = restored.viewport; - glViewport(r.left, r.top, r.right, r.bottom); - mProjectionMatrix.load(removed.orthoMatrix); // TODO: should ortho be stored in 'restored'? + if (restoreViewport) { + glViewport(0, 0, getViewportWidth(), getViewportHeight()); } if (restoreClip) { @@ -671,7 +662,7 @@ void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool // When the layer is not an FBO, we may use glCopyTexImage so we // need to make sure the layer does not extend outside the bounds // of the framebuffer - if (!bounds.intersect(currentSnapshot()->previous->viewport)) { + if (!bounds.intersect(Rect(0, 0, getViewportWidth(), getViewportHeight()))) { bounds.setEmpty(); } else if (fboLayer) { clip.set(bounds); @@ -719,7 +710,8 @@ int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float if (!currentSnapshot()->isIgnored()) { mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); - mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); + mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight()); + mSnapshot->roundRectClipState = NULL; } } @@ -831,8 +823,9 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto layer->setEmpty(false); } - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, - mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + bounds.left, getViewportHeight() - bounds.bottom, + bounds.getWidth(), bounds.getHeight()); // Enqueue the buffer coordinates to clear the corresponding region later mLayers.push(new Rect(bounds)); @@ -847,14 +840,12 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) { layer->setFbo(mCaches.fboCache.get()); mSnapshot->region = &mSnapshot->layer->region; - mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer | - Snapshot::kFlagDirtyOrtho; + mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer; mSnapshot->fbo = layer->getFbo(); mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); - mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); - mSnapshot->height = bounds.getHeight(); - mSnapshot->orthoMatrix.load(mProjectionMatrix); + mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight()); + mSnapshot->roundRectClipState = NULL; endTiling(); debugOverdraw(false, false); @@ -883,9 +874,6 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) { // Change the ortho projection glViewport(0, 0, bounds.getWidth(), bounds.getHeight()); - - mProjectionMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f); - return true; } @@ -904,7 +892,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto bool clipRequired = false; calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom, - &clipRequired, false); // safely ignore return, should never be rejected + &clipRequired, NULL, false); // safely ignore return, should never be rejected mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); if (fboLayer) { @@ -1379,6 +1367,9 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef state.mMatrix.load(*currentMatrix); state.mDrawModifiers = mDrawModifiers; state.mAlpha = currentSnapshot()->alpha; + + // always store/restore, since it's just a pointer + state.mRoundRectClipState = currentSnapshot()->roundRectClipState; return false; } @@ -1386,6 +1377,7 @@ void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool setMatrix(state.mMatrix); mSnapshot->alpha = state.mAlpha; mDrawModifiers = state.mDrawModifiers; + mSnapshot->roundRectClipState = state.mRoundRectClipState; if (state.mClipValid && !skipClipRestore) { mSnapshot->setClip(state.mClip.left, state.mClip.top, @@ -1419,7 +1411,7 @@ void OpenGLRenderer::setScissorFromClip() { Rect clip(*currentClipRect()); clip.snapToPixelBoundaries(); - if (mCaches.setScissor(clip.left, currentSnapshot()->height - clip.bottom, + if (mCaches.setScissor(clip.left, getViewportHeight() - clip.bottom, clip.getWidth(), clip.getHeight())) { mDirtyClip = false; } @@ -1461,7 +1453,7 @@ void OpenGLRenderer::setStencilFromClip() { mCaches.stencil.enableWrite(); - // Clear the stencil but first make sure we restrict drawing + // Clear and update the stencil, but first make sure we restrict drawing // to the region's bounds bool resetScissor = mCaches.enableScissor(); if (resetScissor) { @@ -1469,7 +1461,10 @@ void OpenGLRenderer::setStencilFromClip() { setScissorFromClip(); } mCaches.stencil.clear(); - if (resetScissor) mCaches.disableScissor(); + + // stash and disable the outline clip state, since stencil doesn't account for outline + bool storedSkipOutlineClip = mSkipOutlineClip; + mSkipOutlineClip = true; SkPaint paint; paint.setColor(0xff000000); @@ -1482,6 +1477,8 @@ void OpenGLRenderer::setStencilFromClip() { // The last parameter is important: we are not drawing in the color buffer // so we don't want to dirty the current layer, if any drawRegionRects(*(currentSnapshot()->clipRegion), paint, false); + if (resetScissor) mCaches.disableScissor(); + mSkipOutlineClip = storedSkipOutlineClip; mCaches.stencil.enableTest(); @@ -1506,7 +1503,6 @@ void OpenGLRenderer::setStencilFromClip() { */ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom, const SkPaint* paint) { - bool clipRequired = false; bool snapOut = paint && paint->isAntiAlias(); if (paint && paint->getStyle() != SkPaint::kFill_Style) { @@ -1517,13 +1513,17 @@ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, bottom += outset; } - if (calculateQuickRejectForScissor(left, top, right, bottom, &clipRequired, snapOut)) { + bool clipRequired = false; + bool roundRectClipRequired = false; + if (calculateQuickRejectForScissor(left, top, right, bottom, + &clipRequired, &roundRectClipRequired, snapOut)) { return true; } if (!isRecording()) { // not quick rejected, so enable the scissor if clipRequired mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); + mSkipOutlineClip = !roundRectClipRequired; } return false; } @@ -1680,6 +1680,18 @@ void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool sw void OpenGLRenderer::setupDrawProgram() { useProgram(mCaches.programCache.get(mDescription)); + if (mDescription.hasRoundRectClip) { + // TODO: avoid doing this repeatedly, stashing state pointer in program + const RoundRectClipState* state = mSnapshot->roundRectClipState; + const Rect& innerRect = state->outlineInnerRect; + glUniform4f(mCaches.currentProgram->getUniform("roundRectInnerRectLTRB"), + innerRect.left, innerRect.top, + innerRect.right, innerRect.bottom); + glUniform1f(mCaches.currentProgram->getUniform("roundRectRadius"), + state->outlineRadius); + glUniformMatrix4fv(mCaches.currentProgram->getUniform("roundRectInvTransform"), + 1, GL_FALSE, &state->matrix.data[0]); + } } void OpenGLRenderer::setupDrawDirtyRegionsDisabled() { @@ -1694,12 +1706,14 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset, } bool dirty = right - left > 0.0f && bottom - top > 0.0f; - if (!ignoreTransform) { - mCaches.currentProgram->set(mProjectionMatrix, mModelViewMatrix, *currentTransform(), offset); - if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *currentTransform()); - } else { - mCaches.currentProgram->set(mProjectionMatrix, mModelViewMatrix, mat4::identity(), offset); - if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom); + const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform(); + mCaches.currentProgram->set(mSnapshot->getOrthoMatrix(), mModelViewMatrix, transformMatrix, offset); + if (dirty && mTrackDirtyRegions) { + if (!ignoreTransform) { + dirtyLayer(left, top, right, bottom, *currentTransform()); + } else { + dirtyLayer(left, top, right, bottom); + } } } @@ -2912,7 +2926,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { bool clipRequired = false; const bool rejected = calculateQuickRejectForScissor(x, y, - x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, false); + x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, NULL, false); if (rejected) { if (transform && !transform->isIdentity()) { @@ -3443,6 +3457,13 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description, bool swapSrcDst) { + + if (mSnapshot->roundRectClipState != NULL /*&& !mSkipOutlineClip*/) { + blend = true; + mDescription.hasRoundRectClip = true; + } + mSkipOutlineClip = true; + if (mCountOverdraw) { if (!mCaches.blend) glEnable(GL_BLEND); if (mCaches.lastSrcMode != GL_ONE || mCaches.lastDstMode != GL_ONE) { |
