Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13d1b4ab authored by Season Li's avatar Season Li Committed by John Reck
Browse files

renderthread: add EGL_EXT_buffer_age support

EGL_EXT_buffer_age is better than EGL_BUFFER_PRESERVED
because it can save memory bandwidth used to blit
back buffer into front buffer.

Change-Id: I2fea0ee08dc7dd66e348b04dd694d075d509d01b
parent 4692f42b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ LOCAL_SRC_FILES := \
    renderthread/RenderTask.cpp \
    renderthread/RenderThread.cpp \
    renderthread/TimeLord.cpp \
    renderthread/DirtyHistory.cpp \
    thread/TaskManager.cpp \
    utils/Blur.cpp \
    utils/GLUtils.cpp \
+21 −5
Original line number Diff line number Diff line
@@ -98,6 +98,9 @@ void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height
        setSurface(nullptr);
    }
    mHaveNewSurface = false;
    if (mEglManager.useBufferAgeExt()) {
        mDirtyHistory.prepend(Rect(dirty));
    }
}

void CanvasContext::requireSurface() {
@@ -227,6 +230,8 @@ void CanvasContext::draw() {
            "drawRenderNode called on a context with no canvas or surface!");

    SkRect dirty;
    bool useBufferAgeExt = mEglManager.useBufferAgeExt();
    Rect patchedDirty;
    mDamageAccumulator.finish(&dirty);

    // TODO: Re-enable after figuring out cause of b/22592975
@@ -237,12 +242,18 @@ void CanvasContext::draw() {

    mCurrentFrameInfo->markIssueDrawCommandsStart();

    EGLint width, height;
    mEglManager.beginFrame(mEglSurface, &width, &height);
    EGLint width, height, framebufferAge;
    mEglManager.beginFrame(mEglSurface, &width, &height, &framebufferAge);

    if (useBufferAgeExt && mHaveNewSurface) {
        mDirtyHistory.clear();
    }

    if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
        mCanvas->setViewport(width, height);
        dirty.setEmpty();
    } else if (!mBufferPreserved || mHaveNewSurface) {
        mDirtyHistory.clear();
        dirty.setEmpty();
    } else {
        if (!dirty.isEmpty() && !dirty.intersect(0, 0, width, height)) {
@@ -253,9 +264,14 @@ void CanvasContext::draw() {
        profiler().unionDirty(&dirty);
    }

    if (!dirty.isEmpty()) {
        mCanvas->prepareDirty(dirty.fLeft, dirty.fTop,
                dirty.fRight, dirty.fBottom, mOpaque);
    patchedDirty = dirty;
    if (useBufferAgeExt && !dirty.isEmpty()) {
        patchedDirty = mDirtyHistory.unionWith(Rect(dirty), framebufferAge-1);
    }

    if (!patchedDirty.isEmpty()) {
        mCanvas->prepareDirty(patchedDirty.left, patchedDirty.top,
                patchedDirty.right, patchedDirty.bottom, mOpaque);
    } else {
        mCanvas->prepare(mOpaque);
    }
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "utils/RingBuffer.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
#include "renderthread/DirtyHistory.h"

#include <cutils/compiler.h>
#include <EGL/egl.h>
@@ -146,6 +147,8 @@ private:
    FrameInfoVisualizer mProfiler;

    std::set<RenderNode*> mPrefetechedLayers;

    DirtyHistory mDirtyHistory;
};

} /* namespace renderthread */
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "DirtyHistory.h"

namespace android {
namespace uirenderer {
namespace renderthread {

DirtyHistory::DirtyHistory()
        : mBack(DIRTY_HISTORY_SIZE - 1) {
    clear();
}

void DirtyHistory::clear()
{
    for (int i = 0; i < DIRTY_HISTORY_SIZE; i++) {
        mHistory[i].clear();
    }
}

Rect DirtyHistory::get(int index) {
    if (index >= DIRTY_HISTORY_SIZE || index < 0)
        return Rect();
    return mHistory[(1 + mBack + index) % DIRTY_HISTORY_SIZE];
}

Rect DirtyHistory::unionWith(Rect rect, int count) {
    if (rect.isEmpty() || count > DIRTY_HISTORY_SIZE || count < 0)
        return Rect();

    for (int i = 0; i < count; i++) {
        Rect ith = get(i);
        if (ith.isEmpty())
            return Rect();

        // rect union
        rect.left = fminf(rect.left, ith.left);
        rect.top = fminf(rect.top, ith.top);
        rect.right = fmaxf(rect.right, ith.right);
        rect.bottom = fmaxf(rect.bottom, ith.bottom);
    }
    return rect;
}

void DirtyHistory::prepend(Rect rect) {
    if (rect.isEmpty()) {
        mHistory[mBack].clear();
    } else {
        mHistory[mBack].set(rect);
    }
    mBack = (mBack + DIRTY_HISTORY_SIZE - 1) % DIRTY_HISTORY_SIZE;
}

} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef DIRTYHISTORY_H
#define DIRTYHISTORY_H

#include <Rect.h>

namespace android {
namespace uirenderer {
namespace renderthread {

#define DIRTY_HISTORY_SIZE 4

class DirtyHistory {
public:
    DirtyHistory();
    ~DirtyHistory() {}

    Rect get(int index);
    Rect unionWith(Rect rect, int count);
    void prepend(Rect rect);
    void clear();
private:
    Rect mHistory[DIRTY_HISTORY_SIZE];
    int mBack;
};

} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */

#endif /* DIRTYHISTORY_H */
Loading