Disable partial repaint on Android (flutter/engine#40898)

Disable partial repaint on Android
This commit is contained in:
Jonah Williams
2023-04-03 16:36:58 -07:00
committed by GitHub
parent 8135972f97
commit f82dc83970

View File

@@ -58,128 +58,27 @@ void LogLastEGLError() {
FML_LOG(ERROR) << "Unknown EGL Error";
}
namespace {
static bool HasExtension(const char* extensions, const char* name) {
const char* r = strstr(extensions, name);
auto len = strlen(name);
// check that the extension name is terminated by space or null terminator
return r != nullptr && (r[len] == ' ' || r[len] == 0);
}
} // namespace
class AndroidEGLSurfaceDamage {
public:
void init(EGLDisplay display, EGLContext context) {
if (GetAPILevel() < 29) {
// Disable partial repaint for devices older than Android 10. There
// are old devices that have extensions below available but the
// implementation causes glitches (i.e. Xperia Z3 with Android 6).
partial_redraw_supported_ = false;
return;
}
const char* extensions = eglQueryString(display, EGL_EXTENSIONS);
if (HasExtension(extensions, "EGL_KHR_partial_update")) {
set_damage_region_ = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(
eglGetProcAddress("eglSetDamageRegionKHR"));
}
if (HasExtension(extensions, "EGL_EXT_swap_buffers_with_damage")) {
swap_buffers_with_damage_ =
reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(
eglGetProcAddress("eglSwapBuffersWithDamageEXT"));
} else if (HasExtension(extensions, "EGL_KHR_swap_buffers_with_damage")) {
swap_buffers_with_damage_ =
reinterpret_cast<PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC>(
eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
}
partial_redraw_supported_ =
set_damage_region_ != nullptr && swap_buffers_with_damage_ != nullptr;
}
static int GetAPILevel() {
char sdk_version_string[PROP_VALUE_MAX];
if (__system_property_get("ro.build.version.sdk", sdk_version_string)) {
return atoi(sdk_version_string);
} else {
return -1;
}
}
void init(EGLDisplay display, EGLContext context) {}
void SetDamageRegion(EGLDisplay display,
EGLSurface surface,
const std::optional<SkIRect>& region) {
if (set_damage_region_ && region) {
auto rects = RectToInts(display, surface, *region);
set_damage_region_(display, surface, rects.data(), 1);
}
}
const std::optional<SkIRect>& region) {}
// Maximum damage history - for triple buffering we need to store damage for
// last two frames; Some Android devices (Pixel 4) use quad buffering.
static const int kMaxHistorySize = 10;
bool SupportsPartialRepaint() const { return partial_redraw_supported_; }
/// This was disabled after discussion in
/// https://github.com/flutter/flutter/issues/123353
bool SupportsPartialRepaint() const { return false; }
std::optional<SkIRect> InitialDamage(EGLDisplay display, EGLSurface surface) {
if (!partial_redraw_supported_) {
return std::nullopt;
}
EGLint age;
eglQuerySurface(display, surface, EGL_BUFFER_AGE_EXT, &age);
if (age == 0) { // full repaint
return std::nullopt;
} else {
// join up to (age - 1) last rects from damage history
--age;
auto res = SkIRect::MakeEmpty();
for (auto i = damage_history_.rbegin();
i != damage_history_.rend() && age > 0; ++i, --age) {
res.join(*i);
}
return res;
}
return std::nullopt;
}
bool SwapBuffersWithDamage(EGLDisplay display,
EGLSurface surface,
const std::optional<SkIRect>& damage) {
if (swap_buffers_with_damage_ && damage) {
damage_history_.push_back(*damage);
if (damage_history_.size() > kMaxHistorySize) {
damage_history_.pop_front();
}
auto rects = RectToInts(display, surface, *damage);
return swap_buffers_with_damage_(display, surface, rects.data(), 1);
} else {
return eglSwapBuffers(display, surface);
}
return eglSwapBuffers(display, surface);
}
private:
std::array<EGLint, 4> static RectToInts(EGLDisplay display,
EGLSurface surface,
const SkIRect& rect) {
EGLint height;
eglQuerySurface(display, surface, EGL_HEIGHT, &height);
std::array<EGLint, 4> res{rect.left(), height - rect.bottom(), rect.width(),
rect.height()};
return res;
}
PFNEGLSETDAMAGEREGIONKHRPROC set_damage_region_ = nullptr;
PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage_ = nullptr;
bool partial_redraw_supported_;
std::list<SkIRect> damage_history_;
};
AndroidEGLSurface::AndroidEGLSurface(EGLSurface surface,