summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/androidfw/Asset.cpp12
-rw-r--r--libs/androidfw/CursorWindow.cpp6
-rw-r--r--libs/hwui/Android.bp58
-rw-r--r--libs/hwui/AndroidTest.xml2
-rw-r--r--libs/hwui/Animator.cpp2
-rw-r--r--libs/hwui/CanvasTransform.cpp4
-rw-r--r--libs/hwui/HardwareBitmapUploader.h6
-rw-r--r--libs/hwui/Properties.cpp70
-rw-r--r--libs/hwui/Properties.h1
-rw-r--r--libs/hwui/SkiaCanvas.cpp3
-rw-r--r--libs/hwui/SkiaCanvas.h12
-rw-r--r--libs/hwui/VectorDrawable.cpp6
-rw-r--r--libs/hwui/WebViewFunctorManager.h10
-rw-r--r--libs/hwui/debug/NullGlesDriver.cpp4
-rw-r--r--libs/hwui/debug/NullSkiaInterface.cpp1402
-rw-r--r--libs/hwui/hwui/AnimatedImageDrawable.cpp6
-rw-r--r--libs/hwui/hwui/Bitmap.cpp32
-rw-r--r--libs/hwui/hwui/Bitmap.h10
-rw-r--r--libs/hwui/hwui/Canvas.cpp36
-rw-r--r--libs/hwui/hwui/Typeface.cpp4
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.cpp10
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp5
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp7
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp23
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h2
-rw-r--r--libs/hwui/renderthread/CacheManager.h8
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp21
-rw-r--r--libs/hwui/tests/common/scenes/BitmapShaders.cpp6
-rw-r--r--libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp7
-rw-r--r--libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp2
-rw-r--r--libs/hwui/tests/common/scenes/ListViewAnimation.cpp2
-rw-r--r--libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp18
-rw-r--r--libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp2
-rw-r--r--libs/hwui/tests/common/scenes/TvApp.cpp2
-rw-r--r--libs/hwui/tests/unit/SkiaBehaviorTests.cpp4
-rw-r--r--libs/hwui/tests/unit/VectorDrawableTests.cpp2
-rw-r--r--libs/hwui/utils/TraceUtils.h1
37 files changed, 1679 insertions, 129 deletions
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 9a95fdf80cb5..92125c9da8bb 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -253,8 +253,10 @@ Asset::Asset(void)
pAsset = new _FileAsset;
result = pAsset->openChunk(NULL, fd, offset, length);
- if (result != NO_ERROR)
+ if (result != NO_ERROR) {
+ delete pAsset;
return NULL;
+ }
pAsset->mAccessMode = mode;
return pAsset;
@@ -273,8 +275,10 @@ Asset::Asset(void)
pAsset = new _CompressedAsset;
result = pAsset->openChunk(fd, offset, compressionMethod,
uncompressedLen, compressedLen);
- if (result != NO_ERROR)
+ if (result != NO_ERROR) {
+ delete pAsset;
return NULL;
+ }
pAsset->mAccessMode = mode;
return pAsset;
@@ -328,8 +332,10 @@ Asset::Asset(void)
pAsset = new _CompressedAsset;
result = pAsset->openChunk(dataMap, uncompressedLen);
- if (result != NO_ERROR)
+ if (result != NO_ERROR) {
+ delete pAsset;
return NULL;
+ }
pAsset->mAccessMode = mode;
return pAsset;
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index e1067fcd4d3d..6f05cbd0ebb3 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -69,7 +69,7 @@ status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** o
result = window->clear();
if (!result) {
LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
+ "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
window->mHeader->freeOffset,
window->mHeader->numRows,
window->mHeader->numColumns,
@@ -124,7 +124,7 @@ status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursor
CursorWindow* window = new CursorWindow(name, dupAshmemFd,
data, size, true /*readOnly*/);
LOG_WINDOW("Created CursorWindow from parcel: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
+ "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
window->mHeader->freeOffset,
window->mHeader->numRows,
window->mHeader->numColumns,
@@ -200,7 +200,7 @@ status_t CursorWindow::allocRow() {
FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset));
memset(fieldDir, 0, fieldDirSize);
- LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n",
+ LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %zu bytes at offset %u\n",
mHeader->numRows - 1, offsetFromPtr(rowSlot), fieldDirSize, fieldDirOffset);
rowSlot->offset = fieldDirOffset;
return OK;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ebba4cb79dfb..47f22d6eb51e 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -54,6 +54,7 @@ cc_defaults {
shared_libs: [
"liblog",
"libcutils",
+ "libbase",
"libstatslog",
"libutils",
"libEGL",
@@ -101,6 +102,7 @@ cc_defaults {
"debug/GlesDriver.cpp",
"debug/FatalBaseDriver.cpp",
"debug/NullGlesDriver.cpp",
+ "debug/NullSkiaInterface.cpp",
],
include_dirs: ["frameworks/native/opengl/libs/GLES2"],
}
@@ -396,3 +398,59 @@ phony {
"hwuimacro",
]
}
+
+cc_library_host_shared {
+ name: "libhwui-host",
+
+ defaults: [
+ "skia_deps",
+ ],
+ whole_static_libs: ["libskia"],
+
+ srcs: [
+ "hwui/AnimatedImageDrawable.cpp",
+ "hwui/AnimatedImageThread.cpp",
+ "hwui/Bitmap.cpp",
+ "hwui/Canvas.cpp",
+ "hwui/Typeface.cpp",
+ "hwui/MinikinSkia.cpp",
+ "hwui/MinikinUtils.cpp",
+ "hwui/PaintImpl.cpp",
+ "utils/Blur.cpp",
+ "utils/LinearAllocator.cpp",
+ "utils/VectorDrawableUtils.cpp",
+ "Animator.cpp",
+ "Interpolator.cpp",
+ "Matrix.cpp",
+ "PathParser.cpp",
+ "Properties.cpp",
+ "PropertyValuesAnimatorSet.cpp",
+ "PropertyValuesHolder.cpp",
+ "SkiaCanvas.cpp",
+ "VectorDrawable.cpp",
+ ],
+ include_dirs: [
+ "external/skia/include/private",
+ "external/skia/src/core",
+ "external/vulkan-headers/include",
+ "system/core/base/include",
+ ],
+ cpp_std: "experimental",
+ cflags: [
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+ shared_libs: [
+ "libbase",
+ "libharfbuzz_ng",
+ "libminikin",
+ ],
+ static_libs: [
+ "libandroidfw",
+ "libutils",
+ ],
+ export_include_dirs: ["."],
+ export_static_lib_headers: [
+ "libarect",
+ ],
+}
diff --git a/libs/hwui/AndroidTest.xml b/libs/hwui/AndroidTest.xml
index eab32c5a67ce..381fb9f6c7bf 100644
--- a/libs/hwui/AndroidTest.xml
+++ b/libs/hwui/AndroidTest.xml
@@ -28,9 +28,11 @@
<test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
<option name="native-benchmark-device-path" value="/data/benchmarktest" />
<option name="benchmark-module-name" value="hwuimicro" />
+ <option name="file-exclusion-filter-regex" value=".*\.config$" />
</test>
<test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
<option name="native-benchmark-device-path" value="/data/benchmarktest" />
<option name="benchmark-module-name" value="hwuimacro" />
+ <option name="file-exclusion-filter-regex" value=".*\.config$" />
</test>
</configuration>
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 74cf1fda1b75..93b9decd9cbc 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -155,9 +155,11 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
RenderNode* oldTarget = mTarget;
mTarget = mStagingTarget;
mStagingTarget = nullptr;
+#ifdef __ANDROID__ // Layoutlib does not support RenderNode
if (oldTarget && oldTarget != mTarget) {
oldTarget->onAnimatorTargetChanged(this);
}
+#endif
}
if (!mHasStartValue) {
diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp
index 0cfaa8c61279..8c37d73366c2 100644
--- a/libs/hwui/CanvasTransform.cpp
+++ b/libs/hwui/CanvasTransform.cpp
@@ -100,9 +100,9 @@ static void applyColorTransform(ColorTransform transform, SkPaint& paint) {
SkBlendMode mode;
SkColor color;
// TODO: LRU this or something to avoid spamming new color mode filters
- if (paint.getColorFilter()->asColorMode(&color, &mode)) {
+ if (paint.getColorFilter()->asAColorMode(&color, &mode)) {
color = transformColor(transform, color);
- paint.setColorFilter(SkColorFilter::MakeModeFilter(color, mode));
+ paint.setColorFilter(SkColorFilters::Blend(color, mode));
}
}
}
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index c300593d47a1..72243d23dd35 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -27,7 +27,13 @@ public:
static sk_sp<Bitmap> allocateHardwareBitmap(const SkBitmap& sourceBitmap);
+#ifdef __ANDROID__
static bool hasFP16Support();
+#else
+ static bool hasFP16Support() {
+ return true;
+ }
+#endif
};
} // namespace android::uirenderer
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index af20c4f4f20e..1253beb2d2b2 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -17,19 +17,32 @@
#include "Properties.h"
#include "Debug.h"
#include "DeviceInfo.h"
+#ifdef __ANDROID__
#include "HWUIProperties.sysprop.h"
+#endif
#include "SkTraceEventCommon.h"
#include <algorithm>
#include <cstdlib>
+#include <optional>
+#include <android-base/properties.h>
#include <cutils/compiler.h>
-#include <cutils/properties.h>
#include <log/log.h>
namespace android {
namespace uirenderer {
+#ifndef __ANDROID__ // Layoutlib does not compile HWUIProperties.sysprop as it depends on cutils properties
+std::optional<bool> use_vulkan() {
+ return base::GetBoolProperty("ro.hwui.use_vulkan", false);
+}
+
+std::optional<std::int32_t> render_ahead() {
+ return base::GetIntProperty("ro.hwui.render_ahead", 0);
+}
+#endif
+
bool Properties::debugLayersUpdates = false;
bool Properties::debugOverdraw = false;
bool Properties::showDirtyRegions = false;
@@ -67,64 +80,54 @@ bool Properties::isolatedProcess = false;
int Properties::contextPriority = 0;
int Properties::defaultRenderAhead = -1;
-static int property_get_int(const char* key, int defaultValue) {
- char buf[PROPERTY_VALUE_MAX] = {
- '\0',
- };
-
- if (property_get(key, buf, "") > 0) {
- return atoi(buf);
- }
- return defaultValue;
-}
-
bool Properties::load() {
- char property[PROPERTY_VALUE_MAX];
bool prevDebugLayersUpdates = debugLayersUpdates;
bool prevDebugOverdraw = debugOverdraw;
debugOverdraw = false;
- if (property_get(PROPERTY_DEBUG_OVERDRAW, property, nullptr) > 0) {
- INIT_LOGD(" Overdraw debug enabled: %s", property);
- if (!strcmp(property, "show")) {
+ std::string debugOverdrawProperty = base::GetProperty(PROPERTY_DEBUG_OVERDRAW, "");
+ if (debugOverdrawProperty != "") {
+ INIT_LOGD(" Overdraw debug enabled: %s", debugOverdrawProperty);
+ if (debugOverdrawProperty == "show") {
debugOverdraw = true;
overdrawColorSet = OverdrawColorSet::Default;
- } else if (!strcmp(property, "show_deuteranomaly")) {
+ } else if (debugOverdrawProperty == "show_deuteranomaly") {
debugOverdraw = true;
overdrawColorSet = OverdrawColorSet::Deuteranomaly;
}
}
sProfileType = ProfileType::None;
- if (property_get(PROPERTY_PROFILE, property, "") > 0) {
- if (!strcmp(property, PROPERTY_PROFILE_VISUALIZE_BARS)) {
+ std::string profileProperty = base::GetProperty(PROPERTY_PROFILE, "");
+ if (profileProperty != "") {
+ if (profileProperty == PROPERTY_PROFILE_VISUALIZE_BARS) {
sProfileType = ProfileType::Bars;
- } else if (!strcmp(property, "true")) {
+ } else if (profileProperty == "true") {
sProfileType = ProfileType::Console;
}
}
- debugLayersUpdates = property_get_bool(PROPERTY_DEBUG_LAYERS_UPDATES, false);
+ debugLayersUpdates = base::GetBoolProperty(PROPERTY_DEBUG_LAYERS_UPDATES, false);
INIT_LOGD(" Layers updates debug enabled: %d", debugLayersUpdates);
- showDirtyRegions = property_get_bool(PROPERTY_DEBUG_SHOW_DIRTY_REGIONS, false);
+ showDirtyRegions = base::GetBoolProperty(PROPERTY_DEBUG_SHOW_DIRTY_REGIONS, false);
- debugLevel = (DebugLevel)property_get_int(PROPERTY_DEBUG, kDebugDisabled);
+ debugLevel = (DebugLevel)base::GetIntProperty(PROPERTY_DEBUG, (int)kDebugDisabled);
- skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true);
- useBufferAge = property_get_bool(PROPERTY_USE_BUFFER_AGE, true);
- enablePartialUpdates = property_get_bool(PROPERTY_ENABLE_PARTIAL_UPDATES, true);
+ skipEmptyFrames = base::GetBoolProperty(PROPERTY_SKIP_EMPTY_DAMAGE, true);
+ useBufferAge = base::GetBoolProperty(PROPERTY_USE_BUFFER_AGE, true);
+ enablePartialUpdates = base::GetBoolProperty(PROPERTY_ENABLE_PARTIAL_UPDATES, true);
- filterOutTestOverhead = property_get_bool(PROPERTY_FILTER_TEST_OVERHEAD, false);
+ filterOutTestOverhead = base::GetBoolProperty(PROPERTY_FILTER_TEST_OVERHEAD, false);
- skpCaptureEnabled = debuggingEnabled && property_get_bool(PROPERTY_CAPTURE_SKP_ENABLED, false);
+ skpCaptureEnabled = debuggingEnabled && base::GetBoolProperty(PROPERTY_CAPTURE_SKP_ENABLED, false);
SkAndroidFrameworkTraceUtil::setEnableTracing(
- property_get_bool(PROPERTY_SKIA_ATRACE_ENABLED, false));
+ base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
- runningInEmulator = property_get_bool(PROPERTY_QEMU_KERNEL, false);
+ runningInEmulator = base::GetBoolProperty(PROPERTY_QEMU_KERNEL, false);
- defaultRenderAhead = std::max(-1, std::min(2, property_get_int(PROPERTY_RENDERAHEAD,
+ defaultRenderAhead = std::max(-1, std::min(2, base::GetIntProperty(PROPERTY_RENDERAHEAD,
render_ahead().value_or(0))));
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
@@ -175,9 +178,8 @@ RenderPipelineType Properties::peekRenderPipelineType() {
return sRenderPipelineType;
}
bool useVulkan = use_vulkan().value_or(false);
- char prop[PROPERTY_VALUE_MAX];
- property_get(PROPERTY_RENDERER, prop, useVulkan ? "skiavk" : "skiagl");
- if (!strcmp(prop, "skiavk")) {
+ std::string rendererProperty = base::GetProperty(PROPERTY_RENDERER, useVulkan ? "skiavk" : "skiagl");
+ if (rendererProperty == "skiavk") {
return RenderPipelineType::SkiaVulkan;
}
return RenderPipelineType::SkiaGL;
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 71b07c947716..d3ecb54d94f6 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -18,7 +18,6 @@
#define ANDROID_HWUI_PROPERTIES_H
#include <cutils/compiler.h>
-#include <cutils/properties.h>
/**
* This file contains the list of system properties used to configure libhwui.
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index bebda8527def..6ea6af8f2935 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -644,8 +644,7 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
SkPaint& tmpPaint = paintCoW.writeable();
sk_sp<SkImage> image = bitmap.makeImage();
- sk_sp<SkShader> shader =
- image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ sk_sp<SkShader> shader = image->makeShader();
tmpPaint.setShader(std::move(shader));
mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate,
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index bbe91eb2fbc4..05a6d0dda42d 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -16,7 +16,9 @@
#pragma once
#include "CanvasProperty.h"
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
#include "DeferredLayerUpdater.h"
+#endif
#include "RenderNode.h"
#include "VectorDrawable.h"
#include "hwui/Canvas.h"
@@ -222,16 +224,6 @@ private:
void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode);
- /** Filters the paint for bitmap drawing.
- *
- * After filtering the paint for bitmap drawing,
- * also calls filterPaint on the paint.
- *
- * @param paint the paint to filter. Will be initialized with the default
- * SkPaint before filtering if filtering is required.
- */
- PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) const;
-
class Clip;
std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 5418b337c371..89ad1b99c6b6 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -487,6 +487,7 @@ Bitmap& Tree::getBitmapUpdateIfDirty() {
}
void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context) {
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
SkRect dst;
sk_sp<SkSurface> surface = mCache.getSurface(&dst);
bool canReuseSurface = surface && dst.width() >= mProperties.getScaledWidth() &&
@@ -514,6 +515,7 @@ void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext*
}
mCache.dirty = false;
}
+#endif
}
void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas,
@@ -526,6 +528,7 @@ void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas,
sk_sp<SkSurface> Tree::Cache::getSurface(SkRect* bounds) {
sk_sp<SkSurface> surface;
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
sp<skiapipeline::VectorDrawableAtlas> atlas = mAtlas.promote();
if (atlas.get() && mAtlasKey != INVALID_ATLAS_KEY) {
auto atlasEntry = atlas->getEntry(mAtlasKey);
@@ -533,17 +536,20 @@ sk_sp<SkSurface> Tree::Cache::getSurface(SkRect* bounds) {
surface = atlasEntry.surface;
mAtlasKey = atlasEntry.key;
}
+#endif
return surface;
}
void Tree::Cache::clear() {
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
sp<skiapipeline::VectorDrawableAtlas> lockAtlas = mAtlas.promote();
if (lockAtlas.get()) {
lockAtlas->releaseEntry(mAtlasKey);
}
mAtlas = nullptr;
mAtlasKey = INVALID_ATLAS_KEY;
+#endif
}
void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 2846cb1f087b..675b738c6406 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -17,7 +17,11 @@
#pragma once
#include <private/hwui/WebViewFunctor.h>
+#ifdef __ANDROID__ // Layoutlib does not support render thread
#include <renderthread/RenderProxy.h>
+#else
+#include <utils/Log.h>
+#endif
#include <utils/LightRefBase.h>
#include <mutex>
@@ -34,7 +38,11 @@ public:
class Handle : public LightRefBase<Handle> {
public:
- ~Handle() { renderthread::RenderProxy::destroyFunctor(id()); }
+ ~Handle() {
+#ifdef __ANDROID__ // Layoutlib does not support render thread
+ renderthread::RenderProxy::destroyFunctor(id());
+#endif
+ }
int id() const { return mReference.id(); }
diff --git a/libs/hwui/debug/NullGlesDriver.cpp b/libs/hwui/debug/NullGlesDriver.cpp
index 212b24290e22..f27adf0177d2 100644
--- a/libs/hwui/debug/NullGlesDriver.cpp
+++ b/libs/hwui/debug/NullGlesDriver.cpp
@@ -20,8 +20,10 @@ namespace android {
namespace uirenderer {
namespace debug {
+extern const GrGLInterface* CreateNullSkiaInterface();
+
sk_sp<const GrGLInterface> NullGlesDriver::getSkiaInterface() {
- sk_sp<const GrGLInterface> skiaInterface(GrGLCreateNullInterface());
+ sk_sp<const GrGLInterface> skiaInterface(CreateNullSkiaInterface());
return skiaInterface;
}
diff --git a/libs/hwui/debug/NullSkiaInterface.cpp b/libs/hwui/debug/NullSkiaInterface.cpp
new file mode 100644
index 000000000000..d141b9c0591b
--- /dev/null
+++ b/libs/hwui/debug/NullSkiaInterface.cpp
@@ -0,0 +1,1402 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// TODO: Remove this file. This has been temporarily copied from Skia (where this class is
+// deprecated). The NullGlesDriver should be constructing a GrGLInterface that calls *its*
+// GL functions!
+
+#include "GrNonAtomicRef.h"
+#include "SkMutex.h"
+#include "SkTDArray.h"
+#include "SkTo.h"
+#include "gl/GrGLDefines.h"
+#include "gl/GrGLInterface.h"
+
+#include <type_traits>
+
+// added to suppress 'no previous prototype' warning and because this code is duplicated in
+// SkNullGLContext.cpp
+namespace {
+
+class GLObject : public GrNonAtomicRef<GLObject> {
+public:
+ GLObject(GrGLuint id) : fID(id) {}
+ virtual ~GLObject() {}
+
+ GrGLuint id() const { return fID; }
+
+private:
+ GrGLuint fID;
+};
+
+// This class maintains a sparsely populated array of object pointers.
+template<typename T> class TGLObjectManager {
+ static_assert(std::is_convertible<T*, GLObject*>::value, "T must be a subclass of GLObject");
+
+public:
+ TGLObjectManager() : fFreeListHead(kFreeListEnd) {
+ *fGLObjects.append() = nullptr; // 0 is not a valid GL object id.
+ }
+
+ ~TGLObjectManager() {
+ // nullptr out the entries that are really free list links rather than ptrs before deleting.
+ intptr_t curr = fFreeListHead;
+ while (kFreeListEnd != curr) {
+ intptr_t next = reinterpret_cast<intptr_t>(fGLObjects[SkToS32(curr)]);
+ fGLObjects[SkToS32(curr)] = nullptr;
+ curr = next;
+ }
+
+ fGLObjects.safeUnrefAll();
+ }
+
+ T* lookUp(GrGLuint id) {
+ T* object = fGLObjects[id];
+ SkASSERT(object && object->id() == id);
+ return object;
+ }
+
+ T* create() {
+ GrGLuint id;
+ T* object;
+
+ if (kFreeListEnd == fFreeListHead) {
+ // no free slots - create a new one
+ id = fGLObjects.count();
+ object = new T(id);
+ *fGLObjects.append() = object;
+ } else {
+ // grab the head of the free list and advance the head to the next free slot.
+ id = static_cast<GrGLuint>(fFreeListHead);
+ fFreeListHead = reinterpret_cast<intptr_t>(fGLObjects[id]);
+
+ object = new T(id);
+ fGLObjects[id] = object;
+ }
+
+ return object;
+ }
+
+ void free(T* object) {
+ SkASSERT(object);
+ SkASSERT(fGLObjects.count() > 0);
+
+ GrGLuint id = object->id();
+ object->unref();
+
+ fGLObjects[id] = reinterpret_cast<T*>(fFreeListHead);
+ fFreeListHead = id;
+ }
+
+private:
+ static const intptr_t kFreeListEnd = -1;
+ // Index of the first entry of fGLObjects in the free list. Free slots in fGLObjects are indices
+ // to the next free slot. The last free slot has a value of kFreeListEnd.
+ intptr_t fFreeListHead;
+ SkTDArray<T*> fGLObjects;
+};
+
+class Buffer : public GLObject {
+public:
+ Buffer(GrGLuint id) : INHERITED(id), fDataPtr(nullptr), fSize(0), fMapped(false) {}
+ ~Buffer() { delete[] fDataPtr; }
+
+ void allocate(GrGLsizeiptr size, const GrGLchar* dataPtr) {
+ if (fDataPtr) {
+ SkASSERT(0 != fSize);
+ delete[] fDataPtr;
+ }
+
+ fSize = size;
+ fDataPtr = new char[size];
+ }
+
+ GrGLchar* dataPtr() { return fDataPtr; }
+ GrGLsizeiptr size() const { return fSize; }
+
+ void setMapped(bool mapped) { fMapped = mapped; }
+ bool mapped() const { return fMapped; }
+
+private:
+ GrGLchar* fDataPtr;
+ GrGLsizeiptr fSize; // size in bytes
+ bool fMapped;
+
+ typedef GLObject INHERITED;
+};
+
+class FramebufferAttachment : public GLObject {
+public:
+ int numSamples() const { return fNumSamples; }
+
+protected:
+ FramebufferAttachment(int id) : INHERITED(id), fNumSamples(1) {}
+
+ int fNumSamples;
+
+ typedef GLObject INHERITED;
+};
+
+class Renderbuffer : public FramebufferAttachment {
+public:
+ Renderbuffer(int id) : INHERITED(id) {}
+ void setNumSamples(int numSamples) { fNumSamples = numSamples; }
+
+private:
+ typedef FramebufferAttachment INHERITED;
+};
+
+class Texture : public FramebufferAttachment {
+public:
+ Texture() : INHERITED(1) {}
+
+private:
+ typedef FramebufferAttachment INHERITED;
+};
+
+class Framebuffer : public GLObject {
+public:
+ Framebuffer(int id) : INHERITED(id) {}
+
+ void setAttachment(GrGLenum attachmentPoint, const FramebufferAttachment* attachment) {
+ switch (attachmentPoint) {
+ default:
+ SK_ABORT("Invalid framebuffer attachment.");
+ break;
+ case GR_GL_STENCIL_ATTACHMENT:
+ fAttachments[(int)AttachmentPoint::kStencil].reset(SkRef(attachment));
+ break;
+ case GR_GL_DEPTH_ATTACHMENT:
+ fAttachments[(int)AttachmentPoint::kDepth].reset(SkRef(attachment));
+ break;
+ case GR_GL_COLOR_ATTACHMENT0:
+ fAttachments[(int)AttachmentPoint::kColor].reset(SkRef(attachment));
+ break;
+ }
+ }
+
+ void notifyAttachmentDeleteWhileBound(const FramebufferAttachment* deleted) {
+ for (auto& attachment : fAttachments) {
+ if (attachment.get() == deleted) {
+ attachment.reset(nullptr);
+ }
+ }
+ }
+
+ int numSamples() const {
+ int numSamples = 0;
+ for (auto& attachment : fAttachments) {
+ if (!attachment) {
+ continue;
+ }
+ if (numSamples) {
+ GrAlwaysAssert(attachment->numSamples() == numSamples);
+ continue;
+ }
+ numSamples = attachment->numSamples();
+ }
+ GrAlwaysAssert(numSamples);
+ return numSamples;
+ }
+
+private:
+ enum AttachmentPoint {
+ kStencil,
+ kDepth,
+ kColor
+ };
+ constexpr int static kNumAttachmentPoints = 1 + (int)AttachmentPoint::kColor;
+
+ sk_sp<const FramebufferAttachment> fAttachments[kNumAttachmentPoints];
+
+ typedef GLObject INHERITED;
+};
+
+class TestInterface : public GrGLInterface {
+public:
+ virtual GrGLvoid activeTexture(GrGLenum texture) {}
+ virtual GrGLvoid attachShader(GrGLuint program, GrGLuint shader) {}
+ virtual GrGLvoid beginQuery(GrGLenum target, GrGLuint id) {}
+ virtual GrGLvoid bindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {}
+ virtual GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) {}
+ virtual GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint framebuffer) {}
+ virtual GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {}
+ virtual GrGLvoid bindSampler(GrGLuint unit, GrGLuint sampler) {}
+ virtual GrGLvoid bindTexture(GrGLenum target, GrGLuint texture) {}
+ virtual GrGLvoid bindFragDataLocation(GrGLuint program, GrGLuint colorNumber, const GrGLchar* name) {}
+ virtual GrGLvoid bindFragDataLocationIndexed(GrGLuint program, GrGLuint colorNumber, GrGLuint index, const GrGLchar * name) {}
+ virtual GrGLvoid bindVertexArray(GrGLuint array) {}
+ virtual GrGLvoid blendBarrier() {}
+ virtual GrGLvoid blendColor(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha) {}
+ virtual GrGLvoid blendEquation(GrGLenum mode) {}
+ virtual GrGLvoid blendFunc(GrGLenum sfactor, GrGLenum dfactor) {}
+ virtual GrGLvoid blitFramebuffer(GrGLint srcX0, GrGLint srcY0, GrGLint srcX1, GrGLint srcY1, GrGLint dstX0, GrGLint dstY0, GrGLint dstX1, GrGLint dstY1, GrGLbitfield mask, GrGLenum filter) {}
+ virtual GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage) {}
+ virtual GrGLvoid bufferSubData(GrGLenum target, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid* data) {}
+ virtual GrGLenum checkFramebufferStatus(GrGLenum target) { return GR_GL_FRAMEBUFFER_COMPLETE; }
+ virtual GrGLvoid clear(GrGLbitfield mask) {}
+ virtual GrGLvoid clearColor(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha) {}
+ virtual GrGLvoid clearStencil(GrGLint s) {}
+ virtual GrGLvoid colorMask(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha) {}
+ virtual GrGLvoid compileShader(GrGLuint shader) {}
+ virtual GrGLvoid compressedTexImage2D(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data) {}
+ virtual GrGLvoid compressedTexSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLsizei imageSize, const GrGLvoid* data) {}
+ virtual GrGLvoid copyTexSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLuint createProgram() { return 0; }
+ virtual GrGLuint createShader(GrGLenum type) { return 0; }
+ virtual GrGLvoid cullFace(GrGLenum mode) {}
+ virtual GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* buffers) {}
+ virtual GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {}
+ virtual GrGLvoid deleteProgram(GrGLuint program) {}
+ virtual GrGLvoid deleteQueries(GrGLsizei n, const GrGLuint *ids) {}
+ virtual GrGLvoid deleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {}
+ virtual GrGLvoid deleteSamplers(GrGLsizei n, const GrGLuint* samplers) {}
+ virtual GrGLvoid deleteShader(GrGLuint shader) {}
+ virtual GrGLvoid deleteTextures(GrGLsizei n, const GrGLuint* textures) {}
+ virtual GrGLvoid deleteVertexArrays(GrGLsizei n, const GrGLuint *arrays) {}
+ virtual GrGLvoid depthMask(GrGLboolean flag) {}
+ virtual GrGLvoid disable(GrGLenum cap) {}
+ virtual GrGLvoid disableVertexAttribArray(GrGLuint index) {}
+ virtual GrGLvoid drawArrays(GrGLenum mode, GrGLint first, GrGLsizei count) {}
+ virtual GrGLvoid drawArraysInstanced(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount) {}
+ virtual GrGLvoid drawArraysIndirect(GrGLenum mode, const GrGLvoid* indirect) {}
+ virtual GrGLvoid drawBuffer(GrGLenum mode) {}
+ virtual GrGLvoid drawBuffers(GrGLsizei n, const GrGLenum* bufs) {}
+ virtual GrGLvoid drawElements(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices) {}
+ virtual GrGLvoid drawElementsInstanced(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount) {}
+ virtual GrGLvoid drawElementsIndirect(GrGLenum mode, GrGLenum type, const GrGLvoid* indirect) {}
+ virtual GrGLvoid drawRangeElements(GrGLenum mode, GrGLuint start, GrGLuint end, GrGLsizei count, GrGLenum type, const GrGLvoid* indices) {}
+ virtual GrGLvoid enable(GrGLenum cap) {}
+ virtual GrGLvoid enableVertexAttribArray(GrGLuint index) {}
+ virtual GrGLvoid endQuery(GrGLenum target) {}
+ virtual GrGLvoid finish() {}
+ virtual GrGLvoid flush() {}
+ virtual GrGLvoid flushMappedBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length) {}
+ virtual GrGLvoid framebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
+ virtual GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
+ virtual GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level, GrGLsizei samples) {}
+ virtual GrGLvoid frontFace(GrGLenum mode) {}
+ virtual GrGLvoid genBuffers(GrGLsizei n, GrGLuint* buffers) {}
+ virtual GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) {}
+ virtual GrGLvoid generateMipmap(GrGLenum target) {}
+ virtual GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) {}
+ virtual GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) {}
+ virtual GrGLvoid genSamplers(GrGLsizei n, GrGLuint *samplers) {}
+ virtual GrGLvoid genTextures(GrGLsizei n, GrGLuint* textures) {}
+ virtual GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) {}
+ virtual GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLenum getError() { return GR_GL_NO_ERROR; }
+ virtual GrGLvoid getFramebufferAttachmentParameteriv(GrGLenum target, GrGLenum attachment, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) {}
+ virtual GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) {}
+ virtual GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, char* infolog) {}
+ virtual GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) {}
+ virtual GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) {}
+ virtual GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) {}
+ virtual GrGLvoid getRenderbufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length, char* infolog) {}
+ virtual GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLvoid getShaderPrecisionFormat(GrGLenum shadertype, GrGLenum precisiontype, GrGLint *range, GrGLint *precision) {}
+ virtual const GrGLubyte* getString(GrGLenum name) { return nullptr; }
+ virtual const GrGLubyte* getStringi(GrGLenum name, GrGLuint index) { return nullptr; }
+ virtual GrGLvoid getTexLevelParameteriv(GrGLenum target, GrGLint level, GrGLenum pname, GrGLint* params) {}
+ virtual GrGLint getUniformLocation(GrGLuint program, const char* name) { return 0; }
+ virtual GrGLvoid insertEventMarker(GrGLsizei length, const char* marker) {}
+ virtual GrGLvoid invalidateBufferData(GrGLuint buffer) {}
+ virtual GrGLvoid invalidateBufferSubData(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length) {}
+ virtual GrGLvoid invalidateFramebuffer(GrGLenum target, GrGLsizei numAttachments, const GrGLenum *attachments) {}
+ virtual GrGLvoid invalidateSubFramebuffer(GrGLenum target, GrGLsizei numAttachments, const GrGLenum *attachments, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid invalidateTexImage(GrGLuint texture, GrGLint level) {}
+ virtual GrGLvoid invalidateTexSubImage(GrGLuint texture, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLsizei width, GrGLsizei height, GrGLsizei depth) {}
+ virtual GrGLboolean isTexture(GrGLuint texture) { return GR_GL_FALSE; }
+ virtual GrGLvoid lineWidth(GrGLfloat width) {}
+ virtual GrGLvoid linkProgram(GrGLuint program) {}
+ virtual GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) { return nullptr; }
+ virtual GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access) { return nullptr; }
+ virtual GrGLvoid* mapBufferSubData(GrGLuint target, GrGLintptr offset, GrGLsizeiptr size, GrGLenum access) { return nullptr; }
+ virtual GrGLvoid* mapTexSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLenum access) { return nullptr; }
+ virtual GrGLvoid pixelStorei(GrGLenum pname, GrGLint param) {}
+ virtual GrGLvoid polygonMode(GrGLenum face, GrGLenum mode) {}
+ virtual GrGLvoid popGroupMarker() {}
+ virtual GrGLvoid pushGroupMarker(GrGLsizei length, const char* marker) {}
+ virtual GrGLvoid queryCounter(GrGLuint id, GrGLenum target) {}
+ virtual GrGLvoid rasterSamples(GrGLuint samples, GrGLboolean fixedsamplelocations) {}
+ virtual GrGLvoid readBuffer(GrGLenum src) {}
+ virtual GrGLvoid readPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {}
+ virtual GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid resolveMultisampleFramebuffer() {}
+ virtual GrGLvoid samplerParameteri(GrGLuint sampler, GrGLenum pname, GrGLint param) {}
+ virtual GrGLvoid samplerParameteriv(GrGLuint sampler, GrGLenum pname, const GrGLint* param) {}
+ virtual GrGLvoid scissor(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid bindUniformLocation(GrGLuint program, GrGLint location, const char* name) {}
+ virtual GrGLvoid shaderSource(GrGLuint shader, GrGLsizei count, const char* const * str, const GrGLint* length) {}
+ virtual GrGLvoid stencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask) {}
+ virtual GrGLvoid stencilFuncSeparate(GrGLenum face, GrGLenum func, GrGLint ref, GrGLuint mask) {}
+ virtual GrGLvoid stencilMask(GrGLuint mask) {}
+ virtual GrGLvoid stencilMaskSeparate(GrGLenum face, GrGLuint mask) {}
+ virtual GrGLvoid stencilOp(GrGLenum fail, GrGLenum zfail, GrGLenum zpass) {}
+ virtual GrGLvoid stencilOpSeparate(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass) {}
+ virtual GrGLvoid texBuffer(GrGLenum target, GrGLenum internalformat, GrGLuint buffer) {}
+ virtual GrGLvoid texImage2D(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels) {}
+ virtual GrGLvoid texParameterf(GrGLenum target, GrGLenum pname, GrGLfloat param) {}
+ virtual GrGLvoid texParameterfv(GrGLenum target, GrGLenum pname, const GrGLfloat* params) {}
+ virtual GrGLvoid texParameteri(GrGLenum target, GrGLenum pname, GrGLint param) {}
+ virtual GrGLvoid texParameteriv(GrGLenum target, GrGLenum pname, const GrGLint* params) {}
+ virtual GrGLvoid texStorage2D(GrGLenum target, GrGLsizei levels, GrGLenum internalformat, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid discardFramebuffer(GrGLenum target, GrGLsizei numAttachments, const GrGLenum* attachments) {}
+ virtual GrGLvoid texSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels) {}
+ virtual GrGLvoid textureBarrier() {}
+ virtual GrGLvoid uniform1f(GrGLint location, GrGLfloat v0) {}
+ virtual GrGLvoid uniform1i(GrGLint location, GrGLint v0) {}
+ virtual GrGLvoid uniform1fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
+ virtual GrGLvoid uniform1iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
+ virtual GrGLvoid uniform2f(GrGLint location, GrGLfloat v0, GrGLfloat v1) {}
+ virtual GrGLvoid uniform2i(GrGLint location, GrGLint v0, GrGLint v1) {}
+ virtual GrGLvoid uniform2fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
+ virtual GrGLvoid uniform2iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
+ virtual GrGLvoid uniform3f(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2) {}
+ virtual GrGLvoid uniform3i(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2) {}
+ virtual GrGLvoid uniform3fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
+ virtual GrGLvoid uniform3iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
+ virtual GrGLvoid uniform4f(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2, GrGLfloat v3) {}
+ virtual GrGLvoid uniform4i(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2, GrGLint v3) {}
+ virtual GrGLvoid uniform4fv(GrGLint location, GrGLsizei count, const GrGLfloat* v) {}
+ virtual GrGLvoid uniform4iv(GrGLint location, GrGLsizei count, const GrGLint* v) {}
+ virtual GrGLvoid uniformMatrix2fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
+ virtual GrGLvoid uniformMatrix3fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
+ virtual GrGLvoid uniformMatrix4fv(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value) {}
+ virtual GrGLboolean unmapBuffer(GrGLenum target) { return GR_GL_TRUE; }
+ virtual GrGLvoid unmapBufferSubData(const GrGLvoid* mem) {}
+ virtual GrGLvoid unmapTexSubImage2D(const GrGLvoid* mem) {}
+ virtual GrGLvoid useProgram(GrGLuint program) {}
+ virtual GrGLvoid vertexAttrib1f(GrGLuint indx, const GrGLfloat value) {}
+ virtual GrGLvoid vertexAttrib2fv(GrGLuint indx, const GrGLfloat* values) {}
+ virtual GrGLvoid vertexAttrib3fv(GrGLuint indx, const GrGLfloat* values) {}
+ virtual GrGLvoid vertexAttrib4fv(GrGLuint indx, const GrGLfloat* values) {}
+ virtual GrGLvoid vertexAttribDivisor(GrGLuint index, GrGLuint divisor) {}
+ virtual GrGLvoid vertexAttribIPointer(GrGLuint indx, GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* ptr) {}
+ virtual GrGLvoid vertexAttribPointer(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr) {}
+ virtual GrGLvoid viewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid matrixLoadf(GrGLenum matrixMode, const GrGLfloat* m) {}
+ virtual GrGLvoid matrixLoadIdentity(GrGLenum) {}
+ virtual GrGLvoid pathCommands(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords) {}
+ virtual GrGLvoid pathParameteri(GrGLuint path, GrGLenum pname, GrGLint value) {}
+ virtual GrGLvoid pathParameterf(GrGLuint path, GrGLenum pname, GrGLfloat value) {}
+ virtual GrGLuint genPaths(GrGLsizei range) { return 0; }
+ virtual GrGLvoid deletePaths(GrGLuint path, GrGLsizei range) {}
+ virtual GrGLboolean isPath(GrGLuint path) { return true; }
+ virtual GrGLvoid pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask) {}
+ virtual GrGLvoid stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask) {}
+ virtual GrGLvoid stencilStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask) {}
+ virtual GrGLvoid stencilFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues) {}
+ virtual GrGLvoid stencilStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues) {}
+ virtual GrGLvoid coverFillPath(GrGLuint path, GrGLenum coverMode) {}
+ virtual GrGLvoid coverStrokePath(GrGLuint name, GrGLenum coverMode) {}
+ virtual GrGLvoid coverFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) {}
+ virtual GrGLvoid coverStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues) {}
+ virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode) {}
+ virtual GrGLvoid stencilThenCoverStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask, GrGLenum coverMode) {}
+ virtual GrGLvoid stencilThenCoverFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) {}
+ virtual GrGLvoid stencilThenCoverStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) {}
+ virtual GrGLvoid programPathFragmentInputGen(GrGLuint program, GrGLint location, GrGLenum genMode, GrGLint components,const GrGLfloat *coeffs) {}
+ virtual GrGLvoid bindFragmentInputLocation(GrGLuint program, GrGLint location, const GrGLchar* name) {}
+ virtual GrGLint getProgramResourceLocation(GrGLuint program, GrGLenum programInterface, const GrGLchar *name) { return 0; }
+ virtual GrGLvoid coverageModulation(GrGLenum components) {}
+ virtual GrGLvoid multiDrawArraysIndirect(GrGLenum mode, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride) {}
+ virtual GrGLvoid multiDrawElementsIndirect(GrGLenum mode, GrGLenum type, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride) {}
+ virtual GrGLuint64 getTextureHandle(GrGLuint texture) { return 0; }
+ virtual GrGLuint64 getTextureSamplerHandle(GrGLuint texture, GrGLuint sampler) { return 0; }
+ virtual GrGLvoid makeTextureHandleResident(GrGLuint64 handle) {}
+ virtual GrGLvoid makeTextureHandleNonResident(GrGLuint64 handle) {}
+ virtual GrGLuint64 getImageHandle(GrGLuint texture, GrGLint level, GrGLboolean layered, GrGLint layer, GrGLint format) { return 0; }
+ virtual GrGLvoid makeImageHandleResident(GrGLuint64 handle, GrGLenum access) {}
+ virtual GrGLvoid makeImageHandleNonResident(GrGLuint64 handle) {}
+ virtual GrGLboolean isTextureHandleResident(GrGLuint64 handle) { return GR_GL_FALSE; }
+ virtual GrGLboolean isImageHandleResident(GrGLuint64 handle) { return GR_GL_FALSE; }
+ virtual GrGLvoid uniformHandleui64(GrGLint location, GrGLuint64 v0) {}
+ virtual GrGLvoid uniformHandleui64v(GrGLint location, GrGLsizei count, const GrGLuint64 *value) {}
+ virtual GrGLvoid programUniformHandleui64(GrGLuint program, GrGLint location, GrGLuint64 v0) {}
+ virtual GrGLvoid programUniformHandleui64v(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLuint64 *value) {}
+ virtual GrGLvoid textureParameteri(GrGLuint texture, GrGLenum target, GrGLenum pname, GrGLint param) {}
+ virtual GrGLvoid textureParameteriv(GrGLuint texture, GrGLenum target, GrGLenum pname, const GrGLint *param) {}
+ virtual GrGLvoid textureParameterf(GrGLuint texture, GrGLenum target, GrGLenum pname, float param) {}
+ virtual GrGLvoid textureParameterfv(GrGLuint texture, GrGLenum target, GrGLenum pname, const float *param) {}
+ virtual GrGLvoid textureImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint GrGLinternalformat, GrGLsizei width, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid textureImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint GrGLinternalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid textureSubImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLsizei width, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid textureSubImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid copyTextureImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum GrGLinternalformat, GrGLint x, GrGLint y, GrGLsizei width, GrGLint border) {}
+ virtual GrGLvoid copyTextureImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum GrGLinternalformat, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLint border) {}
+ virtual GrGLvoid copyTextureSubImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint x, GrGLint y, GrGLsizei width) {}
+ virtual GrGLvoid copyTextureSubImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid getTextureImage(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum format, GrGLenum type, GrGLvoid *pixels) {}
+ virtual GrGLvoid getTextureParameterfv(GrGLuint texture, GrGLenum target, GrGLenum pname, float *params) {}
+ virtual GrGLvoid getTextureParameteriv(GrGLuint texture, GrGLenum target, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid getTextureLevelParameterfv(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum pname, float *params) {}
+ virtual GrGLvoid getTextureLevelParameteriv(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid textureImage3D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint GrGLinternalformat, GrGLsizei width, GrGLsizei height, GrGLsizei depth, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid textureSubImage3D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLsizei width, GrGLsizei height, GrGLsizei depth, GrGLenum format, GrGLenum type, const GrGLvoid *pixels) {}
+ virtual GrGLvoid copyTextureSubImage3D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid compressedTextureImage3D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum GrGLinternalformat, GrGLsizei width, GrGLsizei height, GrGLsizei depth, GrGLint border, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid compressedTextureImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum GrGLinternalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid compressedTextureImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLenum GrGLinternalformat, GrGLsizei width, GrGLint border, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid compressedTextureSubImage3D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLsizei width, GrGLsizei height, GrGLsizei depth, GrGLenum format, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid compressedTextureSubImage2D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid compressedTextureSubImage1D(GrGLuint texture, GrGLenum target, GrGLint level, GrGLint xoffset, GrGLsizei width, GrGLenum format, GrGLsizei imageSize, const GrGLvoid *data) {}
+ virtual GrGLvoid getCompressedTextureImage(GrGLuint texture, GrGLenum target, GrGLint level, GrGLvoid *img) {}
+ virtual GrGLvoid namedBufferData(GrGLuint buffer, GrGLsizeiptr size, const GrGLvoid *data, GrGLenum usage) {}
+ virtual GrGLvoid namedBufferSubData(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid *data) {}
+ virtual GrGLvoid* mapNamedBuffer(GrGLuint buffer, GrGLenum access) { return nullptr; }
+ virtual GrGLboolean unmapNamedBuffer(GrGLuint buffer) { return GR_GL_FALSE; }
+ virtual GrGLvoid getNamedBufferParameteriv(GrGLuint buffer, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid getNamedBufferPointerv(GrGLuint buffer, GrGLenum pname, GrGLvoid* *params) {}
+ virtual GrGLvoid getNamedBufferSubData(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr size, GrGLvoid *data) {}
+ virtual GrGLvoid programUniform1f(GrGLuint program, GrGLint location, float v0) {}
+ virtual GrGLvoid programUniform2f(GrGLuint program, GrGLint location, float v0, float v1) {}
+ virtual GrGLvoid programUniform3f(GrGLuint program, GrGLint location, float v0, float v1, float v2) {}
+ virtual GrGLvoid programUniform4f(GrGLuint program, GrGLint location, float v0, float v1, float v2, float v3) {}
+ virtual GrGLvoid programUniform1i(GrGLuint program, GrGLint location, GrGLint v0) {}
+ virtual GrGLvoid programUniform2i(GrGLuint program, GrGLint location, GrGLint v0, GrGLint v1) {}
+ virtual GrGLvoid programUniform3i(GrGLuint program, GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2) {}
+ virtual GrGLvoid programUniform4i(GrGLuint program, GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2, GrGLint v3) {}
+ virtual GrGLvoid programUniform1fv(GrGLuint program, GrGLint location, GrGLsizei count, const float *value) {}
+ virtual GrGLvoid programUniform2fv(GrGLuint program, GrGLint location, GrGLsizei count, const float *value) {}
+ virtual GrGLvoid programUniform3fv(GrGLuint program, GrGLint location, GrGLsizei count, const float *value) {}
+ virtual GrGLvoid programUniform4fv(GrGLuint program, GrGLint location, GrGLsizei count, const float *value) {}
+ virtual GrGLvoid programUniform1iv(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLint *value) {}
+ virtual GrGLvoid programUniform2iv(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLint *value) {}
+ virtual GrGLvoid programUniform3iv(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLint *value) {}
+ virtual GrGLvoid programUniform4iv(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLint *value) {}
+ virtual GrGLvoid programUniformMatrix2fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix3fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix4fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix2x3fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix3x2fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix2x4fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix4x2fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix3x4fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid programUniformMatrix4x3fv(GrGLuint program, GrGLint location, GrGLsizei count, GrGLboolean transpose, const float *value) {}
+ virtual GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLvoid getNamedRenderbufferParameteriv(GrGLuint renderbuffer, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples, GrGLenum GrGLinternalformat, GrGLsizei width, GrGLsizei height) {}
+ virtual GrGLenum checkNamedFramebufferStatus(GrGLuint framebuffer, GrGLenum target) { return GR_GL_FRAMEBUFFER_COMPLETE; }
+ virtual GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
+ virtual GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
+ virtual GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level, GrGLint zoffset) {}
+ virtual GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
+ virtual GrGLvoid getNamedFramebufferAttachmentParameteriv(GrGLuint framebuffer, GrGLenum attachment, GrGLenum pname, GrGLint *params) {}
+ virtual GrGLvoid generateTextureMipmap(GrGLuint texture, GrGLenum target) {}
+ virtual GrGLvoid framebufferDrawBuffer(GrGLuint framebuffer, GrGLenum mode) {}
+ virtual GrGLvoid framebufferDrawBuffers(GrGLuint framebuffer, GrGLsizei n, const GrGLenum *bufs) {}
+ virtual GrGLvoid framebufferReadBuffer(GrGLuint framebuffer, GrGLenum mode) {}
+ virtual GrGLvoid getFramebufferParameteriv(GrGLuint framebuffer, GrGLenum pname, GrGLint *param) {}
+ virtual GrGLvoid namedCopyBufferSubData(GrGLuint readBuffer, GrGLuint writeBuffer, GrGLintptr readOffset, GrGLintptr writeOffset, GrGLsizeiptr size) {}
+ virtual GrGLvoid vertexArrayVertexOffset(GrGLuint vaobj, GrGLuint buffer, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayColorOffset(GrGLuint vaobj, GrGLuint buffer, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayEdgeFlagOffset(GrGLuint vaobj, GrGLuint buffer, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayIndexOffset(GrGLuint vaobj, GrGLuint buffer, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayNormalOffset(GrGLuint vaobj, GrGLuint buffer, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayTexCoordOffset(GrGLuint vaobj, GrGLuint buffer, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayMultiTexCoordOffset(GrGLuint vaobj, GrGLuint buffer, GrGLenum texunit, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayFogCoordOffset(GrGLuint vaobj, GrGLuint buffer, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArraySecondaryColorOffset(GrGLuint vaobj, GrGLuint buffer, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayVertexAttribOffset(GrGLuint vaobj, GrGLuint buffer, GrGLuint index, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid vertexArrayVertexAttribIOffset(GrGLuint vaobj, GrGLuint buffer, GrGLuint index, GrGLint size, GrGLenum type, GrGLsizei stride, GrGLintptr offset) {}
+ virtual GrGLvoid enableVertexArray(GrGLuint vaobj, GrGLenum array) {}
+ virtual GrGLvoid disableVertexArray(GrGLuint vaobj, GrGLenum array) {}
+ virtual GrGLvoid enableVertexArrayAttrib(GrGLuint vaobj, GrGLuint index) {}
+ virtual GrGLvoid disableVertexArrayAttrib(GrGLuint vaobj, GrGLuint index) {}
+ virtual GrGLvoid getVertexArrayIntegerv(GrGLuint vaobj, GrGLenum pname, GrGLint *param) {}
+ virtual GrGLvoid getVertexArrayPointerv(GrGLuint vaobj, GrGLenum pname, GrGLvoid **param) {}
+ virtual GrGLvoid getVertexArrayIntegeri_v(GrGLuint vaobj, GrGLuint index, GrGLenum pname, GrGLint *param) {}
+ virtual GrGLvoid getVertexArrayPointeri_v(GrGLuint vaobj, GrGLuint index, GrGLenum pname, GrGLvoid **param) {}
+ virtual GrGLvoid* mapNamedBufferRange(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access) { return nullptr; }
+ virtual GrGLvoid flushMappedNamedBufferRange(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length) {}
+ virtual GrGLvoid textureBuffer(GrGLuint texture, GrGLenum target, GrGLenum internalformat, GrGLuint buffer) {}
+ virtual GrGLsync fenceSync(GrGLenum condition, GrGLbitfield flags) { return nullptr; }
+ virtual GrGLboolean isSync(GrGLsync) { return false; }
+ virtual GrGLenum clientWaitSync(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout) { return GR_GL_WAIT_FAILED; }
+ virtual GrGLvoid waitSync(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout) {}
+ virtual GrGLvoid deleteSync(GrGLsync sync) {}
+ virtual GrGLvoid debugMessageControl(GrGLenum source, GrGLenum type, GrGLenum severity, GrGLsizei count, const GrGLuint* ids, GrGLboolean enabled) {}
+ virtual GrGLvoid debugMessageInsert(GrGLenum source, GrGLenum type, GrGLuint id, GrGLenum severity, GrGLsizei length, const GrGLchar* buf) {}
+ virtual GrGLvoid debugMessageCallback(GRGLDEBUGPROC callback, const GrGLvoid* userParam) {}
+ virtual GrGLuint getDebugMessageLog(GrGLuint count, GrGLsizei bufSize, GrGLenum* sources, GrGLenum* types, GrGLuint* ids, GrGLenum* severities, GrGLsizei* lengths, GrGLchar* messageLog) { return 0; }
+ virtual GrGLvoid pushDebugGroup(GrGLenum source, GrGLuint id, GrGLsizei length, const GrGLchar * message) {}
+ virtual GrGLvoid popDebugGroup() {}
+ virtual GrGLvoid objectLabel(GrGLenum identifier, GrGLuint name, GrGLsizei length, const GrGLchar *label) {}
+ virtual GrGLvoid getInternalformativ(GrGLenum target, GrGLenum internalformat, GrGLenum pname, GrGLsizei bufSize, GrGLint *params) {}
+ virtual GrGLvoid programBinary(GrGLuint program, GrGLenum binaryFormat, void *binary, GrGLsizei length) {}
+ virtual GrGLvoid getProgramBinary(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, GrGLenum *binaryFormat, void *binary) {}
+ virtual GrGLvoid programParameteri(GrGLuint program, GrGLenum pname, GrGLint value) {}
+
+protected:
+ // This must be called by leaf class
+ void init(GrGLStandard standard) {
+ fStandard = standard;
+ fExtensions.init(standard, fFunctions.fGetString, fFunctions.fGetStringi,
+ fFunctions.fGetIntegerv, nullptr, GR_EGL_NO_DISPLAY);
+ }
+ TestInterface();
+};
+
+template <typename R, typename... A>
+GrGLFunction<R GR_GL_FUNCTION_TYPE(A...)> bind_to_member(TestInterface* interface,
+ R (TestInterface::*member)(A...)) {
+ return [interface, member](A... a) -> R { return (interface->*member)(a...); };
+}
+
+TestInterface::TestInterface() {
+ fFunctions.fActiveTexture = bind_to_member(this, &TestInterface::activeTexture);
+ fFunctions.fAttachShader = bind_to_member(this, &TestInterface::attachShader);
+ fFunctions.fBeginQuery = bind_to_member(this, &TestInterface::beginQuery);
+ fFunctions.fBindAttribLocation = bind_to_member(this, &TestInterface::bindAttribLocation);
+ fFunctions.fBindBuffer = bind_to_member(this, &TestInterface::bindBuffer);
+ fFunctions.fBindFramebuffer = bind_to_member(this, &TestInterface::bindFramebuffer);
+ fFunctions.fBindRenderbuffer = bind_to_member(this, &TestInterface::bindRenderbuffer);
+ fFunctions.fBindSampler = bind_to_member(this, &TestInterface::bindSampler);
+ fFunctions.fBindTexture = bind_to_member(this, &TestInterface::bindTexture);
+ fFunctions.fBindFragDataLocation = bind_to_member(this, &TestInterface::bindFragDataLocation);
+ fFunctions.fBindFragDataLocationIndexed = bind_to_member(this, &TestInterface::bindFragDataLocationIndexed);
+ fFunctions.fBindVertexArray = bind_to_member(this, &TestInterface::bindVertexArray);
+ fFunctions.fBlendBarrier = bind_to_member(this, &TestInterface::blendBarrier);
+ fFunctions.fBlendColor = bind_to_member(this, &TestInterface::blendColor);
+ fFunctions.fBlendEquation = bind_to_member(this, &TestInterface::blendEquation);
+ fFunctions.fBlendFunc = bind_to_member(this, &TestInterface::blendFunc);
+ fFunctions.fBlitFramebuffer = bind_to_member(this, &TestInterface::blitFramebuffer);
+ fFunctions.fBufferData = bind_to_member(this, &TestInterface::bufferData);
+ fFunctions.fBufferSubData = bind_to_member(this, &TestInterface::bufferSubData);
+ fFunctions.fCheckFramebufferStatus = bind_to_member(this, &TestInterface::checkFramebufferStatus);
+ fFunctions.fClear = bind_to_member(this, &TestInterface::clear);
+ fFunctions.fClearColor = bind_to_member(this, &TestInterface::clearColor);
+ fFunctions.fClearStencil = bind_to_member(this, &TestInterface::clearStencil);
+ fFunctions.fColorMask = bind_to_member(this, &TestInterface::colorMask);
+ fFunctions.fCompileShader = bind_to_member(this, &TestInterface::compileShader);
+ fFunctions.fCompressedTexImage2D = bind_to_member(this, &TestInterface::compressedTexImage2D);
+ fFunctions.fCompressedTexSubImage2D = bind_to_member(this, &TestInterface::compressedTexSubImage2D);
+ fFunctions.fCopyTexSubImage2D = bind_to_member(this, &TestInterface::copyTexSubImage2D);
+ fFunctions.fCreateProgram = bind_to_member(this, &TestInterface::createProgram);
+ fFunctions.fCreateShader = bind_to_member(this, &TestInterface::createShader);
+ fFunctions.fCullFace = bind_to_member(this, &TestInterface::cullFace);
+ fFunctions.fDeleteBuffers = bind_to_member(this, &TestInterface::deleteBuffers);
+ fFunctions.fDeleteFramebuffers = bind_to_member(this, &TestInterface::deleteFramebuffers);
+ fFunctions.fDeleteProgram = bind_to_member(this, &TestInterface::deleteProgram);
+ fFunctions.fDeleteQueries = bind_to_member(this, &TestInterface::deleteQueries);
+ fFunctions.fDeleteRenderbuffers = bind_to_member(this, &TestInterface::deleteRenderbuffers);
+ fFunctions.fDeleteSamplers = bind_to_member(this, &TestInterface::deleteSamplers);
+ fFunctions.fDeleteShader = bind_to_member(this, &TestInterface::deleteShader);
+ fFunctions.fDeleteTextures = bind_to_member(this, &TestInterface::deleteTextures);
+ fFunctions.fDeleteVertexArrays = bind_to_member(this, &TestInterface::deleteVertexArrays);
+ fFunctions.fDepthMask = bind_to_member(this, &TestInterface::depthMask);
+ fFunctions.fDisable = bind_to_member(this, &TestInterface::disable);
+ fFunctions.fDisableVertexAttribArray = bind_to_member(this, &TestInterface::disableVertexAttribArray);
+ fFunctions.fDrawArrays = bind_to_member(this, &TestInterface::drawArrays);
+ fFunctions.fDrawArraysInstanced = bind_to_member(this, &TestInterface::drawArraysInstanced);
+ fFunctions.fDrawArraysIndirect = bind_to_member(this, &TestInterface::drawArraysIndirect);
+ fFunctions.fDrawBuffer = bind_to_member(this, &TestInterface::drawBuffer);
+ fFunctions.fDrawBuffers = bind_to_member(this, &TestInterface::drawBuffers);
+ fFunctions.fDrawElements = bind_to_member(this, &TestInterface::drawElements);
+ fFunctions.fDrawElementsInstanced = bind_to_member(this, &TestInterface::drawElementsInstanced);
+ fFunctions.fDrawElementsIndirect = bind_to_member(this, &TestInterface::drawElementsIndirect);
+ fFunctions.fDrawRangeElements = bind_to_member(this, &TestInterface::drawRangeElements);
+ fFunctions.fEnable = bind_to_member(this, &TestInterface::enable);
+ fFunctions.fEnableVertexAttribArray = bind_to_member(this, &TestInterface::enableVertexAttribArray);
+ fFunctions.fEndQuery = bind_to_member(this, &TestInterface::endQuery);
+ fFunctions.fFinish = bind_to_member(this, &TestInterface::finish);
+ fFunctions.fFlush = bind_to_member(this, &TestInterface::flush);
+ fFunctions.fFlushMappedBufferRange = bind_to_member(this, &TestInterface::flushMappedBufferRange);
+ fFunctions.fFramebufferRenderbuffer = bind_to_member(this, &TestInterface::framebufferRenderbuffer);
+ fFunctions.fFramebufferTexture2D = bind_to_member(this, &TestInterface::framebufferTexture2D);
+ fFunctions.fFramebufferTexture2DMultisample = bind_to_member(this, &TestInterface::framebufferTexture2DMultisample);
+ fFunctions.fFrontFace = bind_to_member(this, &TestInterface::frontFace);
+ fFunctions.fGenBuffers = bind_to_member(this, &TestInterface::genBuffers);
+ fFunctions.fGenFramebuffers = bind_to_member(this, &TestInterface::genFramebuffers);
+ fFunctions.fGenerateMipmap = bind_to_member(this, &TestInterface::generateMipmap);
+ fFunctions.fGenQueries = bind_to_member(this, &TestInterface::genQueries);
+ fFunctions.fGenRenderbuffers = bind_to_member(this, &TestInterface::genRenderbuffers);
+ fFunctions.fGenSamplers = bind_to_member(this, &TestInterface::genSamplers);
+ fFunctions.fGenTextures = bind_to_member(this, &TestInterface::genTextures);
+ fFunctions.fGenVertexArrays = bind_to_member(this, &TestInterface::genVertexArrays);
+ fFunctions.fGetBufferParameteriv = bind_to_member(this, &TestInterface::getBufferParameteriv);
+ fFunctions.fGetError = bind_to_member(this, &TestInterface::getError);
+ fFunctions.fGetFramebufferAttachmentParameteriv = bind_to_member(this, &TestInterface::getFramebufferAttachmentParameteriv);
+ fFunctions.fGetIntegerv = bind_to_member(this, &TestInterface::getIntegerv);
+ fFunctions.fGetMultisamplefv = bind_to_member(this, &TestInterface::getMultisamplefv);
+ fFunctions.fGetProgramInfoLog = bind_to_member(this, &TestInterface::getProgramInfoLog);
+ fFunctions.fGetProgramiv = bind_to_member(this, &TestInterface::getProgramiv);
+ fFunctions.fGetQueryiv = bind_to_member(this, &TestInterface::getQueryiv);
+ fFunctions.fGetQueryObjecti64v = bind_to_member(this, &TestInterface::getQueryObjecti64v);
+ fFunctions.fGetQueryObjectiv = bind_to_member(this, &TestInterface::getQueryObjectiv);
+ fFunctions.fGetQueryObjectui64v = bind_to_member(this, &TestInterface::getQueryObjectui64v);
+ fFunctions.fGetQueryObjectuiv = bind_to_member(this, &TestInterface::getQueryObjectuiv);
+ fFunctions.fGetRenderbufferParameteriv = bind_to_member(this, &TestInterface::getRenderbufferParameteriv);
+ fFunctions.fGetShaderInfoLog = bind_to_member(this, &TestInterface::getShaderInfoLog);
+ fFunctions.fGetShaderiv = bind_to_member(this, &TestInterface::getShaderiv);
+ fFunctions.fGetShaderPrecisionFormat = bind_to_member(this, &TestInterface::getShaderPrecisionFormat);
+ fFunctions.fGetString = bind_to_member(this, &TestInterface::getString);
+ fFunctions.fGetStringi = bind_to_member(this, &TestInterface::getStringi);
+ fFunctions.fGetTexLevelParameteriv = bind_to_member(this, &TestInterface::getTexLevelParameteriv);
+ fFunctions.fGetUniformLocation = bind_to_member(this, &TestInterface::getUniformLocation);
+ fFunctions.fInsertEventMarker = bind_to_member(this, &TestInterface::insertEventMarker);
+ fFunctions.fInvalidateBufferData = bind_to_member(this, &TestInterface::invalidateBufferData);
+ fFunctions.fInvalidateBufferSubData = bind_to_member(this, &TestInterface::invalidateBufferSubData);
+ fFunctions.fInvalidateFramebuffer = bind_to_member(this, &TestInterface::invalidateFramebuffer);
+ fFunctions.fInvalidateSubFramebuffer = bind_to_member(this, &TestInterface::invalidateSubFramebuffer);
+ fFunctions.fInvalidateTexImage = bind_to_member(this, &TestInterface::invalidateTexImage);
+ fFunctions.fInvalidateTexSubImage = bind_to_member(this, &TestInterface::invalidateTexSubImage);
+ fFunctions.fIsTexture = bind_to_member(this, &TestInterface::isTexture);
+ fFunctions.fLineWidth = bind_to_member(this, &TestInterface::lineWidth);
+ fFunctions.fLinkProgram = bind_to_member(this, &TestInterface::linkProgram);
+ fFunctions.fMapBuffer = bind_to_member(this, &TestInterface::mapBuffer);
+ fFunctions.fMapBufferRange = bind_to_member(this, &TestInterface::mapBufferRange);
+ fFunctions.fMapBufferSubData = bind_to_member(this, &TestInterface::mapBufferSubData);
+ fFunctions.fMapTexSubImage2D = bind_to_member(this, &TestInterface::mapTexSubImage2D);
+ fFunctions.fPixelStorei = bind_to_member(this, &TestInterface::pixelStorei);
+ fFunctions.fPolygonMode = bind_to_member(this, &TestInterface::polygonMode);
+ fFunctions.fPopGroupMarker = bind_to_member(this, &TestInterface::popGroupMarker);
+ fFunctions.fPushGroupMarker = bind_to_member(this, &TestInterface::pushGroupMarker);
+ fFunctions.fQueryCounter = bind_to_member(this, &TestInterface::queryCounter);
+ fFunctions.fReadBuffer = bind_to_member(this, &TestInterface::readBuffer);
+ fFunctions.fReadPixels = bind_to_member(this, &TestInterface::readPixels);
+ fFunctions.fRenderbufferStorage = bind_to_member(this, &TestInterface::renderbufferStorage);
+ fFunctions.fRenderbufferStorageMultisample = bind_to_member(this, &TestInterface::renderbufferStorageMultisample);
+ fFunctions.fResolveMultisampleFramebuffer = bind_to_member(this, &TestInterface::resolveMultisampleFramebuffer);
+ fFunctions.fScissor = bind_to_member(this, &TestInterface::scissor);
+ fFunctions.fBindUniformLocation = bind_to_member(this, &TestInterface::bindUniformLocation);
+ fFunctions.fSamplerParameteri = bind_to_member(this, &TestInterface::samplerParameteri);
+ fFunctions.fSamplerParameteriv = bind_to_member(this, &TestInterface::samplerParameteriv);
+ fFunctions.fShaderSource = bind_to_member(this, &TestInterface::shaderSource);
+ fFunctions.fStencilFunc = bind_to_member(this, &TestInterface::stencilFunc);
+ fFunctions.fStencilFuncSeparate = bind_to_member(this, &TestInterface::stencilFuncSeparate);
+ fFunctions.fStencilMask = bind_to_member(this, &TestInterface::stencilMask);
+ fFunctions.fStencilMaskSeparate = bind_to_member(this, &TestInterface::stencilMaskSeparate);
+ fFunctions.fStencilOp = bind_to_member(this, &TestInterface::stencilOp);
+ fFunctions.fStencilOpSeparate = bind_to_member(this, &TestInterface::stencilOpSeparate);
+ fFunctions.fTexBuffer = bind_to_member(this, &TestInterface::texBuffer);
+ fFunctions.fTexImage2D = bind_to_member(this, &TestInterface::texImage2D);
+ fFunctions.fTexParameterf = bind_to_member(this, &TestInterface::texParameterf);
+ fFunctions.fTexParameterfv = bind_to_member(this, &TestInterface::texParameterfv);
+ fFunctions.fTexParameteri = bind_to_member(this, &TestInterface::texParameteri);
+ fFunctions.fTexParameteriv = bind_to_member(this, &TestInterface::texParameteriv);
+ fFunctions.fTexStorage2D = bind_to_member(this, &TestInterface::texStorage2D);
+ fFunctions.fDiscardFramebuffer = bind_to_member(this, &TestInterface::discardFramebuffer);
+ fFunctions.fTexSubImage2D = bind_to_member(this, &TestInterface::texSubImage2D);
+ fFunctions.fTextureBarrier = bind_to_member(this, &TestInterface::textureBarrier);
+ fFunctions.fUniform1f = bind_to_member(this, &TestInterface::uniform1f);
+ fFunctions.fUniform1i = bind_to_member(this, &TestInterface::uniform1i);
+ fFunctions.fUniform1fv = bind_to_member(this, &TestInterface::uniform1fv);
+ fFunctions.fUniform1iv = bind_to_member(this, &TestInterface::uniform1iv);
+ fFunctions.fUniform2f = bind_to_member(this, &TestInterface::uniform2f);
+ fFunctions.fUniform2i = bind_to_member(this, &TestInterface::uniform2i);
+ fFunctions.fUniform2fv = bind_to_member(this, &TestInterface::uniform2fv);
+ fFunctions.fUniform2iv = bind_to_member(this, &TestInterface::uniform2iv);
+ fFunctions.fUniform3f = bind_to_member(this, &TestInterface::uniform3f);
+ fFunctions.fUniform3i = bind_to_member(this, &TestInterface::uniform3i);
+ fFunctions.fUniform3fv = bind_to_member(this, &TestInterface::uniform3fv);
+ fFunctions.fUniform3iv = bind_to_member(this, &TestInterface::uniform3iv);
+ fFunctions.fUniform4f = bind_to_member(this, &TestInterface::uniform4f);
+ fFunctions.fUniform4i = bind_to_member(this, &TestInterface::uniform4i);
+ fFunctions.fUniform4fv = bind_to_member(this, &TestInterface::uniform4fv);
+ fFunctions.fUniform4iv = bind_to_member(this, &TestInterface::uniform4iv);
+ fFunctions.fUniformMatrix2fv = bind_to_member(this, &TestInterface::uniformMatrix2fv);
+ fFunctions.fUniformMatrix3fv = bind_to_member(this, &TestInterface::uniformMatrix3fv);
+ fFunctions.fUniformMatrix4fv = bind_to_member(this, &TestInterface::uniformMatrix4fv);
+ fFunctions.fUnmapBuffer = bind_to_member(this, &TestInterface::unmapBuffer);
+ fFunctions.fUnmapBufferSubData = bind_to_member(this, &TestInterface::unmapBufferSubData);
+ fFunctions.fUnmapTexSubImage2D = bind_to_member(this, &TestInterface::unmapTexSubImage2D);
+ fFunctions.fUseProgram = bind_to_member(this, &TestInterface::useProgram);
+ fFunctions.fVertexAttrib1f = bind_to_member(this, &TestInterface::vertexAttrib1f);
+ fFunctions.fVertexAttrib2fv = bind_to_member(this, &TestInterface::vertexAttrib2fv);
+ fFunctions.fVertexAttrib3fv = bind_to_member(this, &TestInterface::vertexAttrib3fv);
+ fFunctions.fVertexAttrib4fv = bind_to_member(this, &TestInterface::vertexAttrib4fv);
+ fFunctions.fVertexAttribDivisor = bind_to_member(this, &TestInterface::vertexAttribDivisor);
+ fFunctions.fVertexAttribIPointer = bind_to_member(this, &TestInterface::vertexAttribIPointer);
+ fFunctions.fVertexAttribPointer = bind_to_member(this, &TestInterface::vertexAttribPointer);
+ fFunctions.fViewport = bind_to_member(this, &TestInterface::viewport);
+ fFunctions.fMatrixLoadf = bind_to_member(this, &TestInterface::matrixLoadf);
+ fFunctions.fMatrixLoadIdentity = bind_to_member(this, &TestInterface::matrixLoadIdentity);
+ fFunctions.fPathCommands = bind_to_member(this, &TestInterface::pathCommands);
+ fFunctions.fPathParameteri = bind_to_member(this, &TestInterface::pathParameteri);
+ fFunctions.fPathParameterf = bind_to_member(this, &TestInterface::pathParameterf);
+ fFunctions.fGenPaths = bind_to_member(this, &TestInterface::genPaths);
+ fFunctions.fDeletePaths = bind_to_member(this, &TestInterface::deletePaths);
+ fFunctions.fIsPath = bind_to_member(this, &TestInterface::isPath);
+ fFunctions.fPathStencilFunc = bind_to_member(this, &TestInterface::pathStencilFunc);
+ fFunctions.fStencilFillPath = bind_to_member(this, &TestInterface::stencilFillPath);
+ fFunctions.fStencilStrokePath = bind_to_member(this, &TestInterface::stencilStrokePath);
+ fFunctions.fStencilFillPathInstanced = bind_to_member(this, &TestInterface::stencilFillPathInstanced);
+ fFunctions.fStencilStrokePathInstanced = bind_to_member(this, &TestInterface::stencilStrokePathInstanced);
+ fFunctions.fCoverFillPath = bind_to_member(this, &TestInterface::coverFillPath);
+ fFunctions.fCoverStrokePath = bind_to_member(this, &TestInterface::coverStrokePath);
+ fFunctions.fCoverFillPathInstanced = bind_to_member(this, &TestInterface::coverFillPathInstanced);
+ fFunctions.fCoverStrokePathInstanced = bind_to_member(this, &TestInterface::coverStrokePathInstanced);
+ fFunctions.fStencilThenCoverFillPath = bind_to_member(this, &TestInterface::stencilThenCoverFillPath);
+ fFunctions.fStencilThenCoverStrokePath = bind_to_member(this, &TestInterface::stencilThenCoverStrokePath);
+ fFunctions.fStencilThenCoverFillPathInstanced = bind_to_member(this, &TestInterface::stencilThenCoverFillPathInstanced);
+ fFunctions.fStencilThenCoverStrokePathInstanced = bind_to_member(this, &TestInterface::stencilThenCoverStrokePathInstanced);
+ fFunctions.fProgramPathFragmentInputGen = bind_to_member(this, &TestInterface::programPathFragmentInputGen);
+ fFunctions.fBindFragmentInputLocation = bind_to_member(this, &TestInterface::bindFragmentInputLocation);
+ fFunctions.fGetProgramResourceLocation = bind_to_member(this, &TestInterface::getProgramResourceLocation);
+ fFunctions.fCoverageModulation = bind_to_member(this, &TestInterface::coverageModulation);
+ fFunctions.fMultiDrawArraysIndirect = bind_to_member(this, &TestInterface::multiDrawArraysIndirect);
+ fFunctions.fMultiDrawElementsIndirect = bind_to_member(this, &TestInterface::multiDrawElementsIndirect);
+ fFunctions.fFenceSync = bind_to_member(this, &TestInterface::fenceSync);
+ fFunctions.fIsSync = bind_to_member(this, &TestInterface::isSync);
+ fFunctions.fClientWaitSync = bind_to_member(this, &TestInterface::clientWaitSync);
+ fFunctions.fWaitSync = bind_to_member(this, &TestInterface::waitSync);
+ fFunctions.fDeleteSync = bind_to_member(this, &TestInterface::deleteSync);
+ fFunctions.fDebugMessageControl = bind_to_member(this, &TestInterface::debugMessageControl);
+ fFunctions.fDebugMessageInsert = bind_to_member(this, &TestInterface::debugMessageInsert);
+ fFunctions.fDebugMessageCallback = bind_to_member(this, &TestInterface::debugMessageCallback);
+ fFunctions.fGetDebugMessageLog = bind_to_member(this, &TestInterface::getDebugMessageLog);
+ fFunctions.fPushDebugGroup = bind_to_member(this, &TestInterface::pushDebugGroup);
+ fFunctions.fPopDebugGroup = bind_to_member(this, &TestInterface::popDebugGroup);
+ fFunctions.fObjectLabel = bind_to_member(this, &TestInterface::objectLabel);
+ fFunctions.fGetInternalformativ = bind_to_member(this, &TestInterface::getInternalformativ);
+ fFunctions.fProgramBinary = bind_to_member(this, &TestInterface::programBinary);
+ fFunctions.fGetProgramBinary = bind_to_member(this, &TestInterface::getProgramBinary);
+ fFunctions.fProgramParameteri = bind_to_member(this, &TestInterface::programParameteri);
+}
+
+/** Null interface implementation */
+class NullInterface : public TestInterface {
+public:
+ NullInterface(bool enableNVPR)
+ : fCurrDrawFramebuffer(0)
+ , fCurrReadFramebuffer(0)
+ , fCurrRenderbuffer(0)
+ , fCurrProgramID(0)
+ , fCurrShaderID(0)
+ , fCurrGenericID(0)
+ , fCurrUniformLocation(0)
+ , fCurrPathID(0) {
+ memset(fBoundBuffers, 0, sizeof(fBoundBuffers));
+ fAdvertisedExtensions.push_back("GL_ARB_framebuffer_object");
+ fAdvertisedExtensions.push_back("GL_ARB_blend_func_extended");
+ fAdvertisedExtensions.push_back("GL_ARB_timer_query");
+ fAdvertisedExtensions.push_back("GL_ARB_draw_buffers");
+ fAdvertisedExtensions.push_back("GL_ARB_occlusion_query");
+ fAdvertisedExtensions.push_back("GL_EXT_stencil_wrap");
+ if (enableNVPR) {
+ fAdvertisedExtensions.push_back("GL_NV_path_rendering");
+ fAdvertisedExtensions.push_back("GL_ARB_program_interface_query");
+ }
+ fAdvertisedExtensions.push_back(nullptr);
+
+ this->init(kGL_GrGLStandard);
+ }
+
+ GrGLenum checkFramebufferStatus(GrGLenum target) override {
+ return GR_GL_FRAMEBUFFER_COMPLETE;
+ }
+
+ GrGLvoid genBuffers(GrGLsizei n, GrGLuint* ids) override {
+ for (int i = 0; i < n; ++i) {
+ Buffer* buffer = fBufferManager.create();
+ ids[i] = buffer->id();
+ }
+ }
+
+ GrGLvoid bufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data,
+ GrGLenum usage) override {
+ GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
+ if (id > 0) {
+ Buffer* buffer = fBufferManager.lookUp(id);
+ buffer->allocate(size, (const GrGLchar*) data);
+ }
+ }
+
+ GrGLuint createProgram() override {
+ return ++fCurrProgramID;
+ }
+
+ GrGLuint createShader(GrGLenum type) override {
+ return ++fCurrShaderID;
+ }
+
+ GrGLvoid bindBuffer(GrGLenum target, GrGLuint buffer) override {
+ fBoundBuffers[GetBufferIndex(target)] = buffer;
+ }
+
+ // deleting a bound buffer has the side effect of binding 0
+ GrGLvoid deleteBuffers(GrGLsizei n, const GrGLuint* ids) override {
+ // First potentially unbind the buffers.
+ for (int buffIdx = 0; buffIdx < kNumBufferTargets; ++buffIdx) {
+ if (!fBoundBuffers[buffIdx]) {
+ continue;
+ }
+ for (int i = 0; i < n; ++i) {
+ if (ids[i] == fBoundBuffers[buffIdx]) {
+ fBoundBuffers[buffIdx] = 0;
+ break;
+ }
+ }
+ }
+
+ // Then actually "delete" the buffers.
+ for (int i = 0; i < n; ++i) {
+ if (ids[i] > 0) {
+ Buffer* buffer = fBufferManager.lookUp(ids[i]);
+ fBufferManager.free(buffer);
+ }
+ }
+ }
+
+ GrGLvoid genFramebuffers(GrGLsizei n, GrGLuint *framebuffers) override {
+ for (int i = 0; i < n; ++i) {
+ Framebuffer* framebuffer = fFramebufferManager.create();
+ framebuffers[i] = framebuffer->id();
+ }
+ }
+
+ GrGLvoid bindFramebuffer(GrGLenum target, GrGLuint framebuffer) override {
+ SkASSERT(GR_GL_FRAMEBUFFER == target || GR_GL_DRAW_FRAMEBUFFER == target ||
+ GR_GL_READ_FRAMEBUFFER == target);
+ if (GR_GL_READ_FRAMEBUFFER != target) {
+ fCurrDrawFramebuffer = framebuffer;
+ }
+ if (GR_GL_DRAW_FRAMEBUFFER != target) {
+ fCurrReadFramebuffer = framebuffer;
+ }
+ }
+
+ GrGLvoid deleteFramebuffers(GrGLsizei n, const GrGLuint* ids) override {
+ for (int i = 0; i < n; ++i) {
+ if (ids[i] == fCurrDrawFramebuffer) {
+ fCurrDrawFramebuffer = 0;
+ }
+ if (ids[i] == fCurrReadFramebuffer) {
+ fCurrReadFramebuffer = 0;
+ }
+
+ if (ids[i] > 0) {
+ Framebuffer* framebuffer = fFramebufferManager.lookUp(ids[i]);
+ fFramebufferManager.free(framebuffer);
+ }
+ }
+ }
+
+ GrGLvoid genQueries(GrGLsizei n, GrGLuint *ids) override { this->genGenericIds(n, ids); }
+
+ GrGLvoid genRenderbuffers(GrGLsizei n, GrGLuint *renderbuffers) override {
+ for (int i = 0; i < n; ++i) {
+ Renderbuffer* renderbuffer = fRenderbufferManager.create();
+ renderbuffers[i] = renderbuffer->id();
+ }
+ }
+
+ GrGLvoid bindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) override {
+ SkASSERT(GR_GL_RENDERBUFFER == target);
+ fCurrRenderbuffer = renderbuffer;
+ }
+
+ GrGLvoid deleteRenderbuffers(GrGLsizei n, const GrGLuint* ids) override {
+ for (int i = 0; i < n; ++i) {
+ if (ids[i] <= 0) {
+ continue;
+ }
+ if (ids[i] == fCurrRenderbuffer) {
+ fCurrRenderbuffer = 0;
+ }
+ Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(ids[i]);
+
+ if (fCurrDrawFramebuffer) {
+ Framebuffer* drawFramebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
+ drawFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
+ }
+ if (fCurrReadFramebuffer) {
+ Framebuffer* readFramebuffer = fFramebufferManager.lookUp(fCurrReadFramebuffer);
+ readFramebuffer->notifyAttachmentDeleteWhileBound(renderbuffer);
+ }
+
+ fRenderbufferManager.free(renderbuffer);
+ }
+ }
+
+ GrGLvoid renderbufferStorage(GrGLenum target, GrGLenum internalformat, GrGLsizei width,
+ GrGLsizei height) override {
+ GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
+ GrAlwaysAssert(fCurrRenderbuffer);
+ Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
+ renderbuffer->setNumSamples(1);
+ }
+
+ GrGLvoid renderbufferStorageMultisample(GrGLenum target, GrGLsizei samples,
+ GrGLenum internalformat, GrGLsizei width,
+ GrGLsizei height) override {
+ GrAlwaysAssert(GR_GL_RENDERBUFFER == target);
+ GrAlwaysAssert(samples > 0);
+ GrAlwaysAssert(fCurrRenderbuffer);
+ Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
+ renderbuffer->setNumSamples(samples);
+ }
+
+ GrGLvoid namedRenderbufferStorage(GrGLuint renderbuffer, GrGLenum GrGLinternalformat,
+ GrGLsizei width, GrGLsizei height) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid namedRenderbufferStorageMultisample(GrGLuint renderbuffer, GrGLsizei samples,
+ GrGLenum GrGLinternalformat, GrGLsizei width,
+ GrGLsizei height) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid framebufferRenderbuffer(GrGLenum target, GrGLenum attachment,
+ GrGLenum renderbuffertarget,
+ GrGLuint renderBufferID) override {
+ GrGLuint id = this->getBoundFramebufferID(target);
+ GrAlwaysAssert(id);
+ Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
+
+ GrAlwaysAssert(GR_GL_RENDERBUFFER == renderbuffertarget);
+ if (!renderBufferID && !fCurrRenderbuffer) {
+ return;
+ }
+ GrAlwaysAssert(fCurrRenderbuffer);
+ Renderbuffer* renderbuffer = fRenderbufferManager.lookUp(fCurrRenderbuffer);
+
+ framebuffer->setAttachment(attachment, renderbuffer);
+ }
+
+ GrGLvoid namedFramebufferRenderbuffer(GrGLuint framebuffer, GrGLenum attachment,
+ GrGLenum renderbuffertarget,
+ GrGLuint renderbuffer) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid genSamplers(GrGLsizei n, GrGLuint* samplers) override {
+ this->genGenericIds(n, samplers);
+ }
+
+ GrGLvoid genTextures(GrGLsizei n, GrGLuint *textures) override {
+ this->genGenericIds(n, textures);
+ }
+
+ GrGLvoid framebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget,
+ GrGLuint textureID, GrGLint level) override {
+ GrGLuint id = this->getBoundFramebufferID(target);
+ GrAlwaysAssert(id);
+ Framebuffer* framebuffer = fFramebufferManager.lookUp(id);
+ framebuffer->setAttachment(attachment, this->getSingleTextureObject());
+ }
+
+ GrGLvoid framebufferTexture2DMultisample(GrGLenum target, GrGLenum attachment,
+ GrGLenum textarget, GrGLuint texture, GrGLint level,
+ GrGLsizei samples) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid namedFramebufferTexture1D(GrGLuint framebuffer, GrGLenum attachment,
+ GrGLenum textarget, GrGLuint texture,
+ GrGLint level) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid namedFramebufferTexture2D(GrGLuint framebuffer, GrGLenum attachment,
+ GrGLenum textarget, GrGLuint texture,
+ GrGLint level) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid namedFramebufferTexture3D(GrGLuint framebuffer, GrGLenum attachment,
+ GrGLenum textarget, GrGLuint texture, GrGLint level,
+ GrGLint zoffset) override {
+ SK_ABORT("Not implemented");
+ }
+
+ GrGLvoid genVertexArrays(GrGLsizei n, GrGLuint *arrays) override {
+ this->genGenericIds(n, arrays);
+ }
+
+ GrGLenum getError() override { return GR_GL_NO_ERROR; }
+
+ GrGLvoid getIntegerv(GrGLenum pname, GrGLint* params) override {
+ // TODO: remove from Ganesh the #defines for gets we don't use.
+ // We would like to minimize gets overall due to performance issues
+ switch (pname) {
+ case GR_GL_CONTEXT_PROFILE_MASK:
+ *params = GR_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+ break;
+ case GR_GL_STENCIL_BITS:
+ *params = 8;
+ break;
+ case GR_GL_SAMPLES: {
+ GrAlwaysAssert(fCurrDrawFramebuffer);
+ Framebuffer* framebuffer = fFramebufferManager.lookUp(fCurrDrawFramebuffer);
+ *params = framebuffer->numSamples();
+ break;
+ }
+ case GR_GL_FRAMEBUFFER_BINDING:
+ *params = 0;
+ break;
+ case GR_GL_VIEWPORT:
+ params[0] = 0;
+ params[1] = 0;
+ params[2] = 800;
+ params[3] = 600;
+ break;
+ case GR_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ case GR_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS:
+ case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
+ case GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ *params = 8;
+ break;
+ case GR_GL_MAX_TEXTURE_COORDS:
+ *params = 8;
+ break;
+ case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
+ *params = kDefaultMaxVertexUniformVectors;
+ break;
+ case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ *params = kDefaultMaxFragmentUniformVectors;
+ break;
+ case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = 16 * 4;
+ break;
+ case GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ *params = 0;
+ break;
+ case GR_GL_COMPRESSED_TEXTURE_FORMATS:
+ break;
+ case GR_GL_MAX_TEXTURE_SIZE:
+ *params = 8192;
+ break;
+ case GR_GL_MAX_RENDERBUFFER_SIZE:
+ *params = 8192;
+ break;
+ case GR_GL_MAX_SAMPLES:
+ *params = 32;
+ break;
+ case GR_GL_MAX_VERTEX_ATTRIBS:
+ *params = kDefaultMaxVertexAttribs;
+ break;
+ case GR_GL_MAX_VARYING_VECTORS:
+ *params = kDefaultMaxVaryingVectors;
+ break;
+ case GR_GL_NUM_EXTENSIONS: {
+ GrGLint i = 0;
+ while (fAdvertisedExtensions[i++]);
+ *params = i;
+ break;
+ }
+ default:
+ SK_ABORT("Unexpected pname to GetIntegerv");
+ }
+ }
+
+ GrGLvoid getProgramiv(GrGLuint program, GrGLenum pname, GrGLint* params) override {
+ this->getShaderOrProgramiv(program, pname, params);
+ }
+
+ GrGLvoid getProgramInfoLog(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length,
+ char* infolog) override {
+ this->getInfoLog(program, bufsize, length, infolog);
+ }
+
+ GrGLvoid getMultisamplefv(GrGLenum pname, GrGLuint index, GrGLfloat* val) override {
+ val[0] = val[1] = 0.5f;
+ }
+
+ GrGLvoid getQueryiv(GrGLenum GLtarget, GrGLenum pname, GrGLint *params) override {
+ switch (pname) {
+ case GR_GL_CURRENT_QUERY:
+ *params = 0;
+ break;
+ case GR_GL_QUERY_COUNTER_BITS:
+ *params = 32;
+ break;
+ default:
+ SK_ABORT("Unexpected pname passed GetQueryiv.");
+ }
+ }
+
+ GrGLvoid getQueryObjecti64v(GrGLuint id, GrGLenum pname, GrGLint64 *params) override {
+ this->queryResult(id, pname, params);
+ }
+
+ GrGLvoid getQueryObjectiv(GrGLuint id, GrGLenum pname, GrGLint *params) override {
+ this->queryResult(id, pname, params);
+ }
+
+ GrGLvoid getQueryObjectui64v(GrGLuint id, GrGLenum pname, GrGLuint64 *params) override {
+ this->queryResult(id, pname, params);
+ }
+
+ GrGLvoid getQueryObjectuiv(GrGLuint id, GrGLenum pname, GrGLuint *params) override {
+ this->queryResult(id, pname, params);
+ }
+
+ GrGLvoid getShaderiv(GrGLuint shader, GrGLenum pname, GrGLint* params) override {
+ this->getShaderOrProgramiv(shader, pname, params);
+ }
+
+ GrGLvoid getShaderInfoLog(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length,
+ char* infolog) override {
+ this->getInfoLog(shader, bufsize, length, infolog);
+ }
+
+ const GrGLubyte* getString(GrGLenum name) override {
+ switch (name) {
+ case GR_GL_EXTENSIONS:
+ return CombinedExtensionString();
+ case GR_GL_VERSION:
+ return (const GrGLubyte*)"4.0 Null GL";
+ case GR_GL_SHADING_LANGUAGE_VERSION:
+ return (const GrGLubyte*)"4.20.8 Null GLSL";
+ case GR_GL_VENDOR:
+ return (const GrGLubyte*)"Null Vendor";
+ case GR_GL_RENDERER:
+ return (const GrGLubyte*)"The Null (Non-)Renderer";
+ default:
+ SK_ABORT("Unexpected name passed to GetString");
+ return nullptr;
+ }
+ }
+
+ const GrGLubyte* getStringi(GrGLenum name, GrGLuint i) override {
+ switch (name) {
+ case GR_GL_EXTENSIONS: {
+ GrGLint count;
+ this->getIntegerv(GR_GL_NUM_EXTENSIONS, &count);
+ if ((GrGLint)i <= count) {
+ return (const GrGLubyte*) fAdvertisedExtensions[i];
+ } else {
+ return nullptr;
+ }
+ }
+ default:
+ SK_ABORT("Unexpected name passed to GetStringi");
+ return nullptr;
+ }
+ }
+
+ GrGLint getUniformLocation(GrGLuint program, const char* name) override {
+ return ++fCurrUniformLocation;
+ }
+
+ GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length,
+ GrGLbitfield access) override {
+ GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
+ if (id > 0) {
+ // We just ignore the offset and length here.
+ Buffer* buffer = fBufferManager.lookUp(id);
+ SkASSERT(!buffer->mapped());
+ buffer->setMapped(true);
+ return buffer->dataPtr();
+ }
+ return nullptr;
+ }
+
+ GrGLvoid* mapBuffer(GrGLenum target, GrGLenum access) override {
+ GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
+ if (id > 0) {
+ Buffer* buffer = fBufferManager.lookUp(id);
+ SkASSERT(!buffer->mapped());
+ buffer->setMapped(true);
+ return buffer->dataPtr();
+ }
+
+ SkASSERT(false);
+ return nullptr; // no buffer bound to target
+ }
+
+ GrGLboolean unmapBuffer(GrGLenum target) override {
+ GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
+ if (id > 0) {
+ Buffer* buffer = fBufferManager.lookUp(id);
+ SkASSERT(buffer->mapped());
+ buffer->setMapped(false);
+ return GR_GL_TRUE;
+ }
+
+ GrAlwaysAssert(false);
+ return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
+ }
+
+ GrGLvoid getBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) override {
+ switch (pname) {
+ case GR_GL_BUFFER_MAPPED: {
+ *params = GR_GL_FALSE;
+ GrGLuint id = fBoundBuffers[GetBufferIndex(target)];
+ if (id > 0) {
+ Buffer* buffer = fBufferManager.lookUp(id);
+ if (buffer->mapped()) {
+ *params = GR_GL_TRUE;
+ }
+ }
+ break; }
+ default:
+ SK_ABORT("Unexpected pname to GetBufferParamateriv");
+ break;
+ }
+ }
+
+ // NV_path_rendering
+ GrGLuint genPaths(GrGLsizei range) override {
+ return ++fCurrPathID;
+ }
+
+
+private:
+ inline int static GetBufferIndex(GrGLenum glTarget) {
+ switch (glTarget) {
+ default: SK_ABORT("Unexpected GL target to GetBufferIndex");
+ case GR_GL_ARRAY_BUFFER: return 0;
+ case GR_GL_ELEMENT_ARRAY_BUFFER: return 1;
+ case GR_GL_TEXTURE_BUFFER: return 2;
+ case GR_GL_DRAW_INDIRECT_BUFFER: return 3;
+ case GR_GL_PIXEL_PACK_BUFFER: return 4;
+ case GR_GL_PIXEL_UNPACK_BUFFER: return 5;
+ }
+ }
+ constexpr int static kNumBufferTargets = 6;
+
+ TGLObjectManager<Buffer> fBufferManager;
+ GrGLuint fBoundBuffers[kNumBufferTargets];
+ TGLObjectManager<Framebuffer> fFramebufferManager;
+ GrGLuint fCurrDrawFramebuffer;
+ GrGLuint fCurrReadFramebuffer;
+ TGLObjectManager<Renderbuffer> fRenderbufferManager;
+ GrGLuint fCurrRenderbuffer;
+ GrGLuint fCurrProgramID;
+ GrGLuint fCurrShaderID;
+ GrGLuint fCurrGenericID;
+ GrGLuint fCurrUniformLocation;
+ GrGLuint fCurrPathID;
+ sk_sp<const Texture> fSingleTextureObject;
+ SkTArray<const char*> fAdvertisedExtensions;
+
+ // the OpenGLES 2.0 spec says this must be >= 128
+ static const GrGLint kDefaultMaxVertexUniformVectors = 128;
+
+ // the OpenGLES 2.0 spec says this must be >=16
+ static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
+
+ // the OpenGLES 2.0 spec says this must be >= 8
+ static const GrGLint kDefaultMaxVertexAttribs = 8;
+
+ // the OpenGLES 2.0 spec says this must be >= 8
+ static const GrGLint kDefaultMaxVaryingVectors = 8;
+
+ GrGLuint getBoundFramebufferID(GrGLenum target) {
+ switch (target) {
+ case GR_GL_FRAMEBUFFER:
+ case GR_GL_DRAW_FRAMEBUFFER:
+ return fCurrDrawFramebuffer;
+ case GR_GL_READ_FRAMEBUFFER:
+ return fCurrReadFramebuffer;
+ default:
+ SK_ABORT("Invalid framebuffer target.");
+ return 0;
+ }
+ }
+
+ const Texture* getSingleTextureObject() {
+ // We currently only use FramebufferAttachment objects for a sample count, and all textures
+ // in Skia have one sample, so there is no need as of yet to track individual textures. This
+ // also works around a bug in chromium's cc_unittests where they send us texture IDs that
+ // were generated by cc::TestGLES2Interface.
+ if (!fSingleTextureObject) {
+ fSingleTextureObject.reset(new Texture);
+ }
+ return fSingleTextureObject.get();
+ }
+
+ const GrGLubyte* CombinedExtensionString() {
+ static SkString gExtString;
+ static SkMutex gMutex;
+ gMutex.acquire();
+ if (0 == gExtString.size()) {
+ int i = 0;
+ while (fAdvertisedExtensions[i]) {
+ if (i > 0) {
+ gExtString.append(" ");
+ }
+ gExtString.append(fAdvertisedExtensions[i]);
+ ++i;
+ }
+ }
+ gMutex.release();
+ return (const GrGLubyte*) gExtString.c_str();
+ }
+
+ GrGLvoid genGenericIds(GrGLsizei n, GrGLuint* ids) {
+ for (int i = 0; i < n; ++i) {
+ ids[i] = ++fCurrGenericID;
+ }
+ }
+
+ GrGLvoid getInfoLog(GrGLuint object, GrGLsizei bufsize, GrGLsizei* length,
+ char* infolog) {
+ if (length) {
+ *length = 0;
+ }
+ if (bufsize > 0) {
+ *infolog = 0;
+ }
+ }
+
+ GrGLvoid getShaderOrProgramiv(GrGLuint object, GrGLenum pname, GrGLint* params) {
+ switch (pname) {
+ case GR_GL_LINK_STATUS: // fallthru
+ case GR_GL_COMPILE_STATUS:
+ *params = GR_GL_TRUE;
+ break;
+ case GR_GL_INFO_LOG_LENGTH: // fallthru
+ case GL_PROGRAM_BINARY_LENGTH:
+ *params = 0;
+ break;
+ // we don't expect any other pnames
+ default:
+ SK_ABORT("Unexpected pname to GetProgramiv");
+ break;
+ }
+ }
+
+ template <typename T>
+ void queryResult(GrGLenum GLtarget, GrGLenum pname, T *params) {
+ switch (pname) {
+ case GR_GL_QUERY_RESULT_AVAILABLE:
+ *params = GR_GL_TRUE;
+ break;
+ case GR_GL_QUERY_RESULT:
+ *params = 0;
+ break;
+ default:
+ SK_ABORT("Unexpected pname passed to GetQueryObject.");
+ break;
+ }
+ }
+
+ typedef TestInterface INHERITED;
+};
+
+} // anonymous namespace
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+const GrGLInterface* CreateNullSkiaInterface() { return new NullInterface(false); }
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 8d4e7e09b458..7677f9c6628d 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -24,6 +24,12 @@
#include <optional>
+#ifdef __APPLE__
+ // macOS SDK 10.10 does not support CLOCK_MONOTONIC, which is not an issue since
+ // the value of the argument is not used in the host definition of systemTime
+#define CLOCK_MONOTONIC
+#endif
+
namespace android {
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 219d04055eae..4c2f0ad102bd 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -17,17 +17,23 @@
#include "HardwareBitmapUploader.h"
#include "Properties.h"
+#ifdef __ANDROID__ // Layoutlib does not support render thread
#include "renderthread/RenderProxy.h"
+#endif
#include "utils/Color.h"
#include <utils/Trace.h>
+#ifndef _WIN32
#include <sys/mman.h>
+#endif
#include <cutils/ashmem.h>
#include <log/log.h>
+#ifndef _WIN32
#include <binder/IServiceManager.h>
#include <private/gui/ComposerService.h>
+#endif
#include <ui/PixelFormat.h>
#include <SkCanvas.h>
@@ -76,6 +82,7 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap) {
}
sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
+#ifdef __ANDROID__
// Create new ashmem region with read/write priv
int fd = ashmem_create_region("bitmap", size);
if (fd < 0) {
@@ -94,10 +101,17 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info,
return nullptr;
}
return sk_sp<Bitmap>(new Bitmap(addr, fd, size, info, rowBytes));
+#else
+ return Bitmap::allocateHeapBitmap(size, info, rowBytes);
+#endif
}
sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(const SkBitmap& bitmap) {
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
return uirenderer::HardwareBitmapUploader::allocateHardwareBitmap(bitmap);
+#else
+ return Bitmap::allocateHeapBitmap(bitmap.info());
+#endif
}
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap) {
@@ -133,6 +147,7 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef)
}
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer, SkColorType colorType,
sk_sp<SkColorSpace> colorSpace, SkAlphaType alphaType,
BitmapPalette palette) {
@@ -140,9 +155,13 @@ sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer, SkColorType co
colorType, alphaType, colorSpace);
return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info, palette));
}
+#endif
sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
size_t size, bool readOnly) {
+#ifdef _WIN32 // ashmem not implemented on Windows
+ return nullptr;
+#else
if (info.colorType() == kUnknown_SkColorType) {
LOG_ALWAYS_FATAL("unknown bitmap configuration");
return nullptr;
@@ -163,6 +182,7 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int f
bitmap->setImmutable();
}
return bitmap;
+#endif
}
void Bitmap::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
@@ -217,6 +237,7 @@ Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info
mPixelStorage.ashmem.size = mappedSize;
}
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette)
: SkPixelRef(info.width(), info.height(), nullptr,
bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride())
@@ -230,6 +251,7 @@ Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette pal
mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast<AHardwareBuffer*>(buffer),
mInfo.alphaType(), mInfo.refColorSpace());
}
+#endif
Bitmap::~Bitmap() {
switch (mPixelStorageType) {
@@ -238,17 +260,23 @@ Bitmap::~Bitmap() {
mPixelStorage.external.context);
break;
case PixelStorageType::Ashmem:
+#ifndef _WIN32 // ashmem not implemented on Windows
munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
+#endif
close(mPixelStorage.ashmem.fd);
break;
case PixelStorageType::Heap:
free(mPixelStorage.heap.address);
+#ifdef __ANDROID__
mallopt(M_PURGE, 0);
+#endif
break;
case PixelStorageType::Hardware:
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
auto buffer = mPixelStorage.hardware.buffer;
buffer->decStrong(buffer);
mPixelStorage.hardware.buffer = nullptr;
+#endif
break;
}
}
@@ -307,11 +335,13 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) {
}
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
if (isHardware()) {
outBitmap->allocPixels(mInfo);
uirenderer::renderthread::RenderProxy::copyHWBitmapInto(this, outBitmap);
return;
}
+#endif
outBitmap->setInfo(mInfo, rowBytes());
outBitmap->setPixelRef(sk_ref_sp(this), 0, 0);
}
@@ -321,12 +351,14 @@ void Bitmap::getBounds(SkRect* bounds) const {
bounds->set(0, 0, SkIntToScalar(width()), SkIntToScalar(height()));
}
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
GraphicBuffer* Bitmap::graphicBuffer() {
if (isHardware()) {
return mPixelStorage.hardware.buffer;
}
return nullptr;
}
+#endif
sk_sp<SkImage> Bitmap::makeImage() {
sk_sp<SkImage> image = mImage;
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index dd98b25ac7e8..c7e18d10de96 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -23,7 +23,9 @@
#include <SkImageInfo.h>
#include <SkPixelRef.h>
#include <cutils/compiler.h>
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
#include <ui/GraphicBuffer.h>
+#endif
namespace android {
@@ -71,11 +73,13 @@ public:
/* The createFrom factories construct a new Bitmap object by wrapping the already allocated
* memory that is provided as an input param.
*/
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
SkAlphaType alphaType = kPremul_SkAlphaType,
BitmapPalette palette = BitmapPalette::Unknown);
+#endif
static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
size_t size, bool readOnly);
static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
@@ -105,7 +109,9 @@ public:
PixelStorageType pixelStorageType() const { return mPixelStorageType; }
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
GraphicBuffer* graphicBuffer();
+#endif
/**
* Creates or returns a cached SkImage and is safe to be invoked from either
@@ -136,7 +142,9 @@ private:
Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info,
size_t rowBytes);
Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes);
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette);
+#endif
virtual ~Bitmap();
void* getStorage() const;
@@ -165,9 +173,11 @@ private:
void* address;
size_t size;
} heap;
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
struct {
GraphicBuffer* buffer;
} hardware;
+#endif
} mPixelStorage;
sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline.
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 68aa7374fec4..e2ddb91f1565 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -30,7 +30,11 @@
namespace android {
Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) {
+#ifdef __ANDROID__ // Layoutlib does not support recording canvas
return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height);
+#else
+ return NULL;
+#endif
}
static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkScalar thickness,
@@ -154,6 +158,11 @@ void Canvas::drawText(const uint16_t* text, int textSize, int start, int count,
// minikin may modify the original paint
Paint paint(origPaint);
+ // interpret 'linear metrics' flag as 'linear', forcing no-hinting when drawing
+ if (paint.getSkFont().isLinearMetrics()) {
+ paint.getSkFont().setHinting(SkFontHinting::kNone);
+ }
+
minikin::Layout layout = MinikinUtils::doLayout(&paint, bidiFlags, typeface, text, textSize,
start, count, contextStart, contextCount, mt);
@@ -234,23 +243,30 @@ private:
};
void Canvas::drawTextOnPath(const uint16_t* text, int count, minikin::Bidi bidiFlags,
- const SkPath& path, float hOffset, float vOffset, const Paint& paint,
- const Typeface* typeface) {
- Paint paintCopy(paint);
+ const SkPath& path, float hOffset, float vOffset,
+ const Paint& origPaint, const Typeface* typeface) {
+ // minikin may modify the original paint
+ Paint paint(origPaint);
+
+ // interpret 'linear metrics' flag as 'linear', forcing no-hinting when drawing
+ if (paint.getSkFont().isLinearMetrics()) {
+ paint.getSkFont().setHinting(SkFontHinting::kNone);
+ }
+
minikin::Layout layout =
- MinikinUtils::doLayout(&paintCopy, bidiFlags, typeface, text, count, // text buffer
- 0, count, // draw range
- 0, count, // context range
+ MinikinUtils::doLayout(&paint, bidiFlags, typeface, text, count, // text buffer
+ 0, count, // draw range
+ 0, count, // context range
nullptr);
- hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
+ hOffset += MinikinUtils::hOffsetForTextAlign(&paint, layout, path);
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
// care of all alignment.
- paintCopy.setTextAlign(Paint::kLeft_Align);
+ paint.setTextAlign(Paint::kLeft_Align);
- DrawTextOnPathFunctor f(layout, this, hOffset, vOffset, paintCopy, path);
- MinikinUtils::forFontRun(layout, &paintCopy, f);
+ DrawTextOnPathFunctor f(layout, this, hOffset, vOffset, paint, path);
+ MinikinUtils::forFontRun(layout, &paint, f);
}
int Canvas::sApiLevel = 1;
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index c4d8aa6c8fad..ccc328c702db 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -18,7 +18,9 @@
#include <fcntl.h> // For tests.
#include <pthread.h>
+#ifndef _WIN32
#include <sys/mman.h> // For tests.
+#endif
#include <sys/stat.h> // For tests.
#include "MinikinSkia.h"
@@ -171,6 +173,7 @@ void Typeface::setDefault(const Typeface* face) {
}
void Typeface::setRobotoTypefaceForTest() {
+#ifndef _WIN32
const char* kRobotoFont = "/system/fonts/Roboto-Regular.ttf";
int fd = open(kRobotoFont, O_RDONLY);
@@ -198,5 +201,6 @@ void Typeface::setRobotoTypefaceForTest() {
hwTypeface->fStyle = minikin::FontStyle();
Typeface::setDefault(hwTypeface);
+#endif
}
} // namespace android
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 1bd30eb5371b..e65fe3a3b811 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -187,17 +187,13 @@ public:
AlphaFilterCanvas(SkCanvas* canvas, float alpha) : SkPaintFilterCanvas(canvas), mAlpha(alpha) {}
protected:
- bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
- std::optional<SkPaint> defaultPaint;
- if (!*paint) {
- paint->init(defaultPaint.emplace());
- }
- paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha() * mAlpha);
+ bool onFilter(SkPaint& paint) const override {
+ paint.setAlpha((uint8_t)paint.getAlpha() * mAlpha);
return true;
}
void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
// We unroll the drawable using "this" canvas, so that draw calls contained inside will
- // get their alpha applied. THe default SkPaintFilterCanvas::onDrawDrawable does not unroll.
+ // get their alpha applied. The default SkPaintFilterCanvas::onDrawDrawable does not unroll.
drawable->draw(this, matrix);
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 41bcfc25f5c1..780ac20c65aa 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -131,13 +131,12 @@ bool SkiaDisplayList::prepareListAndChildren(
}
}
- for (auto& vectorDrawablePair : mVectorDrawables) {
+ for (auto& [vectorDrawable, cachedMatrix] : mVectorDrawables) {
// If any vector drawable in the display list needs update, damage the node.
- auto& vectorDrawable = vectorDrawablePair.first;
if (vectorDrawable->isDirty()) {
Matrix4 totalMatrix;
info.damageAccumulator->computeCurrentTransform(&totalMatrix);
- Matrix4 canvasMatrix(vectorDrawablePair.second);
+ Matrix4 canvasMatrix(cachedMatrix);
totalMatrix.multiply(canvasMatrix);
const SkRect& bounds = vectorDrawable->properties().getBounds();
if (intersects(info.screenSize, totalMatrix, bounds)) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 1f9ab5a242b4..066828190627 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -30,6 +30,8 @@
#include <unistd.h>
+#include <android-base/properties.h>
+
using namespace android::uirenderer::renderthread;
namespace android {
@@ -240,12 +242,11 @@ static void savePictureAsync(const sk_sp<SkData>& data, const std::string& filen
SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
- char prop[PROPERTY_VALUE_MAX] = {'\0'};
if (mCaptureSequence <= 0) {
- property_get(PROPERTY_CAPTURE_SKP_FILENAME, prop, "0");
+ std::string prop = base::GetProperty(PROPERTY_CAPTURE_SKP_FILENAME, "0");
if (prop[0] != '0' && mCapturedFile != prop) {
mCapturedFile = prop;
- mCaptureSequence = property_get_int32(PROPERTY_CAPTURE_SKP_FRAMES, 1);
+ mCaptureSequence = base::GetIntProperty(PROPERTY_CAPTURE_SKP_FRAMES, 1);
}
}
if (mCaptureSequence > 0 || mPictureCapturedCallback) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 0a2894945dc8..16c8b8923074 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -161,8 +161,7 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
// Recording Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
-SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
- sk_sp<SkColorFilter> colorSpaceFilter) {
+SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) {
bool fixBlending = false;
bool fixAA = false;
if (paint) {
@@ -172,23 +171,13 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
fixAA = paint->isAntiAlias();
}
- if (fixBlending || fixAA || colorSpaceFilter) {
+ if (fixBlending || fixAA) {
SkPaint& tmpPaint = paint.writeable();
if (fixBlending) {
tmpPaint.setBlendMode(SkBlendMode::kDstOut);
}
- if (colorSpaceFilter) {
- if (tmpPaint.getColorFilter()) {
- tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(
- tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
- } else {
- tmpPaint.setColorFilter(std::move(colorSpaceFilter));
- }
- LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
- }
-
// disabling AA on bitmap draws matches legacy HWUI behavior
tmpPaint.setAntiAlias(false);
}
@@ -198,7 +187,7 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImage(image, left, top, filterPaint(paint), bitmap.palette());
+ mRecorder.drawImage(image, left, top, filterBitmap(paint), bitmap.palette());
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
// when this function ends.
@@ -212,7 +201,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con
concat(matrix);
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImage(image, 0, 0, filterPaint(paint), bitmap.palette());
+ mRecorder.drawImage(image, 0, 0, filterBitmap(paint), bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
@@ -225,7 +214,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImageRect(image, srcRect, dstRect, filterPaint(paint),
+ mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint),
SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
!dstRect.isEmpty()) {
@@ -263,7 +252,7 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
}
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImageLattice(image, lattice, dst, filterPaint(std::move(filteredPaint)),
+ mRecorder.drawImageLattice(image, lattice, dst, filterBitmap(std::move(filteredPaint)),
bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index afeccea3fb70..c42cea33211e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -90,7 +90,7 @@ private:
*/
void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
- PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter);
+ PaintCoW&& filterBitmap(PaintCoW&& paint);
};
} // namespace skiapipeline
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 9a5a00fcf762..ad251f2364fe 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -17,7 +17,9 @@
#ifndef CACHEMANAGER_H
#define CACHEMANAGER_H
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
#include <GrContext.h>
+#endif
#include <SkSurface.h>
#include <ui/DisplayInfo.h>
#include <utils/String8.h>
@@ -42,7 +44,9 @@ class CacheManager {
public:
enum class TrimMemoryMode { Complete, UiHidden };
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
void configureContext(GrContextOptions* context, const void* identity, ssize_t size);
+#endif
void trimMemory(TrimMemoryMode mode);
void trimStaleResources();
void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr);
@@ -57,11 +61,15 @@ private:
explicit CacheManager(const DisplayInfo& display);
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
void reset(sk_sp<GrContext> grContext);
+#endif
void destroy();
const size_t mMaxSurfaceArea;
+#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
sk_sp<GrContext> mGrContext;
+#endif
int mMaxResources = 0;
const size_t mMaxResourceBytes;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 5173f638068d..46c3f2fc62d2 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -480,6 +480,13 @@ struct DestroySemaphoreInfo {
PFN_vkDestroySemaphore mDestroyFunction;
VkDevice mDevice;
VkSemaphore mSemaphore;
+ // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
+ // (including by the GPU) and inside the VulkanManager. So we always start with two refs, one
+ // owned by Skia and one owned by the VulkanManager. The refs are decremented each time
+ // destroy_semaphore is called with this object. Skia will call destroy_semaphore once it is
+ // done with the semaphore and the GPU has finished work on the semaphore. The VulkanManager
+ // calls destroy_semaphore after sending the semaphore to Skia and exporting it if need be.
+ int mRefs = 2;
DestroySemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
VkSemaphore semaphore)
@@ -488,8 +495,11 @@ struct DestroySemaphoreInfo {
static void destroy_semaphore(void* context) {
DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(context);
- info->mDestroyFunction(info->mDevice, info->mSemaphore, nullptr);
- delete info;
+ --info->mRefs;
+ if (!info->mRefs) {
+ info->mDestroyFunction(info->mDevice, info->mSemaphore, nullptr);
+ delete info;
+ }
}
void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
@@ -540,6 +550,7 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect)
ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
mQueueWaitIdle(mGraphicsQueue);
}
+ destroy_semaphore(destroyInfo);
surface->presentCurrentBuffer(dirtyRect, fenceFd);
}
@@ -642,13 +653,16 @@ status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence, GrContext* gr
DestroySemaphoreInfo* destroyInfo = new DestroySemaphoreInfo(mDestroySemaphore, mDevice,
semaphore);
+ // Even if Skia fails to submit the semaphore, it will still call the destroy_semaphore callback
+ // which will remove its ref to the semaphore. The VulkanManager must still release its ref,
+ // when it is done with the semaphore.
GrSemaphoresSubmitted submitted =
grContext->flush(kNone_GrFlushFlags, 1, &backendSemaphore,
destroy_semaphore, destroyInfo);
if (submitted == GrSemaphoresSubmitted::kNo) {
ALOGE("VulkanManager::createReleaseFence: Failed to submit semaphore");
- mDestroySemaphore(mDevice, semaphore, nullptr);
+ destroy_semaphore(destroyInfo);
return INVALID_OPERATION;
}
@@ -661,6 +675,7 @@ status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence, GrContext* gr
int fenceFd = 0;
err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+ destroy_semaphore(destroyInfo);
if (VK_SUCCESS != err) {
ALOGE("VulkanManager::createReleaseFence: Failed to get semaphore Fd");
return INVALID_OPERATION;
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index 510766073b08..400196b203b9 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -46,14 +46,12 @@ public:
SkPaint paint;
sk_sp<SkImage> image = hwuiBitmap->makeImage();
sk_sp<SkShader> repeatShader =
- image->makeShader(SkShader::TileMode::kRepeat_TileMode,
- SkShader::TileMode::kRepeat_TileMode, nullptr);
+ image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
paint.setShader(std::move(repeatShader));
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
sk_sp<SkShader> mirrorShader =
- image->makeShader(SkShader::TileMode::kMirror_TileMode,
- SkShader::TileMode::kMirror_TileMode, nullptr);
+ image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
paint.setShader(std::move(mirrorShader));
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
}
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 2af955fbb711..659926bae06f 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -60,10 +60,10 @@ public:
colors[0] = Color::Black;
colors[1] = Color::White;
sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial(
- center, 50, colors, nullptr, 2, SkShader::TileMode::kRepeat_TileMode);
+ center, 50, colors, nullptr, 2, SkTileMode::kRepeat);
sk_sp<SkShader> compositeShader(
- SkShader::MakeComposeShader(hardwareShader, gradientShader, SkBlendMode::kDstATop));
+ SkShaders::Blend(SkBlendMode::kDstATop, hardwareShader, gradientShader));
SkPaint paint;
paint.setShader(std::move(compositeShader));
@@ -74,7 +74,6 @@ public:
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
sk_sp<SkImage> image = bitmap.makeImage();
- return image->makeShader(SkShader::TileMode::kClamp_TileMode,
- SkShader::TileMode::kClamp_TileMode);
+ return image->makeShader();
}
};
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index ecaaf487e4f8..c6b60aaec9c5 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -44,7 +44,7 @@ class ListOfFadedTextAnimation : public TestListViewSceneBase {
SkColor colors[2] = {Color::Black, Color::Transparent};
sk_sp<SkShader> s(
- SkGradientShader::MakeLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode));
+ SkGradientShader::MakeLinear(pts, colors, NULL, 2, SkTileMode::kClamp));
SkMatrix matrix;
matrix.setScale(1, length);
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index feb881f654f8..fb7e34dfa513 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -53,7 +53,7 @@ class ListViewAnimation : public TestListViewSceneBase {
char charToShow = 'A' + (rand() % 26);
const SkPoint pos = {SkIntToScalar(size / 2),
/*approximate centering*/ SkFloatToScalar(size * 0.7f)};
- canvas.drawSimpleText(&charToShow, 1, kUTF8_SkTextEncoding, pos.fX, pos.fY, font, paint);
+ canvas.drawSimpleText(&charToShow, 1, SkTextEncoding::kUTF8, pos.fX, pos.fY, font, paint);
return bitmap;
}
diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
index ff0cb3705cb8..e60bd5fae198 100644
--- a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
@@ -53,20 +53,12 @@ private:
x, y, x + width, y + height,
[width, height](RenderProperties& props, Canvas& canvas) {
SkPaint paint;
- float matrix[20] = {0};
-
// Simple scale/translate case where R, G, and B are all treated equivalently
- matrix[SkColorMatrix::kR_Scale] = 1.1f;
- matrix[SkColorMatrix::kG_Scale] = 1.1f;
- matrix[SkColorMatrix::kB_Scale] = 1.1f;
- matrix[SkColorMatrix::kA_Scale] = 0.5f;
-
- matrix[SkColorMatrix::kR_Trans] = 5.0f;
- matrix[SkColorMatrix::kG_Trans] = 5.0f;
- matrix[SkColorMatrix::kB_Trans] = 5.0f;
- matrix[SkColorMatrix::kA_Trans] = 10.0f;
+ SkColorMatrix cm;
+ cm.setScale(1.1f, 1.1f, 1.1f, 0.5f);
+ cm.postTranslate(5.0f/255, 5.0f/255, 5.0f/255, 10.0f/255);
- paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
+ paint.setColorFilter(SkColorFilters::Matrix(cm));
// set a shader so it's not likely for the matrix to be optimized away (since a
// clever
@@ -75,7 +67,7 @@ private:
SkPoint pts[] = {SkPoint::Make(0, 0), SkPoint::Make(width, height)};
SkColor colors[2] = {Color::DeepPurple_500, Color::DeepOrange_500};
paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2,
- SkShader::kClamp_TileMode));
+ SkTileMode::kClamp));
// overdraw several times to emphasize shader cost
for (int i = 0; i < 10; i++) {
diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
index 016c65c17c4c..8bd804e75674 100644
--- a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
@@ -57,7 +57,7 @@ private:
// use i%2 start position to pick 2 color combo with black in it
SkColor colors[3] = {Color::Transparent, Color::Black, Color::Cyan_500};
paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2,
- SkShader::kClamp_TileMode));
+ SkTileMode::kClamp));
canvas.drawRect(i, i, width, height, paint);
}
});
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
index 229c7f392629..76f02888f994 100644
--- a/libs/hwui/tests/common/scenes/TvApp.cpp
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -219,7 +219,7 @@ private:
image.get()));
SkPaint paint;
sk_sp<SkColorFilter> filter(
- SkColorFilter::MakeModeFilter((curFrame % 150) << 24, SkBlendMode::kSrcATop));
+ SkColorFilters::Blend((curFrame % 150) << 24, SkBlendMode::kSrcATop));
paint.setColorFilter(filter);
sk_sp<Bitmap> bitmap = mCachedBitmaps[ci];
canvas->drawBitmap(*bitmap, 0, 0, &paint);
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index df5f45618070..7951537e1525 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -48,14 +48,14 @@ TEST(SkiaBehavior, lightingColorFilter_simplify) {
SkColor observedColor;
SkBlendMode observedMode;
- ASSERT_TRUE(filter->asColorMode(&observedColor, &observedMode));
+ ASSERT_TRUE(filter->asAColorMode(&observedColor, &observedMode));
EXPECT_EQ(0xFF223344, observedColor);
EXPECT_EQ(SkBlendMode::kModulate, observedMode);
}
{
sk_sp<SkColorFilter> failFilter(SkColorMatrixFilter::MakeLightingFilter(0x11223344, 0x1));
- EXPECT_FALSE(failFilter->asColorMode(nullptr, nullptr));
+ EXPECT_FALSE(failFilter->asAColorMode(nullptr, nullptr));
}
}
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 5db002862fcd..60fd7a753f2d 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -395,7 +395,7 @@ TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
bitmap.allocN32Pixels(5, 5, false);
SkCanvas canvas(bitmap);
- sk_sp<SkShader> shader = SkShader::MakeColorShader(SK_ColorBLACK);
+ sk_sp<SkShader> shader = SkShaders::Color(SK_ColorBLACK);
// Initial ref count is 1
EXPECT_TRUE(shader->unique());
diff --git a/libs/hwui/utils/TraceUtils.h b/libs/hwui/utils/TraceUtils.h
index 1869d00396c0..e61b4be1784e 100644
--- a/libs/hwui/utils/TraceUtils.h
+++ b/libs/hwui/utils/TraceUtils.h
@@ -16,6 +16,7 @@
#ifndef TRACE_UTILS_H
#define TRACE_UTILS_H
+#include <cutils/trace.h>
#include <utils/Trace.h>
#define ATRACE_FORMAT(fmt, ...) \