summaryrefslogtreecommitdiff
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/Android.mk112
-rw-r--r--libs/hwui/Caches.cpp11
-rw-r--r--libs/hwui/Caches.h7
-rw-r--r--libs/hwui/CanvasState.cpp19
-rw-r--r--libs/hwui/CanvasState.h28
-rw-r--r--libs/hwui/Debug.h3
-rw-r--r--libs/hwui/DeferredDisplayList.cpp686
-rw-r--r--libs/hwui/DeferredDisplayList.h200
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp7
-rw-r--r--libs/hwui/DeferredLayerUpdater.h8
-rw-r--r--libs/hwui/DisplayList.cpp10
-rw-r--r--libs/hwui/DisplayList.h69
-rw-r--r--libs/hwui/DisplayListCanvas.cpp597
-rw-r--r--libs/hwui/DisplayListCanvas.h359
-rw-r--r--libs/hwui/DisplayListOp.h1555
-rw-r--r--libs/hwui/FontRenderer.cpp23
-rw-r--r--libs/hwui/FontRenderer.h19
-rw-r--r--libs/hwui/FrameBuilder.cpp2
-rw-r--r--libs/hwui/FrameInfoVisualizer.cpp4
-rw-r--r--libs/hwui/FrameInfoVisualizer.h11
-rw-r--r--libs/hwui/Glop.h15
-rw-r--r--libs/hwui/GlopBuilder.cpp36
-rw-r--r--libs/hwui/GlopBuilder.h15
-rw-r--r--libs/hwui/Layer.cpp206
-rw-r--r--libs/hwui/Layer.h217
-rw-r--r--libs/hwui/LayerCache.cpp162
-rw-r--r--libs/hwui/LayerCache.h142
-rw-r--r--libs/hwui/LayerRenderer.cpp426
-rw-r--r--libs/hwui/LayerRenderer.h35
-rw-r--r--libs/hwui/OpDumper.cpp1
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2451
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h785
-rw-r--r--libs/hwui/PatchCache.cpp29
-rw-r--r--libs/hwui/PatchCache.h7
-rw-r--r--libs/hwui/Properties.cpp18
-rw-r--r--libs/hwui/Properties.h21
-rw-r--r--libs/hwui/Readback.cpp87
-rw-r--r--libs/hwui/Readback.h12
-rw-r--r--libs/hwui/RecordedOp.h7
-rw-r--r--libs/hwui/RecordingCanvas.cpp1
-rw-r--r--libs/hwui/RenderNode.cpp571
-rw-r--r--libs/hwui/RenderNode.h108
-rw-r--r--libs/hwui/RenderProperties.cpp1
-rw-r--r--libs/hwui/RenderProperties.h7
-rw-r--r--libs/hwui/SkiaCanvas.cpp10
-rw-r--r--libs/hwui/SkiaCanvasProxy.cpp3
-rw-r--r--libs/hwui/SkiaCanvasProxy.h2
-rw-r--r--libs/hwui/Snapshot.cpp86
-rw-r--r--libs/hwui/Snapshot.h67
-rw-r--r--libs/hwui/TessellationCache.cpp16
-rw-r--r--libs/hwui/TessellationCache.h21
-rw-r--r--libs/hwui/TreeInfo.h13
-rw-r--r--libs/hwui/VectorDrawable.h7
-rw-r--r--libs/hwui/debug/DefaultGlesDriver.cpp40
-rw-r--r--libs/hwui/debug/DefaultGlesDriver.h35
-rw-r--r--libs/hwui/debug/FatalBaseDriver.cpp40
-rw-r--r--libs/hwui/debug/FatalBaseDriver.h37
-rw-r--r--libs/hwui/debug/GlesDriver.cpp41
-rw-r--r--libs/hwui/debug/GlesDriver.h53
-rw-r--r--libs/hwui/debug/GlesErrorCheckWrapper.cpp74
-rw-r--r--libs/hwui/debug/GlesErrorCheckWrapper.h41
-rw-r--r--libs/hwui/debug/MockGlesDriver.h36
-rw-r--r--libs/hwui/debug/NullGlesDriver.cpp165
-rw-r--r--libs/hwui/debug/NullGlesDriver.h167
-rw-r--r--libs/hwui/debug/ScopedReplaceDriver.h46
-rw-r--r--libs/hwui/debug/gles_decls.in544
-rw-r--r--libs/hwui/debug/gles_stubs.in1632
-rw-r--r--libs/hwui/debug/gles_undefine.h (renamed from libs/hwui/debug/unwrap_gles.h)5
-rw-r--r--libs/hwui/debug/nullegl.cpp7
-rw-r--r--libs/hwui/debug/nullgles.cpp284
-rw-r--r--libs/hwui/debug/wrap_gles.cpp84
-rw-r--r--libs/hwui/debug/wrap_gles.h908
-rw-r--r--libs/hwui/font/CachedGlyphInfo.h12
-rw-r--r--libs/hwui/font/Font.cpp6
-rw-r--r--libs/hwui/font/FontUtil.h4
-rw-r--r--libs/hwui/hwui/Canvas.cpp24
-rw-r--r--libs/hwui/hwui/Canvas.h6
-rw-r--r--libs/hwui/hwui/MinikinSkia.cpp17
-rw-r--r--libs/hwui/hwui/MinikinSkia.h13
-rw-r--r--libs/hwui/hwui/MinikinUtils.cpp38
-rw-r--r--libs/hwui/hwui/MinikinUtils.h20
-rw-r--r--libs/hwui/hwui/Paint.h6
-rw-r--r--libs/hwui/hwui/PaintImpl.cpp4
-rw-r--r--libs/hwui/hwui/Typeface.cpp24
-rw-r--r--libs/hwui/hwui/Typeface.h6
-rw-r--r--libs/hwui/renderstate/MeshState.cpp8
-rw-r--r--libs/hwui/renderstate/MeshState.h1
-rw-r--r--libs/hwui/renderstate/RenderState.cpp32
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp430
-rw-r--r--libs/hwui/renderthread/CanvasContext.h46
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h76
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.cpp189
-rw-r--r--libs/hwui/renderthread/OpenGLPipeline.h69
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp39
-rw-r--r--libs/hwui/renderthread/RenderProxy.h5
-rw-r--r--libs/hwui/tests/common/LeakChecker.cpp94
-rw-r--r--libs/hwui/tests/common/LeakChecker.h29
-rw-r--r--libs/hwui/tests/common/TestContext.cpp51
-rw-r--r--libs/hwui/tests/common/TestContext.h18
-rw-r--r--libs/hwui/tests/common/TestListViewSceneBase.cpp78
-rw-r--r--libs/hwui/tests/common/TestListViewSceneBase.h44
-rw-r--r--libs/hwui/tests/common/TestScene.h14
-rw-r--r--libs/hwui/tests/common/TestUtils.cpp24
-rw-r--r--libs/hwui/tests/common/TestUtils.h15
-rw-r--r--libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp4
-rw-r--r--libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp60
-rw-r--r--libs/hwui/tests/common/scenes/ListViewAnimation.cpp116
-rw-r--r--libs/hwui/tests/common/scenes/TestSceneBase.h7
-rw-r--r--libs/hwui/tests/macrobench/TestSceneRunner.cpp73
-rw-r--r--libs/hwui/tests/macrobench/main.cpp83
-rw-r--r--libs/hwui/tests/microbench/DisplayListCanvasBench.cpp42
-rw-r--r--libs/hwui/tests/microbench/TaskManagerBench.cpp2
-rwxr-xr-xlibs/hwui/tests/microbench/how_to_run.txt5
-rw-r--r--libs/hwui/tests/microbench/main.cpp15
-rwxr-xr-xlibs/hwui/tests/scripts/prep_buller.sh49
-rwxr-xr-xlibs/hwui/tests/scripts/prep_volantis.sh10
-rw-r--r--libs/hwui/tests/scripts/stopruntime.sh27
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp4
-rw-r--r--libs/hwui/tests/unit/GlopBuilderTests.cpp6
-rw-r--r--libs/hwui/tests/unit/MeshStateTests.cpp36
-rw-r--r--libs/hwui/tests/unit/RecordingCanvasTests.cpp4
-rw-r--r--libs/hwui/tests/unit/RenderNodeTests.cpp9
-rw-r--r--libs/hwui/tests/unit/main.cpp80
-rw-r--r--libs/hwui/utils/NinePatchImpl.cpp9
-rw-r--r--libs/hwui/utils/TestWindowContext.cpp19
-rw-r--r--libs/hwui/utils/VectorDrawableUtils.cpp4
126 files changed, 4614 insertions, 11046 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 5dcfa4e102fd..3cce353052f1 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,8 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-HWUI_NEW_OPS := true
-
# Enables fine-grained GLES error checking
# If set to true, every GLES call is wrapped & error checked
# Has moderate overhead
@@ -26,6 +24,7 @@ hwui_src_files := \
renderstate/Stencil.cpp \
renderstate/TextureState.cpp \
renderthread/CanvasContext.cpp \
+ renderthread/OpenGLPipeline.cpp \
renderthread/DrawFrameTask.cpp \
renderthread/EglManager.cpp \
renderthread/RenderProxy.cpp \
@@ -45,19 +44,21 @@ hwui_src_files := \
Animator.cpp \
AnimatorManager.cpp \
AssetAtlas.cpp \
+ BakedOpDispatcher.cpp \
+ BakedOpRenderer.cpp \
+ BakedOpState.cpp \
Caches.cpp \
CanvasState.cpp \
ClipArea.cpp \
DamageAccumulator.cpp \
- DeferredDisplayList.cpp \
DeferredLayerUpdater.cpp \
DeviceInfo.cpp \
DisplayList.cpp \
- DisplayListCanvas.cpp \
Dither.cpp \
Extensions.cpp \
FboCache.cpp \
FontRenderer.cpp \
+ FrameBuilder.cpp \
FrameInfo.cpp \
FrameInfoVisualizer.cpp \
GammaFontRenderer.cpp \
@@ -68,23 +69,24 @@ hwui_src_files := \
Interpolator.cpp \
JankTracker.cpp \
Layer.cpp \
- LayerCache.cpp \
+ LayerBuilder.cpp \
LayerRenderer.cpp \
LayerUpdateQueue.cpp \
Matrix.cpp \
- OpenGLRenderer.cpp \
+ OpDumper.cpp \
Patch.cpp \
PatchCache.cpp \
PathCache.cpp \
- PathTessellator.cpp \
PathParser.cpp \
+ PathTessellator.cpp \
PixelBuffer.cpp \
Program.cpp \
ProgramCache.cpp \
Properties.cpp \
- PropertyValuesHolder.cpp \
PropertyValuesAnimatorSet.cpp \
+ PropertyValuesHolder.cpp \
Readback.cpp \
+ RecordingCanvas.cpp \
RenderBufferCache.cpp \
RenderNode.cpp \
RenderProperties.cpp \
@@ -104,10 +106,20 @@ hwui_src_files := \
hwui_test_common_src_files := \
$(call all-cpp-files-under, tests/common/scenes) \
+ tests/common/LeakChecker.cpp \
+ tests/common/TestListViewSceneBase.cpp \
tests/common/TestContext.cpp \
tests/common/TestScene.cpp \
tests/common/TestUtils.cpp
+hwui_debug_common_src_files := \
+ debug/wrap_gles.cpp \
+ debug/DefaultGlesDriver.cpp \
+ debug/GlesErrorCheckWrapper.cpp \
+ debug/GlesDriver.cpp \
+ debug/FatalBaseDriver.cpp \
+ debug/NullGlesDriver.cpp
+
hwui_cflags := \
-DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES \
-DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \
@@ -117,19 +129,8 @@ hwui_cflags := \
# a problem
hwui_cflags += -Wno-free-nonheap-object
-ifeq (true, $(HWUI_NEW_OPS))
- hwui_src_files += \
- BakedOpDispatcher.cpp \
- BakedOpRenderer.cpp \
- BakedOpState.cpp \
- FrameBuilder.cpp \
- LayerBuilder.cpp \
- OpDumper.cpp \
- RecordingCanvas.cpp
-
- hwui_cflags += -DHWUI_NEW_OPS
-
-endif
+# clang's warning is broken, see: https://llvm.org/bugs/show_bug.cgi?id=21629
+hwui_cflags += -Wno-missing-braces
ifndef HWUI_COMPILE_SYMBOLS
hwui_cflags += -fvisibility=hidden
@@ -160,14 +161,6 @@ ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
frameworks/rs
endif
-ifeq (true, $(HWUI_ENABLE_OPENGL_VALIDATION))
- hwui_cflags += -include debug/wrap_gles.h
- hwui_src_files += debug/wrap_gles.cpp
- hwui_c_includes += frameworks/native/opengl/libs/GLES2
- hwui_cflags += -DDEBUG_OPENGL=3
-endif
-
-
# ------------------------
# static library
# ------------------------
@@ -178,6 +171,13 @@ LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_MODULE := libhwui_static
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_SRC_FILES := $(hwui_src_files)
+
+ifeq (true, $(HWUI_ENABLE_OPENGL_VALIDATION))
+ LOCAL_CFLAGS += -include debug/wrap_gles.h
+ LOCAL_CFLAGS += -DDEBUG_OPENGL=3
+ LOCAL_SRC_FILES += $(hwui_debug_common_src_files)
+endif
+
LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH) \
@@ -193,14 +193,15 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := libhwui_static_null_gpu
+LOCAL_MODULE := libhwui_static_debug
LOCAL_CFLAGS := \
$(hwui_cflags) \
+ -include debug/wrap_gles.h \
-DHWUI_NULL_GPU
LOCAL_SRC_FILES := \
$(hwui_src_files) \
- debug/nullegl.cpp \
- debug/nullgles.cpp
+ $(hwui_debug_common_src_files) \
+ debug/nullegl.cpp
LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH) \
@@ -231,49 +232,47 @@ include $(CLEAR_VARS)
LOCAL_MODULE := hwui_unit_tests
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_LIBRARIES := libhwui_static_null_gpu
+LOCAL_STATIC_LIBRARIES := libgmock libhwui_static_debug
LOCAL_SHARED_LIBRARIES := libmemunreachable
LOCAL_CFLAGS := \
$(hwui_cflags) \
+ -include debug/wrap_gles.h \
-DHWUI_NULL_GPU
LOCAL_C_INCLUDES := $(hwui_c_includes)
LOCAL_SRC_FILES += \
$(hwui_test_common_src_files) \
tests/unit/main.cpp \
+ tests/unit/BakedOpDispatcherTests.cpp \
+ tests/unit/BakedOpRendererTests.cpp \
+ tests/unit/BakedOpStateTests.cpp \
tests/unit/CanvasStateTests.cpp \
tests/unit/ClipAreaTests.cpp \
tests/unit/DamageAccumulatorTests.cpp \
tests/unit/DeviceInfoTests.cpp \
tests/unit/FatVectorTests.cpp \
tests/unit/FontRendererTests.cpp \
+ tests/unit/FrameBuilderTests.cpp \
tests/unit/GlopBuilderTests.cpp \
tests/unit/GpuMemoryTrackerTests.cpp \
tests/unit/GradientCacheTests.cpp \
tests/unit/LayerUpdateQueueTests.cpp \
+ tests/unit/LeakCheckTests.cpp \
tests/unit/LinearAllocatorTests.cpp \
tests/unit/MatrixTests.cpp \
+ tests/unit/MeshStateTests.cpp \
tests/unit/OffscreenBufferPoolTests.cpp \
+ tests/unit/OpDumperTests.cpp \
+ tests/unit/RecordingCanvasTests.cpp \
tests/unit/RenderNodeTests.cpp \
tests/unit/RenderPropertiesTests.cpp \
tests/unit/SkiaBehaviorTests.cpp \
+ tests/unit/SkiaCanvasTests.cpp \
tests/unit/SnapshotTests.cpp \
tests/unit/StringUtilsTests.cpp \
tests/unit/TestUtilsTests.cpp \
tests/unit/TextDropShadowCacheTests.cpp \
- tests/unit/VectorDrawableTests.cpp
-
-ifeq (true, $(HWUI_NEW_OPS))
- LOCAL_SRC_FILES += \
- tests/unit/BakedOpDispatcherTests.cpp \
- tests/unit/BakedOpRendererTests.cpp \
- tests/unit/BakedOpStateTests.cpp \
- tests/unit/FrameBuilderTests.cpp \
- tests/unit/LeakCheckTests.cpp \
- tests/unit/OpDumperTests.cpp \
- tests/unit/RecordingCanvasTests.cpp \
- tests/unit/SkiaCanvasTests.cpp
-endif
+ tests/unit/VectorDrawableTests.cpp \
include $(LOCAL_PATH)/hwui_static_deps.mk
include $(BUILD_NATIVE_TEST)
@@ -294,8 +293,10 @@ LOCAL_MODULE_STEM_64 := hwuitest64
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_C_INCLUDES := $(hwui_c_includes)
-# set to libhwui_static_null_gpu to skip actual GL commands
+# set to libhwui_static_debug to skip actual GL commands
LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
+LOCAL_SHARED_LIBRARIES := libmemunreachable
+LOCAL_STATIC_LIBRARIES := libgoogle-benchmark
LOCAL_SRC_FILES += \
$(hwui_test_common_src_files) \
@@ -310,36 +311,29 @@ include $(BUILD_EXECUTABLE)
# ---------------------
include $(CLEAR_VARS)
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
LOCAL_MODULE:= hwuimicro
LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := hwuimicro
-LOCAL_MODULE_STEM_64 := hwuimicro64
LOCAL_CFLAGS := \
$(hwui_cflags) \
+ -include debug/wrap_gles.h \
-DHWUI_NULL_GPU
LOCAL_C_INCLUDES := $(hwui_c_includes)
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_null_gpu
-LOCAL_STATIC_LIBRARIES := libgoogle-benchmark
+LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_debug
+LOCAL_SHARED_LIBRARIES := libmemunreachable
LOCAL_SRC_FILES += \
$(hwui_test_common_src_files) \
tests/microbench/main.cpp \
tests/microbench/DisplayListCanvasBench.cpp \
tests/microbench/FontBench.cpp \
+ tests/microbench/FrameBuilderBench.cpp \
tests/microbench/LinearAllocatorBench.cpp \
tests/microbench/PathParserBench.cpp \
tests/microbench/ShadowBench.cpp \
tests/microbench/TaskManagerBench.cpp
-ifeq (true, $(HWUI_NEW_OPS))
- LOCAL_SRC_FILES += \
- tests/microbench/FrameBuilderBench.cpp
-endif
include $(LOCAL_PATH)/hwui_static_deps.mk
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_BENCHMARK)
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 949ad450d5f7..ef81a522c050 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -68,8 +68,6 @@ bool Caches::init() {
mRegionMesh = nullptr;
mProgram = nullptr;
- patchCache.init();
-
mInitialized = true;
mPixelBufferState = new PixelBufferState();
@@ -165,17 +163,15 @@ void Caches::dumpMemoryUsage(String8 &log) {
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
log.appendFormat(" TextureCache %8d / %8d\n",
textureCache.getSize(), textureCache.getMaxSize());
- log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n",
- layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
if (mRenderState) {
int memused = 0;
for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
it != mRenderState->mActiveLayers.end(); it++) {
const Layer* layer = *it;
- log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
+ log.appendFormat(" Layer size %dx%d; texid=%u refs=%d\n",
layer->getWidth(), layer->getHeight(),
- layer->isTextureLayer(), layer->getTextureId(),
- layer->getFbo(), layer->getStrongCount());
+ layer->getTextureId(),
+ layer->getStrongCount());
memused += layer->getWidth() * layer->getHeight() * 4;
}
log.appendFormat(" Layers total %8d (numLayers = %zu)\n",
@@ -250,7 +246,6 @@ void Caches::flush(FlushMode mode) {
tessellationCache.clear();
// fall through
case FlushMode::Layers:
- layerCache.clear();
renderBufferCache.clear();
break;
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index eac9359beab3..fe9411d8bb3f 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_CACHES_H
-#define ANDROID_HWUI_CACHES_H
+#pragma once
#include "AssetAtlas.h"
#include "Dither.h"
@@ -23,7 +22,6 @@
#include "FboCache.h"
#include "GammaFontRenderer.h"
#include "GradientCache.h"
-#include "LayerCache.h"
#include "PatchCache.h"
#include "ProgramCache.h"
#include "PathCache.h"
@@ -146,7 +144,6 @@ private:
Extensions mExtensions;
public:
TextureCache textureCache;
- LayerCache layerCache;
RenderBufferCache renderBufferCache;
GradientCache gradientCache;
PatchCache patchCache;
@@ -205,5 +202,3 @@ private:
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_CACHES_H
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index e2149d1e4a69..7e2c28c5eb41 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -23,8 +23,7 @@ namespace uirenderer {
CanvasState::CanvasState(CanvasStateClient& renderer)
- : mDirtyClip(false)
- , mWidth(-1)
+ : mWidth(-1)
, mHeight(-1)
, mSaveCount(1)
, mCanvas(renderer)
@@ -205,19 +204,16 @@ void CanvasState::concatMatrix(const Matrix4& matrix) {
bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
mSnapshot->clip(Rect(left, top, right, bottom), op);
- mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
mSnapshot->clipPath(*path, op);
- mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
mSnapshot->clipRegionTransformed(*region, op);
- mDirtyClip = true;
return !mSnapshot->clipIsEmpty();
}
@@ -236,15 +232,6 @@ void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline*
}
}
-void CanvasState::setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius, bool highPriority) {
- mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
-}
-
-void CanvasState::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
- mSnapshot->setProjectionPathMask(allocator, path);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Quick Rejection
///////////////////////////////////////////////////////////////////////////////
@@ -263,7 +250,7 @@ bool CanvasState::calculateQuickRejectForScissor(float left, float top,
float right, float bottom,
bool* clipRequired, bool* roundRectClipRequired,
bool snapOut) const {
- if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
+ if (bottom <= top || right <= left) {
return true;
}
@@ -291,7 +278,7 @@ bool CanvasState::calculateQuickRejectForScissor(float left, float top,
bool CanvasState::quickRejectConservative(float left, float top,
float right, float bottom) const {
- if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
+ if (bottom <= top || right <= left) {
return true;
}
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index b9e87ae5595d..ba260d1ab88e 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_CANVAS_STATE_H
-#define ANDROID_HWUI_CANVAS_STATE_H
+#pragma once
#include "Snapshot.h"
@@ -62,11 +61,11 @@ public:
* Renderer interface. Drawing and recording classes that include a CanvasState will have
* different use cases:
*
- * Drawing code maintaining canvas state (i.e. OpenGLRenderer) can query attributes (such as
+ * Drawing code maintaining canvas state (e.g. FrameBuilder) can query attributes (such as
* transform) or hook into changes (e.g. save/restore) with minimal surface area for manipulating
* the stack itself.
*
- * Recording code maintaining canvas state (i.e. DisplayListCanvas) can both record and pass
+ * Recording code maintaining canvas state (e.g. RecordingCanvas) can both record and pass
* through state operations to CanvasState, so that not only will querying operations work
* (getClip/Matrix), but so that quickRejection can also be used.
*/
@@ -134,8 +133,12 @@ public:
*/
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
void setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius, bool highPriority = true);
- void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
+ const Rect& rect, float radius, bool highPriority = true) {
+ mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
+ }
+ void setProjectionPathMask(const SkPath* path) {
+ mSnapshot->setProjectionPathMask(path);
+ }
/**
* Returns true if drawing in the rectangle (left, top, right, bottom)
@@ -145,19 +148,12 @@ public:
bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
- void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
- bool getDirtyClip() const { return mDirtyClip; }
-
void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
- void setEmpty(bool value) { mSnapshot->empty = value; }
- void setInvisible(bool value) { mSnapshot->invisible = value; }
inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
inline const Rect& currentRenderTargetClip() const { return currentSnapshot()->getRenderTargetClip(); }
- inline Region* currentRegion() const { return currentSnapshot()->region; }
inline int currentFlags() const { return currentSnapshot()->flags; }
const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
- inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
int getWidth() const { return mWidth; }
@@ -173,10 +169,6 @@ private:
void freeSnapshot(Snapshot* snapshot);
void freeAllSnapshots();
- /// indicates that the clip has been changed since the last time it was consumed
- // TODO: delete when switching to HWUI_NEW_OPS
- bool mDirtyClip;
-
/// Dimensions of the drawing surface
int mWidth, mHeight;
@@ -201,5 +193,3 @@ private:
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_CANVAS_STATE_H
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 748edef730b7..e29699d0faf4 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -98,6 +98,9 @@
// Turn on to enable debugging shadow
#define DEBUG_SHADOW 0
+// Turn on to enable debugging vector drawable
+#define DEBUG_VECTOR_DRAWABLE 0
+
#if DEBUG_INIT
#define INIT_LOGD(...) ALOGD(__VA_ARGS__)
#else
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
deleted file mode 100644
index 689179dd8fb4..000000000000
--- a/libs/hwui/DeferredDisplayList.cpp
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/Trace.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-#include "Caches.h"
-#include "Debug.h"
-#include "DeferredDisplayList.h"
-#include "DisplayListOp.h"
-#include "OpenGLRenderer.h"
-#include "Properties.h"
-#include "utils/MathUtils.h"
-
-#if DEBUG_DEFER
- #define DEFER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define DEFER_LOGD(...)
-#endif
-
-namespace android {
-namespace uirenderer {
-
-// Depth of the save stack at the beginning of batch playback at flush time
-#define FLUSH_SAVE_STACK_DEPTH 2
-
-#define DEBUG_COLOR_BARRIER 0x1f000000
-#define DEBUG_COLOR_MERGEDBATCH 0x5f7f7fff
-#define DEBUG_COLOR_MERGEDBATCH_SOLO 0x5f7fff7f
-
-static bool avoidOverdraw() {
- // Don't avoid overdraw when visualizing it, since that makes it harder to
- // debug where it's coming from, and when the problem occurs.
- return !Properties::debugOverdraw;
-};
-
-/////////////////////////////////////////////////////////////////////////////////
-// Operation Batches
-/////////////////////////////////////////////////////////////////////////////////
-
-class Batch {
-public:
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) = 0;
- virtual ~Batch() {}
- virtual bool purelyDrawBatch() { return false; }
- virtual bool coversBounds(const Rect& bounds) { return false; }
-};
-
-class DrawBatch : public Batch {
-public:
- explicit DrawBatch(const DeferInfo& deferInfo) : mAllOpsOpaque(true),
- mBatchId(deferInfo.batchId), mMergeId(deferInfo.mergeId) {
- mOps.clear();
- }
-
- virtual ~DrawBatch() { mOps.clear(); }
-
- virtual void add(DrawOp* op, const DeferredDisplayState* state, bool opaqueOverBounds) {
- // NOTE: ignore empty bounds special case, since we don't merge across those ops
- mBounds.unionWith(state->mBounds);
- mAllOpsOpaque &= opaqueOverBounds;
- mOps.push_back(OpStatePair(op, state));
- }
-
- bool intersects(const Rect& rect) {
- if (!rect.intersects(mBounds)) return false;
-
- for (unsigned int i = 0; i < mOps.size(); i++) {
- if (rect.intersects(mOps[i].state->mBounds)) {
-#if DEBUG_DEFER
- DEFER_LOGD("op intersects with op %p with bounds %f %f %f %f:", mOps[i].op,
- mOps[i].state->mBounds.left, mOps[i].state->mBounds.top,
- mOps[i].state->mBounds.right, mOps[i].state->mBounds.bottom);
- mOps[i].op->output(2);
-#endif
- return true;
- }
- }
- return false;
- }
-
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) override {
- DEFER_LOGD("%d replaying DrawBatch %p, with %d ops (batch id %x, merge id %p)",
- index, this, mOps.size(), getBatchId(), getMergeId());
-
- for (unsigned int i = 0; i < mOps.size(); i++) {
- DrawOp* op = mOps[i].op;
- const DeferredDisplayState* state = mOps[i].state;
- renderer.restoreDisplayState(*state);
-
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
- renderer.eventMark(op->name());
-#endif
- op->applyDraw(renderer, dirty);
-
-#if DEBUG_MERGE_BEHAVIOR
- const Rect& bounds = state->mBounds;
- int batchColor = 0x1f000000;
- if (getBatchId() & 0x1) batchColor |= 0x0000ff;
- if (getBatchId() & 0x2) batchColor |= 0x00ff00;
- if (getBatchId() & 0x4) batchColor |= 0xff0000;
- renderer.drawScreenSpaceColorRect(bounds.left, bounds.top, bounds.right, bounds.bottom,
- batchColor);
-#endif
- }
- }
-
- virtual bool purelyDrawBatch() override { return true; }
-
- virtual bool coversBounds(const Rect& bounds) override {
- if (CC_LIKELY(!mAllOpsOpaque || !mBounds.contains(bounds) || count() == 1)) return false;
-
- Region uncovered(android::Rect(bounds.left, bounds.top, bounds.right, bounds.bottom));
- for (unsigned int i = 0; i < mOps.size(); i++) {
- const Rect &r = mOps[i].state->mBounds;
- uncovered.subtractSelf(android::Rect(r.left, r.top, r.right, r.bottom));
- }
- return uncovered.isEmpty();
- }
-
- inline int getBatchId() const { return mBatchId; }
- inline mergeid_t getMergeId() const { return mMergeId; }
- inline int count() const { return mOps.size(); }
-
-protected:
- std::vector<OpStatePair> mOps;
- Rect mBounds; // union of bounds of contained ops
-private:
- bool mAllOpsOpaque;
- int mBatchId;
- mergeid_t mMergeId;
-};
-
-class MergingDrawBatch : public DrawBatch {
-public:
- MergingDrawBatch(DeferInfo& deferInfo, int width, int height) :
- DrawBatch(deferInfo), mClipRect(width, height),
- mClipSideFlags(kClipSide_None) {}
-
- /*
- * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
- * and clip side flags. Positive bounds delta means new bounds fit in old.
- */
- static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
- float boundsDelta) {
- bool currentClipExists = currentFlags & side;
- bool newClipExists = newFlags & side;
-
- // if current is clipped, we must be able to fit new bounds in current
- if (boundsDelta > 0 && currentClipExists) return false;
-
- // if new is clipped, we must be able to fit current bounds in new
- if (boundsDelta < 0 && newClipExists) return false;
-
- return true;
- }
-
- /*
- * Checks if a (mergeable) op can be merged into this batch
- *
- * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
- * important to consider all paint attributes used in the draw calls in deciding both a) if an
- * op tries to merge at all, and b) if the op can merge with another set of ops
- *
- * False positives can lead to information from the paints of subsequent merged operations being
- * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
- */
- bool canMergeWith(const DrawOp* op, const DeferredDisplayState* state) {
- bool isTextBatch = getBatchId() == DeferredDisplayList::kOpBatch_Text ||
- getBatchId() == DeferredDisplayList::kOpBatch_ColorText;
-
- // Overlapping other operations is only allowed for text without shadow. For other ops,
- // multiDraw isn't guaranteed to overdraw correctly
- if (!isTextBatch || op->hasTextShadow()) {
- if (intersects(state->mBounds)) return false;
- }
- const DeferredDisplayState* lhs = state;
- const DeferredDisplayState* rhs = mOps[0].state;
-
- if (!MathUtils::areEqual(lhs->mAlpha, rhs->mAlpha)) return false;
-
- // Identical round rect clip state means both ops will clip in the same way, or not at all.
- // As the state objects are const, we can compare their pointers to determine mergeability
- if (lhs->mRoundRectClipState != rhs->mRoundRectClipState) return false;
- if (lhs->mProjectionPathMask != rhs->mProjectionPathMask) return false;
-
- /* Clipping compatibility check
- *
- * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its
- * clip for that side.
- */
- const int currentFlags = mClipSideFlags;
- const int newFlags = state->mClipSideFlags;
- if (currentFlags != kClipSide_None || newFlags != kClipSide_None) {
- const Rect& opBounds = state->mBounds;
- float boundsDelta = mBounds.left - opBounds.left;
- if (!checkSide(currentFlags, newFlags, kClipSide_Left, boundsDelta)) return false;
- boundsDelta = mBounds.top - opBounds.top;
- if (!checkSide(currentFlags, newFlags, kClipSide_Top, boundsDelta)) return false;
-
- // right and bottom delta calculation reversed to account for direction
- boundsDelta = opBounds.right - mBounds.right;
- if (!checkSide(currentFlags, newFlags, kClipSide_Right, boundsDelta)) return false;
- boundsDelta = opBounds.bottom - mBounds.bottom;
- if (!checkSide(currentFlags, newFlags, kClipSide_Bottom, boundsDelta)) return false;
- }
-
- // if paints are equal, then modifiers + paint attribs don't need to be compared
- if (op->mPaint == mOps[0].op->mPaint) return true;
-
- if (PaintUtils::getAlphaDirect(op->mPaint)
- != PaintUtils::getAlphaDirect(mOps[0].op->mPaint)) {
- return false;
- }
-
- if (op->mPaint && mOps[0].op->mPaint &&
- op->mPaint->getColorFilter() != mOps[0].op->mPaint->getColorFilter()) {
- return false;
- }
-
- if (op->mPaint && mOps[0].op->mPaint &&
- op->mPaint->getShader() != mOps[0].op->mPaint->getShader()) {
- return false;
- }
-
- return true;
- }
-
- virtual void add(DrawOp* op, const DeferredDisplayState* state,
- bool opaqueOverBounds) override {
- DrawBatch::add(op, state, opaqueOverBounds);
-
- const int newClipSideFlags = state->mClipSideFlags;
- mClipSideFlags |= newClipSideFlags;
- if (newClipSideFlags & kClipSide_Left) mClipRect.left = state->mClip.left;
- if (newClipSideFlags & kClipSide_Top) mClipRect.top = state->mClip.top;
- if (newClipSideFlags & kClipSide_Right) mClipRect.right = state->mClip.right;
- if (newClipSideFlags & kClipSide_Bottom) mClipRect.bottom = state->mClip.bottom;
- }
-
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) override {
- DEFER_LOGD("%d replaying MergingDrawBatch %p, with %d ops,"
- " clip flags %x (batch id %x, merge id %p)",
- index, this, mOps.size(), mClipSideFlags, getBatchId(), getMergeId());
- if (mOps.size() == 1) {
- DrawBatch::replay(renderer, dirty, -1);
- return;
- }
-
- // clipping in the merged case is done ahead of time since all ops share the clip (if any)
- renderer.setupMergedMultiDraw(mClipSideFlags ? &mClipRect : nullptr);
-
- DrawOp* op = mOps[0].op;
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
- renderer.eventMark("multiDraw");
- renderer.eventMark(op->name());
-#endif
- op->multiDraw(renderer, dirty, mOps, mBounds);
-
-#if DEBUG_MERGE_BEHAVIOR
- renderer.drawScreenSpaceColorRect(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom,
- DEBUG_COLOR_MERGEDBATCH);
-#endif
- }
-
-private:
- /*
- * Contains the effective clip rect shared by all merged ops. Initialized to the layer viewport,
- * it will shrink if an op must be clipped on a certain side. The clipped sides are reflected in
- * mClipSideFlags.
- */
- Rect mClipRect;
- int mClipSideFlags;
-};
-
-class StateOpBatch : public Batch {
-public:
- // creates a single operation batch
- StateOpBatch(const StateOp* op, const DeferredDisplayState* state) : mOp(op), mState(state) {}
-
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) override {
- DEFER_LOGD("replaying state op batch %p", this);
- renderer.restoreDisplayState(*mState);
-
- // use invalid save count because it won't be used at flush time - RestoreToCountOp is the
- // only one to use it, and we don't use that class at flush time, instead calling
- // renderer.restoreToCount directly
- int saveCount = -1;
- mOp->applyState(renderer, saveCount);
- }
-
-private:
- const StateOp* mOp;
- const DeferredDisplayState* mState;
-};
-
-class RestoreToCountBatch : public Batch {
-public:
- RestoreToCountBatch(const StateOp* op, const DeferredDisplayState* state, int restoreCount) :
- mState(state), mRestoreCount(restoreCount) {}
-
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) override {
- DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
-
- renderer.restoreDisplayState(*mState);
- renderer.restoreToCount(mRestoreCount);
- }
-
-private:
- // we use the state storage for the RestoreToCountOp, but don't replay the op itself
- const DeferredDisplayState* mState;
-
- /*
- * The count used here represents the flush() time saveCount. This is as opposed to the
- * DisplayList record time, or defer() time values (which are RestoreToCountOp's mCount, and
- * (saveCount + mCount) respectively). Since the count is different from the original
- * RestoreToCountOp, we don't store a pointer to the op, as elsewhere.
- */
- const int mRestoreCount;
-};
-
-#if DEBUG_MERGE_BEHAVIOR
-class BarrierDebugBatch : public Batch {
- virtual void replay(OpenGLRenderer& renderer, Rect& dirty, int index) {
- renderer.drawScreenSpaceColorRect(0, 0, 10000, 10000, DEBUG_COLOR_BARRIER);
- }
-};
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////
-// DeferredDisplayList
-/////////////////////////////////////////////////////////////////////////////////
-
-void DeferredDisplayList::resetBatchingState() {
- for (int i = 0; i < kOpBatch_Count; i++) {
- mBatchLookup[i] = nullptr;
- mMergingBatches[i].clear();
- }
-#if DEBUG_MERGE_BEHAVIOR
- if (mBatches.size() != 0) {
- mBatches.add(new BarrierDebugBatch());
- }
-#endif
- mEarliestBatchIndex = mBatches.size();
-}
-
-void DeferredDisplayList::clear() {
- resetBatchingState();
- mComplexClipStackStart = -1;
-
- for (unsigned int i = 0; i < mBatches.size(); i++) {
- delete mBatches[i];
- }
- mBatches.clear();
- mSaveStack.clear();
- mEarliestBatchIndex = 0;
- mEarliestUnclearedIndex = 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-// Operation adding
-/////////////////////////////////////////////////////////////////////////////////
-
-int DeferredDisplayList::getStateOpDeferFlags() const {
- // For both clipOp and save(Layer)Op, we don't want to save drawing info, and only want to save
- // the clip if we aren't recording a complex clip (and can thus trust it to be a rect)
- return recordingComplexClip() ? 0 : kStateDeferFlag_Clip;
-}
-
-int DeferredDisplayList::getDrawOpDeferFlags() const {
- return kStateDeferFlag_Draw | getStateOpDeferFlags();
-}
-
-/**
- * When an clipping operation occurs that could cause a complex clip, record the operation and all
- * subsequent clipOps, save/restores (if the clip flag is set). During a flush, instead of loading
- * the clip from deferred state, we play back all of the relevant state operations that generated
- * the complex clip.
- *
- * Note that we don't need to record the associated restore operation, since operations at defer
- * time record whether they should store the renderer's current clip
- */
-void DeferredDisplayList::addClip(OpenGLRenderer& renderer, ClipOp* op) {
- if (recordingComplexClip() || op->canCauseComplexClip() || !renderer.hasRectToRectTransform()) {
- DEFER_LOGD("%p Received complex clip operation %p", this, op);
-
- // NOTE: defer clip op before setting mComplexClipStackStart so previous clip is recorded
- storeStateOpBarrier(renderer, op);
-
- if (!recordingComplexClip()) {
- mComplexClipStackStart = renderer.getSaveCount() - 1;
- DEFER_LOGD(" Starting complex clip region, start is %d", mComplexClipStackStart);
- }
- }
-}
-
-/**
- * For now, we record save layer operations as barriers in the batch list, preventing drawing
- * operations from reordering around the saveLayer and it's associated restore()
- *
- * In the future, we should send saveLayer commands (if they can be played out of order) and their
- * contained drawing operations to a seperate list of batches, so that they may draw at the
- * beginning of the frame. This would avoid targetting and removing an FBO in the middle of a frame.
- *
- * saveLayer operations should be pulled to the beginning of the frame if the canvas doesn't have a
- * complex clip, and if the flags (SaveFlags::Clip & SaveFlags::ClipToLayer) are set.
- */
-void DeferredDisplayList::addSaveLayer(OpenGLRenderer& renderer,
- SaveLayerOp* op, int newSaveCount) {
- DEFER_LOGD("%p adding saveLayerOp %p, flags %x, new count %d",
- this, op, op->getFlags(), newSaveCount);
-
- storeStateOpBarrier(renderer, op);
- mSaveStack.push_back(newSaveCount);
-}
-
-/**
- * Takes save op and it's return value - the new save count - and stores it into the stream as a
- * barrier if it's needed to properly modify a complex clip
- */
-void DeferredDisplayList::addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount) {
- int saveFlags = op->getFlags();
- DEFER_LOGD("%p adding saveOp %p, flags %x, new count %d", this, op, saveFlags, newSaveCount);
-
- if (recordingComplexClip() && (saveFlags & SaveFlags::Clip)) {
- // store and replay the save operation, as it may be needed to correctly playback the clip
- DEFER_LOGD(" adding save barrier with new save count %d", newSaveCount);
- storeStateOpBarrier(renderer, op);
- mSaveStack.push_back(newSaveCount);
- }
-}
-
-/**
- * saveLayer() commands must be associated with a restoreToCount batch that will clean up and draw
- * the layer in the deferred list
- *
- * other save() commands which occur as children of a snapshot with complex clip will be deferred,
- * and must be restored
- *
- * Either will act as a barrier to draw operation reordering, as we want to play back layer
- * save/restore and complex canvas modifications (including save/restore) in order.
- */
-void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* op,
- int newSaveCount) {
- DEFER_LOGD("%p addRestoreToCount %d", this, newSaveCount);
-
- if (recordingComplexClip() && newSaveCount <= mComplexClipStackStart) {
- mComplexClipStackStart = -1;
- resetBatchingState();
- }
-
- if (mSaveStack.empty() || newSaveCount > mSaveStack.back()) {
- return;
- }
-
- while (!mSaveStack.empty() && mSaveStack.back() >= newSaveCount) mSaveStack.pop_back();
-
- storeRestoreToCountBarrier(renderer, op, mSaveStack.size() + FLUSH_SAVE_STACK_DEPTH);
-}
-
-void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
- /* 1: op calculates local bounds */
- DeferredDisplayState* const state = createState();
- if (op->getLocalBounds(state->mBounds)) {
- if (state->mBounds.isEmpty()) {
- // valid empty bounds, don't bother deferring
- tryRecycleState(state);
- return;
- }
- } else {
- state->mBounds.setEmpty();
- }
-
- /* 2: renderer calculates global bounds + stores state */
- if (renderer.storeDisplayState(*state, getDrawOpDeferFlags())) {
- tryRecycleState(state);
- return; // quick rejected
- }
-
- /* 3: ask op for defer info, given renderer state */
- DeferInfo deferInfo;
- op->onDefer(renderer, deferInfo, *state);
-
- // complex clip has a complex set of expectations on the renderer state - for now, avoid taking
- // the merge path in those cases
- deferInfo.mergeable &= !recordingComplexClip();
- deferInfo.opaqueOverBounds &= !recordingComplexClip()
- && mSaveStack.empty()
- && !state->mRoundRectClipState;
-
- if (CC_LIKELY(avoidOverdraw()) && mBatches.size() &&
- state->mClipSideFlags != kClipSide_ConservativeFull &&
- deferInfo.opaqueOverBounds && state->mBounds.contains(mBounds)) {
- // avoid overdraw by resetting drawing state + discarding drawing ops
- discardDrawingBatches(mBatches.size() - 1);
- resetBatchingState();
- }
-
- if (CC_UNLIKELY(Properties::drawReorderDisabled)) {
- // TODO: elegant way to reuse batches?
- DrawBatch* b = new DrawBatch(deferInfo);
- b->add(op, state, deferInfo.opaqueOverBounds);
- mBatches.push_back(b);
- return;
- }
-
- // find the latest batch of the new op's type, and try to merge the new op into it
- DrawBatch* targetBatch = nullptr;
-
- // insertion point of a new batch, will hopefully be immediately after similar batch
- // (eventually, should be similar shader)
- int insertBatchIndex = mBatches.size();
- if (!mBatches.empty()) {
- if (state->mBounds.isEmpty()) {
- // don't know the bounds for op, so create new batch and start from scratch on next op
- DrawBatch* b = new DrawBatch(deferInfo);
- b->add(op, state, deferInfo.opaqueOverBounds);
- mBatches.push_back(b);
- resetBatchingState();
-#if DEBUG_DEFER
- DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches");
- op->output(2);
-#endif
- return;
- }
-
- if (deferInfo.mergeable) {
- // Try to merge with any existing batch with same mergeId.
- std::unordered_map<mergeid_t, DrawBatch*>& mergingBatch
- = mMergingBatches[deferInfo.batchId];
- auto getResult = mergingBatch.find(deferInfo.mergeId);
- if (getResult != mergingBatch.end()) {
- targetBatch = getResult->second;
- if (!((MergingDrawBatch*) targetBatch)->canMergeWith(op, state)) {
- targetBatch = nullptr;
- }
- }
- } else {
- // join with similar, non-merging batch
- targetBatch = (DrawBatch*)mBatchLookup[deferInfo.batchId];
- }
-
- if (targetBatch || deferInfo.mergeable) {
- // iterate back toward target to see if anything drawn since should overlap the new op
- // if no target, merging ops still interate to find similar batch to insert after
- for (int i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
- DrawBatch* overBatch = (DrawBatch*)mBatches[i];
-
- if (overBatch == targetBatch) break;
-
- // TODO: also consider shader shared between batch types
- if (deferInfo.batchId == overBatch->getBatchId()) {
- insertBatchIndex = i + 1;
- if (!targetBatch) break; // found insert position, quit
- }
-
- if (overBatch->intersects(state->mBounds)) {
- // NOTE: it may be possible to optimize for special cases where two operations
- // of the same batch/paint could swap order, such as with a non-mergeable
- // (clipped) and a mergeable text operation
- targetBatch = nullptr;
-#if DEBUG_DEFER
- DEFER_LOGD("op couldn't join batch %p, was intersected by batch %d",
- targetBatch, i);
- op->output(2);
-#endif
- break;
- }
- }
- }
- }
-
- if (!targetBatch) {
- if (deferInfo.mergeable) {
- targetBatch = new MergingDrawBatch(deferInfo,
- renderer.getViewportWidth(), renderer.getViewportHeight());
- mMergingBatches[deferInfo.batchId].insert(
- std::make_pair(deferInfo.mergeId, targetBatch));
- } else {
- targetBatch = new DrawBatch(deferInfo);
- mBatchLookup[deferInfo.batchId] = targetBatch;
- }
-
- DEFER_LOGD("creating %singBatch %p, bid %x, at %d",
- deferInfo.mergeable ? "Merg" : "Draw",
- targetBatch, deferInfo.batchId, insertBatchIndex);
- mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
- }
-
- targetBatch->add(op, state, deferInfo.opaqueOverBounds);
-}
-
-void DeferredDisplayList::storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op) {
- DEFER_LOGD("%p adding state op barrier at pos %d", this, mBatches.size());
-
- DeferredDisplayState* state = createState();
- renderer.storeDisplayState(*state, getStateOpDeferFlags());
- mBatches.push_back(new StateOpBatch(op, state));
- resetBatchingState();
-}
-
-void DeferredDisplayList::storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op,
- int newSaveCount) {
- DEFER_LOGD("%p adding restore to count %d barrier, pos %d",
- this, newSaveCount, mBatches.size());
-
- // store displayState for the restore operation, as it may be associated with a saveLayer that
- // doesn't have SaveFlags::Clip set
- DeferredDisplayState* state = createState();
- renderer.storeDisplayState(*state, getStateOpDeferFlags());
- mBatches.push_back(new RestoreToCountBatch(op, state, newSaveCount));
- resetBatchingState();
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-// Replay / flush
-/////////////////////////////////////////////////////////////////////////////////
-
-static void replayBatchList(const std::vector<Batch*>& batchList,
- OpenGLRenderer& renderer, Rect& dirty) {
-
- for (unsigned int i = 0; i < batchList.size(); i++) {
- if (batchList[i]) {
- batchList[i]->replay(renderer, dirty, i);
- }
- }
- DEFER_LOGD("--flushed, drew %d batches", batchList.size());
-}
-
-void DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
- ATRACE_NAME("flush drawing commands");
- Caches::getInstance().fontRenderer.endPrecaching();
-
- if (isEmpty()) return; // nothing to flush
- renderer.restoreToCount(1);
-
- DEFER_LOGD("--flushing");
- renderer.eventMark("Flush");
-
- // save and restore so that reordering doesn't affect final state
- renderer.save(SaveFlags::MatrixClip);
-
- if (CC_LIKELY(avoidOverdraw())) {
- for (unsigned int i = 1; i < mBatches.size(); i++) {
- if (mBatches[i] && mBatches[i]->coversBounds(mBounds)) {
- discardDrawingBatches(i - 1);
- }
- }
- }
- // NOTE: depth of the save stack at this point, before playback, should be reflected in
- // FLUSH_SAVE_STACK_DEPTH, so that save/restores match up correctly
- replayBatchList(mBatches, renderer, dirty);
-
- renderer.restoreToCount(1);
-
- DEFER_LOGD("--flush complete, returning %x", status);
- clear();
-}
-
-void DeferredDisplayList::discardDrawingBatches(const unsigned int maxIndex) {
- for (unsigned int i = mEarliestUnclearedIndex; i <= maxIndex; i++) {
- // leave deferred state ops alone for simplicity (empty save restore pairs may now exist)
- if (mBatches[i] && mBatches[i]->purelyDrawBatch()) {
- delete mBatches[i];
- mBatches[i] = nullptr;
- }
- }
- mEarliestUnclearedIndex = maxIndex + 1;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
deleted file mode 100644
index 98ccf11b1c2a..000000000000
--- a/libs/hwui/DeferredDisplayList.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
-#define ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
-
-#include <unordered_map>
-
-#include <utils/Errors.h>
-#include <utils/LinearAllocator.h>
-
-#include "Matrix.h"
-#include "OpenGLRenderer.h"
-#include "Rect.h"
-
-#include <vector>
-
-class SkBitmap;
-
-namespace android {
-namespace uirenderer {
-
-class ClipOp;
-class DrawOp;
-class SaveOp;
-class SaveLayerOp;
-class StateOp;
-
-class DeferredDisplayState;
-
-class Batch;
-class DrawBatch;
-class MergingDrawBatch;
-
-typedef const void* mergeid_t;
-
-class DeferredDisplayState {
-public:
- // global op bounds, mapped by mMatrix to be in screen space coordinates, clipped
- Rect mBounds;
-
- // the below are set and used by the OpenGLRenderer at record and deferred playback
- bool mClipValid;
- Rect mClip;
- int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared
- mat4 mMatrix;
- float mAlpha;
- const RoundRectClipState* mRoundRectClipState;
- const ProjectionPathMask* mProjectionPathMask;
-};
-
-class OpStatePair {
-public:
- OpStatePair()
- : op(nullptr), state(nullptr) {}
- OpStatePair(DrawOp* newOp, const DeferredDisplayState* newState)
- : op(newOp), state(newState) {}
- OpStatePair(const OpStatePair& other)
- : op(other.op), state(other.state) {}
- DrawOp* op;
- const DeferredDisplayState* state;
-};
-
-class DeferredDisplayList {
- friend struct DeferStateStruct; // used to give access to allocator
-public:
- DeferredDisplayList(const Rect& bounds)
- : mBounds(bounds) {
- clear();
- }
- ~DeferredDisplayList() { clear(); }
-
- enum OpBatchId {
- kOpBatch_None = 0, // Don't batch
- kOpBatch_Bitmap,
- kOpBatch_Patch,
- kOpBatch_AlphaVertices,
- kOpBatch_Vertices,
- kOpBatch_AlphaMaskTexture,
- kOpBatch_Text,
- kOpBatch_ColorText,
-
- kOpBatch_Count, // Add other batch ids before this
- };
-
- bool isEmpty() { return mBatches.empty(); }
-
- /**
- * Plays back all of the draw ops recorded into batches to the renderer.
- * Adjusts the state of the renderer as necessary, and restores it when complete
- */
- void flush(OpenGLRenderer& renderer, Rect& dirty);
-
- void addClip(OpenGLRenderer& renderer, ClipOp* op);
- void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
- void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
- void addRestoreToCount(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
-
- /**
- * Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
- * disallowReorder is false, respecting draw order when overlaps occur.
- */
- void addDrawOp(OpenGLRenderer& renderer, DrawOp* op);
-
-private:
- DeferredDisplayList(const DeferredDisplayList& other); // disallow copy
-
- DeferredDisplayState* createState() {
- return mAllocator.create_trivial<DeferredDisplayState>();
- }
-
- void tryRecycleState(DeferredDisplayState* state) {
- mAllocator.rewindIfLastAlloc(state);
- }
-
- /**
- * Resets the batching back-pointers, creating a barrier in the operation stream so that no ops
- * added in the future will be inserted into a batch that already exist.
- */
- void resetBatchingState();
-
- void clear();
-
- void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
- void storeRestoreToCountBarrier(OpenGLRenderer& renderer, StateOp* op, int newSaveCount);
-
- bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }
-
- int getStateOpDeferFlags() const;
- int getDrawOpDeferFlags() const;
-
- void discardDrawingBatches(const unsigned int maxIndex);
-
- // layer space bounds of rendering
- Rect mBounds;
-
- /**
- * At defer time, stores the *defer time* savecount of save/saveLayer ops that were deferred, so
- * that when an associated restoreToCount is deferred, it can be recorded as a
- * RestoreToCountBatch
- */
- std::vector<int> mSaveStack;
- int mComplexClipStackStart;
-
- std::vector<Batch*> mBatches;
-
- // Maps batch ids to the most recent *non-merging* batch of that id
- Batch* mBatchLookup[kOpBatch_Count];
-
- // Points to the index after the most recent barrier
- int mEarliestBatchIndex;
-
- // Points to the first index that may contain a pure drawing batch
- int mEarliestUnclearedIndex;
-
- /**
- * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
- * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
- * collide, which avoids the need to resolve mergeid collisions.
- */
- std::unordered_map<mergeid_t, DrawBatch*> mMergingBatches[kOpBatch_Count];
-
- LinearAllocator mAllocator;
-};
-
-/**
- * Struct containing information that instructs the defer
- */
-struct DeferInfo {
-public:
- DeferInfo() :
- batchId(DeferredDisplayList::kOpBatch_None),
- mergeId((mergeid_t) -1),
- mergeable(false),
- opaqueOverBounds(false) {
- };
-
- int batchId;
- mergeid_t mergeId;
- bool mergeable;
- bool opaqueOverBounds; // opaque over bounds in DeferredDisplayState - can skip ops below
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index f833a5405a5c..f13cb8d7d1d7 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -15,11 +15,10 @@
*/
#include "DeferredLayerUpdater.h"
-#include "OpenGLRenderer.h"
-
#include "LayerRenderer.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderTask.h"
+#include "utils/PaintUtils.h"
namespace android {
namespace uirenderer {
@@ -29,8 +28,7 @@ DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer)
, mTransform(nullptr)
, mNeedsGLContextAttach(false)
, mUpdateTexImage(false)
- , mLayer(layer)
- , mCaches(Caches::getInstance()) {
+ , mLayer(layer) {
mWidth = mLayer->layer.getWidth();
mHeight = mLayer->layer.getHeight();
mBlend = mLayer->isBlend();
@@ -54,7 +52,6 @@ void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
}
void DeferredLayerUpdater::apply() {
- // These properties are applied the same to both layer types
mLayer->setColorFilter(mColorFilter);
mLayer->setAlpha(mAlpha, mMode);
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 44a24c840892..389e17d12080 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef DEFERREDLAYERUPDATE_H_
-#define DEFERREDLAYERUPDATE_H_
+
+#pragma once
#include <cutils/compiler.h>
#include <gui/GLConsumer.h>
@@ -100,19 +100,15 @@ private:
SkColorFilter* mColorFilter;
int mAlpha;
SkXfermode::Mode mMode;
-
sp<GLConsumer> mSurfaceTexture;
SkMatrix* mTransform;
bool mNeedsGLContextAttach;
bool mUpdateTexImage;
Layer* mLayer;
- Caches& mCaches;
void doUpdateTexImage();
};
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* DEFERREDLAYERUPDATE_H_ */
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 28be05c52cfc..ca9e2bd4d3ef 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -21,13 +21,8 @@
#include "Debug.h"
#include "DisplayList.h"
-#include "RenderNode.h"
-
-#if HWUI_NEW_OPS
#include "RecordedOp.h"
-#else
-#include "DisplayListOp.h"
-#endif
+#include "RenderNode.h"
namespace android {
namespace uirenderer {
@@ -45,8 +40,7 @@ DisplayList::DisplayList()
, regions(stdAllocator)
, referenceHolders(stdAllocator)
, functors(stdAllocator)
- , vectorDrawables(stdAllocator)
- , hasDrawOps(false) {
+ , vectorDrawables(stdAllocator) {
}
DisplayList::~DisplayList() {
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index ccf71c6d360b..a8205c854c14 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_DISPLAY_LIST_H
-#define ANDROID_HWUI_DISPLAY_LIST_H
+#pragma once
#include <SkCamera.h>
#include <SkMatrix.h>
@@ -34,7 +33,6 @@
#include "Debug.h"
#include "CanvasProperty.h"
-#include "DeferredDisplayList.h"
#include "GlFunctorLifecycleListener.h"
#include "Matrix.h"
#include "RenderProperties.h"
@@ -49,72 +47,20 @@ class SkRegion;
namespace android {
namespace uirenderer {
-class DeferredDisplayList;
-class DisplayListOp;
-class DisplayListCanvas;
-class OpenGLRenderer;
class Rect;
class Layer;
-#if HWUI_NEW_OPS
struct RecordedOp;
struct RenderNodeOp;
typedef RecordedOp BaseOpType;
typedef RenderNodeOp NodeOpType;
-#else
-class DrawRenderNodeOp;
-
-typedef DisplayListOp BaseOpType;
-typedef DrawRenderNodeOp NodeOpType;
-#endif
namespace VectorDrawable {
class Tree;
};
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
-/**
- * Holds data used in the playback a tree of DisplayLists.
- */
-struct PlaybackStateStruct {
-protected:
- PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator)
- : mRenderer(renderer)
- , mReplayFlags(replayFlags)
- , mAllocator(allocator) {}
-
-public:
- OpenGLRenderer& mRenderer;
- const int mReplayFlags;
-
- // Allocator with the lifetime of a single frame. replay uses an Allocator owned by the struct,
- // while defer shares the DeferredDisplayList's Allocator
- // TODO: move this allocator to be owned by object with clear frame lifecycle
- LinearAllocator * const mAllocator;
-
- SkPath* allocPathForFrame() {
- return mRenderer.allocPathForFrame();
- }
-};
-
-struct DeferStateStruct : public PlaybackStateStruct {
- DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags)
- : PlaybackStateStruct(renderer, replayFlags, &(deferredList.mAllocator)),
- mDeferredList(deferredList) {}
-
- DeferredDisplayList& mDeferredList;
-};
-
-struct ReplayStateStruct : public PlaybackStateStruct {
- ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags)
- : PlaybackStateStruct(renderer, replayFlags, &mReplayAllocator),
- mDirty(dirty) {}
-
- Rect& mDirty;
- LinearAllocator mReplayAllocator;
-};
-
struct FunctorContainer {
Functor* functor;
GlFunctorLifecycleListener* listener;
@@ -124,7 +70,6 @@ struct FunctorContainer {
* Data structure that holds the list of commands used in display list stream
*/
class DisplayList {
- friend class DisplayListCanvas;
friend class RecordingCanvas;
public:
struct Chunk {
@@ -138,9 +83,9 @@ public:
// whether children with non-zero Z in the chunk should be reordered
bool reorderChildren;
-#if HWUI_NEW_OPS
+
+ // clip at the beginning of a reorder section, applied to reordered children
const ClipBase* reorderClip;
-#endif
};
DisplayList();
@@ -169,11 +114,7 @@ public:
return allocator.usedSize();
}
bool isEmpty() {
-#if HWUI_NEW_OPS
return ops.empty();
-#else
- return !hasDrawOps;
-#endif
}
private:
@@ -203,12 +144,8 @@ private:
// gets special treatment exclusive for webview.
LsaVector<VectorDrawableRoot*> vectorDrawables;
- bool hasDrawOps; // only used if !HWUI_NEW_OPS
-
void cleanupResources();
};
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_OPENGL_RENDERER_H
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
deleted file mode 100644
index bec662959f91..000000000000
--- a/libs/hwui/DisplayListCanvas.cpp
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "DisplayListCanvas.h"
-
-#include "DeferredDisplayList.h"
-#include "DeferredLayerUpdater.h"
-#include "DisplayListOp.h"
-#include "ResourceCache.h"
-#include "RenderNode.h"
-#include "VectorDrawable.h"
-#include "utils/PaintUtils.h"
-
-#include <SkCamera.h>
-#include <SkCanvas.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-namespace android {
-namespace uirenderer {
-
-DisplayListCanvas::DisplayListCanvas(int width, int height)
- : mState(*this)
- , mResourceCache(ResourceCache::getInstance())
- , mDisplayList(nullptr)
- , mTranslateX(0.0f)
- , mTranslateY(0.0f)
- , mHasDeferredTranslate(false)
- , mDeferredBarrierType(kBarrier_None)
- , mHighContrastText(false)
- , mRestoreSaveCount(-1) {
- resetRecording(width, height);
-}
-
-DisplayListCanvas::~DisplayListCanvas() {
- LOG_ALWAYS_FATAL_IF(mDisplayList,
- "Destroyed a DisplayListCanvas during a record!");
-}
-
-void DisplayListCanvas::resetRecording(int width, int height) {
- LOG_ALWAYS_FATAL_IF(mDisplayList,
- "prepareDirty called a second time during a recording!");
- mDisplayList = new DisplayList();
-
- mState.initializeSaveStack(width, height,
- 0, 0, width, height, Vector3());
-
- mDeferredBarrierType = kBarrier_InOrder;
- mState.setDirtyClip(false);
- mRestoreSaveCount = -1;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Operations
-///////////////////////////////////////////////////////////////////////////////
-
-DisplayList* DisplayListCanvas::finishRecording() {
- flushRestoreToCount();
- flushTranslate();
-
- mPaintMap.clear();
- mRegionMap.clear();
- mPathMap.clear();
- DisplayList* displayList = mDisplayList;
- mDisplayList = nullptr;
- mSkiaCanvasProxy.reset(nullptr);
- return displayList;
-}
-
-void DisplayListCanvas::callDrawGLFunction(Functor* functor,
- GlFunctorLifecycleListener* listener) {
- addDrawOp(new (alloc()) DrawFunctorOp(functor));
- mDisplayList->functors.push_back({functor, listener});
- mDisplayList->ref(listener);
-}
-
-SkCanvas* DisplayListCanvas::asSkCanvas() {
- LOG_ALWAYS_FATAL_IF(!mDisplayList,
- "attempting to get an SkCanvas when we are not recording!");
- if (!mSkiaCanvasProxy) {
- mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
- }
-
- // SkCanvas instances default to identity transform, but should inherit
- // the state of this Canvas; if this code was in the SkiaCanvasProxy
- // constructor, we couldn't cache mSkiaCanvasProxy.
- SkMatrix parentTransform;
- getMatrix(&parentTransform);
- mSkiaCanvasProxy.get()->setMatrix(parentTransform);
-
- return mSkiaCanvasProxy.get();
-}
-
-int DisplayListCanvas::save(SaveFlags::Flags flags) {
- addStateOp(new (alloc()) SaveOp((int) flags));
- return mState.save((int) flags);
-}
-
-void DisplayListCanvas::restore() {
- if (mRestoreSaveCount < 0) {
- restoreToCount(getSaveCount() - 1);
- return;
- }
-
- mRestoreSaveCount--;
- flushTranslate();
- mState.restore();
-}
-
-void DisplayListCanvas::restoreToCount(int saveCount) {
- mRestoreSaveCount = saveCount;
- flushTranslate();
- mState.restoreToCount(saveCount);
-}
-
-int DisplayListCanvas::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) {
- // force matrix/clip isolation for layer
- flags |= SaveFlags::MatrixClip;
-
- paint = refPaint(paint);
- addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, (int) flags));
- return mState.save((int) flags);
-}
-
-void DisplayListCanvas::translate(float dx, float dy) {
- if (dx == 0.0f && dy == 0.0f) return;
-
- mHasDeferredTranslate = true;
- mTranslateX += dx;
- mTranslateY += dy;
- flushRestoreToCount();
- mState.translate(dx, dy, 0.0f);
-}
-
-void DisplayListCanvas::rotate(float degrees) {
- if (degrees == 0.0f) return;
-
- addStateOp(new (alloc()) RotateOp(degrees));
- mState.rotate(degrees);
-}
-
-void DisplayListCanvas::scale(float sx, float sy) {
- if (sx == 1.0f && sy == 1.0f) return;
-
- addStateOp(new (alloc()) ScaleOp(sx, sy));
- mState.scale(sx, sy);
-}
-
-void DisplayListCanvas::skew(float sx, float sy) {
- addStateOp(new (alloc()) SkewOp(sx, sy));
- mState.skew(sx, sy);
-}
-
-void DisplayListCanvas::setMatrix(const SkMatrix& matrix) {
- addStateOp(new (alloc()) SetMatrixOp(matrix));
- mState.setMatrix(matrix);
-}
-
-void DisplayListCanvas::concat(const SkMatrix& matrix) {
- addStateOp(new (alloc()) ConcatMatrixOp(matrix));
- mState.concatMatrix(matrix);
-}
-
-bool DisplayListCanvas::getClipBounds(SkRect* outRect) const {
- Rect bounds = mState.getLocalClipBounds();
- *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
- return !(outRect->isEmpty());
-}
-
-bool DisplayListCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
- return mState.quickRejectConservative(left, top, right, bottom);
-}
-
-bool DisplayListCanvas::quickRejectPath(const SkPath& path) const {
- SkRect bounds = path.getBounds();
- return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
-}
-
-
-bool DisplayListCanvas::clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op) {
- addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
- return mState.clipRect(left, top, right, bottom, op);
-}
-
-bool DisplayListCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
- path = refPath(path);
- addStateOp(new (alloc()) ClipPathOp(path, op));
- return mState.clipPath(path, op);
-}
-
-bool DisplayListCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
- region = refRegion(region);
- addStateOp(new (alloc()) ClipRegionOp(region, op));
- return mState.clipRegion(region, op);
-}
-
-void DisplayListCanvas::drawRenderNode(RenderNode* renderNode) {
- LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
- DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(
- renderNode,
- *mState.currentTransform(),
- mState.clipIsSimple());
- addRenderNodeOp(op);
-}
-
-void DisplayListCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
- // We ref the DeferredLayerUpdater due to its thread-safe ref-counting
- // semantics.
- mDisplayList->ref(layerHandle);
- addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer()));
-}
-
-void DisplayListCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
- bitmap = refBitmap(*bitmap);
- paint = refPaint(paint);
-
- addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
-}
-
-void DisplayListCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top,
- const SkPaint* paint) {
- save(SaveFlags::Matrix);
- translate(left, top);
- drawBitmap(&bitmap, paint);
- restore();
-}
-
-void DisplayListCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) {
- if (matrix.isIdentity()) {
- drawBitmap(&bitmap, paint);
- } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
- && MathUtils::isPositive(matrix.getScaleX())
- && MathUtils::isPositive(matrix.getScaleY())) {
- // SkMatrix::isScaleTranslate() not available in L
- SkRect src;
- SkRect dst;
- bitmap.getBounds(&src);
- matrix.mapRect(&dst, src);
- drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
- dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
- } else {
- save(SaveFlags::Matrix);
- concat(matrix);
- drawBitmap(&bitmap, paint);
- restore();
- }
-}
-
-void DisplayListCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
- if (srcLeft == 0 && srcTop == 0
- && srcRight == bitmap.width()
- && srcBottom == bitmap.height()
- && (srcBottom - srcTop == dstBottom - dstTop)
- && (srcRight - srcLeft == dstRight - dstLeft)) {
- // transform simple rect to rect drawing case into position bitmap ops, since they merge
- save(SaveFlags::Matrix);
- translate(dstLeft, dstTop);
- drawBitmap(&bitmap, paint);
- restore();
- } else {
- paint = refPaint(paint);
-
- if (paint && paint->getShader()) {
- float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft);
- float scaleY = (dstBottom - dstTop) / (srcBottom - srcTop);
- if (!MathUtils::areEqual(scaleX, 1.0f) || !MathUtils::areEqual(scaleY, 1.0f)) {
- // Apply the scale transform on the canvas, so that the shader
- // effectively calculates positions relative to src rect space
-
- save(SaveFlags::Matrix);
- translate(dstLeft, dstTop);
- scale(scaleX, scaleY);
-
- dstLeft = 0.0f;
- dstTop = 0.0f;
- dstRight = srcRight - srcLeft;
- dstBottom = srcBottom - srcTop;
-
- addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
- srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, paint));
- restore();
- return;
- }
- }
-
- addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
- srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, paint));
- }
-}
-
-void DisplayListCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
- int vertexCount = (meshWidth + 1) * (meshHeight + 1);
- vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
- paint = refPaint(paint);
- colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
-
- addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(bitmap), meshWidth, meshHeight,
- vertices, colors, paint));
-}
-
-void DisplayListCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& patch,
- float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
- const SkBitmap* bitmapPtr = refBitmap(bitmap);
- const Res_png_9patch* patchPtr = refPatch(&patch);
- paint = refPaint(paint);
-
- addDrawOp(new (alloc()) DrawPatchOp(bitmapPtr, patchPtr,
- dstLeft, dstTop, dstRight, dstBottom, paint));
-}
-
-void DisplayListCanvas::drawColor(int color, SkXfermode::Mode mode) {
- addDrawOp(new (alloc()) DrawColorOp(color, mode));
-}
-
-void DisplayListCanvas::drawPaint(const SkPaint& paint) {
- SkRect bounds;
- if (getClipBounds(&bounds)) {
- drawRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, paint);
- }
-}
-
-
-void DisplayListCanvas::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
- addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) {
- addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawRoundRect(
- CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
- CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
- CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
- CanvasPropertyPaint* paint) {
- mDisplayList->ref(left);
- mDisplayList->ref(top);
- mDisplayList->ref(right);
- mDisplayList->ref(bottom);
- mDisplayList->ref(rx);
- mDisplayList->ref(ry);
- mDisplayList->ref(paint);
- refBitmapsInShader(paint->value.getShader());
- addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value,
- &right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
-}
-
-void DisplayListCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
- addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
- CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
- mDisplayList->ref(x);
- mDisplayList->ref(y);
- mDisplayList->ref(radius);
- mDisplayList->ref(paint);
- refBitmapsInShader(paint->value.getShader());
- addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
- &radius->value, &paint->value));
-}
-
-void DisplayListCanvas::drawOval(float left, float top, float right, float bottom,
- const SkPaint& paint) {
- addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
- if (fabs(sweepAngle) >= 360.0f) {
- drawOval(left, top, right, bottom, paint);
- } else {
- addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
- startAngle, sweepAngle, useCenter, refPaint(&paint)));
- }
-}
-
-void DisplayListCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
- addDrawOp(new (alloc()) DrawPathOp(refPath(&path), refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
- points = refBuffer<float>(points, count);
-
- addDrawOp(new (alloc()) DrawLinesOp(points, count, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
- points = refBuffer<float>(points, count);
-
- addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint)));
-}
-
-void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
- mDisplayList->ref(tree);
- mDisplayList->vectorDrawables.push_back(tree);
- addDrawOp(new (alloc()) DrawVectorDrawableOp(tree, tree->stagingProperties()->getBounds()));
-}
-
-void DisplayListCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count,
- const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
- if (!glyphs || count <= 0) return;
-
- int bytesCount = 2 * count;
- DrawOp* op = new (alloc()) DrawTextOnPathOp(refBuffer<glyph_t>(glyphs, count),
- bytesCount, count, refPath(&path),
- hOffset, vOffset, refPaint(&paint));
- addDrawOp(op);
-}
-
-void DisplayListCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions,
- int count, const SkPaint& paint, float x, float y,
- float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) {
-
- if (!glyphs || count <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
-
- int bytesCount = count * 2;
- positions = refBuffer<float>(positions, count * 2);
- Rect bounds(boundsLeft, boundsTop, boundsRight, boundsBottom);
-
- DrawOp* op = new (alloc()) DrawTextOp(refBuffer<glyph_t>(glyphs, count), bytesCount, count,
- x, y, positions, refPaint(&paint), totalAdvance, bounds);
- addDrawOp(op);
- drawTextDecorations(x, y, totalAdvance, paint);
-}
-
-void DisplayListCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
- if (paint.getStyle() != SkPaint::kFill_Style ||
- (paint.isAntiAlias() && !mState.currentTransform()->isSimple())) {
- SkRegion::Iterator it(region);
- while (!it.done()) {
- const SkIRect& r = it.rect();
- drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
- it.next();
- }
- } else {
- int count = 0;
- Vector<float> rects;
- SkRegion::Iterator it(region);
- while (!it.done()) {
- const SkIRect& r = it.rect();
- rects.push(r.fLeft);
- rects.push(r.fTop);
- rects.push(r.fRight);
- rects.push(r.fBottom);
- count += 4;
- it.next();
- }
- drawRects(rects.array(), count, &paint);
- }
-}
-
-void DisplayListCanvas::drawRects(const float* rects, int count, const SkPaint* paint) {
- if (count <= 0) return;
-
- rects = refBuffer<float>(rects, count);
- paint = refPaint(paint);
- addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
-}
-
-void DisplayListCanvas::setDrawFilter(SkDrawFilter* filter) {
- mDrawFilter.reset(SkSafeRef(filter));
-}
-
-void DisplayListCanvas::insertReorderBarrier(bool enableReorder) {
- flushRestoreToCount();
- flushTranslate();
- mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
-}
-
-void DisplayListCanvas::flushRestoreToCount() {
- if (mRestoreSaveCount >= 0) {
- addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
- mRestoreSaveCount = -1;
- }
-}
-
-void DisplayListCanvas::flushTranslate() {
- if (mHasDeferredTranslate) {
- if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
- addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
- mTranslateX = mTranslateY = 0.0f;
- }
- mHasDeferredTranslate = false;
- }
-}
-
-size_t DisplayListCanvas::addOpAndUpdateChunk(DisplayListOp* op) {
- int insertIndex = mDisplayList->ops.size();
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("unsupported");
-#else
- mDisplayList->ops.push_back(op);
-#endif
- if (mDeferredBarrierType != kBarrier_None) {
- // op is first in new chunk
- mDisplayList->chunks.emplace_back();
- DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
- newChunk.beginOpIndex = insertIndex;
- newChunk.endOpIndex = insertIndex + 1;
- newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
-
- int nextChildIndex = mDisplayList->children.size();
- newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
- mDeferredBarrierType = kBarrier_None;
- } else {
- // standard case - append to existing chunk
- mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
- }
- return insertIndex;
-}
-
-size_t DisplayListCanvas::flushAndAddOp(DisplayListOp* op) {
- flushRestoreToCount();
- flushTranslate();
- return addOpAndUpdateChunk(op);
-}
-
-size_t DisplayListCanvas::addStateOp(StateOp* op) {
- return flushAndAddOp(op);
-}
-
-size_t DisplayListCanvas::addDrawOp(DrawOp* op) {
- Rect localBounds;
- if (op->getLocalBounds(localBounds)) {
- bool rejected = quickRejectRect(localBounds.left, localBounds.top,
- localBounds.right, localBounds.bottom);
- op->setQuickRejected(rejected);
- }
-
- mDisplayList->hasDrawOps = true;
- return flushAndAddOp(op);
-}
-
-size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) {
- int opIndex = addDrawOp(op);
-#if !HWUI_NEW_OPS
- int childIndex = mDisplayList->addChild(op);
-
- // update the chunk's child indices
- DisplayList::Chunk& chunk = mDisplayList->chunks.back();
- chunk.endChildIndex = childIndex + 1;
-
- if (op->renderNode->stagingProperties().isProjectionReceiver()) {
- // use staging property, since recording on UI thread
- mDisplayList->projectionReceiveIndex = opIndex;
- }
-#endif
- return opIndex;
-}
-
-void DisplayListCanvas::refBitmapsInShader(const SkShader* shader) {
- if (!shader) return;
-
- // If this paint has an SkShader that has an SkBitmap add
- // it to the bitmap pile
- SkBitmap bitmap;
- SkShader::TileMode xy[2];
- if (shader->isABitmap(&bitmap, nullptr, xy)) {
- refBitmap(bitmap);
- return;
- }
- SkShader::ComposeRec rec;
- if (shader->asACompose(&rec)) {
- refBitmapsInShader(rec.fShaderA);
- refBitmapsInShader(rec.fShaderB);
- return;
- }
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
deleted file mode 100644
index 664f79e283b6..000000000000
--- a/libs/hwui/DisplayListCanvas.h
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
-#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
-
-#include "CanvasState.h"
-#include "DisplayList.h"
-#include "RenderNode.h"
-#include "ResourceCache.h"
-#include "SkiaCanvasProxy.h"
-#include "hwui/Canvas.h"
-#include "utils/Macros.h"
-
-#include <SkDrawFilter.h>
-#include <SkMatrix.h>
-#include <SkPaint.h>
-#include <SkPath.h>
-#include <SkRegion.h>
-#include <SkTLazy.h>
-#include <cutils/compiler.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Debug
-#if DEBUG_DISPLAY_LIST
- #define DISPLAY_LIST_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define DISPLAY_LIST_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Display list
-///////////////////////////////////////////////////////////////////////////////
-
-class DeferredDisplayList;
-class DeferredLayerUpdater;
-class DisplayListOp;
-class DrawOp;
-class DrawRenderNodeOp;
-class RenderNode;
-class StateOp;
-
-/**
- * Records drawing commands in a display list for later playback into an OpenGLRenderer.
- */
-class ANDROID_API DisplayListCanvas: public Canvas, public CanvasStateClient {
-public:
- DisplayListCanvas(int width, int height);
- virtual ~DisplayListCanvas();
-
- virtual void resetRecording(int width, int height) override;
- virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
-
-// ----------------------------------------------------------------------------
-// HWUI Canvas state operations
-// ----------------------------------------------------------------------------
-
- virtual void insertReorderBarrier(bool enableReorder) override;
-
-// ----------------------------------------------------------------------------
-// HWUI Canvas draw operations
-// ----------------------------------------------------------------------------
-
- // Shapes
- virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
- CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
- CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
- CanvasPropertyPaint* paint) override;
- virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
- CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
-
-// ----------------------------------------------------------------------------
-// HWUI Canvas draw operations - special
-// ----------------------------------------------------------------------------
- virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
- virtual void drawRenderNode(RenderNode* renderNode) override;
- virtual void callDrawGLFunction(Functor* functor,
- GlFunctorLifecycleListener* listener) override;
-
-// ----------------------------------------------------------------------------
-// CanvasStateClient interface
-// ----------------------------------------------------------------------------
- virtual void onViewportInitialized() override { }
- virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override { }
- virtual GLuint getTargetFbo() const override { return -1; }
-
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas interface
-// ----------------------------------------------------------------------------
- virtual SkCanvas* asSkCanvas() override;
-
- virtual void setBitmap(const SkBitmap& bitmap) override {
- LOG_ALWAYS_FATAL("DisplayListCanvas is not backed by a bitmap.");
- }
-
- virtual bool isOpaque() override { return false; }
- virtual int width() override { return mState.getWidth(); }
- virtual int height() override { return mState.getHeight(); }
-
- virtual void setHighContrastText(bool highContrastText) override {
- mHighContrastText = highContrastText;
- }
- virtual bool isHighContrastText() override { return mHighContrastText; }
-
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas state operations
-// ----------------------------------------------------------------------------
- // Save (layer)
- virtual int getSaveCount() const override { return mState.getSaveCount(); }
- virtual int save(SaveFlags::Flags flags) override;
- virtual void restore() override;
- virtual void restoreToCount(int saveCount) override;
-
- virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
- SaveFlags::Flags flags) override;
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) override {
- SkPaint paint;
- paint.setAlpha(alpha);
- return saveLayer(left, top, right, bottom, &paint, flags);
- }
-
- // Matrix
- virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
- virtual void setMatrix(const SkMatrix& matrix) override;
-
- virtual void concat(const SkMatrix& matrix) override;
- virtual void rotate(float degrees) override;
- virtual void scale(float sx, float sy) override;
- virtual void skew(float sx, float sy) override;
- virtual void translate(float dx, float dy) override;
-
- // Clip
- virtual bool getClipBounds(SkRect* outRect) const override;
- virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
- virtual bool quickRejectPath(const SkPath& path) const override;
-
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) override;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
-
- // Misc
- virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
- virtual void setDrawFilter(SkDrawFilter* filter) override;
-
-// ----------------------------------------------------------------------------
-// android/graphics/Canvas draw operations
-// ----------------------------------------------------------------------------
- virtual void drawColor(int color, SkXfermode::Mode mode) override;
- virtual void drawPaint(const SkPaint& paint) override;
-
- // Geometry
- virtual void drawPoint(float x, float y, const SkPaint& paint) override {
- float points[2] = { x, y };
- drawPoints(points, 2, paint);
- }
- virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
- virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) override {
- float points[4] = { startX, startY, stopX, stopY };
- drawLines(points, 4, paint);
- }
- virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
- virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
- virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) override;
- virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
- virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint) override;
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
- virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
- virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
- const float* verts, const float* tex, const int* colors,
- const uint16_t* indices, int indexCount, const SkPaint& paint) override
- { /* DisplayListCanvas does not support drawVertices(); ignore */ }
-
- // Bitmap-based
- virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
- virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) override;
- virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) override;
- virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) override;
- virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) override;
-
- virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
-
- // Text
- virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int count,
- const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
- float boundsRight, float boundsBottom, float totalAdvance) override;
- virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
- float hOffset, float vOffset, const SkPaint& paint) override;
- virtual bool drawTextAbsolutePos() const override { return false; }
-
-private:
-
- CanvasState mState;
- std::unique_ptr<SkiaCanvasProxy> mSkiaCanvasProxy;
-
- enum DeferredBarrierType {
- kBarrier_None,
- kBarrier_InOrder,
- kBarrier_OutOfOrder,
- };
-
- void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
- void drawRects(const float* rects, int count, const SkPaint* paint);
-
- void flushRestoreToCount();
- void flushTranslate();
- void flushReorderBarrier();
-
- LinearAllocator& alloc() { return mDisplayList->allocator; }
-
- // Each method returns final index of op
- size_t addOpAndUpdateChunk(DisplayListOp* op);
- // flushes any deferred operations, and appends the op
- size_t flushAndAddOp(DisplayListOp* op);
-
- size_t addStateOp(StateOp* op);
- size_t addDrawOp(DrawOp* op);
- size_t addRenderNodeOp(DrawRenderNodeOp* op);
-
- void refBitmapsInShader(const SkShader* shader);
-
- template<class T>
- inline const T* refBuffer(const T* srcBuffer, int32_t count) {
- if (!srcBuffer) return nullptr;
-
- T* dstBuffer = (T*) mDisplayList->allocator.alloc<T>(count * sizeof(T));
- memcpy(dstBuffer, srcBuffer, count * sizeof(T));
- return dstBuffer;
- }
-
- inline const SkPath* refPath(const SkPath* path) {
- if (!path) return nullptr;
-
- // The points/verbs within the path are refcounted so this copy operation
- // is inexpensive and maintains the generationID of the original path.
- const SkPath* cachedPath = new SkPath(*path);
- mDisplayList->pathResources.push_back(cachedPath);
- return cachedPath;
- }
-
- inline const SkPaint* refPaint(const SkPaint* paint) {
- if (!paint) return nullptr;
-
- // If there is a draw filter apply it here and store the modified paint
- // so that we don't need to modify the paint every time we access it.
- SkTLazy<SkPaint> filteredPaint;
- if (mDrawFilter.get()) {
- filteredPaint.set(*paint);
- mDrawFilter->filter(filteredPaint.get(), SkDrawFilter::kPaint_Type);
- paint = filteredPaint.get();
- }
-
- // compute the hash key for the paint and check the cache.
- const uint32_t key = paint->getHash();
- const SkPaint* cachedPaint = mPaintMap.valueFor(key);
- // In the unlikely event that 2 unique paints have the same hash we do a
- // object equality check to ensure we don't erroneously dedup them.
- if (cachedPaint == nullptr || *cachedPaint != *paint) {
- cachedPaint = new SkPaint(*paint);
- std::unique_ptr<const SkPaint> copy(cachedPaint);
- mDisplayList->paints.push_back(std::move(copy));
-
- // replaceValueFor() performs an add if the entry doesn't exist
- mPaintMap.replaceValueFor(key, cachedPaint);
- refBitmapsInShader(cachedPaint->getShader());
- }
-
- return cachedPaint;
- }
-
- inline const SkRegion* refRegion(const SkRegion* region) {
- if (!region) {
- return region;
- }
-
- const SkRegion* cachedRegion = mRegionMap.valueFor(region);
- // TODO: Add generation ID to SkRegion
- if (cachedRegion == nullptr) {
- std::unique_ptr<const SkRegion> copy(new SkRegion(*region));
- cachedRegion = copy.get();
- mDisplayList->regions.push_back(std::move(copy));
-
- // replaceValueFor() performs an add if the entry doesn't exist
- mRegionMap.replaceValueFor(region, cachedRegion);
- }
-
- return cachedRegion;
- }
-
- inline const SkBitmap* refBitmap(const SkBitmap& bitmap) {
- // Note that this assumes the bitmap is immutable. There are cases this won't handle
- // correctly, such as creating the bitmap from scratch, drawing with it, changing its
- // contents, and drawing again. The only fix would be to always copy it the first time,
- // which doesn't seem worth the extra cycles for this unlikely case.
- SkBitmap* localBitmap = alloc().create<SkBitmap>(bitmap);
- mDisplayList->bitmapResources.push_back(localBitmap);
- return localBitmap;
- }
-
- inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
- mDisplayList->patchResources.push_back(patch);
- mResourceCache.incrementRefcount(patch);
- return patch;
- }
-
- DefaultKeyedVector<uint32_t, const SkPaint*> mPaintMap;
- DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
- DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
-
- ResourceCache& mResourceCache;
- DisplayList* mDisplayList;
-
- float mTranslateX;
- float mTranslateY;
- bool mHasDeferredTranslate;
- DeferredBarrierType mDeferredBarrierType;
- bool mHighContrastText;
-
- int mRestoreSaveCount;
-
- SkAutoTUnref<SkDrawFilter> mDrawFilter;
-
- friend class RenderNode;
-
-}; // class DisplayListCanvas
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
deleted file mode 100644
index 2a859132e783..000000000000
--- a/libs/hwui/DisplayListOp.h
+++ /dev/null
@@ -1,1555 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
-#define ANDROID_HWUI_DISPLAY_OPERATION_H
-
-#include "OpenGLRenderer.h"
-#include "AssetAtlas.h"
-#include "DeferredDisplayList.h"
-#include "DisplayListCanvas.h"
-#include "GammaFontRenderer.h"
-#include "Patch.h"
-#include "RenderNode.h"
-#include "renderstate/RenderState.h"
-#include "UvMapper.h"
-#include "utils/LinearAllocator.h"
-#include "utils/PaintUtils.h"
-#include "VectorDrawable.h"
-
-#include <algorithm>
-
-#include <SkColor.h>
-#include <SkPath.h>
-#include <SkPathOps.h>
-#include <SkXfermode.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
-#define OP_LOGS(s) OP_LOG("%s", (s))
-#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
- * may be replayed to an OpenGLRenderer.
- *
- * To avoid individual memory allocations, DisplayListOps may only be allocated into a
- * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
- * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
- * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
- * never called as LinearAllocators are simply discarded, so no memory management should be done in
- * this class.
- */
-class DisplayListOp {
-public:
- // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
- // standard new() intentionally not implemented, and delete/deconstructor should never be used.
- virtual ~DisplayListOp() { LOG_ALWAYS_FATAL("Destructor not supported"); }
- static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
- static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
- static void* operator new(size_t size, LinearAllocator& allocator) {
- // FIXME: Quick hack to keep old pipeline working, delete this when
- // we no longer need to support HWUI_NEWOPS := false
- return allocator.alloc<char>(size);
- }
-
- enum OpLogFlag {
- kOpLogFlag_Recurse = 0x1,
- kOpLogFlag_JSON = 0x2 // TODO: add?
- };
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) = 0;
-
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
- bool useQuickReject) = 0;
-
- virtual void output(int level, uint32_t logFlags = 0) const = 0;
-
- // NOTE: it would be nice to declare constants and overriding the implementation in each op to
- // point at the constants, but that seems to require a .cpp file
- virtual const char* name() = 0;
-};
-
-class StateOp : public DisplayListOp {
-public:
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- // default behavior only affects immediate, deferrable state, issue directly to renderer
- applyState(deferStruct.mRenderer, saveCount);
- }
-
- /**
- * State operations are applied directly to the renderer, but can cause the deferred drawing op
- * list to flush
- */
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
- bool useQuickReject) override {
- applyState(replayStruct.mRenderer, saveCount);
- }
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
-};
-
-class DrawOp : public DisplayListOp {
-friend class MergingDrawBatch;
-public:
- DrawOp(const SkPaint* paint)
- : mPaint(paint), mQuickRejected(false) {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- if (mQuickRejected && CC_LIKELY(useQuickReject)) {
- return;
- }
-
- deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
- }
-
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
- bool useQuickReject) override {
- if (mQuickRejected && CC_LIKELY(useQuickReject)) {
- return;
- }
-
- applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
-
- /**
- * Draw multiple instances of an operation, must be overidden for operations that merge
- *
- * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
- * and pure translation transformations. Other guarantees of similarity should be enforced by
- * reducing which operations are tagged as mergeable.
- */
- virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
- const std::vector<OpStatePair>& ops, const Rect& bounds) {
- for (unsigned int i = 0; i < ops.size(); i++) {
- renderer.restoreDisplayState(*(ops[i].state), true);
- ops[i].op->applyDraw(renderer, dirty);
- }
- }
-
- /**
- * When this method is invoked the state field is initialized to have the
- * final rendering state. We can thus use it to process data as it will be
- * used at draw time.
- *
- * Additionally, this method allows subclasses to provide defer-time preferences for batching
- * and merging.
- *
- * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
- */
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) {}
-
- /**
- * Query the conservative, local bounds (unmapped) bounds of the op.
- *
- * returns true if bounds exist
- */
- virtual bool getLocalBounds(Rect& localBounds) {
- return false;
- }
-
- // TODO: better refine localbounds usage
- void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
- bool getQuickRejected() { return mQuickRejected; }
-
- virtual bool hasTextShadow() const {
- return false;
- }
-
- inline float strokeWidthOutset() {
- // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
- // 1.0 stroke, treat 1.0 as minimum.
-
- // TODO: it would be nice if this could take scale into account, but scale isn't stable
- // since higher levels of the view hierarchy can change scale out from underneath it.
- return std::max(mPaint->getStrokeWidth(), 1.0f) * 0.5f;
- }
-
-protected:
- // Helper method for determining op opaqueness. Assumes op fills its bounds in local
- // coordinates, and that paint's alpha is used
- inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
- // ensure that local bounds cover mapped bounds
- if (!state.mMatrix.isSimple()) return false;
-
- if (state.mRoundRectClipState) return false;
-
- // check state/paint for transparency
- if (mPaint) {
- if (mPaint->getAlpha() != 0xFF) {
- return false;
- }
- if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
- return false;
- }
- if (PaintUtils::isBlendedColorFilter(mPaint->getColorFilter())) {
- return false;
- }
- }
-
- if (state.mAlpha != 1.0f) return false;
-
- SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
- return (mode == SkXfermode::kSrcOver_Mode ||
- mode == SkXfermode::kSrc_Mode);
-
- }
-
- const SkPaint* mPaint;
- bool mQuickRejected;
-};
-
-class DrawBoundedOp : public DrawOp {
-public:
- DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
- : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
-
- DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
- : DrawOp(paint), mLocalBounds(localBounds) {}
-
- // Calculates bounds as smallest rect encompassing all points
- // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
- // subclass' constructor)
- DrawBoundedOp(const float* points, int count, const SkPaint* paint)
- : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
- for (int i = 2; i < count; i += 2) {
- mLocalBounds.left = std::min(mLocalBounds.left, points[i]);
- mLocalBounds.right = std::max(mLocalBounds.right, points[i]);
- mLocalBounds.top = std::min(mLocalBounds.top, points[i + 1]);
- mLocalBounds.bottom = std::max(mLocalBounds.bottom, points[i + 1]);
- }
- }
-
- // default empty constructor for bounds, to be overridden in child constructor body
- DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
-
- virtual bool getLocalBounds(Rect& localBounds) override {
- localBounds.set(mLocalBounds);
- PaintUtils::TextShadow textShadow;
- if (PaintUtils::getTextShadow(mPaint, &textShadow)) {
- Rect shadow(mLocalBounds);
- shadow.translate(textShadow.dx, textShadow.dx);
- shadow.outset(textShadow.radius);
- localBounds.unionWith(shadow);
- }
- return true;
- }
-
-protected:
- Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
-// not directly draw or alter output
-///////////////////////////////////////////////////////////////////////////////
-
-class SaveOp : public StateOp {
-public:
- SaveOp(int flags)
- : mFlags(flags) {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- int newSaveCount = deferStruct.mRenderer.save(mFlags);
- deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
- }
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.save(mFlags);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Save flags %x", mFlags);
- }
-
- virtual const char* name() override { return "Save"; }
-
- int getFlags() const { return mFlags; }
-private:
- int mFlags;
-};
-
-class RestoreToCountOp : public StateOp {
-public:
- RestoreToCountOp(int count)
- : mCount(count) {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
- this, saveCount + mCount);
- deferStruct.mRenderer.restoreToCount(saveCount + mCount);
- }
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.restoreToCount(saveCount + mCount);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Restore to count %d", mCount);
- }
-
- virtual const char* name() override { return "RestoreToCount"; }
-
-private:
- int mCount;
-};
-
-class SaveLayerOp : public StateOp {
-public:
- SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
- : mArea(left, top, right, bottom)
- , mPaint(&mCachedPaint)
- , mFlags(flags)
- , mConvexMask(nullptr) {
- mCachedPaint.setAlpha(alpha);
- }
-
- SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
- : mArea(left, top, right, bottom)
- , mPaint(paint)
- , mFlags(flags)
- , mConvexMask(nullptr)
- {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
- int newSaveCount = deferStruct.mRenderer.getSaveCount();
- deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
-
- // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
- // setup the snapshot for deferral, and re-issue the op at flush time
- deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
- mPaint, mFlags);
- }
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
- mPaint, mFlags, mConvexMask);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("SaveLayer%s of area " RECT_STRING,
- (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
- }
-
- virtual const char* name() override {
- return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer";
- }
-
- int getFlags() { return mFlags; }
-
- // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
- void setMask(const SkPath* convexMask) {
- mConvexMask = convexMask;
- }
-
-private:
- bool isSaveLayerAlpha() const {
- SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
- int alpha = PaintUtils::getAlphaDirect(mPaint);
- return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
- }
-
- Rect mArea;
- const SkPaint* mPaint;
- SkPaint mCachedPaint;
- int mFlags;
-
- // Convex path, points at data in RenderNode, valid for the duration of the frame only
- // Only used for masking the SaveLayer which wraps projected RenderNodes
- const SkPath* mConvexMask;
-};
-
-class TranslateOp : public StateOp {
-public:
- TranslateOp(float dx, float dy)
- : mDx(dx), mDy(dy) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.translate(mDx, mDy);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Translate by %f %f", mDx, mDy);
- }
-
- virtual const char* name() override { return "Translate"; }
-
-private:
- float mDx;
- float mDy;
-};
-
-class RotateOp : public StateOp {
-public:
- RotateOp(float degrees)
- : mDegrees(degrees) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.rotate(mDegrees);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Rotate by %f degrees", mDegrees);
- }
-
- virtual const char* name() override { return "Rotate"; }
-
-private:
- float mDegrees;
-};
-
-class ScaleOp : public StateOp {
-public:
- ScaleOp(float sx, float sy)
- : mSx(sx), mSy(sy) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.scale(mSx, mSy);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Scale by %f %f", mSx, mSy);
- }
-
- virtual const char* name() override { return "Scale"; }
-
-private:
- float mSx;
- float mSy;
-};
-
-class SkewOp : public StateOp {
-public:
- SkewOp(float sx, float sy)
- : mSx(sx), mSy(sy) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.skew(mSx, mSy);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Skew by %f %f", mSx, mSy);
- }
-
- virtual const char* name() override { return "Skew"; }
-
-private:
- float mSx;
- float mSy;
-};
-
-class SetMatrixOp : public StateOp {
-public:
- SetMatrixOp(const SkMatrix& matrix)
- : mMatrix(matrix) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- // Setting a matrix on a Canvas isn't equivalent to setting a total matrix on the scene.
- // Set a canvas-relative matrix on the renderer instead.
- renderer.setLocalMatrix(mMatrix);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- if (mMatrix.isIdentity()) {
- OP_LOGS("SetMatrix (reset)");
- } else {
- OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
- }
- }
-
- virtual const char* name() override { return "SetMatrix"; }
-
-private:
- const SkMatrix mMatrix;
-};
-
-class ConcatMatrixOp : public StateOp {
-public:
- ConcatMatrixOp(const SkMatrix& matrix)
- : mMatrix(matrix) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.concatMatrix(mMatrix);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
- }
-
- virtual const char* name() override { return "ConcatMatrix"; }
-
-private:
- const SkMatrix mMatrix;
-};
-
-class ClipOp : public StateOp {
-public:
- ClipOp(SkRegion::Op op) : mOp(op) {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- // NOTE: must defer op BEFORE applying state, since it may read clip
- deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
-
- // TODO: Can we avoid applying complex clips at defer time?
- applyState(deferStruct.mRenderer, saveCount);
- }
-
- bool canCauseComplexClip() {
- return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
- }
-
-protected:
- virtual bool isRect() { return false; }
-
- SkRegion::Op mOp;
-};
-
-class ClipRectOp : public ClipOp {
-public:
- ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
- : ClipOp(op), mArea(left, top, right, bottom) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
- }
-
- virtual const char* name() override { return "ClipRect"; }
-
-protected:
- virtual bool isRect() override { return true; }
-
-private:
- Rect mArea;
-};
-
-class ClipPathOp : public ClipOp {
-public:
- ClipPathOp(const SkPath* path, SkRegion::Op op)
- : ClipOp(op), mPath(path) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.clipPath(mPath, mOp);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- SkRect bounds = mPath->getBounds();
- OP_LOG("ClipPath bounds " RECT_STRING,
- bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
- }
-
- virtual const char* name() override { return "ClipPath"; }
-
-private:
- const SkPath* mPath;
-};
-
-class ClipRegionOp : public ClipOp {
-public:
- ClipRegionOp(const SkRegion* region, SkRegion::Op op)
- : ClipOp(op), mRegion(region) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
- renderer.clipRegion(mRegion, mOp);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- SkIRect bounds = mRegion->getBounds();
- OP_LOG("ClipRegion bounds %d %d %d %d",
- bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
- }
-
- virtual const char* name() override { return "ClipRegion"; }
-
-private:
- const SkRegion* mRegion;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// DRAW OPERATIONS - these are operations that can draw to the canvas's device
-///////////////////////////////////////////////////////////////////////////////
-
-class DrawBitmapOp : public DrawBoundedOp {
-public:
- DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
- : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
- , mBitmap(bitmap)
- , mEntryValid(false), mEntry(nullptr) {
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawBitmap(mBitmap, mPaint);
- }
-
- AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
- if (!mEntryValid) {
- mEntryValid = true;
- mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
- }
- return mEntry;
- }
-
-#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
- TextureVertex::set((ptr)++, (posRect).xDim - (offsetRect).left, (posRect).yDim - (offsetRect).top, \
- (texCoordsRect).xDim, (texCoordsRect).yDim)
-
- /**
- * This multi-draw operation builds a mesh on the stack by generating a quad
- * for each bitmap in the batch. This method is also responsible for dirtying
- * the current layer, if any.
- */
- virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
- const std::vector<OpStatePair>& ops, const Rect& bounds) override {
- const DeferredDisplayState& firstState = *(ops[0].state);
- renderer.restoreDisplayState(firstState, true); // restore all but the clip
-
- TextureVertex vertices[6 * ops.size()];
- TextureVertex* vertex = &vertices[0];
-
- const bool hasLayer = renderer.hasLayer();
- bool pureTranslate = true;
-
- // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
- // and allowing them to be merged in getBatchId()
- for (unsigned int i = 0; i < ops.size(); i++) {
- const DeferredDisplayState& state = *(ops[i].state);
- const Rect& opBounds = state.mBounds;
- // When we reach multiDraw(), the matrix can be either
- // pureTranslate or simple (translate and/or scale).
- // If the matrix is not pureTranslate, then we have a scale
- pureTranslate &= state.mMatrix.isPureTranslate();
-
- Rect texCoords(0, 0, 1, 1);
- ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
-
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
-
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
- SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
-
- if (hasLayer) {
- renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
- }
- }
-
- renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
- pureTranslate, bounds, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw bitmap %p of size %dx%d%s",
- mBitmap, mBitmap->width(), mBitmap->height(),
- mEntry ? " using AssetAtlas" : "");
- }
-
- virtual const char* name() override { return "DrawBitmap"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
- deferInfo.mergeId = getAtlasEntry(renderer) ?
- (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
-
- // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
- // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
- // MergingDrawBatch::canMergeWith()
- // TODO: support clipped bitmaps by handling them in SET_TEXTURE
- deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
- !state.mClipSideFlags &&
- PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
- (mBitmap->colorType() != kAlpha_8_SkColorType);
- }
-
- void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
- if (getAtlasEntry(renderer)) {
- mEntry->uvMapper.map(texCoords);
- }
- }
-
- const SkBitmap* bitmap() { return mBitmap; }
-protected:
- const SkBitmap* mBitmap;
- bool mEntryValid;
- AssetAtlas::Entry* mEntry;
-};
-
-class DrawBitmapRectOp : public DrawBoundedOp {
-public:
- DrawBitmapRectOp(const SkBitmap* bitmap,
- float srcLeft, float srcTop, float srcRight, float srcBottom,
- float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
- : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
- mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawBitmap(mBitmap, mSrc, mLocalBounds, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
- mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
- }
-
- virtual const char* name() override { return "DrawBitmapRect"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
- }
-
-private:
- const SkBitmap* mBitmap;
- Rect mSrc;
-};
-
-class DrawBitmapMeshOp : public DrawBoundedOp {
-public:
- DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint)
- : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
- mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
- mVertices(vertices), mColors(colors) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
- mVertices, mColors, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
- }
-
- virtual const char* name() override { return "DrawBitmapMesh"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
- }
-
-private:
- const SkBitmap* mBitmap;
- int mMeshWidth;
- int mMeshHeight;
- const float* mVertices;
- const int* mColors;
-};
-
-class DrawPatchOp : public DrawBoundedOp {
-public:
- DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
- float left, float top, float right, float bottom, const SkPaint* paint)
- : DrawBoundedOp(left, top, right, bottom, paint),
- mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(nullptr),
- mEntryValid(false), mEntry(nullptr) {
- };
-
- AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
- if (!mEntryValid) {
- mEntryValid = true;
- mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
- }
- return mEntry;
- }
-
- const Patch* getMesh(OpenGLRenderer& renderer) {
- if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
- PatchCache& cache = renderer.getCaches().patchCache;
- mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
- mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
- mGenerationId = cache.getGenerationId();
- }
- return mMesh;
- }
-
- /**
- * This multi-draw operation builds an indexed mesh on the stack by copying
- * and transforming the vertices of each 9-patch in the batch. This method
- * is also responsible for dirtying the current layer, if any.
- */
- virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
- const std::vector<OpStatePair>& ops, const Rect& bounds) override {
- const DeferredDisplayState& firstState = *(ops[0].state);
- renderer.restoreDisplayState(firstState, true); // restore all but the clip
-
- // Batches will usually contain a small number of items so it's
- // worth performing a first iteration to count the exact number
- // of vertices we need in the new mesh
- uint32_t totalVertices = 0;
- for (unsigned int i = 0; i < ops.size(); i++) {
- totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
- }
-
- const bool hasLayer = renderer.hasLayer();
-
- uint32_t indexCount = 0;
-
- TextureVertex vertices[totalVertices];
- TextureVertex* vertex = &vertices[0];
-
- // Create a mesh that contains the transformed vertices for all the
- // 9-patch objects that are part of the batch. Note that onDefer()
- // enforces ops drawn by this function to have a pure translate or
- // identity matrix
- for (unsigned int i = 0; i < ops.size(); i++) {
- DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
- const DeferredDisplayState* state = ops[i].state;
- const Patch* opMesh = patchOp->getMesh(renderer);
- uint32_t vertexCount = opMesh->verticesCount;
- if (vertexCount == 0) continue;
-
- // We use the bounds to know where to translate our vertices
- // Using patchOp->state.mBounds wouldn't work because these
- // bounds are clipped
- const float tx = (int) floorf(state->mMatrix.getTranslateX() +
- patchOp->mLocalBounds.left + 0.5f);
- const float ty = (int) floorf(state->mMatrix.getTranslateY() +
- patchOp->mLocalBounds.top + 0.5f);
-
- // Copy & transform all the vertices for the current operation
- TextureVertex* opVertices = opMesh->vertices.get();
- for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
- TextureVertex::set(vertex++,
- opVertices->x + tx, opVertices->y + ty,
- opVertices->u, opVertices->v);
- }
-
- // Dirty the current layer if possible. When the 9-patch does not
- // contain empty quads we can take a shortcut and simply set the
- // dirty rect to the object's bounds.
- if (hasLayer) {
- if (!opMesh->hasEmptyQuads) {
- renderer.dirtyLayer(tx, ty,
- tx + patchOp->mLocalBounds.getWidth(),
- ty + patchOp->mLocalBounds.getHeight());
- } else {
- const size_t count = opMesh->quads.size();
- for (size_t i = 0; i < count; i++) {
- const Rect& quadBounds = opMesh->quads[i];
- const float x = tx + quadBounds.left;
- const float y = ty + quadBounds.top;
- renderer.dirtyLayer(x, y,
- x + quadBounds.getWidth(), y + quadBounds.getHeight());
- }
- }
- }
-
- indexCount += opMesh->indexCount;
- }
-
- renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
- &vertices[0], indexCount, mPaint);
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- // We're not calling the public variant of drawPatch() here
- // This method won't perform the quickReject() since we've already done it at this point
- renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
- mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
- mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
- mEntry ? " with AssetAtlas" : "");
- }
-
- virtual const char* name() override { return "DrawPatch"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
- deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
- deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
- PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
- deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
- }
-
-private:
- const SkBitmap* mBitmap;
- const Res_png_9patch* mPatch;
-
- uint32_t mGenerationId;
- const Patch* mMesh;
-
- bool mEntryValid;
- AssetAtlas::Entry* mEntry;
-};
-
-class DrawColorOp : public DrawOp {
-public:
- DrawColorOp(int color, SkXfermode::Mode mode)
- : DrawOp(nullptr), mColor(color), mMode(mode) {};
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawColor(mColor, mMode);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw color %#x, mode %d", mColor, mMode);
- }
-
- virtual const char* name() override { return "DrawColor"; }
-
-private:
- int mColor;
- SkXfermode::Mode mMode;
-};
-
-class DrawStrokableOp : public DrawBoundedOp {
-public:
- DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
- : DrawBoundedOp(left, top, right, bottom, paint) {};
- DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
- : DrawBoundedOp(localBounds, paint) {};
-
- virtual bool getLocalBounds(Rect& localBounds) override {
- localBounds.set(mLocalBounds);
- if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
- localBounds.outset(strokeWidthOutset());
- }
- return true;
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- if (mPaint->getPathEffect()) {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
- } else {
- deferInfo.batchId = mPaint->isAntiAlias() ?
- DeferredDisplayList::kOpBatch_AlphaVertices :
- DeferredDisplayList::kOpBatch_Vertices;
- }
- }
-};
-
-class DrawRectOp : public DrawStrokableOp {
-public:
- DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
- : DrawStrokableOp(left, top, right, bottom, paint) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
- mLocalBounds.right, mLocalBounds.bottom, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- DrawStrokableOp::onDefer(renderer, deferInfo, state);
- deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
- mPaint->getStyle() == SkPaint::kFill_Style;
- }
-
- virtual const char* name() override { return "DrawRect"; }
-};
-
-class DrawRectsOp : public DrawBoundedOp {
-public:
- DrawRectsOp(const float* rects, int count, const SkPaint* paint)
- : DrawBoundedOp(rects, count, paint),
- mRects(rects), mCount(count) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawRects(mRects, mCount, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Rects count %d", mCount);
- }
-
- virtual const char* name() override { return "DrawRects"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
- }
-
-private:
- const float* mRects;
- int mCount;
-};
-
-class DrawRoundRectOp : public DrawStrokableOp {
-public:
- DrawRoundRectOp(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint* paint)
- : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
- mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- DrawStrokableOp::onDefer(renderer, deferInfo, state);
- if (!mPaint->getPathEffect()) {
- renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
- mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
- }
- }
-
- virtual const char* name() override { return "DrawRoundRect"; }
-
-private:
- float mRx;
- float mRy;
-};
-
-class DrawRoundRectPropsOp : public DrawOp {
-public:
- DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
- float *rx, float *ry, const SkPaint* paint)
- : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
- mRx(rx), mRy(ry) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
- *mRx, *mRy, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
- *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
- }
-
- virtual const char* name() override { return "DrawRoundRectProps"; }
-
-private:
- float* mLeft;
- float* mTop;
- float* mRight;
- float* mBottom;
- float* mRx;
- float* mRy;
-};
-
-class DrawCircleOp : public DrawStrokableOp {
-public:
- DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
- : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
- mX(x), mY(y), mRadius(radius) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawCircle(mX, mY, mRadius, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
- }
-
- virtual const char* name() override { return "DrawCircle"; }
-
-private:
- float mX;
- float mY;
- float mRadius;
-};
-
-class DrawCirclePropsOp : public DrawOp {
-public:
- DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
- : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
- }
-
- virtual const char* name() override { return "DrawCircleProps"; }
-
-private:
- float* mX;
- float* mY;
- float* mRadius;
-};
-
-class DrawVectorDrawableOp : public DrawOp {
-public:
- DrawVectorDrawableOp(VectorDrawableRoot* tree, const SkRect& bounds)
- : DrawOp(nullptr), mTree(tree), mDst(bounds) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- const SkBitmap& bitmap = mTree->getBitmapUpdateIfDirty();
- SkPaint* paint = mTree->getPaint();
- renderer.drawBitmap(&bitmap, Rect(0, 0, bitmap.width(), bitmap.height()),
- mDst, paint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Vector Drawable %p", mTree);
- }
-
- virtual const char* name() override { return "DrawVectorDrawable"; }
-
-private:
- VectorDrawableRoot* mTree;
- SkRect mDst;
-
-};
-
-class DrawOvalOp : public DrawStrokableOp {
-public:
- DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
- : DrawStrokableOp(left, top, right, bottom, paint) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
- mLocalBounds.right, mLocalBounds.bottom, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
- }
-
- virtual const char* name() override { return "DrawOval"; }
-};
-
-class DrawArcOp : public DrawStrokableOp {
-public:
- DrawArcOp(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
- : DrawStrokableOp(left, top, right, bottom, paint),
- mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
- mLocalBounds.right, mLocalBounds.bottom,
- mStartAngle, mSweepAngle, mUseCenter, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
- RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
- }
-
- virtual const char* name() override { return "DrawArc"; }
-
-private:
- float mStartAngle;
- float mSweepAngle;
- bool mUseCenter;
-};
-
-class DrawPathOp : public DrawBoundedOp {
-public:
- DrawPathOp(const SkPath* path, const SkPaint* paint)
- : DrawBoundedOp(paint), mPath(path) {
- float left, top, offset;
- uint32_t width, height;
- PathCache::computePathBounds(path, paint, left, top, offset, width, height);
- left -= offset;
- top -= offset;
- mLocalBounds.set(left, top, left + width, top + height);
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawPath(mPath, mPaint);
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- renderer.getCaches().pathCache.precache(mPath, mPaint);
-
- deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
- }
-
- virtual const char* name() override { return "DrawPath"; }
-
-private:
- const SkPath* mPath;
-};
-
-class DrawLinesOp : public DrawBoundedOp {
-public:
- DrawLinesOp(const float* points, int count, const SkPaint* paint)
- : DrawBoundedOp(points, count, paint),
- mPoints(points), mCount(count) {
- mLocalBounds.outset(strokeWidthOutset());
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawLines(mPoints, mCount, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Lines count %d", mCount);
- }
-
- virtual const char* name() override { return "DrawLines"; }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- deferInfo.batchId = mPaint->isAntiAlias() ?
- DeferredDisplayList::kOpBatch_AlphaVertices :
- DeferredDisplayList::kOpBatch_Vertices;
- }
-
-protected:
- const float* mPoints;
- int mCount;
-};
-
-class DrawPointsOp : public DrawLinesOp {
-public:
- DrawPointsOp(const float* points, int count, const SkPaint* paint)
- : DrawLinesOp(points, count, paint) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawPoints(mPoints, mCount, mPaint);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Points count %d", mCount);
- }
-
- virtual const char* name() override { return "DrawPoints"; }
-};
-
-class DrawSomeTextOp : public DrawOp {
-public:
- DrawSomeTextOp(const glyph_t* text, int bytesCount, int count, const SkPaint* paint)
- : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw some text, %d bytes", mBytesCount);
- }
-
- virtual bool hasTextShadow() const override {
- return PaintUtils::hasTextShadow(mPaint);
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
- fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
-
- deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
- DeferredDisplayList::kOpBatch_Text :
- DeferredDisplayList::kOpBatch_ColorText;
- }
-
-protected:
- const glyph_t* mText;
- int mBytesCount;
- int mCount;
-};
-
-class DrawTextOnPathOp : public DrawSomeTextOp {
-public:
- DrawTextOnPathOp(const glyph_t* text, int bytesCount, int count,
- const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
- : DrawSomeTextOp(text, bytesCount, count, paint),
- mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
- /* TODO: inherit from DrawBounded and init mLocalBounds */
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
- mHOffset, mVOffset, mPaint);
- }
-
- virtual const char* name() override { return "DrawTextOnPath"; }
-
-private:
- const SkPath* mPath;
- float mHOffset;
- float mVOffset;
-};
-
-class DrawTextOp : public DrawStrokableOp {
-public:
- DrawTextOp(const glyph_t* text, int bytesCount, int count, float x, float y,
- const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
- : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
- mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
- mPrecacheTransform = SkMatrix::InvalidMatrix();
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
- SkMatrix transform;
- renderer.findBestFontTransform(state.mMatrix, &transform);
- if (mPrecacheTransform != transform) {
- fontRenderer.precache(mPaint, mText, mCount, transform);
- mPrecacheTransform = transform;
- }
- deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
- DeferredDisplayList::kOpBatch_Text :
- DeferredDisplayList::kOpBatch_ColorText;
-
- deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
-
- // don't merge decorated text - the decorations won't draw in order
- bool hasDecorations = mPaint->getFlags()
- & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
-
- deferInfo.mergeable = state.mMatrix.isPureTranslate()
- && !hasDecorations
- && PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- Rect bounds;
- getLocalBounds(bounds);
- renderer.drawText(mText, mBytesCount, mCount, mX, mY,
- mPositions, mPaint, mTotalAdvance, bounds);
- }
-
- virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
- const std::vector<OpStatePair>& ops, const Rect& bounds) override {
- for (unsigned int i = 0; i < ops.size(); i++) {
- const DeferredDisplayState& state = *(ops[i].state);
- DrawOpMode drawOpMode = (i == ops.size() - 1) ? DrawOpMode::kFlush : DrawOpMode::kDefer;
- renderer.restoreDisplayState(state, true); // restore all but the clip
-
- DrawTextOp& op = *((DrawTextOp*)ops[i].op);
- // quickReject() will not occure in drawText() so we can use mLocalBounds
- // directly, we do not need to account for shadow by calling getLocalBounds()
- renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
- op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
- drawOpMode);
- }
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
- }
-
- virtual const char* name() override { return "DrawText"; }
-
-private:
- const glyph_t* mText;
- int mBytesCount;
- int mCount;
- float mX;
- float mY;
- const float* mPositions;
- float mTotalAdvance;
- SkMatrix mPrecacheTransform;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// SPECIAL DRAW OPERATIONS
-///////////////////////////////////////////////////////////////////////////////
-
-class DrawFunctorOp : public DrawOp {
-public:
- DrawFunctorOp(Functor* functor)
- : DrawOp(nullptr), mFunctor(functor) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.startMark("GL functor");
- renderer.callDrawGLFunction(mFunctor, dirty);
- renderer.endMark();
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Functor %p", mFunctor);
- }
-
- virtual const char* name() override { return "DrawFunctor"; }
-
-private:
- Functor* mFunctor;
-};
-
-class DrawRenderNodeOp : public DrawBoundedOp {
- friend class RenderNode; // grant RenderNode access to info of child
- friend class DisplayList; // grant DisplayList access to info of child
- friend class DisplayListCanvas;
- friend class TestUtils;
-public:
- DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
- : DrawBoundedOp(0, 0,
- renderNode->stagingProperties().getWidth(),
- renderNode->stagingProperties().getHeight(),
- nullptr)
- , renderNode(renderNode)
- , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
- , localMatrix(transformFromParent)
- , skipInOrderDraw(false) {}
-
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
- bool useQuickReject) override {
- if (renderNode->isRenderable() && !skipInOrderDraw) {
- renderNode->defer(deferStruct, level + 1);
- }
- }
-
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
- bool useQuickReject) override {
- if (renderNode->isRenderable() && !skipInOrderDraw) {
- renderNode->replay(replayStruct, level + 1);
- }
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw RenderNode %p %s", renderNode, renderNode->getName());
- if (renderNode && (logFlags & kOpLogFlag_Recurse)) {
- renderNode->output(level + 1);
- }
- }
-
- virtual const char* name() override { return "DrawRenderNode"; }
-
-private:
- RenderNode* renderNode;
-
- /**
- * This RenderNode was drawn into a DisplayList with the canvas in a state that will likely
- * require rendering with stencil clipping. Either:
- *
- * 1) A path clip or rotated rect clip was in effect on the canvas at record time
- * 2) The RenderNode was recorded with a non-simple canvas transform (e.g. rotation)
- *
- * Note: even if this is false, non-rect clipping may still be applied applied either due to
- * property-driven rotation (either in this RenderNode, or any ancestor), or record time
- * clipping in an ancestor. These are handled in RenderNode::prepareTreeImpl since they are
- * dynamic (relative to a static DisplayList of a parent), and don't affect this flag.
- */
- bool mRecordedWithPotentialStencilClip;
-
- ///////////////////////////
- // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
- ///////////////////////////
- /**
- * Records transform vs parent, used for computing total transform without rerunning DL contents
- */
- const mat4 localMatrix;
-
- /**
- * Holds the transformation between the projection surface ViewGroup and this RenderNode
- * drawing instance. Represents any translations / transformations done within the drawing of
- * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
- * DisplayList draw instance.
- *
- * Note: doesn't include transformation within the RenderNode, or its properties.
- */
- mat4 transformFromCompositingAncestor;
- bool skipInOrderDraw;
-};
-
-/**
- * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
- */
-class DrawShadowOp : public DrawOp {
-public:
- DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
- float casterAlpha, const SkPath* casterOutline)
- : DrawOp(nullptr)
- , mTransformXY(transformXY)
- , mTransformZ(transformZ)
- , mCasterAlpha(casterAlpha)
- , mCasterOutline(casterOutline) {
- }
-
- virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
- const DeferredDisplayState& state) override {
- renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
- renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
- &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
- }
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- TessellationCache::vertexBuffer_pair_t buffers;
- Matrix4 drawTransform(*(renderer.currentTransform()));
- renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
- renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
- &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
- buffers);
-
- renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOGS("DrawShadow");
- }
-
- virtual const char* name() override { return "DrawShadow"; }
-
-private:
- bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
-
- const mat4 mTransformXY;
- const mat4 mTransformZ;
- const float mCasterAlpha;
- const SkPath* mCasterOutline;
-};
-
-class DrawLayerOp : public DrawOp {
-public:
- DrawLayerOp(Layer* layer)
- : DrawOp(nullptr), mLayer(layer) {}
-
- virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
- renderer.drawLayer(mLayer);
- }
-
- virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw Layer %p", mLayer);
- }
-
- virtual const char* name() override { return "DrawLayer"; }
-
-private:
- Layer* mLayer;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_DISPLAY_OPERATION_H
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 276c18d0d3f9..25dc92c8a8dc 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -16,6 +16,9 @@
#include "FontRenderer.h"
+#include "BakedOpDispatcher.h"
+#include "BakedOpRenderer.h"
+#include "BakedOpState.h"
#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
@@ -27,15 +30,6 @@
#include "utils/Blur.h"
#include "utils/Timing.h"
-
-#if HWUI_NEW_OPS
-#include "BakedOpDispatcher.h"
-#include "BakedOpRenderer.h"
-#include "BakedOpState.h"
-#else
-#include "OpenGLRenderer.h"
-#endif
-
#include <algorithm>
#include <cutils/properties.h>
#include <SkGlyph.h>
@@ -67,7 +61,6 @@ void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
int transformFlags = pureTranslate
? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
Glop glop;
-#if HWUI_NEW_OPS
GlopBuilder(renderer->renderState(), renderer->caches(), &glop)
.setRoundRectClipState(bakedState->roundRectClipState)
.setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
@@ -77,16 +70,6 @@ void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
.build();
// Note: don't pass dirty bounds here, so user must manage passing dirty bounds to renderer
renderer->renderGlop(nullptr, clip, glop);
-#else
- GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop)
- .setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState)
- .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
- .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha)
- .setTransform(*(renderer->currentSnapshot()), transformFlags)
- .setModelViewOffsetRect(0, 0, Rect())
- .build();
- renderer->renderGlop(glop);
-#endif
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index e10a81b8ccd8..dedc4944299d 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_FONT_RENDERER_H
-#define ANDROID_HWUI_FONT_RENDERER_H
+#pragma once
#include "font/FontUtil.h"
#include "font/CacheTexture.h"
@@ -44,31 +43,21 @@ namespace RSC {
namespace android {
namespace uirenderer {
-#if HWUI_NEW_OPS
class BakedOpState;
class BakedOpRenderer;
struct ClipBase;
-#else
-class OpenGLRenderer;
-#endif
class TextDrawFunctor {
public:
TextDrawFunctor(
-#if HWUI_NEW_OPS
BakedOpRenderer* renderer,
const BakedOpState* bakedState,
const ClipBase* clip,
-#else
- OpenGLRenderer* renderer,
-#endif
float x, float y, bool pureTranslate,
int alpha, SkXfermode::Mode mode, const SkPaint* paint)
: renderer(renderer)
-#if HWUI_NEW_OPS
, bakedState(bakedState)
, clip(clip)
-#endif
, x(x)
, y(y)
, pureTranslate(pureTranslate)
@@ -79,13 +68,9 @@ public:
void draw(CacheTexture& texture, bool linearFiltering);
-#if HWUI_NEW_OPS
BakedOpRenderer* renderer;
const BakedOpState* bakedState;
const ClipBase* clip;
-#else
- OpenGLRenderer* renderer;
-#endif
float x;
float y;
bool pureTranslate;
@@ -218,5 +203,3 @@ private:
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_FONT_RENDERER_H
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 37d9d0e749e6..be4fdac5f800 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -477,7 +477,7 @@ void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
projectionReceiverOutline->transform(
skCurrentTransform,
&transformedMaskPath);
- mCanvasState.setProjectionPathMask(mAllocator, &transformedMaskPath);
+ mCanvasState.setProjectionPathMask(&transformedMaskPath);
}
for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index adadd32a2fc0..570322dfb4eb 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -15,11 +15,7 @@
*/
#include "FrameInfoVisualizer.h"
-#if HWUI_NEW_OPS
#include "BakedOpRenderer.h"
-#else
-#include "OpenGLRenderer.h"
-#endif
#include "utils/Color.h"
#include <cutils/compiler.h>
diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h
index 83adf1985c72..fc958b8b414a 100644
--- a/libs/hwui/FrameInfoVisualizer.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef DRAWPROFILER_H
-#define DRAWPROFILER_H
+
+#pragma once
#include "FrameInfo.h"
#include "Properties.h"
@@ -28,13 +28,8 @@
namespace android {
namespace uirenderer {
-#if HWUI_NEW_OPS
class BakedOpRenderer;
typedef BakedOpRenderer ContentRenderer;
-#else
-class OpenGLRenderer;
-typedef OpenGLRenderer ContentRenderer;
-#endif
// TODO: This is a bit awkward as it needs to match the thing in CanvasContext
// A better abstraction here would be nice but iterators are painful
@@ -93,5 +88,3 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* DRAWPROFILER_H */
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index 6433c86908e7..46dd598711b8 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_GLOP_H
-#define ANDROID_HWUI_GLOP_H
+#pragma once
#include "FloatColor.h"
#include "Matrix.h"
@@ -68,7 +67,7 @@ namespace TransformFlags {
OffsetByFudgeFactor = 1 << 0,
// Canvas transform isn't applied to the mesh at draw time,
- //since it's already built in.
+ // since it's already built in.
MeshIgnoresCanvasTransform = 1 << 1, // TODO: remove for HWUI_NEW_OPS
};
};
@@ -168,14 +167,6 @@ public:
GLenum dst;
} blend;
-#if !HWUI_NEW_OPS
- /**
- * Bounds of the drawing command in layer space. Only mapped into layer
- * space once GlopBuilder::build() is called.
- */
- Rect bounds; // TODO: remove for HWUI_NEW_OPS
-#endif
-
/**
* Additional render state to enumerate:
* - scissor + (bits for whether each of LTRB needed?)
@@ -185,5 +176,3 @@ public:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif // ANDROID_HWUI_GLOP_H
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index e502725ddb09..1091736ab9c3 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -17,8 +17,10 @@
#include "Caches.h"
#include "Glop.h"
+#include "Layer.h"
#include "Matrix.h"
#include "Patch.h"
+#include "PathCache.h"
#include "renderstate/MeshState.h"
#include "renderstate/RenderState.h"
#include "SkiaShader.h"
@@ -165,20 +167,6 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData,
return *this;
}
-GlopBuilder& GlopBuilder::setMeshTexturedMesh(TextureVertex* vertexData, int elementCount) {
- TRIGGER_STAGE(kMeshStage);
-
- mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.indices = { 0, nullptr };
- mOutGlop->mesh.vertices = {
- 0,
- VertexAttribFlags::TextureCoord,
- &vertexData[0].x, &vertexData[0].u, nullptr,
- kTextureVertexStride };
- mOutGlop->mesh.elementCount = elementCount;
- return *this;
-}
-
GlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount) {
TRIGGER_STAGE(kMeshStage);
@@ -514,9 +502,6 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
-#if !HWUI_NEW_OPS
- mOutGlop->bounds = destination;
-#endif
return *this;
}
@@ -540,9 +525,6 @@ GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination)
mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
-#if !HWUI_NEW_OPS
- mOutGlop->bounds = destination;
-#endif
return *this;
}
@@ -550,10 +532,6 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, c
TRIGGER_STAGE(kModelViewStage);
mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
-#if !HWUI_NEW_OPS
- mOutGlop->bounds = source;
- mOutGlop->bounds.translate(offsetX, offsetY);
-#endif
return *this;
}
@@ -573,10 +551,6 @@ GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offset
}
mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
-#if !HWUI_NEW_OPS
- mOutGlop->bounds = source;
- mOutGlop->bounds.translate(offsetX, offsetY);
-#endif
return *this;
}
@@ -676,9 +650,6 @@ void GlopBuilder::build() {
// Final step: populate program and map bounds into render target space
mOutGlop->fill.program = mCaches.programCache.get(mDescription);
-#if !HWUI_NEW_OPS
- mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds);
-#endif
}
void GlopBuilder::dump(const Glop& glop) {
@@ -718,9 +689,6 @@ void GlopBuilder::dump(const Glop& glop) {
ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState);
ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
-#if !HWUI_NEW_OPS
- ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds));
-#endif
}
} /* namespace uirenderer */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 1c520c26110e..11524615074e 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef RENDERSTATE_GLOPBUILDER_H
-#define RENDERSTATE_GLOPBUILDER_H
+
+#pragma once
#include "Glop.h"
-#include "OpenGLRenderer.h"
#include "Program.h"
#include "renderstate/Blend.h"
#include "utils/Macros.h"
@@ -30,9 +29,13 @@ namespace uirenderer {
class Caches;
class Matrix4;
+class Patch;
class RenderState;
class Texture;
+class UvMapper;
class VertexBuffer;
+struct PathTexture;
+struct ShadowTexture;
namespace TextureFillFlags {
enum {
@@ -53,7 +56,6 @@ public:
GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs);
GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer);
GlopBuilder& setMeshIndexedQuads(Vertex* vertexData, int quadCount);
- GlopBuilder& setMeshTexturedMesh(TextureVertex* vertexData, int elementCount); // TODO: delete
GlopBuilder& setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount); // TODO: use indexed quads
GlopBuilder& setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount); // TODO: take quadCount
GlopBuilder& setMeshPatchQuads(const Patch& patch);
@@ -75,9 +77,6 @@ public:
// Similarly setFillLayer normally forces its own wrap & filter mode
GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform);
- GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
- return setTransform(*snapshot.transform, transformFlags);
- }
GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags);
GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
@@ -133,5 +132,3 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif // RENDERSTATE_GLOPBUILDER_H
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index cdbbbab7730d..b911b6825226 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -17,9 +17,6 @@
#include "Layer.h"
#include "Caches.h"
-#include "DeferredDisplayList.h"
-#include "LayerRenderer.h"
-#include "OpenGLRenderer.h"
#include "RenderNode.h"
#include "renderstate/RenderState.h"
#include "utils/TraceUtils.h"
@@ -35,13 +32,12 @@
namespace android {
namespace uirenderer {
-Layer::Layer(Type layerType, RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
+Layer::Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight)
: GpuMemoryTracker(GpuObjectType::Layer)
, state(State::Uncached)
, caches(Caches::getInstance())
, renderState(renderState)
- , texture(caches)
- , type(layerType) {
+ , texture(caches) {
// TODO: This is a violation of Android's typical ref counting, but it
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
@@ -55,125 +51,15 @@ Layer::~Layer() {
renderState.unregisterLayer(this);
SkSafeUnref(colorFilter);
- if (stencil || fbo || texture.mId) {
- removeFbo();
+ if (texture.mId) {
texture.deleteTexture();
}
-
- delete[] mesh;
}
void Layer::onGlContextLost() {
- removeFbo();
texture.deleteTexture();
}
-uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
- return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
-}
-
-uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
- return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
-}
-
-void Layer::requireRenderer() {
- if (!renderer) {
- renderer.reset(new LayerRenderer(renderState, this));
- renderer->initProperties();
- }
-}
-
-void Layer::updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer) {
- if (renderer && rendererLightPosDirty) {
- // re-init renderer's light position, based upon last cached location in window
- Vector3 lightPos = rootRenderer.getLightCenter();
- cachedInvTransformInWindow.mapPoint3d(lightPos);
- renderer->initLight(rootRenderer.getLightRadius(),
- rootRenderer.getAmbientShadowAlpha(),
- rootRenderer.getSpotShadowAlpha());
- renderer->setLightCenter(lightPos);
- rendererLightPosDirty = false;
- }
-}
-
-bool Layer::resize(const uint32_t width, const uint32_t height) {
- uint32_t desiredWidth = computeIdealWidth(width);
- uint32_t desiredHeight = computeIdealWidth(height);
-
- if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) {
- return true;
- }
-
- ATRACE_NAME("resizeLayer");
-
- const uint32_t maxTextureSize = caches.maxTextureSize;
- if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) {
- ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
- desiredWidth, desiredHeight, maxTextureSize, maxTextureSize);
- return false;
- }
-
- uint32_t oldWidth = getWidth();
- uint32_t oldHeight = getHeight();
-
- setSize(desiredWidth, desiredHeight);
-
- if (fbo) {
- caches.textureState().activateTexture(0);
- bindTexture();
- allocateTexture();
-
- if (glGetError() != GL_NO_ERROR) {
- setSize(oldWidth, oldHeight);
- return false;
- }
- }
-
- if (stencil) {
- stencil->bind();
- stencil->resize(desiredWidth, desiredHeight);
-
- if (glGetError() != GL_NO_ERROR) {
- setSize(oldWidth, oldHeight);
- return false;
- }
- }
-
- return true;
-}
-
-void Layer::removeFbo(bool flush) {
- if (stencil) {
- GLuint previousFbo = renderState.getFramebuffer();
- renderState.bindFramebuffer(fbo);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
- renderState.bindFramebuffer(previousFbo);
-
- caches.renderBufferCache.put(stencil);
- stencil = nullptr;
- }
-
- if (fbo) {
- if (flush) LayerRenderer::flushLayer(renderState, this);
- renderState.deleteFramebuffer(fbo);
- fbo = 0;
- }
-}
-
-void Layer::updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom) {
- requireRenderer();
- this->renderNode = renderNode;
- const Rect r(left, top, right, bottom);
- dirtyRect.unionWith(r);
- deferredUpdateScheduled = true;
-}
-
-void Layer::setPaint(const SkPaint* paint) {
- alpha = PaintUtils::getAlphaDirect(paint);
- mode = PaintUtils::getXfermodeDirect(paint);
- setColorFilter((paint) ? paint->getColorFilter() : nullptr);
-}
-
void Layer::setColorFilter(SkColorFilter* filter) {
SkRefCnt_SafeAssign(colorFilter, filter);
}
@@ -184,12 +70,6 @@ void Layer::bindTexture() const {
}
}
-void Layer::bindStencilRenderBuffer() const {
- if (stencil) {
- stencil->bind();
- }
-}
-
void Layer::generateTexture() {
if (!texture.mId) {
glGenTextures(1, &texture.mId);
@@ -206,86 +86,6 @@ void Layer::clearTexture() {
texture.mId = 0;
}
-void Layer::allocateTexture() {
-#if DEBUG_LAYERS
- ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight());
-#endif
- if (texture.mId) {
- texture.updateSize(getWidth(), getHeight(), GL_RGBA);
- glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- }
-}
-
-void Layer::defer(const OpenGLRenderer& rootRenderer) {
- ATRACE_LAYER_WORK("Optimize");
-
- updateLightPosFromRenderer(rootRenderer);
- const float width = layer.getWidth();
- const float height = layer.getHeight();
-
- if (dirtyRect.isEmpty() || (dirtyRect.left <= 0 && dirtyRect.top <= 0 &&
- dirtyRect.right >= width && dirtyRect.bottom >= height)) {
- dirtyRect.set(0, 0, width, height);
- }
-
- deferredList.reset(new DeferredDisplayList(dirtyRect));
-
- DeferStateStruct deferredState(*deferredList, *renderer,
- RenderNode::kReplayFlag_ClipChildren);
-
- renderer->setupFrameState(width, height, dirtyRect.left, dirtyRect.top,
- dirtyRect.right, dirtyRect.bottom, !isBlend());
-
- renderNode->computeOrdering();
- renderNode->defer(deferredState, 0);
-
- deferredUpdateScheduled = false;
-}
-
-void Layer::cancelDefer() {
- renderNode = nullptr;
- deferredUpdateScheduled = false;
- deferredList.reset(nullptr);
-}
-
-void Layer::flush() {
- // renderer is checked as layer may be destroyed/put in layer cache with flush scheduled
- if (deferredList && renderer) {
- ATRACE_LAYER_WORK("Issue");
- renderer->startMark((renderNode.get() != nullptr) ? renderNode->getName() : "Layer");
-
- renderer->prepareDirty(layer.getWidth(), layer.getHeight(),
- dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend());
-
- deferredList->flush(*renderer, dirtyRect);
-
- renderer->finish();
-
- dirtyRect.setEmpty();
- renderNode = nullptr;
-
- renderer->endMark();
- }
-}
-
-void Layer::render(const OpenGLRenderer& rootRenderer) {
- ATRACE_LAYER_WORK("Direct-Issue");
-
- updateLightPosFromRenderer(rootRenderer);
- renderer->prepareDirty(layer.getWidth(), layer.getHeight(),
- dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend());
-
- renderer->drawRenderNode(renderNode.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
-
- renderer->finish();
-
- dirtyRect.setEmpty();
-
- deferredUpdateScheduled = false;
- renderNode = nullptr;
-}
-
void Layer::postDecStrong() {
renderState.postDecStrong(this);
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 1e5498bb3d21..153184149db6 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_LAYER_H
-#define ANDROID_HWUI_LAYER_H
+#pragma once
#include <cutils/compiler.h>
#include <sys/types.h>
@@ -46,22 +45,13 @@ namespace uirenderer {
// Forward declarations
class Caches;
-class RenderNode;
class RenderState;
-class OpenGLRenderer;
-class DeferredDisplayList;
-struct DeferStateStruct;
/**
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
class Layer : public VirtualLightRefBase, GpuMemoryTracker {
public:
- enum class Type {
- Texture,
- DisplayList,
- };
-
// layer lifecycle, controlled from outside
enum class State {
Uncached = 0,
@@ -73,45 +63,9 @@ public:
};
State state; // public for logging/debugging purposes
- Layer(Type type, RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
+ Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight);
~Layer();
- static uint32_t computeIdealWidth(uint32_t layerWidth);
- static uint32_t computeIdealHeight(uint32_t layerHeight);
-
- /**
- * Calling this method will remove (either by recycling or
- * destroying) the associated FBO, if present, and any render
- * buffer (stencil for instance.)
- */
- void removeFbo(bool flush = true);
-
- /**
- * Sets this layer's region to a rectangle. Computes the appropriate
- * texture coordinates.
- */
- void setRegionAsRect() {
- const android::Rect& bounds = region.getBounds();
- regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
- bounds.rightBottom().x, bounds.rightBottom().y);
-
- const float texX = 1.0f / float(texture.mWidth);
- const float texY = 1.0f / float(texture.mHeight);
- const float height = layer.getHeight();
- texCoords.set(
- regionRect.left * texX, (height - regionRect.top) * texY,
- regionRect.right * texX, (height - regionRect.bottom) * texY);
-
- regionRect.translate(layer.left, layer.top);
- }
-
- void setWindowTransform(Matrix4& windowTransform) {
- cachedInvTransformInWindow.loadInverse(windowTransform);
- rendererLightPosDirty = true;
- }
-
- void updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom);
-
inline uint32_t getWidth() const {
return texture.mWidth;
}
@@ -120,23 +74,10 @@ public:
return texture.mHeight;
}
- /**
- * Resize the layer and its texture if needed.
- *
- * @param width The new width of the layer
- * @param height The new height of the layer
- *
- * @return True if the layer was resized or nothing happened, false if
- * a failure occurred during the resizing operation
- */
- bool resize(const uint32_t width, const uint32_t height);
-
void setSize(uint32_t width, uint32_t height) {
texture.updateSize(width, height, texture.format());
}
- ANDROID_API void setPaint(const SkPaint* paint);
-
inline void setBlend(bool blend) {
texture.blend = blend;
}
@@ -170,36 +111,6 @@ public:
return mode;
}
- inline void setEmpty(bool empty) {
- this->empty = empty;
- }
-
- inline bool isEmpty() const {
- return empty;
- }
-
- inline void setFbo(GLuint fbo) {
- this->fbo = fbo;
- }
-
- inline GLuint getFbo() const {
- return fbo;
- }
-
- inline void setStencilRenderBuffer(RenderBuffer* renderBuffer) {
- if (RenderBuffer::isStencilBuffer(renderBuffer->getFormat())) {
- this->stencil = renderBuffer;
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, stencil->getName());
- } else {
- ALOGE("The specified render buffer is not a stencil buffer");
- }
- }
-
- inline RenderBuffer* getStencilRenderBuffer() const {
- return stencil;
- }
-
inline GLuint getTextureId() const {
return texture.id();
}
@@ -228,52 +139,21 @@ public:
texture.setFilter(filter, bindTexture, force, renderTarget);
}
- inline bool isCacheable() const {
- return cacheable;
- }
-
- inline void setCacheable(bool cacheable) {
- this->cacheable = cacheable;
- }
-
- inline bool isDirty() const {
- return dirty;
- }
-
- inline void setDirty(bool dirty) {
- this->dirty = dirty;
- }
-
- inline bool isTextureLayer() const {
- return type == Type::Texture;
- }
-
inline SkColorFilter* getColorFilter() const {
return colorFilter;
}
- ANDROID_API void setColorFilter(SkColorFilter* filter);
-
- inline void setConvexMask(const SkPath* convexMask) {
- this->convexMask = convexMask;
- }
-
- inline const SkPath* getConvexMask() {
- return convexMask;
- }
-
- void bindStencilRenderBuffer() const;
+ void setColorFilter(SkColorFilter* filter);
void bindTexture() const;
void generateTexture();
- void allocateTexture();
/**
* When the caller frees the texture itself, the caller
* must call this method to tell this layer that it lost
* the texture.
*/
- ANDROID_API void clearTexture();
+ void clearTexture();
inline mat4& getTexTransform() {
return texTransform;
@@ -283,11 +163,6 @@ public:
return transform;
}
- void defer(const OpenGLRenderer& rootRenderer);
- void cancelDefer();
- void flush();
- void render(const OpenGLRenderer& rootRenderer);
-
/**
* Posts a decStrong call to the appropriate thread.
* Thread-safe.
@@ -313,80 +188,17 @@ public:
*/
Rect clipRect;
- /**
- * Dirty region indicating what parts of the layer
- * have been drawn.
- */
- Region region;
- /**
- * If the region is a rectangle, coordinates of the
- * region are stored here.
- */
- Rect regionRect;
-
- /**
- * If the layer can be rendered as a mesh, this is non-null.
- */
- TextureVertex* mesh = nullptr;
- GLsizei meshElementCount = 0;
-
- /**
- * Used for deferred updates.
- */
- bool deferredUpdateScheduled = false;
- std::unique_ptr<OpenGLRenderer> renderer;
- sp<RenderNode> renderNode;
- Rect dirtyRect;
- bool debugDrawUpdate = false;
- bool hasDrawnSinceUpdate = false;
- bool wasBuildLayered = false;
-
private:
- void requireRenderer();
- void updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer);
-
Caches& caches;
RenderState& renderState;
/**
- * Name of the FBO used to render the layer. If the name is 0
- * this layer is not backed by an FBO, but a simple texture.
- */
- GLuint fbo = 0;
-
- /**
- * The render buffer used as the stencil buffer.
- */
- RenderBuffer* stencil = nullptr;
-
- /**
- * Indicates whether this layer has been used already.
- */
- bool empty = true;
-
- /**
* The texture backing this layer.
*/
Texture texture;
/**
- * If set to true (by default), the layer can be reused.
- */
- bool cacheable = true;
-
- /**
- * Denotes whether the layer is a DisplayList, or Texture layer.
- */
- const Type type;
-
- /**
- * When set to true, this layer is dirty and should be cleared
- * before any rendering occurs.
- */
- bool dirty = false;
-
- /**
* Indicates the render target.
*/
GLenum renderTarget = GL_TEXTURE_2D;
@@ -421,28 +233,7 @@ private:
*/
mat4 transform;
- /**
- * Cached transform of layer in window, updated only on creation / resize
- */
- mat4 cachedInvTransformInWindow;
- bool rendererLightPosDirty = true;
-
- /**
- * Used to defer display lists when the layer is updated with a
- * display list.
- */
- std::unique_ptr<DeferredDisplayList> deferredList;
-
- /**
- * This convex path should be used to mask the layer's draw to the screen.
- *
- * Data not owned/managed by layer object.
- */
- const SkPath* convexMask = nullptr;
-
}; // struct Layer
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_LAYER_H
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
deleted file mode 100644
index f5681ce712d5..000000000000
--- a/libs/hwui/LayerCache.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "LayerCache.h"
-
-#include "Caches.h"
-#include "Properties.h"
-
-#include <utils/Log.h>
-
-#include <GLES2/gl2.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-LayerCache::LayerCache()
- : mSize(0)
- , mMaxSize(Properties::layerPoolSize) {}
-
-LayerCache::~LayerCache() {
- clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Size management
-///////////////////////////////////////////////////////////////////////////////
-
-size_t LayerCache::getCount() {
- return mCache.size();
-}
-
-uint32_t LayerCache::getSize() {
- return mSize;
-}
-
-uint32_t LayerCache::getMaxSize() {
- return mMaxSize;
-}
-
-void LayerCache::setMaxSize(uint32_t maxSize) {
- clear();
- mMaxSize = maxSize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Caching
-///////////////////////////////////////////////////////////////////////////////
-
-int LayerCache::LayerEntry::compare(const LayerCache::LayerEntry& lhs,
- const LayerCache::LayerEntry& rhs) {
- int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
- if (deltaInt != 0) return deltaInt;
-
- return int(lhs.mHeight) - int(rhs.mHeight);
-}
-
-void LayerCache::deleteLayer(Layer* layer) {
- if (layer) {
- LAYER_LOGD("Destroying layer %dx%d, fbo %d", layer->getWidth(), layer->getHeight(),
- layer->getFbo());
- mSize -= layer->getWidth() * layer->getHeight() * 4;
- layer->state = Layer::State::DeletedFromCache;
- layer->decStrong(nullptr);
- }
-}
-
-void LayerCache::clear() {
- for (auto entry : mCache) {
- deleteLayer(entry.mLayer);
- }
- mCache.clear();
-}
-
-Layer* LayerCache::get(RenderState& renderState, const uint32_t width, const uint32_t height) {
- Layer* layer = nullptr;
-
- LayerEntry entry(width, height);
- auto iter = mCache.find(entry);
-
- if (iter != mCache.end()) {
- entry = *iter;
- mCache.erase(iter);
-
- layer = entry.mLayer;
- layer->state = Layer::State::RemovedFromCache;
- mSize -= layer->getWidth() * layer->getHeight() * 4;
-
- LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
- } else {
- LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
-
- layer = new Layer(Layer::Type::DisplayList, renderState, entry.mWidth, entry.mHeight);
- layer->setBlend(true);
- layer->generateTexture();
- layer->bindTexture();
- layer->setFilter(GL_NEAREST);
- layer->setWrap(GL_CLAMP_TO_EDGE, false);
-
-#if DEBUG_LAYERS
- dump();
-#endif
- }
-
- return layer;
-}
-
-void LayerCache::dump() {
- for (auto entry : mCache) {
- ALOGD(" Layer size %dx%d", entry.mWidth, entry.mHeight);
- }
-}
-
-bool LayerCache::put(Layer* layer) {
- if (!layer->isCacheable()) return false;
-
- const uint32_t size = layer->getWidth() * layer->getHeight() * 4;
- // Don't even try to cache a layer that's bigger than the cache
- if (size < mMaxSize) {
- // TODO: Use an LRU
- while (mSize + size > mMaxSize) {
- Layer* victim = mCache.begin()->mLayer;
- deleteLayer(victim);
- mCache.erase(mCache.begin());
-
- LAYER_LOGD(" Deleting layer %.2fx%.2f", victim->layer.getWidth(),
- victim->layer.getHeight());
- }
-
- layer->cancelDefer();
-
- LayerEntry entry(layer);
-
- mCache.insert(entry);
- mSize += size;
-
- layer->state = Layer::State::InCache;
- return true;
- }
-
- layer->state = Layer::State::FailedToCache;
- return false;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
deleted file mode 100644
index 6fe7b3aae859..000000000000
--- a/libs/hwui/LayerCache.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_LAYER_CACHE_H
-#define ANDROID_HWUI_LAYER_CACHE_H
-
-#include "Debug.h"
-#include "Layer.h"
-
-#include <set>
-
-namespace android {
-namespace uirenderer {
-
-class RenderState;
-
-///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-#if DEBUG_LAYERS
- #define LAYER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define LAYER_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Cache
-///////////////////////////////////////////////////////////////////////////////
-
-class LayerCache {
-public:
- LayerCache();
- ~LayerCache();
-
- /**
- * Returns a layer large enough for the specified dimensions. If no suitable
- * layer can be found, a new one is created and returned. If creating a new
- * layer fails, NULL is returned.
- *
- * When a layer is obtained from the cache, it is removed and the total
- * size of the cache goes down.
- *
- * @param width The desired width of the layer
- * @param height The desired height of the layer
- */
- Layer* get(RenderState& renderState, const uint32_t width, const uint32_t height);
-
- /**
- * Adds the layer to the cache. The layer will not be added if there is
- * not enough space available. Adding a layer can cause other layers to
- * be removed from the cache.
- *
- * @param layer The layer to add to the cache
- *
- * @return True if the layer was added, false otherwise.
- */
- bool put(Layer* layer);
- /**
- * Clears the cache. This causes all layers to be deleted.
- */
- void clear();
-
- /**
- * Sets the maximum size of the cache in bytes.
- */
- void setMaxSize(uint32_t maxSize);
- /**
- * Returns the maximum size of the cache in bytes.
- */
- uint32_t getMaxSize();
- /**
- * Returns the current size of the cache in bytes.
- */
- uint32_t getSize();
-
- size_t getCount();
-
- /**
- * Prints out the content of the cache.
- */
- void dump();
-
-private:
- struct LayerEntry {
- LayerEntry():
- mLayer(nullptr), mWidth(0), mHeight(0) {
- }
-
- LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(nullptr) {
- mWidth = Layer::computeIdealWidth(layerWidth);
- mHeight = Layer::computeIdealHeight(layerHeight);
- }
-
- LayerEntry(Layer* layer):
- mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) {
- }
-
- static int compare(const LayerEntry& lhs, const LayerEntry& rhs);
-
- bool operator==(const LayerEntry& other) const {
- return compare(*this, other) == 0;
- }
-
- bool operator!=(const LayerEntry& other) const {
- return compare(*this, other) != 0;
- }
-
- bool operator<(const LayerEntry& other) const {
- return LayerEntry::compare(*this, other) < 0;
- }
-
- Layer* mLayer;
- uint32_t mWidth;
- uint32_t mHeight;
- }; // struct LayerEntry
-
- void deleteLayer(Layer* layer);
-
- std::multiset<LayerEntry> mCache;
-
- uint32_t mSize;
- uint32_t mMaxSize;
-}; // class LayerCache
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_LAYER_CACHE_H
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 137316f57725..8d50dc2ccd94 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include "LayerCache.h"
#include "LayerRenderer.h"
#include "Matrix.h"
#include "Properties.h"
@@ -27,257 +26,15 @@
#include <private/hwui/DrawGlInfo.h>
-
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Rendering
-///////////////////////////////////////////////////////////////////////////////
-
-LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer)
- : OpenGLRenderer(renderState)
- , mLayer(layer) {
-}
-
-LayerRenderer::~LayerRenderer() {
-}
-
-void LayerRenderer::prepareDirty(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque) {
- LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
-
- mRenderState.bindFramebuffer(mLayer->getFbo());
-
- const float width = mLayer->layer.getWidth();
- const float height = mLayer->layer.getHeight();
-
- Rect dirty(left, top, right, bottom);
- if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 &&
- dirty.right >= width && dirty.bottom >= height)) {
- mLayer->region.clear();
- dirty.set(0.0f, 0.0f, width, height);
- } else {
- dirty.doIntersect(0.0f, 0.0f, width, height);
- android::Rect r(dirty.left, dirty.top, dirty.right, dirty.bottom);
- mLayer->region.subtractSelf(r);
- }
- mLayer->clipRect.set(dirty);
-
- OpenGLRenderer::prepareDirty(viewportWidth, viewportHeight,
- dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
-}
-
-void LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
- if (mLayer->isDirty()) {
- mRenderState.scissor().setEnabled(false);
- glClear(GL_COLOR_BUFFER_BIT);
-
- mRenderState.scissor().reset();
- mLayer->setDirty(false);
- } else {
- OpenGLRenderer::clear(left, top, right, bottom, opaque);
- }
-}
-
-bool LayerRenderer::finish() {
- bool retval = OpenGLRenderer::finish();
-
- generateMesh();
-
- LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->getFbo());
-
- // No need to unbind our FBO, this will be taken care of by the caller
- // who will invoke OpenGLRenderer::resume()
- return retval;
-}
-
-GLuint LayerRenderer::getTargetFbo() const {
- return mLayer->getFbo();
-}
-
-bool LayerRenderer::suppressErrorChecks() const {
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Layer support
-///////////////////////////////////////////////////////////////////////////////
-
-bool LayerRenderer::hasLayer() const {
- return true;
-}
-
-void LayerRenderer::ensureStencilBuffer() {
- attachStencilBufferToLayer(mLayer);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Dirty region tracking
-///////////////////////////////////////////////////////////////////////////////
-
-Region* LayerRenderer::getRegion() const {
- if (mState.currentFlags() & Snapshot::kFlagFboTarget) {
- return OpenGLRenderer::getRegion();
- }
- return &mLayer->region;
-}
-
-// TODO: This implementation uses a very simple approach to fixing T-junctions which keeps the
-// results as rectangles, and is thus not necessarily efficient in the geometry
-// produced. Eventually, it may be better to develop triangle-based mechanism.
-void LayerRenderer::generateMesh() {
- if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
- if (mLayer->mesh) {
- delete[] mLayer->mesh;
- mLayer->mesh = nullptr;
- mLayer->meshElementCount = 0;
- }
-
- mLayer->setRegionAsRect();
- return;
- }
-
- // avoid T-junctions as they cause artifacts in between the resultant
- // geometry when complex transforms occur.
- // TODO: generate the safeRegion only if necessary based on drawing transform (see
- // OpenGLRenderer::composeLayerRegion())
- Region safeRegion = Region::createTJunctionFreeRegion(mLayer->region);
-
- size_t count;
- const android::Rect* rects = safeRegion.getArray(&count);
-
- GLsizei elementCount = count * 6;
-
- if (mLayer->mesh && mLayer->meshElementCount < elementCount) {
- delete[] mLayer->mesh;
- mLayer->mesh = nullptr;
- }
-
- if (!mLayer->mesh) {
- mLayer->mesh = new TextureVertex[count * 4];
- }
- mLayer->meshElementCount = elementCount;
-
- const float texX = 1.0f / float(mLayer->getWidth());
- const float texY = 1.0f / float(mLayer->getHeight());
- const float height = mLayer->layer.getHeight();
-
- TextureVertex* mesh = mLayer->mesh;
-
- for (size_t i = 0; i < count; i++) {
- const android::Rect* r = &rects[i];
-
- const float u1 = r->left * texX;
- const float v1 = (height - r->top) * texY;
- const float u2 = r->right * texX;
- const float v2 = (height - r->bottom) * texY;
-
- TextureVertex::set(mesh++, r->left, r->top, u1, v1);
- TextureVertex::set(mesh++, r->right, r->top, u2, v1);
- TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
- TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Layers management
-///////////////////////////////////////////////////////////////////////////////
-
-Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) {
- ATRACE_FORMAT("Allocate %ux%u HW Layer", width, height);
- LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
-
- Caches& caches = Caches::getInstance();
- GLuint fbo = renderState.createFramebuffer();
- if (!fbo) {
- ALOGW("Could not obtain an FBO");
- return nullptr;
- }
-
- caches.textureState().activateTexture(0);
- Layer* layer = caches.layerCache.get(renderState, width, height);
- if (!layer) {
- ALOGW("Could not obtain a layer");
- return nullptr;
- }
-
- // We first obtain a layer before comparing against the max texture size
- // because layers are not allocated at the exact desired size. They are
- // always created slightly larger to improve recycling
- const uint32_t maxTextureSize = caches.maxTextureSize;
- if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) {
- ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
- width, height, maxTextureSize, maxTextureSize);
-
- // Creating a new layer always increment its refcount by 1, this allows
- // us to destroy the layer object if one was created for us
- layer->decStrong(nullptr);
-
- return nullptr;
- }
-
- layer->setFbo(fbo);
- layer->layer.set(0.0f, 0.0f, width, height);
- layer->texCoords.set(0.0f, height / float(layer->getHeight()),
- width / float(layer->getWidth()), 0.0f);
- layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
- layer->setColorFilter(nullptr);
- layer->setDirty(true);
- layer->region.clear();
-
- GLuint previousFbo = renderState.getFramebuffer();
-
- renderState.bindFramebuffer(layer->getFbo());
- layer->bindTexture();
-
- // Initialize the texture if needed
- if (layer->isEmpty()) {
- layer->setEmpty(false);
- layer->allocateTexture();
-
- // This should only happen if we run out of memory
- if (CC_UNLIKELY(GLUtils::dumpGLErrors())) {
- LOG_ALWAYS_FATAL("Could not allocate texture for layer (fbo=%d %dx%d)",
- fbo, width, height);
- renderState.bindFramebuffer(previousFbo);
- layer->decStrong(nullptr);
- return nullptr;
- }
- }
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- layer->getTextureId(), 0);
-
- renderState.bindFramebuffer(previousFbo);
-
- return layer;
-}
-
-bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
- if (layer) {
- LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
-
- if (layer->resize(width, height)) {
- layer->layer.set(0.0f, 0.0f, width, height);
- layer->texCoords.set(0.0f, height / float(layer->getHeight()),
- width / float(layer->getWidth()), 0.0f);
- } else {
- return false;
- }
- }
-
- return true;
-}
-
Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
LAYER_RENDERER_LOGD("Creating new texture layer");
- Layer* layer = new Layer(Layer::Type::Texture, renderState, 0, 0);
- layer->setCacheable(false);
+ Layer* layer = new Layer(renderState, 0, 0);
layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
- layer->region.clear();
layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer()
Caches::getInstance().textureState().activateTexture(0);
@@ -287,178 +44,19 @@ Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
}
void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
- bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform) {
- if (layer) {
- layer->setBlend(!isOpaque);
- layer->setForceFilter(forceFilter);
- layer->setSize(width, height);
- layer->layer.set(0.0f, 0.0f, width, height);
- layer->region.set(width, height);
- layer->regionRect.set(0.0f, 0.0f, width, height);
- layer->getTexTransform().load(textureTransform);
-
- if (renderTarget != layer->getRenderTarget()) {
- layer->setRenderTarget(renderTarget);
- layer->bindTexture();
- layer->setFilter(GL_NEAREST, false, true);
- layer->setWrap(GL_CLAMP_TO_EDGE, false, true);
- }
- }
-}
-
-void LayerRenderer::destroyLayer(Layer* layer) {
- if (layer) {
- ATRACE_FORMAT("Destroy %ux%u HW Layer", layer->getWidth(), layer->getHeight());
- LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
- layer->getWidth(), layer->getHeight(), layer->getFbo());
-
- if (!Caches::getInstance().layerCache.put(layer)) {
- LAYER_RENDERER_LOGD(" Destroyed!");
- layer->decStrong(nullptr);
- } else {
- LAYER_RENDERER_LOGD(" Cached!");
-#if DEBUG_LAYER_RENDERER
- Caches::getInstance().layerCache.dump();
-#endif
- layer->removeFbo();
- layer->region.clear();
- }
- }
-}
-
-void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
-#ifdef GL_EXT_discard_framebuffer
- if (!layer) return;
-
- GLuint fbo = layer->getFbo();
- if (fbo) {
- // If possible, discard any enqueud operations on deferred
- // rendering architectures
- if (Caches::getInstance().extensions().hasDiscardFramebuffer()) {
- GLuint previousFbo = renderState.getFramebuffer();
- if (fbo != previousFbo) {
- renderState.bindFramebuffer(fbo);
- }
-
- const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 };
- glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
-
- if (fbo != previousFbo) {
- renderState.bindFramebuffer(previousFbo);
- }
- }
- }
-#endif
-}
-
-bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
- Caches& caches = Caches::getInstance();
- if (layer && layer->isRenderable()
- && bitmap->width() <= caches.maxTextureSize
- && bitmap->height() <= caches.maxTextureSize) {
-
- GLuint fbo = renderState.createFramebuffer();
- if (!fbo) {
- ALOGW("Could not obtain an FBO");
- return false;
- }
-
- SkAutoLockPixels alp(*bitmap);
-
- GLuint texture;
- GLuint previousFbo;
- GLsizei previousViewportWidth;
- GLsizei previousViewportHeight;
-
- GLenum format;
- GLenum type;
-
- bool status = false;
-
- switch (bitmap->colorType()) {
- case kAlpha_8_SkColorType:
- format = GL_ALPHA;
- type = GL_UNSIGNED_BYTE;
- break;
- case kRGB_565_SkColorType:
- format = GL_RGB;
- type = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case kARGB_4444_SkColorType:
- format = GL_RGBA;
- type = GL_UNSIGNED_SHORT_4_4_4_4;
- break;
- case kN32_SkColorType:
- default:
- format = GL_RGBA;
- type = GL_UNSIGNED_BYTE;
- break;
- }
-
- float alpha = layer->getAlpha();
- SkXfermode::Mode mode = layer->getMode();
- GLuint previousLayerFbo = layer->getFbo();
-
- layer->setAlpha(255, SkXfermode::kSrc_Mode);
- layer->setFbo(fbo);
-
- previousFbo = renderState.getFramebuffer();
- renderState.getViewport(&previousViewportWidth, &previousViewportHeight);
- renderState.bindFramebuffer(fbo);
-
- glGenTextures(1, &texture);
-
- caches.textureState().activateTexture(0);
- caches.textureState().bindTexture(texture);
-
- glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D(GL_TEXTURE_2D, 0, format, bitmap->width(), bitmap->height(),
- 0, format, type, nullptr);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, texture, 0);
-
- {
- LayerRenderer renderer(renderState, layer);
- renderer.OpenGLRenderer::prepareDirty(bitmap->width(), bitmap->height(),
- 0.0f, 0.0f, bitmap->width(), bitmap->height(), !layer->isBlend());
-
- renderState.scissor().setEnabled(false);
- renderer.translate(0.0f, bitmap->height());
- renderer.scale(1.0f, -1.0f);
-
- {
- Rect bounds;
- bounds.set(0.0f, 0.0f, bitmap->width(), bitmap->height());
- renderer.drawTextureLayer(layer, bounds);
-
- glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
- type, bitmap->getPixels());
-
- }
-
- status = true;
- }
-
- renderState.bindFramebuffer(previousFbo);
- layer->setAlpha(alpha, mode);
- layer->setFbo(previousLayerFbo);
- caches.textureState().deleteTexture(texture);
- renderState.deleteFramebuffer(fbo);
- renderState.setViewport(previousViewportWidth, previousViewportHeight);
-
- GL_CHECKPOINT(MODERATE);
+ bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform) {
+ layer->setBlend(!isOpaque);
+ layer->setForceFilter(forceFilter);
+ layer->setSize(width, height);
+ layer->layer.set(0.0f, 0.0f, width, height);
+ layer->getTexTransform().load(textureTransform);
- return status;
+ if (renderTarget != layer->getRenderTarget()) {
+ layer->setRenderTarget(renderTarget);
+ layer->bindTexture();
+ layer->setFilter(GL_NEAREST, false, true);
+ layer->setWrap(GL_CLAMP_TO_EDGE, false, true);
}
- return false;
}
}; // namespace uirenderer
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 38c3705cfa25..7460e3e47fa2 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_LAYER_RENDERER_H
-#define ANDROID_HWUI_LAYER_RENDERER_H
+#pragma once
#include <cutils/compiler.h>
-#include "OpenGLRenderer.h"
#include "Layer.h"
#include <SkBitmap.h>
@@ -44,41 +42,12 @@ class RenderState;
// Renderer
///////////////////////////////////////////////////////////////////////////////
-class LayerRenderer: public OpenGLRenderer {
+class LayerRenderer {
public:
- LayerRenderer(RenderState& renderState, Layer* layer);
- virtual ~LayerRenderer();
-
- virtual void onViewportInitialized() override { /* do nothing */ }
- virtual void prepareDirty(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque) override;
- virtual void clear(float left, float top, float right, float bottom, bool opaque) override;
- virtual bool finish() override;
-
static Layer* createTextureLayer(RenderState& renderState);
- static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height);
- static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform);
- static void destroyLayer(Layer* layer);
- static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
-
- static void flushLayer(RenderState& renderState, Layer* layer);
-
-protected:
- virtual void ensureStencilBuffer() override;
- virtual bool hasLayer() const override;
- virtual Region* getRegion() const override;
- virtual GLuint getTargetFbo() const override;
- virtual bool suppressErrorChecks() const override;
-
-private:
- void generateMesh();
-
- Layer* mLayer;
}; // class LayerRenderer
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_LAYER_RENDERER_H
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index ec9ffdeebb4c..f4b7ee0fe430 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -16,6 +16,7 @@
#include "OpDumper.h"
+#include "ClipArea.h"
#include "RecordedOp.h"
namespace android {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
deleted file mode 100644
index 9d821f38fab6..000000000000
--- a/libs/hwui/OpenGLRenderer.cpp
+++ /dev/null
@@ -1,2451 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <GpuMemoryTracker.h>
-#include "OpenGLRenderer.h"
-
-#include "DeferredDisplayList.h"
-#include "GammaFontRenderer.h"
-#include "Glop.h"
-#include "GlopBuilder.h"
-#include "Patch.h"
-#include "PathTessellator.h"
-#include "Properties.h"
-#include "RenderNode.h"
-#include "renderstate/MeshState.h"
-#include "renderstate/RenderState.h"
-#include "ShadowTessellator.h"
-#include "SkiaShader.h"
-#include "Vector.h"
-#include "VertexBuffer.h"
-#include "hwui/Canvas.h"
-#include "utils/GLUtils.h"
-#include "utils/PaintUtils.h"
-#include "utils/TraceUtils.h"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <SkColor.h>
-#include <SkPaintDefaults.h>
-#include <SkPathOps.h>
-#include <SkShader.h>
-#include <SkTypeface.h>
-
-#include <utils/Log.h>
-#include <utils/StopWatch.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include <ui/Rect.h>
-
-#if DEBUG_DETAILED_EVENTS
- #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
-#else
- #define EVENT_LOGD(...)
-#endif
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
- : mState(*this)
- , mCaches(Caches::getInstance())
- , mRenderState(renderState)
- , mFrameStarted(false)
- , mScissorOptimizationDisabled(false)
- , mDirty(false)
- , mLightCenter((Vector3){FLT_MIN, FLT_MIN, FLT_MIN})
- , mLightRadius(FLT_MIN)
- , mAmbientShadowAlpha(0)
- , mSpotShadowAlpha(0) {
-}
-
-OpenGLRenderer::~OpenGLRenderer() {
- // The context has already been destroyed at this point, do not call
- // GL APIs. All GL state should be kept in Caches.h
-}
-
-void OpenGLRenderer::initProperties() {
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
- mScissorOptimizationDisabled = !strcasecmp(property, "true");
- INIT_LOGD(" Scissor optimization %s",
- mScissorOptimizationDisabled ? "disabled" : "enabled");
- } else {
- INIT_LOGD(" Scissor optimization enabled");
- }
-}
-
-void OpenGLRenderer::initLight(float lightRadius, uint8_t ambientShadowAlpha,
- uint8_t spotShadowAlpha) {
- mLightRadius = lightRadius;
- mAmbientShadowAlpha = ambientShadowAlpha;
- mSpotShadowAlpha = spotShadowAlpha;
-}
-
-void OpenGLRenderer::setLightCenter(const Vector3& lightCenter) {
- mLightCenter = lightCenter;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Setup
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::onViewportInitialized() {
- glDisable(GL_DITHER);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-}
-
-void OpenGLRenderer::setupFrameState(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque) {
- mCaches.clearGarbage();
- mState.initializeSaveStack(viewportWidth, viewportHeight,
- left, top, right, bottom, mLightCenter);
- mOpaque = opaque;
- mTilingClip.set(left, top, right, bottom);
-}
-
-void OpenGLRenderer::startFrame() {
- if (mFrameStarted) return;
- mFrameStarted = true;
-
- mState.setDirtyClip(true);
-
- discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
-
- mRenderState.setViewport(mState.getWidth(), mState.getHeight());
-
- debugOverdraw(true, true);
-
- clear(mTilingClip.left, mTilingClip.top,
- mTilingClip.right, mTilingClip.bottom, mOpaque);
-}
-
-void OpenGLRenderer::prepareDirty(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque) {
-
- setupFrameState(viewportWidth, viewportHeight, left, top, right, bottom, opaque);
-
- // Layer renderers will start the frame immediately
- // The framebuffer renderer will first defer the display list
- // for each layer and wait until the first drawing command
- // to start the frame
- if (currentSnapshot()->fbo == 0) {
- mRenderState.blend().syncEnabled();
- updateLayers();
- } else {
- startFrame();
- }
-}
-
-void OpenGLRenderer::discardFramebuffer(float left, float top, float right, float bottom) {
- // If we know that we are going to redraw the entire framebuffer,
- // perform a discard to let the driver know we don't need to preserve
- // the back buffer for this frame.
- if (mCaches.extensions().hasDiscardFramebuffer() &&
- left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) {
- const bool isFbo = getTargetFbo() == 0;
- const GLenum attachments[] = {
- isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0,
- isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT };
- glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
- }
-}
-
-void OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
- if (!opaque) {
- mRenderState.scissor().setEnabled(true);
- mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
- glClear(GL_COLOR_BUFFER_BIT);
- mDirty = true;
- return;
- }
-
- mRenderState.scissor().reset();
-}
-
-bool OpenGLRenderer::finish() {
- renderOverdraw();
- mTempPaths.clear();
-
- // When finish() is invoked on FBO 0 we've reached the end
- // of the current frame
- if (getTargetFbo() == 0) {
- mCaches.pathCache.trim();
- mCaches.tessellationCache.trim();
- }
-
- if (!suppressErrorChecks()) {
- GL_CHECKPOINT(MODERATE);
-
-#if DEBUG_MEMORY_USAGE
- mCaches.dumpMemoryUsage();
- GPUMemoryTracker::dump();
-#else
- if (Properties::debugLevel & kDebugMemory) {
- mCaches.dumpMemoryUsage();
- }
-#endif
- }
-
- mFrameStarted = false;
-
- return reportAndClearDirty();
-}
-
-void OpenGLRenderer::resumeAfterLayer() {
- mRenderState.setViewport(getViewportWidth(), getViewportHeight());
- mRenderState.bindFramebuffer(currentSnapshot()->fbo);
- debugOverdraw(true, false);
-
- mRenderState.scissor().reset();
- dirtyClip();
-}
-
-void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
- if (mState.currentlyIgnored()) return;
-
- Rect clip(mState.currentRenderTargetClip());
- clip.snapToPixelBoundaries();
-
- // Since we don't know what the functor will draw, let's dirty
- // the entire clip region
- if (hasLayer()) {
- dirtyLayerUnchecked(clip, getRegion());
- }
-
- DrawGlInfo info;
- info.clipLeft = clip.left;
- info.clipTop = clip.top;
- info.clipRight = clip.right;
- info.clipBottom = clip.bottom;
- info.isLayer = hasLayer();
- info.width = getViewportWidth();
- info.height = getViewportHeight();
- currentTransform()->copyTo(&info.transform[0]);
-
- bool prevDirtyClip = mState.getDirtyClip();
- // setup GL state for functor
- if (mState.getDirtyClip()) {
- setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
- }
- if (mRenderState.scissor().setEnabled(true) || prevDirtyClip) {
- setScissorFromClip();
- }
-
- mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
- // Scissor may have been modified, reset dirty clip
- dirtyClip();
-
- mDirty = true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Debug
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::eventMarkDEBUG(const char* fmt, ...) const {
-#if DEBUG_DETAILED_EVENTS
- const int BUFFER_SIZE = 256;
- va_list ap;
- char buf[BUFFER_SIZE];
-
- va_start(ap, fmt);
- vsnprintf(buf, BUFFER_SIZE, fmt, ap);
- va_end(ap);
-
- eventMark(buf);
-#endif
-}
-
-
-void OpenGLRenderer::eventMark(const char* name) const {
- mCaches.eventMark(0, name);
-}
-
-void OpenGLRenderer::startMark(const char* name) const {
- mCaches.startMark(0, name);
-}
-
-void OpenGLRenderer::endMark() const {
- mCaches.endMark();
-}
-
-void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
- mRenderState.debugOverdraw(enable, clear);
-}
-
-void OpenGLRenderer::renderOverdraw() {
- if (Properties::debugOverdraw && getTargetFbo() == 0) {
- const Rect* clip = &mTilingClip;
-
- mRenderState.scissor().setEnabled(true);
- mRenderState.scissor().set(clip->left,
- mState.firstSnapshot()->getViewportHeight() - clip->bottom,
- clip->right - clip->left,
- clip->bottom - clip->top);
-
- // 1x overdraw
- mRenderState.stencil().enableDebugTest(2);
- drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
-
- // 2x overdraw
- mRenderState.stencil().enableDebugTest(3);
- drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
-
- // 3x overdraw
- mRenderState.stencil().enableDebugTest(4);
- drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
-
- // 4x overdraw and higher
- mRenderState.stencil().enableDebugTest(4, true);
- drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
-
- mRenderState.stencil().disable();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Layers
-///////////////////////////////////////////////////////////////////////////////
-
-bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
- if (layer->deferredUpdateScheduled && layer->renderer
- && layer->renderNode.get() && layer->renderNode->isRenderable()) {
-
- if (inFrame) {
- debugOverdraw(false, false);
- }
-
- if (CC_UNLIKELY(inFrame || Properties::drawDeferDisabled)) {
- layer->render(*this);
- } else {
- layer->defer(*this);
- }
-
- if (inFrame) {
- resumeAfterLayer();
- }
-
- layer->debugDrawUpdate = Properties::debugLayersUpdates;
- layer->hasDrawnSinceUpdate = false;
-
- return true;
- }
-
- return false;
-}
-
-void OpenGLRenderer::updateLayers() {
- // If draw deferring is enabled this method will simply defer
- // the display list of each individual layer. The layers remain
- // in the layer updates list which will be cleared by flushLayers().
- int count = mLayerUpdates.size();
- if (count > 0) {
- if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
- startMark("Layer Updates");
- } else {
- startMark("Defer Layer Updates");
- }
-
- // Note: it is very important to update the layers in order
- for (int i = 0; i < count; i++) {
- Layer* layer = mLayerUpdates[i].get();
- updateLayer(layer, false);
- }
-
- if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
- mLayerUpdates.clear();
- mRenderState.bindFramebuffer(getTargetFbo());
- }
- endMark();
- }
-}
-
-void OpenGLRenderer::flushLayers() {
- int count = mLayerUpdates.size();
- if (count > 0) {
- startMark("Apply Layer Updates");
-
- // Note: it is very important to update the layers in order
- for (int i = 0; i < count; i++) {
- mLayerUpdates[i]->flush();
- }
-
- mLayerUpdates.clear();
- mRenderState.bindFramebuffer(getTargetFbo());
-
- endMark();
- }
-}
-
-void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
- if (layer) {
- // Make sure we don't introduce duplicates.
- // SortedVector would do this automatically but we need to respect
- // the insertion order. The linear search is not an issue since
- // this list is usually very short (typically one item, at most a few)
- for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
- if (mLayerUpdates[i] == layer) {
- return;
- }
- }
- mLayerUpdates.push_back(layer);
- }
-}
-
-void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
- if (layer) {
- for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
- if (mLayerUpdates[i] == layer) {
- mLayerUpdates.erase(mLayerUpdates.begin() + i);
- break;
- }
- }
- }
-}
-
-void OpenGLRenderer::flushLayerUpdates() {
- ATRACE_NAME("Update HW Layers");
- mRenderState.blend().syncEnabled();
- updateLayers();
- flushLayers();
- // Wait for all the layer updates to be executed
- glFinish();
-}
-
-void OpenGLRenderer::markLayersAsBuildLayers() {
- for (size_t i = 0; i < mLayerUpdates.size(); i++) {
- mLayerUpdates[i]->wasBuildLayered = true;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State management
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
- bool restoreViewport = removed.flags & Snapshot::kFlagIsFboLayer;
- bool restoreClip = removed.flags & Snapshot::kFlagClipSet;
- bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
-
- if (restoreViewport) {
- mRenderState.setViewport(getViewportWidth(), getViewportHeight());
- }
-
- if (restoreClip) {
- dirtyClip();
- }
-
- if (restoreLayer) {
- endMark(); // Savelayer
- ATRACE_END(); // SaveLayer
- startMark("ComposeLayer");
- composeLayer(removed, restored);
- endMark();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Layers
-///////////////////////////////////////////////////////////////////////////////
-
-int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags, const SkPath* convexMask) {
- // force matrix/clip isolation for layer
- flags |= SaveFlags::MatrixClip;
-
- const int count = mState.saveSnapshot(flags);
-
- if (!mState.currentlyIgnored()) {
- createLayer(left, top, right, bottom, paint, flags, convexMask);
- }
-
- return count;
-}
-
-void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
- const Rect untransformedBounds(bounds);
-
- currentTransform()->mapRect(bounds);
-
- // Layers only make sense if they are in the framebuffer's bounds
- bounds.doIntersect(mState.currentRenderTargetClip());
- if (!bounds.isEmpty()) {
- // We cannot work with sub-pixels in this case
- bounds.snapToPixelBoundaries();
-
- // When the layer is not an FBO, we may use glCopyTexImage so we
- // need to make sure the layer does not extend outside the bounds
- // of the framebuffer
- const Snapshot& previous = *(currentSnapshot()->previous);
- Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
-
- bounds.doIntersect(previousViewport);
- if (!bounds.isEmpty() && fboLayer) {
- clip.set(bounds);
- mat4 inverse;
- inverse.loadInverse(*currentTransform());
- inverse.mapRect(clip);
- clip.snapToPixelBoundaries();
- clip.doIntersect(untransformedBounds);
- if (!clip.isEmpty()) {
- clip.translate(-untransformedBounds.left, -untransformedBounds.top);
- bounds.set(untransformedBounds);
- }
- }
- }
-}
-
-void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
- bool fboLayer, int alpha) {
- if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
- bounds.getHeight() > mCaches.maxTextureSize ||
- (fboLayer && clip.isEmpty())) {
- writableSnapshot()->empty = fboLayer;
- } else {
- writableSnapshot()->invisible = writableSnapshot()->invisible || (alpha <= 0 && fboLayer);
- }
-}
-
-int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags) {
- const int count = mState.saveSnapshot(flags);
-
- if (!mState.currentlyIgnored() && (flags & SaveFlags::ClipToLayer)) {
- // initialize the snapshot as though it almost represents an FBO layer so deferred draw
- // operations will be able to store and restore the current clip and transform info, and
- // quick rejection will be correct (for display lists)
-
- Rect bounds(left, top, right, bottom);
- Rect clip;
- calculateLayerBoundsAndClip(bounds, clip, true);
- updateSnapshotIgnoreForLayer(bounds, clip, true, PaintUtils::getAlphaDirect(paint));
-
- if (!mState.currentlyIgnored()) {
- writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
- writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
- writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
- writableSnapshot()->roundRectClipState = nullptr;
- }
- }
-
- return count;
-}
-
-/**
- * Layers are viewed by Skia are slightly different than layers in image editing
- * programs (for instance.) When a layer is created, previously created layers
- * and the frame buffer still receive every drawing command. For instance, if a
- * layer is created and a shape intersecting the bounds of the layers and the
- * framebuffer is draw, the shape will be drawn on both (unless the layer was
- * created with the SaveFlags::ClipToLayer flag.)
- *
- * A way to implement layers is to create an FBO for each layer, backed by an RGBA
- * texture. Unfortunately, this is inefficient as it requires every primitive to
- * be drawn n + 1 times, where n is the number of active layers. In practice this
- * means, for every primitive:
- * - Switch active frame buffer
- * - Change viewport, clip and projection matrix
- * - Issue the drawing
- *
- * Switching rendering target n + 1 times per drawn primitive is extremely costly.
- * To avoid this, layers are implemented in a different way here, at least in the
- * general case. FBOs are used, as an optimization, when the "clip to layer" flag
- * is set. When this flag is set we can redirect all drawing operations into a
- * single FBO.
- *
- * This implementation relies on the frame buffer being at least RGBA 8888. When
- * a layer is created, only a texture is created, not an FBO. The content of the
- * frame buffer contained within the layer's bounds is copied into this texture
- * using glCopyTexImage2D(). The layer's region is then cleared(1) in the frame
- * buffer and drawing continues as normal. This technique therefore treats the
- * frame buffer as a scratch buffer for the layers.
- *
- * To compose the layers back onto the frame buffer, each layer texture
- * (containing the original frame buffer data) is drawn as a simple quad over
- * the frame buffer. The trick is that the quad is set as the composition
- * destination in the blending equation, and the frame buffer becomes the source
- * of the composition.
- *
- * Drawing layers with an alpha value requires an extra step before composition.
- * An empty quad is drawn over the layer's region in the frame buffer. This quad
- * is drawn with the rgba color (0,0,0,alpha). The alpha value offered by the
- * quad is used to multiply the colors in the frame buffer. This is achieved by
- * changing the GL blend functions for the GL_FUNC_ADD blend equation to
- * GL_ZERO, GL_SRC_ALPHA.
- *
- * Because glCopyTexImage2D() can be slow, an alternative implementation might
- * be use to draw a single clipped layer. The implementation described above
- * is correct in every case.
- *
- * (1) The frame buffer is actually not cleared right away. To allow the GPU
- * to potentially optimize series of calls to glCopyTexImage2D, the frame
- * buffer is left untouched until the first drawing operation. Only when
- * something actually gets drawn are the layers regions cleared.
- */
-bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags, const SkPath* convexMask) {
- LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
- LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
-
- const bool fboLayer = flags & SaveFlags::ClipToLayer;
-
- // Window coordinates of the layer
- Rect clip;
- Rect bounds(left, top, right, bottom);
- calculateLayerBoundsAndClip(bounds, clip, fboLayer);
- updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, PaintUtils::getAlphaDirect(paint));
-
- // Bail out if we won't draw in this snapshot
- if (mState.currentlyIgnored()) {
- return false;
- }
-
- mCaches.textureState().activateTexture(0);
- Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
- if (!layer) {
- return false;
- }
-
- layer->setPaint(paint);
- layer->layer.set(bounds);
- layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
- bounds.getWidth() / float(layer->getWidth()), 0.0f);
-
- layer->setBlend(true);
- layer->setDirty(false);
- layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
-
- // Save the layer in the snapshot
- writableSnapshot()->flags |= Snapshot::kFlagIsLayer;
- writableSnapshot()->layer = layer;
-
- ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u",
- fboLayer ? "" : "unclipped ",
- layer->getWidth(), layer->getHeight());
- startMark("SaveLayer");
- if (fboLayer) {
- return createFboLayer(layer, bounds, clip);
- } else {
- // Copy the framebuffer into the layer
- layer->bindTexture();
- if (!bounds.isEmpty()) {
- if (layer->isEmpty()) {
- // Workaround for some GL drivers. When reading pixels lying outside
- // of the window we should get undefined values for those pixels.
- // Unfortunately some drivers will turn the entire target texture black
- // when reading outside of the window.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->getWidth(), layer->getHeight(),
- 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- layer->setEmpty(false);
- }
-
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
- bounds.left, getViewportHeight() - bounds.bottom,
- bounds.getWidth(), bounds.getHeight());
-
- // Enqueue the buffer coordinates to clear the corresponding region later
- mLayers.push_back(Rect(bounds));
- }
- }
-
- return true;
-}
-
-bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) {
- layer->clipRect.set(clip);
- layer->setFbo(mRenderState.createFramebuffer());
-
- writableSnapshot()->region = &writableSnapshot()->layer->region;
- writableSnapshot()->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
- writableSnapshot()->fbo = layer->getFbo();
- writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
- writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom);
- writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight());
- writableSnapshot()->roundRectClipState = nullptr;
-
- debugOverdraw(false, false);
- // Bind texture to FBO
- mRenderState.bindFramebuffer(layer->getFbo());
- layer->bindTexture();
-
- // Initialize the texture if needed
- if (layer->isEmpty()) {
- layer->allocateTexture();
- layer->setEmpty(false);
- }
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- layer->getTextureId(), 0);
-
- // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
- mRenderState.scissor().setEnabled(true);
- mRenderState.scissor().set(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
- clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- dirtyClip();
-
- // Change the ortho projection
- mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
- return true;
-}
-
-/**
- * Read the documentation of createLayer() before doing anything in this method.
- */
-void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& restored) {
- if (!removed.layer) {
- ALOGE("Attempting to compose a layer that does not exist");
- return;
- }
-
- Layer* layer = removed.layer;
- const Rect& rect = layer->layer;
- const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer;
-
- bool clipRequired = false;
- mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
- &clipRequired, nullptr, false); // safely ignore return, should never be rejected
- mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
-
- if (fboLayer) {
- // Detach the texture from the FBO
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-
- layer->removeFbo(false);
-
- // Unbind current FBO and restore previous one
- mRenderState.bindFramebuffer(restored.fbo);
- debugOverdraw(true, false);
- }
-
- if (!fboLayer && layer->getAlpha() < 255) {
- SkPaint layerPaint;
- layerPaint.setAlpha(layer->getAlpha());
- layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
- layerPaint.setColorFilter(layer->getColorFilter());
-
- drawColorRect(rect.left, rect.top, rect.right, rect.bottom, &layerPaint, true);
- // Required below, composeLayerRect() will divide by 255
- layer->setAlpha(255);
- }
-
- mRenderState.meshState().unbindMeshBuffer();
-
- mCaches.textureState().activateTexture(0);
-
- // When the layer is stored in an FBO, we can save a bit of fillrate by
- // drawing only the dirty region
- if (fboLayer) {
- dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *restored.transform);
- composeLayerRegion(layer, rect);
- } else if (!rect.isEmpty()) {
- dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
-
- save(0);
- // the layer contains screen buffer content that shouldn't be alpha modulated
- // (and any necessary alpha modulation was handled drawing into the layer)
- writableSnapshot()->alpha = 1.0f;
- composeLayerRectSwapped(layer, rect);
- restore();
- }
-
- dirtyClip();
-
- // Failing to add the layer to the cache should happen only if the layer is too large
- layer->setConvexMask(nullptr);
- if (!mCaches.layerCache.put(layer)) {
- LAYER_LOGD("Deleting layer");
- layer->decStrong(nullptr);
- }
-}
-
-void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
- const bool tryToSnap = !layer->getForceFilter()
- && layer->getWidth() == (uint32_t) rect.getWidth()
- && layer->getHeight() == (uint32_t) rect.getHeight();
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
- .setFillTextureLayer(*layer, getLayerAlpha(layer))
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::composeLayerRectSwapped(Layer* layer, const Rect& rect) {
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUvQuad(nullptr, layer->texCoords)
- .setFillLayer(layer->getTexture(), layer->getColorFilter(),
- getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::Swap)
- .setTransform(*currentSnapshot(), TransformFlags::MeshIgnoresCanvasTransform)
- .setModelViewMapUnitToRect(rect)
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect) {
- if (layer->isTextureLayer()) {
- EVENT_LOGD("composeTextureLayerRect");
- drawTextureLayer(layer, rect);
- } else {
- EVENT_LOGD("composeHardwareLayerRect");
-
- const bool tryToSnap = layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
- && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUvQuad(nullptr, layer->texCoords)
- .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
- .build();
- renderGlop(glop);
- }
-}
-
-/**
- * Issues the command X, and if we're composing a save layer to the fbo or drawing a newly updated
- * hardware layer with overdraw debug on, draws again to the stencil only, so that these draw
- * operations are correctly counted twice for overdraw. NOTE: assumes composeLayerRegion only used
- * by saveLayer's restore
- */
-#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \
- DRAW_COMMAND; \
- if (CC_UNLIKELY(Properties::debugOverdraw && getTargetFbo() == 0 && (COND))) { \
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
- DRAW_COMMAND; \
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
- } \
- }
-
-#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
-
-// This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
-// use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
-class LayerShader : public SkShader {
-public:
- LayerShader(Layer* layer, const SkMatrix* localMatrix)
- : INHERITED(localMatrix)
- , mLayer(layer) {
- }
-
- virtual bool asACustomShader(void** data) const override {
- if (data) {
- *data = static_cast<void*>(mLayer);
- }
- return true;
- }
-
- virtual bool isOpaque() const override {
- return !mLayer->isBlend();
- }
-
-protected:
- virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
- LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
- }
-
- virtual void flatten(SkWriteBuffer&) const override {
- LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
- }
-
- virtual Factory getFactory() const override {
- LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
- return nullptr;
- }
-private:
- // Unowned.
- Layer* mLayer;
- typedef SkShader INHERITED;
-};
-
-void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
- if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
-
- if (layer->getConvexMask()) {
- save(SaveFlags::MatrixClip);
-
- // clip to the area of the layer the mask can be larger
- clipRect(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kIntersect_Op);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
-
- // create LayerShader to map SaveLayer content into subsequent draw
- SkMatrix shaderMatrix;
- shaderMatrix.setTranslate(rect.left, rect.bottom);
- shaderMatrix.preScale(1, -1);
- LayerShader layerShader(layer, &shaderMatrix);
- paint.setShader(&layerShader);
-
- // Since the drawing primitive is defined in local drawing space,
- // we don't need to modify the draw matrix
- const SkPath* maskPath = layer->getConvexMask();
- DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
-
- paint.setShader(nullptr);
- restore();
-
- return;
- }
-
- if (layer->region.isRect()) {
- layer->setRegionAsRect();
-
- DRAW_DOUBLE_STENCIL(composeLayerRect(layer, layer->regionRect));
-
- layer->region.clear();
- return;
- }
-
- EVENT_LOGD("composeLayerRegion");
- // standard Region based draw
- size_t count;
- const android::Rect* rects;
- Region safeRegion;
- if (CC_LIKELY(hasRectToRectTransform())) {
- rects = layer->region.getArray(&count);
- } else {
- safeRegion = Region::createTJunctionFreeRegion(layer->region);
- rects = safeRegion.getArray(&count);
- }
-
- const float texX = 1.0f / float(layer->getWidth());
- const float texY = 1.0f / float(layer->getHeight());
- const float height = rect.getHeight();
-
- TextureVertex quadVertices[count * 4];
- TextureVertex* mesh = &quadVertices[0];
- for (size_t i = 0; i < count; i++) {
- const android::Rect* r = &rects[i];
-
- const float u1 = r->left * texX;
- const float v1 = (height - r->top) * texY;
- const float u2 = r->right * texX;
- const float v2 = (height - r->bottom) * texY;
-
- // TODO: Reject quads outside of the clip
- TextureVertex::set(mesh++, r->left, r->top, u1, v1);
- TextureVertex::set(mesh++, r->right, r->top, u2, v1);
- TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
- TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
- }
- Rect modelRect = Rect(rect.getWidth(), rect.getHeight());
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
- .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect)
- .build();
- DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-
-#if DEBUG_LAYERS_AS_REGIONS
- drawRegionRectsDebug(layer->region);
-#endif
-
- layer->region.clear();
-}
-
-#if DEBUG_LAYERS_AS_REGIONS
-void OpenGLRenderer::drawRegionRectsDebug(const Region& region) {
- size_t count;
- const android::Rect* rects = region.getArray(&count);
-
- uint32_t colors[] = {
- 0x7fff0000, 0x7f00ff00,
- 0x7f0000ff, 0x7fff00ff,
- };
-
- int offset = 0;
- int32_t top = rects[0].top;
-
- for (size_t i = 0; i < count; i++) {
- if (top != rects[i].top) {
- offset ^= 0x2;
- top = rects[i].top;
- }
-
- SkPaint paint;
- paint.setColor(colors[offset + (i & 0x1)]);
- Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
- drawColorRect(r.left, r.top, r.right, r.bottom, paint);
- }
-}
-#endif
-
-void OpenGLRenderer::drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty) {
- Vector<float> rects;
-
- SkRegion::Iterator it(region);
- while (!it.done()) {
- const SkIRect& r = it.rect();
- rects.push(r.fLeft);
- rects.push(r.fTop);
- rects.push(r.fRight);
- rects.push(r.fBottom);
- it.next();
- }
-
- drawColorRects(rects.array(), rects.size(), &paint, true, dirty, false);
-}
-
-void OpenGLRenderer::dirtyLayer(const float left, const float top,
- const float right, const float bottom, const Matrix4& transform) {
- if (hasLayer()) {
- Rect bounds(left, top, right, bottom);
- transform.mapRect(bounds);
- dirtyLayerUnchecked(bounds, getRegion());
- }
-}
-
-void OpenGLRenderer::dirtyLayer(const float left, const float top,
- const float right, const float bottom) {
- if (hasLayer()) {
- Rect bounds(left, top, right, bottom);
- dirtyLayerUnchecked(bounds, getRegion());
- }
-}
-
-void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
- bounds.doIntersect(mState.currentRenderTargetClip());
- if (!bounds.isEmpty()) {
- bounds.snapToPixelBoundaries();
- android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
- if (!dirty.isEmpty()) {
- region->orSelf(dirty);
- }
- }
-}
-
-void OpenGLRenderer::clearLayerRegions() {
- const size_t quadCount = mLayers.size();
- if (quadCount == 0) return;
-
- if (!mState.currentlyIgnored()) {
- EVENT_LOGD("clearLayerRegions");
- // Doing several glScissor/glClear here can negatively impact
- // GPUs with a tiler architecture, instead we draw quads with
- // the Clear blending mode
-
- // The list contains bounds that have already been clipped
- // against their initial clip rect, and the current clip
- // is likely different so we need to disable clipping here
- bool scissorChanged = mRenderState.scissor().setEnabled(false);
-
- Vertex mesh[quadCount * 4];
- Vertex* vertex = mesh;
-
- for (uint32_t i = 0; i < quadCount; i++) {
- const Rect& bounds = mLayers[i];
-
- Vertex::set(vertex++, bounds.left, bounds.top);
- Vertex::set(vertex++, bounds.right, bounds.top);
- Vertex::set(vertex++, bounds.left, bounds.bottom);
- Vertex::set(vertex++, bounds.right, bounds.bottom);
- }
- // We must clear the list of dirty rects before we
- // call clearLayerRegions() in renderGlop to prevent
- // stencil setup from doing the same thing again
- mLayers.clear();
-
- const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(nullptr) // clear ignores clip state
- .setMeshIndexedQuads(&mesh[0], quadCount)
- .setFillClear()
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getRenderTargetClip()))
- .build();
- renderGlop(glop, GlopRenderType::LayerClear);
-
- if (scissorChanged) mRenderState.scissor().setEnabled(true);
- } else {
- mLayers.clear();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// State Deferral
-///////////////////////////////////////////////////////////////////////////////
-
-bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
- const Rect& currentClip = mState.currentRenderTargetClip();
- const mat4* currentMatrix = currentTransform();
-
- if (stateDeferFlags & kStateDeferFlag_Draw) {
- // state has bounds initialized in local coordinates
- if (!state.mBounds.isEmpty()) {
- currentMatrix->mapRect(state.mBounds);
- Rect clippedBounds(state.mBounds);
- // NOTE: if we ever want to use this clipping info to drive whether the scissor
- // is used, it should more closely duplicate the quickReject logic (in how it uses
- // snapToPixelBoundaries)
-
- clippedBounds.doIntersect(currentClip);
- if (clippedBounds.isEmpty()) {
- // quick rejected
- return true;
- }
-
- state.mClipSideFlags = kClipSide_None;
- if (!currentClip.contains(state.mBounds)) {
- int& flags = state.mClipSideFlags;
- // op partially clipped, so record which sides are clipped for clip-aware merging
- if (currentClip.left > state.mBounds.left) flags |= kClipSide_Left;
- if (currentClip.top > state.mBounds.top) flags |= kClipSide_Top;
- if (currentClip.right < state.mBounds.right) flags |= kClipSide_Right;
- if (currentClip.bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
- }
- state.mBounds.set(clippedBounds);
- } else {
- // Empty bounds implies size unknown. Label op as conservatively clipped to disable
- // overdraw avoidance (since we don't know what it overlaps)
- state.mClipSideFlags = kClipSide_ConservativeFull;
- state.mBounds.set(currentClip);
- }
- }
-
- state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
- if (state.mClipValid) {
- state.mClip.set(currentClip);
- }
-
- // Transform and alpha always deferred, since they are used by state operations
- // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
- state.mMatrix = *currentMatrix;
- state.mAlpha = currentSnapshot()->alpha;
-
- // always store/restore, since these are just pointers
- state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
-#if !HWUI_NEW_OPS
- state.mProjectionPathMask = currentSnapshot()->projectionPathMask;
-#endif
- return false;
-}
-
-void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) {
- setGlobalMatrix(state.mMatrix);
- writableSnapshot()->alpha = state.mAlpha;
- writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
-#if !HWUI_NEW_OPS
- writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
-#endif
-
- if (state.mClipValid && !skipClipRestore) {
- writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
- state.mClip.right, state.mClip.bottom);
- dirtyClip();
- }
-}
-
-/**
- * Merged multidraw (such as in drawText and drawBitmaps rely on the fact that no clipping is done
- * in the draw path. Instead, clipping is done ahead of time - either as a single clip rect (when at
- * least one op is clipped), or disabled entirely (because no merged op is clipped)
- *
- * This method should be called when restoreDisplayState() won't be restoring the clip
- */
-void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) {
- if (clipRect != nullptr) {
- writableSnapshot()->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
- } else {
- writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight());
- }
- dirtyClip();
- bool enableScissor = (clipRect != nullptr) || mScissorOptimizationDisabled;
- mRenderState.scissor().setEnabled(enableScissor);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Clipping
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::setScissorFromClip() {
- Rect clip(mState.currentRenderTargetClip());
- clip.snapToPixelBoundaries();
-
- if (mRenderState.scissor().set(clip.left, getViewportHeight() - clip.bottom,
- clip.getWidth(), clip.getHeight())) {
- mState.setDirtyClip(false);
- }
-}
-
-void OpenGLRenderer::ensureStencilBuffer() {
- // Thanks to the mismatch between EGL and OpenGL ES FBO we
- // cannot attach a stencil buffer to fbo0 dynamically. Let's
- // just hope we have one when hasLayer() returns false.
- if (hasLayer()) {
- attachStencilBufferToLayer(currentSnapshot()->layer);
- }
-}
-
-void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
- // The layer's FBO is already bound when we reach this stage
- if (!layer->getStencilRenderBuffer()) {
- RenderBuffer* buffer = mCaches.renderBufferCache.get(
- Stencil::getLayerStencilFormat(),
- layer->getWidth(), layer->getHeight());
- layer->setStencilRenderBuffer(buffer);
- }
-}
-
-static void handlePoint(std::vector<Vertex>& rectangleVertices, const Matrix4& transform,
- float x, float y) {
- Vertex v;
- v.x = x;
- v.y = y;
- transform.mapPoint(v.x, v.y);
- rectangleVertices.push_back(v);
-}
-
-static void handlePointNoTransform(std::vector<Vertex>& rectangleVertices, float x, float y) {
- Vertex v;
- v.x = x;
- v.y = y;
- rectangleVertices.push_back(v);
-}
-
-void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) {
- int quadCount = rectangleList.getTransformedRectanglesCount();
- std::vector<Vertex> rectangleVertices(quadCount * 4);
- Rect scissorBox = rectangleList.calculateBounds();
- scissorBox.snapToPixelBoundaries();
- for (int i = 0; i < quadCount; ++i) {
- const TransformedRectangle& tr(rectangleList.getTransformedRectangle(i));
- const Matrix4& transform = tr.getTransform();
- Rect bounds = tr.getBounds();
- if (transform.rectToRect()) {
- transform.mapRect(bounds);
- bounds.doIntersect(scissorBox);
- if (!bounds.isEmpty()) {
- handlePointNoTransform(rectangleVertices, bounds.left, bounds.top);
- handlePointNoTransform(rectangleVertices, bounds.right, bounds.top);
- handlePointNoTransform(rectangleVertices, bounds.left, bounds.bottom);
- handlePointNoTransform(rectangleVertices, bounds.right, bounds.bottom);
- }
- } else {
- handlePoint(rectangleVertices, transform, bounds.left, bounds.top);
- handlePoint(rectangleVertices, transform, bounds.right, bounds.top);
- handlePoint(rectangleVertices, transform, bounds.left, bounds.bottom);
- handlePoint(rectangleVertices, transform, bounds.right, bounds.bottom);
- }
- }
-
- mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
- scissorBox.getWidth(), scissorBox.getHeight());
- const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
- Glop glop;
- Vertex* vertices = &rectangleVertices[0];
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
- .setFillBlack()
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRect(0, 0, scissorBox)
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::setStencilFromClip() {
- if (!Properties::debugOverdraw) {
- if (!currentSnapshot()->clipIsSimple()) {
- int incrementThreshold;
- EVENT_LOGD("setStencilFromClip - enabling");
-
- // NOTE: The order here is important, we must set dirtyClip to false
- // before any draw call to avoid calling back into this method
- mState.setDirtyClip(false);
-
- ensureStencilBuffer();
-
- const ClipArea& clipArea = currentSnapshot()->getClipArea();
-
- bool isRectangleList = clipArea.isRectangleList();
- if (isRectangleList) {
- incrementThreshold = clipArea.getRectangleList().getTransformedRectanglesCount();
- } else {
- incrementThreshold = 0;
- }
-
- mRenderState.stencil().enableWrite(incrementThreshold);
-
- // Clean and update the stencil, but first make sure we restrict drawing
- // to the region's bounds
- bool resetScissor = mRenderState.scissor().setEnabled(true);
- if (resetScissor) {
- // The scissor was not set so we now need to update it
- setScissorFromClip();
- }
-
- mRenderState.stencil().clear();
-
- // stash and disable the outline clip state, since stencil doesn't account for outline
- bool storedSkipOutlineClip = mSkipOutlineClip;
- mSkipOutlineClip = true;
-
- SkPaint paint;
- paint.setColor(SK_ColorBLACK);
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-
- if (isRectangleList) {
- drawRectangleList(clipArea.getRectangleList());
- } else {
- // NOTE: We could use the region contour path to generate a smaller mesh
- // Since we are using the stencil we could use the red book path
- // drawing technique. It might increase bandwidth usage though.
-
- // The last parameter is important: we are not drawing in the color buffer
- // so we don't want to dirty the current layer, if any
- drawRegionRects(clipArea.getClipRegion(), paint, false);
- }
- if (resetScissor) mRenderState.scissor().setEnabled(false);
- mSkipOutlineClip = storedSkipOutlineClip;
-
- mRenderState.stencil().enableTest(incrementThreshold);
-
- // Draw the region used to generate the stencil if the appropriate debug
- // mode is enabled
- // TODO: Implement for rectangle list clip areas
- if (Properties::debugStencilClip == StencilClipDebug::ShowRegion
- && !clipArea.isRectangleList()) {
- paint.setColor(0x7f0000ff);
- paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
- drawRegionRects(currentSnapshot()->getClipRegion(), paint);
- }
- } else {
- EVENT_LOGD("setStencilFromClip - disabling");
- mRenderState.stencil().disable();
- }
- }
-}
-
-/**
- * Returns false and sets scissor enable based upon bounds if drawing won't be clipped out.
- *
- * @param paint if not null, the bounds will be expanded to account for stroke depending on paint
- * style, and tessellated AA ramp
- */
-bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom,
- const SkPaint* paint) {
- bool snapOut = paint && paint->isAntiAlias();
-
- if (paint && paint->getStyle() != SkPaint::kFill_Style) {
- float outset = paint->getStrokeWidth() * 0.5f;
- left -= outset;
- top -= outset;
- right += outset;
- bottom += outset;
- }
-
- bool clipRequired = false;
- bool roundRectClipRequired = false;
- if (mState.calculateQuickRejectForScissor(left, top, right, bottom,
- &clipRequired, &roundRectClipRequired, snapOut)) {
- return true;
- }
-
- // not quick rejected, so enable the scissor if clipRequired
- mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
- mSkipOutlineClip = !roundRectClipRequired;
- return false;
-}
-
-void OpenGLRenderer::debugClip() {
-#if DEBUG_CLIP_REGIONS
- if (!currentSnapshot()->clipRegion->isEmpty()) {
- SkPaint paint;
- paint.setColor(0x7f00ff00);
- drawRegionRects(*(currentSnapshot()->clipRegion, paint);
-
- }
-#endif
-}
-
-void OpenGLRenderer::renderGlop(const Glop& glop, GlopRenderType type) {
- // TODO: It would be best if we could do this before quickRejectSetupScissor()
- // changes the scissor test state
- if (type != GlopRenderType::LayerClear) {
- // Regular draws need to clear the dirty area on the layer before they start drawing on top
- // of it. If this draw *is* a layer clear, it skips the clear step (since it would
- // infinitely recurse)
- clearLayerRegions();
- }
-
- if (mState.getDirtyClip()) {
- if (mRenderState.scissor().isEnabled()) {
- setScissorFromClip();
- }
-
- setStencilFromClip();
- }
- mRenderState.render(glop, currentSnapshot()->getOrthoMatrix());
- if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) {
- // TODO: specify more clearly when a draw should dirty the layer.
- // is writing to the stencil the only time we should ignore this?
-#if !HWUI_NEW_OPS
- dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom);
-#endif
- mDirty = true;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Drawing
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags) {
- // All the usual checks and setup operations (quickReject, setupDraw, etc.)
- // will be performed by the display list itself
- if (renderNode && renderNode->isRenderable()) {
- // compute 3d ordering
- renderNode->computeOrdering();
- if (CC_UNLIKELY(Properties::drawDeferDisabled)) {
- startFrame();
- ReplayStateStruct replayStruct(*this, dirty, replayFlags);
- renderNode->replay(replayStruct, 0);
- return;
- }
-
- DeferredDisplayList deferredList(mState.currentRenderTargetClip());
- DeferStateStruct deferStruct(deferredList, *this, replayFlags);
- renderNode->defer(deferStruct, 0);
-
- flushLayers();
- startFrame();
-
- deferredList.flush(*this, dirty);
- } else {
- // Even if there is no drawing command(Ex: invisible),
- // it still needs startFrame to clear buffer and start tiling.
- startFrame();
- }
-}
-
-/**
- * Important note: this method is intended to draw batches of bitmaps and
- * will not set the scissor enable or dirty the current layer, if any.
- * The caller is responsible for properly dirtying the current layer.
- */
-void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
- int bitmapCount, TextureVertex* vertices, bool pureTranslate,
- const Rect& bounds, const SkPaint* paint) {
- Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
- if (!texture) return;
-
- const AutoTexture autoCleanup(texture);
-
- // TODO: remove layer dirty in multi-draw callers
- // TODO: snap doesn't need to touch transform, only texture filter.
- bool snap = pureTranslate;
- const float x = floorf(bounds.left + 0.5f);
- const float y = floorf(bounds.top + 0.5f);
-
- const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
- const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedMesh(vertices, bitmapCount * 6)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(bounds.getWidth(), bounds.getHeight()))
- .build();
- renderGlop(glop, GlopRenderType::Multi);
-}
-
-void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
- if (quickRejectSetupScissor(0, 0, bitmap->width(), bitmap->height())) {
- return;
- }
-
- mCaches.textureState().activateTexture(0);
- Texture* texture = getTexture(bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUnitQuad(texture->uvMapper)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height()))
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
- if (!vertices || mState.currentlyIgnored()) {
- return;
- }
-
- float left = FLT_MAX;
- float top = FLT_MAX;
- float right = FLT_MIN;
- float bottom = FLT_MIN;
-
- const uint32_t elementCount = meshWidth * meshHeight * 6;
-
- std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]);
- ColorTextureVertex* vertex = &mesh[0];
-
- std::unique_ptr<int[]> tempColors;
- if (!colors) {
- uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
- tempColors.reset(new int[colorsCount]);
- memset(tempColors.get(), 0xff, colorsCount * sizeof(int));
- colors = tempColors.get();
- }
-
- Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
- const UvMapper& mapper(getMapper(texture));
-
- for (int32_t y = 0; y < meshHeight; y++) {
- for (int32_t x = 0; x < meshWidth; x++) {
- uint32_t i = (y * (meshWidth + 1) + x) * 2;
-
- float u1 = float(x) / meshWidth;
- float u2 = float(x + 1) / meshWidth;
- float v1 = float(y) / meshHeight;
- float v2 = float(y + 1) / meshHeight;
-
- mapper.map(u1, v1, u2, v2);
-
- int ax = i + (meshWidth + 1) * 2;
- int ay = ax + 1;
- int bx = i;
- int by = bx + 1;
- int cx = i + 2;
- int cy = cx + 1;
- int dx = i + (meshWidth + 1) * 2 + 2;
- int dy = dx + 1;
-
- ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
- ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
- ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
-
- ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
- ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
- ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);
-
- left = std::min(left, std::min(vertices[ax], std::min(vertices[bx], vertices[cx])));
- top = std::min(top, std::min(vertices[ay], std::min(vertices[by], vertices[cy])));
- right = std::max(right, std::max(vertices[ax], std::max(vertices[bx], vertices[cx])));
- bottom = std::max(bottom, std::max(vertices[ay], std::max(vertices[by], vertices[cy])));
- }
- }
-
- if (quickRejectSetupScissor(left, top, right, bottom)) {
- return;
- }
-
- if (!texture) {
- texture = mCaches.textureCache.get(bitmap);
- if (!texture) {
- return;
- }
- }
- const AutoTexture autoCleanup(texture);
-
- /*
- * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
- * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
- */
- const int textureFillFlags = TextureFillFlags::None;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshColoredTexturedMesh(mesh.get(), elementCount)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) {
- if (quickRejectSetupScissor(dst)) {
- return;
- }
-
- Texture* texture = getTexture(bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- Rect uv(std::max(0.0f, src.left / texture->width()),
- std::max(0.0f, src.top / texture->height()),
- std::min(1.0f, src.right / texture->width()),
- std::min(1.0f, src.bottom / texture->height()));
-
- const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
- ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
- const bool tryToSnap = MathUtils::areEqual(src.getWidth(), dst.getWidth())
- && MathUtils::areEqual(src.getHeight(), dst.getHeight());
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUvQuad(texture->uvMapper, uv)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRectOptionalSnap(tryToSnap, dst)
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
- AssetAtlas::Entry* entry, float left, float top, float right, float bottom,
- const SkPaint* paint) {
- if (!mesh || !mesh->verticesCount || quickRejectSetupScissor(left, top, right, bottom)) {
- return;
- }
-
- Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- // 9 patches are built for stretching - always filter
- int textureFillFlags = TextureFillFlags::ForceFilter;
- if (bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
- }
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshPatchQuads(*mesh)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewOffsetRectSnap(left, top, Rect(right - left, bottom - top)) // TODO: get minimal bounds from patch
- .build();
- renderGlop(glop);
-}
-
-/**
- * Important note: this method is intended to draw batches of 9-patch objects and
- * will not set the scissor enable or dirty the current layer, if any.
- * The caller is responsible for properly dirtying the current layer.
- */
-void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
- TextureVertex* vertices, uint32_t elementCount, const SkPaint* paint) {
- mCaches.textureState().activateTexture(0);
- Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- // TODO: get correct bounds from caller
- const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
- // 9 patches are built for stretching - always filter
- int textureFillFlags = TextureFillFlags::ForceFilter;
- if (bitmap->colorType() == kAlpha_8_SkColorType) {
- textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
- }
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedIndexedQuads(vertices, elementCount)
- .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRect(0, 0, Rect())
- .build();
- renderGlop(glop, GlopRenderType::Multi);
-}
-
-void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
- const VertexBuffer& vertexBuffer, const SkPaint* paint, int displayFlags) {
- // not missing call to quickReject/dirtyLayer, always done at a higher level
- if (!vertexBuffer.getVertexCount()) {
- // no vertices to draw
- return;
- }
-
- bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
- const int transformFlags = TransformFlags::OffsetByFudgeFactor;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshVertexBuffer(vertexBuffer)
- .setFillPaint(*paint, currentSnapshot()->alpha, shadowInterp)
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
- .build();
- renderGlop(glop);
-}
-
-/**
- * Renders a convex path via tessellation. For AA paths, this function uses a similar approach to
- * that of AA lines in the drawLines() function. We expand the convex path by a half pixel in
- * screen space in all directions. However, instead of using a fragment shader to compute the
- * translucency of the color from its position, we simply use a varying parameter to define how far
- * a given pixel is from the edge. For non-AA paths, the expansion and alpha varying are not used.
- *
- * Doesn't yet support joins, caps, or path effects.
- */
-void OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint) {
- VertexBuffer vertexBuffer;
- // TODO: try clipping large paths to viewport
-
- PathTessellator::tessellatePath(path, paint, *currentTransform(), vertexBuffer);
- drawVertexBuffer(vertexBuffer, paint);
-}
-
-/**
- * We create tristrips for the lines much like shape stroke tessellation, using a per-vertex alpha
- * and additional geometry for defining an alpha slope perimeter.
- *
- * Using GL_LINES can be difficult because the rasterization rules for those lines produces some
- * unexpected results, and may vary between hardware devices. Previously we used a varying-base
- * in-shader alpha region, but found it to be taxing on some GPUs.
- *
- * TODO: try using a fixed input buffer for non-capped lines as in text rendering. this may reduce
- * memory transfer by removing need for degenerate vertices.
- */
-void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
- if (mState.currentlyIgnored() || count < 4) return;
-
- count &= ~0x3; // round down to nearest four
-
- VertexBuffer buffer;
- PathTessellator::tessellateLines(points, count, paint, *currentTransform(), buffer);
- const Rect& bounds = buffer.getBounds();
-
- if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) {
- return;
- }
-
- int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
- drawVertexBuffer(buffer, paint, displayFlags);
-}
-
-void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
- if (mState.currentlyIgnored() || count < 2) return;
-
- count &= ~0x1; // round down to nearest two
-
- VertexBuffer buffer;
- PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), buffer);
-
- const Rect& bounds = buffer.getBounds();
- if (quickRejectSetupScissor(bounds.left, bounds.top, bounds.right, bounds.bottom)) {
- return;
- }
-
- int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
- drawVertexBuffer(buffer, paint, displayFlags);
-
- mDirty = true;
-}
-
-void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
- // No need to check against the clip, we fill the clip region
- if (mState.currentlyIgnored()) return;
-
- Rect clip(mState.currentRenderTargetClip());
- clip.snapToPixelBoundaries();
-
- SkPaint paint;
- paint.setColor(color);
- paint.setXfermodeMode(mode);
-
- drawColorRect(clip.left, clip.top, clip.right, clip.bottom, &paint, true);
-
- mDirty = true;
-}
-
-void OpenGLRenderer::drawShape(float left, float top, PathTexture* texture,
- const SkPaint* paint) {
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- const float x = left + texture->left - texture->offset;
- const float y = top + texture->top - texture->offset;
-
- drawPathTexture(texture, x, y, paint);
-
- mDirty = true;
-}
-
-void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint* p) {
- if (mState.currentlyIgnored()
- || quickRejectSetupScissor(left, top, right, bottom, p)
- || PaintUtils::paintWillNotDraw(*p)) {
- return;
- }
-
- if (p->getPathEffect() != nullptr) {
- mCaches.textureState().activateTexture(0);
- PathTexture* texture = mCaches.pathCache.getRoundRect(
- right - left, bottom - top, rx, ry, p);
- drawShape(left, top, texture, p);
- } else {
- const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(
- *currentTransform(), *p, right - left, bottom - top, rx, ry);
- drawVertexBuffer(left, top, *vertexBuffer, p);
- }
-}
-
-void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
- if (mState.currentlyIgnored()
- || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
- || PaintUtils::paintWillNotDraw(*p)) {
- return;
- }
-
- if (p->getPathEffect() != nullptr) {
- mCaches.textureState().activateTexture(0);
- PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
- drawShape(x - radius, y - radius, texture, p);
- return;
- }
-
- SkPath path;
- if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
- path.addCircle(x, y, radius + p->getStrokeWidth() / 2);
- } else {
- path.addCircle(x, y, radius);
- }
-
-#if !HWUI_NEW_OPS
- if (CC_UNLIKELY(currentSnapshot()->projectionPathMask != nullptr)) {
- // mask ripples with projection mask
- SkPath maskPath = *(currentSnapshot()->projectionPathMask->projectionMask);
-
- Matrix4 screenSpaceTransform;
- currentSnapshot()->buildScreenSpaceTransform(&screenSpaceTransform);
-
- Matrix4 totalTransform;
- totalTransform.loadInverse(screenSpaceTransform);
- totalTransform.multiply(currentSnapshot()->projectionPathMask->projectionMaskTransform);
-
- SkMatrix skTotalTransform;
- totalTransform.copyTo(skTotalTransform);
- maskPath.transform(skTotalTransform);
-
- // Mask the ripple path by the projection mask, now that it's
- // in local space. Note that this can create CCW paths.
- Op(path, maskPath, kIntersect_SkPathOp, &path);
- }
-#endif
- drawConvexPath(path, p);
-}
-
-void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
- const SkPaint* p) {
- if (mState.currentlyIgnored()
- || quickRejectSetupScissor(left, top, right, bottom, p)
- || PaintUtils::paintWillNotDraw(*p)) {
- return;
- }
-
- if (p->getPathEffect() != nullptr) {
- mCaches.textureState().activateTexture(0);
- PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
- drawShape(left, top, texture, p);
- } else {
- SkPath path;
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
- rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
- }
- path.addOval(rect);
- drawConvexPath(path, p);
- }
-}
-
-void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
- if (mState.currentlyIgnored()
- || quickRejectSetupScissor(left, top, right, bottom, p)
- || PaintUtils::paintWillNotDraw(*p)) {
- return;
- }
-
- // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
- if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != nullptr || useCenter) {
- mCaches.textureState().activateTexture(0);
- PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
- startAngle, sweepAngle, useCenter, p);
- drawShape(left, top, texture, p);
- return;
- }
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
- rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
- }
-
- SkPath path;
- if (useCenter) {
- path.moveTo(rect.centerX(), rect.centerY());
- }
- path.arcTo(rect, startAngle, sweepAngle, !useCenter);
- if (useCenter) {
- path.close();
- }
- drawConvexPath(path, p);
-}
-
-void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
- const SkPaint* p) {
- if (mState.currentlyIgnored()
- || quickRejectSetupScissor(left, top, right, bottom, p)
- || PaintUtils::paintWillNotDraw(*p)) {
- return;
- }
-
- if (p->getStyle() != SkPaint::kFill_Style) {
- // only fill style is supported by drawConvexPath, since others have to handle joins
- static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed");
- if (p->getPathEffect() != nullptr || p->getStrokeJoin() != SkPaint::kMiter_Join ||
- p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
- mCaches.textureState().activateTexture(0);
- PathTexture* texture =
- mCaches.pathCache.getRect(right - left, bottom - top, p);
- drawShape(left, top, texture, p);
- } else {
- SkPath path;
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- if (p->getStyle() == SkPaint::kStrokeAndFill_Style) {
- rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2);
- }
- path.addRect(rect);
- drawConvexPath(path, p);
- }
- } else {
- if (p->isAntiAlias() && !currentTransform()->isSimple()) {
- SkPath path;
- path.addRect(left, top, right, bottom);
- drawConvexPath(path, p);
- } else {
- drawColorRect(left, top, right, bottom, p);
-
- mDirty = true;
- }
- }
-}
-
-void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const glyph_t* glyphs,
- int count, const float* positions,
- FontRenderer& fontRenderer, int alpha, float x, float y) {
- mCaches.textureState().activateTexture(0);
-
- PaintUtils::TextShadow textShadow;
- if (!PaintUtils::getTextShadow(paint, &textShadow)) {
- LOG_ALWAYS_FATAL("failed to query shadow attributes");
- }
-
- // NOTE: The drop shadow will not perform gamma correction
- // if shader-based correction is enabled
- mCaches.dropShadowCache.setFontRenderer(fontRenderer);
- ShadowTexture* texture = mCaches.dropShadowCache.get(
- paint, glyphs, count, textShadow.radius, positions);
- // If the drop shadow exceeds the max texture size or couldn't be
- // allocated, skip drawing
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
-
- const float sx = x - texture->left + textShadow.dx;
- const float sy = y - texture->top + textShadow.dy;
-
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUnitQuad(nullptr)
- .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height()))
- .build();
- renderGlop(glop);
-}
-
-// TODO: remove this, once mState.currentlyIgnored captures snapshot alpha
-bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
- float alpha = (PaintUtils::hasTextShadow(paint)
- ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
- return MathUtils::isZero(alpha)
- && PaintUtils::getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
-}
-
-bool OpenGLRenderer::findBestFontTransform(const mat4& transform, SkMatrix* outMatrix) const {
- if (CC_LIKELY(transform.isPureTranslate())) {
- outMatrix->setIdentity();
- return false;
- } else if (CC_UNLIKELY(transform.isPerspective())) {
- outMatrix->setIdentity();
- return true;
- }
-
- /**
- * Input is a non-perspective, scaling transform. Generate a scale-only transform,
- * with values rounded to the nearest int.
- */
- float sx, sy;
- transform.decomposeScale(sx, sy);
- outMatrix->setScale(
- roundf(std::max(1.0f, sx)),
- roundf(std::max(1.0f, sy)));
- return true;
-}
-
-int OpenGLRenderer::getSaveCount() const {
- return mState.getSaveCount();
-}
-
-int OpenGLRenderer::save(int flags) {
- return mState.save(flags);
-}
-
-void OpenGLRenderer::restore() {
- mState.restore();
-}
-
-void OpenGLRenderer::restoreToCount(int saveCount) {
- mState.restoreToCount(saveCount);
-}
-
-
-void OpenGLRenderer::translate(float dx, float dy, float dz) {
- mState.translate(dx, dy, dz);
-}
-
-void OpenGLRenderer::rotate(float degrees) {
- mState.rotate(degrees);
-}
-
-void OpenGLRenderer::scale(float sx, float sy) {
- mState.scale(sx, sy);
-}
-
-void OpenGLRenderer::skew(float sx, float sy) {
- mState.skew(sx, sy);
-}
-
-void OpenGLRenderer::setLocalMatrix(const Matrix4& matrix) {
- mState.setMatrix(mBaseTransform);
- mState.concatMatrix(matrix);
-}
-
-void OpenGLRenderer::setLocalMatrix(const SkMatrix& matrix) {
- mState.setMatrix(mBaseTransform);
- mState.concatMatrix(matrix);
-}
-
-void OpenGLRenderer::concatMatrix(const Matrix4& matrix) {
- mState.concatMatrix(matrix);
-}
-
-bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
- return mState.clipRect(left, top, right, bottom, op);
-}
-
-bool OpenGLRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
- return mState.clipPath(path, op);
-}
-
-bool OpenGLRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
- return mState.clipRegion(region, op);
-}
-
-void OpenGLRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
- mState.setClippingOutline(allocator, outline);
-}
-
-void OpenGLRenderer::setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius, bool highPriority) {
- mState.setClippingRoundRect(allocator, rect, radius, highPriority);
-}
-
-void OpenGLRenderer::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
- mState.setProjectionPathMask(allocator, path);
-}
-
-void OpenGLRenderer::drawText(const glyph_t* glyphs, int bytesCount, int count, float x, float y,
- const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
- DrawOpMode drawOpMode) {
-
- if (drawOpMode == DrawOpMode::kImmediate) {
- // The checks for corner-case ignorable text and quick rejection is only done for immediate
- // drawing as ops from DeferredDisplayList are already filtered for these
- if (glyphs == nullptr || count == 0 || mState.currentlyIgnored() || canSkipText(paint) ||
- quickRejectSetupScissor(bounds)) {
- return;
- }
- }
-
- const float oldX = x;
- const float oldY = y;
-
- const mat4& transform = *currentTransform();
- const bool pureTranslate = transform.isPureTranslate();
-
- if (CC_LIKELY(pureTranslate)) {
- x = floorf(x + transform.getTranslateX() + 0.5f);
- y = floorf(y + transform.getTranslateY() + 0.5f);
- }
-
- int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
- SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
-
- FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
-
- if (CC_UNLIKELY(PaintUtils::hasTextShadow(paint))) {
- fontRenderer.setFont(paint, SkMatrix::I());
- drawTextShadow(paint, glyphs, count, positions, fontRenderer,
- alpha, oldX, oldY);
- }
-
- const bool hasActiveLayer = hasLayer();
-
- // We only pass a partial transform to the font renderer. That partial
- // matrix defines how glyphs are rasterized. Typically we want glyphs
- // to be rasterized at their final size on screen, which means the partial
- // matrix needs to take the scale factor into account.
- // When a partial matrix is used to transform glyphs during rasterization,
- // the mesh is generated with the inverse transform (in the case of scale,
- // the mesh is generated at 1.0 / scale for instance.) This allows us to
- // apply the full transform matrix at draw time in the vertex shader.
- // Applying the full matrix in the shader is the easiest way to handle
- // rotation and perspective and allows us to always generated quads in the
- // font renderer which greatly simplifies the code, clipping in particular.
- SkMatrix fontTransform;
- bool linearFilter = findBestFontTransform(transform, &fontTransform)
- || fabs(y - (int) y) > 0.0f
- || fabs(x - (int) x) > 0.0f;
- fontRenderer.setFont(paint, fontTransform);
- fontRenderer.setTextureFiltering(linearFilter);
-
- // TODO: Implement better clipping for scaled/rotated text
- const Rect* clip = !pureTranslate ? nullptr : &mState.currentRenderTargetClip();
- Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
-
- bool status;
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("unsupported");
- TextDrawFunctor functor(nullptr, nullptr, nullptr, x, y, pureTranslate, alpha, mode, paint);
-#else
- TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
-#endif
-
- // don't call issuedrawcommand, do it at end of batch
- bool forceFinish = (drawOpMode != DrawOpMode::kDefer);
- if (CC_UNLIKELY(paint->getTextAlign() != SkPaint::kLeft_Align)) {
- SkPaint paintCopy(*paint);
- paintCopy.setTextAlign(SkPaint::kLeft_Align);
- status = fontRenderer.renderPosText(&paintCopy, clip, glyphs, count, x, y,
- positions, hasActiveLayer ? &layerBounds : nullptr, &functor, forceFinish);
- } else {
- status = fontRenderer.renderPosText(paint, clip, glyphs, count, x, y,
- positions, hasActiveLayer ? &layerBounds : nullptr, &functor, forceFinish);
- }
-
- if ((status || drawOpMode != DrawOpMode::kImmediate) && hasActiveLayer) {
- if (!pureTranslate) {
- transform.mapRect(layerBounds);
- }
- dirtyLayerUnchecked(layerBounds, getRegion());
- }
-
- mDirty = true;
-}
-
-void OpenGLRenderer::drawTextOnPath(const glyph_t* glyphs, int bytesCount, int count,
- const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
- if (glyphs == nullptr || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) {
- return;
- }
-
- // TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
- mRenderState.scissor().setEnabled(true);
-
- FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
- fontRenderer.setFont(paint, SkMatrix::I());
- fontRenderer.setTextureFiltering(true);
-
- int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
- SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("unsupported");
- TextDrawFunctor functor(nullptr, nullptr, nullptr, 0.0f, 0.0f, false, alpha, mode, paint);
-#else
- TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
-#endif
-
- const Rect* clip = &writableSnapshot()->getLocalClip();
- Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
-
- if (fontRenderer.renderTextOnPath(paint, clip, glyphs, count, path,
- hOffset, vOffset, hasLayer() ? &bounds : nullptr, &functor)) {
- dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
- mDirty = true;
- }
-}
-
-void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
- if (mState.currentlyIgnored()) return;
-
- mCaches.textureState().activateTexture(0);
-
- PathTexture* texture = mCaches.pathCache.get(path, paint);
- if (!texture) return;
-
- const float x = texture->left - texture->offset;
- const float y = texture->top - texture->offset;
-
- drawPathTexture(texture, x, y, paint);
-
- if (texture->cleanup) {
- mCaches.pathCache.remove(path, paint);
- }
- mDirty = true;
-}
-
-void OpenGLRenderer::drawLayer(Layer* layer) {
- if (!layer) {
- return;
- }
-
- mat4* transform = nullptr;
- if (layer->isTextureLayer()) {
- transform = &layer->getTransform();
- if (!transform->isIdentity()) {
- save(SaveFlags::Matrix);
- concatMatrix(*transform);
- }
- }
-
- bool clipRequired = false;
- const bool rejected = mState.calculateQuickRejectForScissor(
- 0, 0, layer->layer.getWidth(), layer->layer.getHeight(),
- &clipRequired, nullptr, false);
-
- if (rejected) {
- if (transform && !transform->isIdentity()) {
- restore();
- }
- return;
- }
-
- EVENT_LOGD("drawLayer," RECT_STRING ", clipRequired %d", x, y,
- x + layer->layer.getWidth(), y + layer->layer.getHeight(), clipRequired);
-
- updateLayer(layer, true);
-
- mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
- mCaches.textureState().activateTexture(0);
-
- if (CC_LIKELY(!layer->region.isEmpty())) {
- if (layer->region.isRect()) {
- DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
- composeLayerRect(layer, layer->regionRect));
- } else if (layer->mesh) {
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
- .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewOffsetRectSnap(0, 0, Rect(layer->layer.getWidth(), layer->layer.getHeight()))
- .build();
- DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-#if DEBUG_LAYERS_AS_REGIONS
- drawRegionRectsDebug(layer->region);
-#endif
- }
-
- if (layer->debugDrawUpdate) {
- layer->debugDrawUpdate = false;
-
- SkPaint paint;
- paint.setColor(0x7f00ff00);
- drawColorRect(0, 0, layer->layer.getWidth(), layer->layer.getHeight(), &paint);
- }
- }
- layer->hasDrawnSinceUpdate = true;
-
- if (transform && !transform->isIdentity()) {
- restore();
- }
-
- mDirty = true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Draw filters
-///////////////////////////////////////////////////////////////////////////////
-void OpenGLRenderer::setDrawFilter(SkDrawFilter* filter) {
- // We should never get here since we apply the draw filter when stashing
- // the paints in the DisplayList.
- LOG_ALWAYS_FATAL("OpenGLRenderer does not directly support DrawFilters");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Drawing implementation
-///////////////////////////////////////////////////////////////////////////////
-
-Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) {
- Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
- if (!texture) {
- return mCaches.textureCache.get(bitmap);
- }
- return texture;
-}
-
-void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y,
- const SkPaint* paint) {
- if (quickRejectSetupScissor(x, y, x + texture->width(), y + texture->height())) {
- return;
- }
-
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshTexturedUnitQuad(nullptr)
- .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), TransformFlags::None)
- .setModelViewMapUnitToRect(Rect(x, y, x + texture->width(), y + texture->height()))
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
- if (mState.currentlyIgnored()) {
- return;
- }
-
- drawColorRects(rects, count, paint, false, true, true);
-}
-
-void OpenGLRenderer::drawShadow(float casterAlpha,
- const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) {
- if (mState.currentlyIgnored()) return;
-
- // TODO: use quickRejectWithScissor. For now, always force enable scissor.
- mRenderState.scissor().setEnabled(true);
-
- SkPaint paint;
- paint.setAntiAlias(true); // want to use AlphaVertex
-
- // The caller has made sure casterAlpha > 0.
- float ambientShadowAlpha = mAmbientShadowAlpha;
- if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
- ambientShadowAlpha = Properties::overrideAmbientShadowStrength;
- }
- if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
- paint.setARGB(casterAlpha * ambientShadowAlpha, 0, 0, 0);
- drawVertexBuffer(*ambientShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
- }
-
- float spotShadowAlpha = mSpotShadowAlpha;
- if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
- spotShadowAlpha = Properties::overrideSpotShadowStrength;
- }
- if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
- paint.setARGB(casterAlpha * spotShadowAlpha, 0, 0, 0);
- drawVertexBuffer(*spotShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
- }
-
- mDirty=true;
-}
-
-void OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint* paint,
- bool ignoreTransform, bool dirty, bool clip) {
- if (count == 0) {
- return;
- }
-
- float left = FLT_MAX;
- float top = FLT_MAX;
- float right = FLT_MIN;
- float bottom = FLT_MIN;
-
- Vertex mesh[count];
- Vertex* vertex = mesh;
-
- for (int index = 0; index < count; index += 4) {
- float l = rects[index + 0];
- float t = rects[index + 1];
- float r = rects[index + 2];
- float b = rects[index + 3];
-
- Vertex::set(vertex++, l, t);
- Vertex::set(vertex++, r, t);
- Vertex::set(vertex++, l, b);
- Vertex::set(vertex++, r, b);
-
- left = std::min(left, l);
- top = std::min(top, t);
- right = std::max(right, r);
- bottom = std::max(bottom, b);
- }
-
- if (clip && quickRejectSetupScissor(left, top, right, bottom)) {
- return;
- }
-
- const int transformFlags = ignoreTransform
- ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshIndexedQuads(&mesh[0], count / 4)
- .setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
- .build();
- renderGlop(glop);
-}
-
-void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
- const SkPaint* paint, bool ignoreTransform) {
- const int transformFlags = ignoreTransform
- ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
- Glop glop;
- GlopBuilder(mRenderState, mCaches, &glop)
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .setMeshUnitQuad()
- .setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransform(*currentSnapshot(), transformFlags)
- .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
- .build();
- renderGlop(glop);
-}
-
-float OpenGLRenderer::getLayerAlpha(const Layer* layer) const {
- return (layer->getAlpha() / 255.0f) * currentSnapshot()->alpha;
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
deleted file mode 100755
index dacd8ccaa6ea..000000000000
--- a/libs/hwui/OpenGLRenderer.h
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_OPENGL_RENDERER_H
-#define ANDROID_HWUI_OPENGL_RENDERER_H
-
-#include "CanvasState.h"
-#include "Debug.h"
-#include "Extensions.h"
-#include "Matrix.h"
-#include "Program.h"
-#include "Rect.h"
-#include "Snapshot.h"
-#include "UvMapper.h"
-#include "Vertex.h"
-#include "Caches.h"
-#include "utils/PaintUtils.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkColorFilter.h>
-#include <SkDrawLooper.h>
-#include <SkMatrix.h>
-#include <SkPaint.h>
-#include <SkRegion.h>
-#include <SkXfermode.h>
-
-#include <utils/Blur.h>
-#include <utils/Functor.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-
-#include <cutils/compiler.h>
-
-#include <androidfw/ResourceTypes.h>
-
-#include <vector>
-
-class SkShader;
-
-namespace android {
-namespace uirenderer {
-
-enum class DrawOpMode {
- kImmediate,
- kDefer,
- kFlush
-};
-
-class DeferredDisplayState;
-struct Glop;
-class RenderState;
-class RenderNode;
-class TextDrawFunctor;
-class VertexBuffer;
-
-enum StateDeferFlags {
- kStateDeferFlag_Draw = 0x1,
- kStateDeferFlag_Clip = 0x2
-};
-
-enum ClipSideFlags {
- kClipSide_None = 0x0,
- kClipSide_Left = 0x1,
- kClipSide_Top = 0x2,
- kClipSide_Right = 0x4,
- kClipSide_Bottom = 0x8,
- kClipSide_Full = 0xF,
- kClipSide_ConservativeFull = 0x1F
-};
-
-enum VertexBufferDisplayFlags {
- kVertexBuffer_Offset = 0x1,
- kVertexBuffer_ShadowInterp = 0x2,
-};
-
-/**
- * Defines additional transformation that should be applied by the model view matrix, beyond that of
- * the currentTransform()
- */
-enum ModelViewMode {
- /**
- * Used when the model view should simply translate geometry passed to the shader. The resulting
- * matrix will be a simple translation.
- */
- kModelViewMode_Translate = 0,
-
- /**
- * Used when the model view should translate and scale geometry. The resulting matrix will be a
- * translation + scale. This is frequently used together with VBO 0, the (0,0,1,1) rect.
- */
- kModelViewMode_TranslateAndScale = 1,
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Renderer
-///////////////////////////////////////////////////////////////////////////////
-/**
- * OpenGL Renderer implementation.
- */
-class OpenGLRenderer : public CanvasStateClient {
-public:
- OpenGLRenderer(RenderState& renderState);
- virtual ~OpenGLRenderer();
-
- void initProperties();
- void initLight(float lightRadius, uint8_t ambientShadowAlpha,
- uint8_t spotShadowAlpha);
- void setLightCenter(const Vector3& lightCenter);
-
- /*
- * Prepares the renderer to draw a frame. This method must be invoked
- * at the beginning of each frame. Only the specified rectangle of the
- * frame is assumed to be dirty. A clip will automatically be set to
- * the specified rectangle.
- *
- * @param opaque If true, the target surface is considered opaque
- * and will not be cleared. If false, the target surface
- * will be cleared
- */
- virtual void prepareDirty(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque);
-
- /**
- * Indicates the end of a frame. This method must be invoked whenever
- * the caller is done rendering a frame.
- * Returns true if any drawing was done during the frame (the output
- * has changed / is "dirty" and should be displayed to the user).
- */
- virtual bool finish();
-
- void callDrawGLFunction(Functor* functor, Rect& dirty);
-
- void pushLayerUpdate(Layer* layer);
- void cancelLayerUpdate(Layer* layer);
- void flushLayerUpdates();
- void markLayersAsBuildLayers();
-
- virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags) {
- return saveLayer(left, top, right, bottom, paint, flags, nullptr);
- }
-
- // Specialized saveLayer implementation, which will pass the convexMask to an FBO layer, if
- // created, which will in turn clip to that mask when drawn back/restored.
- int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags, const SkPath* convexMask);
-
- int saveLayerDeferred(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags);
-
- void drawRenderNode(RenderNode* displayList, Rect& dirty, int32_t replayFlags = 1);
- void drawLayer(Layer* layer);
- void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
- void drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
- TextureVertex* vertices, bool pureTranslate, const Rect& bounds, const SkPaint* paint);
- void drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst,
- const SkPaint* paint);
- void drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint);
- void drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
- TextureVertex* vertices, uint32_t indexCount, const SkPaint* paint);
- void drawPatch(const SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
- float left, float top, float right, float bottom, const SkPaint* paint);
- void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom,
- const SkPaint* paint);
- void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint* paint);
- void drawCircle(float x, float y, float radius, const SkPaint* paint);
- void drawOval(float left, float top, float right, float bottom,
- const SkPaint* paint);
- void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint);
- void drawPath(const SkPath* path, const SkPaint* paint);
- void drawLines(const float* points, int count, const SkPaint* paint);
- void drawPoints(const float* points, int count, const SkPaint* paint);
- void drawTextOnPath(const glyph_t* glyphs, int bytesCount, int count, const SkPath* path,
- float hOffset, float vOffset, const SkPaint* paint);
- void drawText(const glyph_t* glyphs, int bytesCount, int count, float x, float y,
- const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
- DrawOpMode drawOpMode = DrawOpMode::kImmediate);
- void drawRects(const float* rects, int count, const SkPaint* paint);
-
- void drawShadow(float casterAlpha,
- const VertexBuffer* ambientShadowVertexBuffer,
- const VertexBuffer* spotShadowVertexBuffer);
-
- void setDrawFilter(SkDrawFilter* filter);
-
- /**
- * Store the current display state (most importantly, the current clip and transform), and
- * additionally map the state's bounds from local to window coordinates.
- *
- * Returns true if quick-rejected
- */
- bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
- void restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore = false);
- void setupMergedMultiDraw(const Rect* clipRect);
-
- bool isCurrentTransformSimple() {
- return currentTransform()->isSimple();
- }
-
- Caches& getCaches() {
- return mCaches;
- }
-
- RenderState& renderState() {
- return mRenderState;
- }
-
- int getViewportWidth() { return mState.getViewportWidth(); }
- int getViewportHeight() { return mState.getViewportHeight(); }
-
- /**
- * Scales the alpha on the current snapshot. This alpha value will be modulated
- * with other alpha values when drawing primitives.
- */
- void scaleAlpha(float alpha) { mState.scaleAlpha(alpha); }
-
- /**
- * Inserts a named event marker in the stream of GL commands.
- */
- void eventMark(const char* name) const;
-
- /**
- * Inserts a formatted event marker in the stream of GL commands.
- */
- void eventMarkDEBUG(const char *fmt, ...) const;
-
- /**
- * Inserts a named group marker in the stream of GL commands. This marker
- * can be used by tools to group commands into logical groups. A call to
- * this method must always be followed later on by a call to endMark().
- */
- void startMark(const char* name) const;
-
- /**
- * Closes the last group marker opened by startMark().
- */
- void endMark() const;
-
- /**
- * Build the best transform to use to rasterize text given a full
- * transform matrix, and whether filteration is needed.
- *
- * Returns whether filtration is needed
- */
- bool findBestFontTransform(const mat4& transform, SkMatrix* outMatrix) const;
-
-#if DEBUG_MERGE_BEHAVIOR
- void drawScreenSpaceColorRect(float left, float top, float right, float bottom, int color) {
- mCaches.setScissorEnabled(false);
-
- // should only be called outside of other draw ops, so stencil can only be in test state
- bool stencilWasEnabled = mCaches.stencil.isTestEnabled();
- mCaches.stencil.disable();
-
- drawColorRect(left, top, right, bottom, color, SkXfermode::kSrcOver_Mode, true);
-
- if (stencilWasEnabled) mCaches.stencil.enableTest();
- mDirty = true;
- }
-#endif
-
- const Vector3& getLightCenter() const { return mState.currentLightCenter(); }
- float getLightRadius() const { return mLightRadius; }
- uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; }
- uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; }
-
- ///////////////////////////////////////////////////////////////////
- /// State manipulation
-
- int getSaveCount() const;
- int save(int flags);
- void restore();
- void restoreToCount(int saveCount);
-
- void setGlobalMatrix(const Matrix4& matrix) {
- mState.setMatrix(matrix);
- }
- void setLocalMatrix(const Matrix4& matrix);
- void setLocalMatrix(const SkMatrix& matrix);
- void concatMatrix(const SkMatrix& matrix) { mState.concatMatrix(matrix); }
-
- void translate(float dx, float dy, float dz = 0.0f);
- void rotate(float degrees);
- void scale(float sx, float sy);
- void skew(float sx, float sy);
-
- void setMatrix(const Matrix4& matrix); // internal only convenience method
- void concatMatrix(const Matrix4& matrix); // internal only convenience method
-
- const Rect& getLocalClipBounds() const { return mState.getLocalClipBounds(); }
- const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
- bool quickRejectConservative(float left, float top,
- float right, float bottom) const {
- return mState.quickRejectConservative(left, top, right, bottom);
- }
-
- bool clipRect(float left, float top,
- float right, float bottom, SkRegion::Op op);
- bool clipPath(const SkPath* path, SkRegion::Op op);
- bool clipRegion(const SkRegion* region, SkRegion::Op op);
-
- /**
- * Does not support different clipping Ops (that is, every call to setClippingOutline is
- * effectively using SkRegion::kReplaceOp)
- *
- * The clipping outline is independent from the regular clip.
- */
- void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
- void setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius, bool highPriority = true);
- void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
-
- inline bool hasRectToRectTransform() const { return mState.hasRectToRectTransform(); }
- inline const mat4* currentTransform() const { return mState.currentTransform(); }
-
- ///////////////////////////////////////////////////////////////////
- /// CanvasStateClient interface
-
- virtual void onViewportInitialized() override;
- virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override;
- virtual GLuint getTargetFbo() const override { return 0; }
-
- SkPath* allocPathForFrame() {
- std::unique_ptr<SkPath> path(new SkPath());
- SkPath* returnPath = path.get();
- mTempPaths.push_back(std::move(path));
- return returnPath;
- }
-
- void setBaseTransform(const Matrix4& matrix) { mBaseTransform = matrix; }
-
-protected:
- /**
- * Perform the setup specific to a frame. This method does not
- * issue any OpenGL commands.
- */
- void setupFrameState(int viewportWidth, int viewportHeight,
- float left, float top, float right, float bottom, bool opaque);
-
- /**
- * Indicates the start of rendering. This method will setup the
- * initial OpenGL state (viewport, clearing the buffer, etc.)
- */
- void startFrame();
-
- /**
- * Clears the underlying surface if needed.
- */
- virtual void clear(float left, float top, float right, float bottom, bool opaque);
-
- /**
- * Call this method after updating a layer during a drawing pass.
- */
- void resumeAfterLayer();
-
- /**
- * This method is called whenever a stencil buffer is required. Subclasses
- * should override this method and call attachStencilBufferToLayer() on the
- * appropriate layer(s).
- */
- virtual void ensureStencilBuffer();
-
- /**
- * Obtains a stencil render buffer (allocating it if necessary) and
- * attaches it to the specified layer.
- */
- void attachStencilBufferToLayer(Layer* layer);
-
- /**
- * Draw a rectangle list. Currently only used for the the stencil buffer so that the stencil
- * will have a value of 'n' in every unclipped pixel, where 'n' is the number of rectangles
- * in the list.
- */
- void drawRectangleList(const RectangleList& rectangleList);
-
- bool quickRejectSetupScissor(float left, float top, float right, float bottom,
- const SkPaint* paint = nullptr);
- bool quickRejectSetupScissor(const Rect& bounds, const SkPaint* paint = nullptr) {
- return quickRejectSetupScissor(bounds.left, bounds.top,
- bounds.right, bounds.bottom, paint);
- }
-
- /**
- * Compose the layer defined in the current snapshot with the layer
- * defined by the previous snapshot.
- *
- * The current snapshot *must* be a layer (flag kFlagIsLayer set.)
- *
- * @param curent The current snapshot containing the layer to compose
- * @param previous The previous snapshot to compose the current layer with
- */
- virtual void composeLayer(const Snapshot& current, const Snapshot& previous);
-
- /**
- * Marks the specified region as dirty at the specified bounds.
- */
- void dirtyLayerUnchecked(Rect& bounds, Region* region);
-
- /**
- * Returns the region of the current layer.
- */
- virtual Region* getRegion() const {
- return mState.currentRegion();
- }
-
- /**
- * Indicates whether rendering is currently targeted at a layer.
- */
- virtual bool hasLayer() const {
- return (mState.currentFlags() & Snapshot::kFlagFboTarget) && mState.currentRegion();
- }
-
- /**
- * Renders the specified layer as a textured quad.
- *
- * @param layer The layer to render
- * @param rect The bounds of the layer
- */
- void drawTextureLayer(Layer* layer, const Rect& rect);
-
- /**
- * Gets the alpha from a layer, accounting for snapshot alpha
- *
- * @param layer The layer from which the alpha is extracted
- */
- inline float getLayerAlpha(const Layer* layer) const;
-
- /**
- * Set to true to suppress error checks at the end of a frame.
- */
- virtual bool suppressErrorChecks() const {
- return false;
- }
-
- CanvasState mState;
- Caches& mCaches;
- RenderState& mRenderState;
-
-private:
- enum class GlopRenderType {
- Standard,
- Multi,
- LayerClear
- };
-
- void renderGlop(const Glop& glop, GlopRenderType type = GlopRenderType::Standard);
-
- /**
- * Discards the content of the framebuffer if supported by the driver.
- * This method should be called at the beginning of a frame to optimize
- * rendering on some tiler architectures.
- */
- void discardFramebuffer(float left, float top, float right, float bottom);
-
- /**
- * Sets the clipping rectangle using glScissor. The clip is defined by
- * the current snapshot's clipRect member.
- */
- void setScissorFromClip();
-
- /**
- * Sets the clipping region using the stencil buffer. The clip region
- * is defined by the current snapshot's clipRegion member.
- */
- void setStencilFromClip();
-
- /**
- * Given the local bounds of the layer, calculates ...
- */
- void calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer);
-
- /**
- * Given the local bounds + clip of the layer, updates current snapshot's empty/invisible
- */
- void updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect& clip,
- bool fboLayer, int alpha);
-
- /**
- * Creates a new layer stored in the specified snapshot.
- *
- * @param snapshot The snapshot associated with the new layer
- * @param left The left coordinate of the layer
- * @param top The top coordinate of the layer
- * @param right The right coordinate of the layer
- * @param bottom The bottom coordinate of the layer
- * @param alpha The translucency of the layer
- * @param mode The blending mode of the layer
- * @param flags The layer save flags
- * @param mask A mask to use when drawing the layer back, may be empty
- *
- * @return True if the layer was successfully created, false otherwise
- */
- bool createLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags, const SkPath* convexMask);
-
- /**
- * Creates a new layer stored in the specified snapshot as an FBO.
- *
- * @param layer The layer to store as an FBO
- * @param snapshot The snapshot associated with the new layer
- * @param bounds The bounds of the layer
- */
- bool createFboLayer(Layer* layer, Rect& bounds, Rect& clip);
-
- /**
- * Compose the specified layer as a region.
- *
- * @param layer The layer to compose
- * @param rect The layer's bounds
- */
- void composeLayerRegion(Layer* layer, const Rect& rect);
-
- /**
- * Restores the content in layer to the screen, swapping the blend mode,
- * specifically used in the restore() of a saveLayerAlpha().
- *
- * This allows e.g. a layer that would have been drawn on top of existing content (with SrcOver)
- * to be drawn underneath.
- *
- * This will always ignore the canvas transform.
- */
- void composeLayerRectSwapped(Layer* layer, const Rect& rect);
-
- /**
- * Draws the content in layer to the screen.
- */
- void composeLayerRect(Layer* layer, const Rect& rect);
-
- /**
- * Clears all the regions corresponding to the current list of layers.
- * This method MUST be invoked before any drawing operation.
- */
- void clearLayerRegions();
-
- /**
- * Mark the layer as dirty at the specified coordinates. The coordinates
- * are transformed with the supplied matrix.
- */
- void dirtyLayer(const float left, const float top,
- const float right, const float bottom, const Matrix4& transform);
-
- /**
- * Mark the layer as dirty at the specified coordinates.
- */
- void dirtyLayer(const float left, const float top,
- const float right, const float bottom);
-
- /**
- * Draws a colored rectangle with the specified color. The specified coordinates
- * are transformed by the current snapshot's transform matrix unless specified
- * otherwise.
- *
- * @param left The left coordinate of the rectangle
- * @param top The top coordinate of the rectangle
- * @param right The right coordinate of the rectangle
- * @param bottom The bottom coordinate of the rectangle
- * @param paint The paint containing the color, blending mode, etc.
- * @param ignoreTransform True if the current transform should be ignored
- */
- void drawColorRect(float left, float top, float right, float bottom,
- const SkPaint* paint, bool ignoreTransform = false);
-
- /**
- * Draws a series of colored rectangles with the specified color. The specified
- * coordinates are transformed by the current snapshot's transform matrix unless
- * specified otherwise.
- *
- * @param rects A list of rectangles, 4 floats (left, top, right, bottom)
- * per rectangle
- * @param paint The paint containing the color, blending mode, etc.
- * @param ignoreTransform True if the current transform should be ignored
- * @param dirty True if calling this method should dirty the current layer
- * @param clip True if the rects should be clipped, false otherwise
- */
- void drawColorRects(const float* rects, int count, const SkPaint* paint,
- bool ignoreTransform = false, bool dirty = true, bool clip = true);
-
- /**
- * Draws the shape represented by the specified path texture.
- * This method invokes drawPathTexture() but takes into account
- * the extra left/top offset and the texture offset to correctly
- * position the final shape.
- *
- * @param left The left coordinate of the shape to render
- * @param top The top coordinate of the shape to render
- * @param texture The texture reprsenting the shape
- * @param paint The paint to draw the shape with
- */
- void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint);
-
- /**
- * Renders a strip of polygons with the specified paint, used for tessellated geometry.
- *
- * @param vertexBuffer The VertexBuffer to be drawn
- * @param paint The paint to render with
- * @param flags flags with which to draw
- */
- void drawVertexBuffer(float translateX, float translateY, const VertexBuffer& vertexBuffer,
- const SkPaint* paint, int flags = 0);
-
- /**
- * Convenience for translating method
- */
- void drawVertexBuffer(const VertexBuffer& vertexBuffer,
- const SkPaint* paint, int flags = 0) {
- drawVertexBuffer(0.0f, 0.0f, vertexBuffer, paint, flags);
- }
-
- /**
- * Renders the convex hull defined by the specified path as a strip of polygons.
- *
- * @param path The hull of the path to draw
- * @param paint The paint to render with
- */
- void drawConvexPath(const SkPath& path, const SkPaint* paint);
-
- /**
- * Draws shadow layer on text (with optional positions).
- *
- * @param paint The paint to draw the shadow with
- * @param text The text to draw
- * @param count The number of glyphs in the text
- * @param positions The x, y positions of individual glyphs (or NULL)
- * @param fontRenderer The font renderer object
- * @param alpha The alpha value for drawing the shadow
- * @param x The x coordinate where the shadow will be drawn
- * @param y The y coordinate where the shadow will be drawn
- */
- void drawTextShadow(const SkPaint* paint, const glyph_t* glyphs, int count,
- const float* positions, FontRenderer& fontRenderer, int alpha,
- float x, float y);
-
- /**
- * Draws a path texture. Path textures are alpha8 bitmaps that need special
- * compositing to apply colors/filters/etc.
- *
- * @param texture The texture to render
- * @param x The x coordinate where the texture will be drawn
- * @param y The y coordinate where the texture will be drawn
- * @param paint The paint to draw the texture with
- */
- void drawPathTexture(PathTexture* texture, float x, float y, const SkPaint* paint);
-
- /**
- * Resets the texture coordinates stored in mMeshVertices. Setting the values
- * back to default is achieved by calling:
- *
- * resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
- *
- * @param u1 The left coordinate of the texture
- * @param v1 The bottom coordinate of the texture
- * @param u2 The right coordinate of the texture
- * @param v2 The top coordinate of the texture
- */
- void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2);
-
- /**
- * Returns true if the specified paint will draw invisible text.
- */
- bool canSkipText(const SkPaint* paint) const;
-
- bool updateLayer(Layer* layer, bool inFrame);
- void updateLayers();
- void flushLayers();
-
-#if DEBUG_LAYERS_AS_REGIONS
- /**
- * Renders the specified region as a series of rectangles. This method
- * is used for debugging only.
- */
- void drawRegionRectsDebug(const Region& region);
-#endif
-
- /**
- * Renders the specified region as a series of rectangles. The region
- * must be in screen-space coordinates.
- */
- void drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty = false);
-
- /**
- * Draws the current clip region if any. Only when DEBUG_CLIP_REGIONS
- * is turned on.
- */
- void debugClip();
-
- void debugOverdraw(bool enable, bool clear);
- void renderOverdraw();
- void countOverdraw();
-
- /**
- * Should be invoked every time the glScissor is modified.
- */
- inline void dirtyClip() { mState.setDirtyClip(true); }
-
- inline const UvMapper& getMapper(const Texture* texture) {
- return texture && texture->uvMapper ? *texture->uvMapper : mUvMapper;
- }
-
- /**
- * Returns a texture object for the specified bitmap. The texture can
- * come from the texture cache or an atlas. If this method returns
- * NULL, the texture could not be found and/or allocated.
- */
- Texture* getTexture(const SkBitmap* bitmap);
-
- bool reportAndClearDirty() { bool ret = mDirty; mDirty = false; return ret; }
- inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); }
- inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); }
-
- // State used to define the clipping region
- Rect mTilingClip;
- // Is the target render surface opaque
- bool mOpaque;
- // Is a frame currently being rendered
- bool mFrameStarted;
-
- // Default UV mapper
- const UvMapper mUvMapper;
-
- // List of rectangles to clear after saveLayer() is invoked
- std::vector<Rect> mLayers;
- // List of layers to update at the beginning of a frame
- std::vector< sp<Layer> > mLayerUpdates;
-
- // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
- // Properties.h
- bool mScissorOptimizationDisabled;
-
- bool mSkipOutlineClip;
-
- // True if anything has been drawn since the last call to
- // reportAndClearDirty()
- bool mDirty;
-
- // Lighting + shadows
- Vector3 mLightCenter;
- float mLightRadius;
- uint8_t mAmbientShadowAlpha;
- uint8_t mSpotShadowAlpha;
-
- // Paths kept alive for the duration of the frame
- std::vector<std::unique_ptr<SkPath>> mTempPaths;
-
- /**
- * Initial transform for a rendering pass; transform from global device
- * coordinates to the current RenderNode's drawing content coordinates,
- * with the RenderNode's RenderProperty transforms already applied.
- * Calling setMatrix(mBaseTransform) will result in drawing at the origin
- * of the DisplayList's recorded surface prior to any Canvas
- * transformation.
- */
- Matrix4 mBaseTransform;
-
- friend class Layer;
- friend class TextDrawFunctor;
- friend class DrawBitmapOp;
- friend class DrawPatchOp;
-
-}; // class OpenGLRenderer
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_OPENGL_RENDERER_H
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index bd6feb9fc762..a6c281dc9839 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -43,21 +43,6 @@ PatchCache::~PatchCache() {
clear();
}
-void PatchCache::init() {
- bool created = false;
- if (!mMeshBuffer) {
- glGenBuffers(1, &mMeshBuffer);
- created = true;
- }
-
- mRenderState.meshState().bindMeshBuffer(mMeshBuffer);
- mRenderState.meshState().resetVertexPointers();
-
- if (created) {
- createVertexBuffer();
- }
-}
-
///////////////////////////////////////////////////////////////////////////////
// Caching
///////////////////////////////////////////////////////////////////////////////
@@ -80,8 +65,7 @@ void PatchCache::clear() {
clearCache();
if (mMeshBuffer) {
- mRenderState.meshState().unbindMeshBuffer();
- glDeleteBuffers(1, &mMeshBuffer);
+ mRenderState.meshState().deleteMeshBuffer(mMeshBuffer);
mMeshBuffer = 0;
mSize = 0;
}
@@ -170,7 +154,8 @@ void PatchCache::clearGarbage() {
}
void PatchCache::createVertexBuffer() {
- glBufferData(GL_ARRAY_BUFFER, mMaxSize, nullptr, GL_DYNAMIC_DRAW);
+ mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer,
+ mMaxSize, nullptr, GL_DYNAMIC_DRAW);
mSize = 0;
mFreeBlocks = new BufferBlock(0, mMaxSize);
mGenerationId++;
@@ -182,7 +167,9 @@ void PatchCache::createVertexBuffer() {
*/
void PatchCache::setupMesh(Patch* newMesh) {
// This call ensures the VBO exists and that it is bound
- init();
+ if (!mMeshBuffer) {
+ createVertexBuffer();
+ }
// If we're running out of space, let's clear the entire cache
uint32_t size = newMesh->getSize();
@@ -215,7 +202,9 @@ void PatchCache::setupMesh(Patch* newMesh) {
// Copy the 9patch mesh in the VBO
newMesh->positionOffset = (GLintptr) (block->offset);
newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset;
- glBufferSubData(GL_ARRAY_BUFFER, newMesh->positionOffset, size, newMesh->vertices.get());
+
+ mRenderState.meshState().updateMeshBufferSubData(mMeshBuffer, newMesh->positionOffset, size,
+ newMesh->vertices.get());
// Remove the block since we've used it entirely
if (block->size == size) {
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 66ef6a0279ba..4e587fb719d4 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_PATCH_CACHE_H
-#define ANDROID_HWUI_PATCH_CACHE_H
+#pragma once
#include <GLES2/gl2.h>
@@ -48,12 +47,12 @@ class Patch;
///////////////////////////////////////////////////////////////////////////////
class Caches;
+class RenderState;
class PatchCache {
public:
PatchCache(RenderState& renderState);
~PatchCache();
- void init();
const Patch* get(const AssetAtlas::Entry* entry,
const uint32_t bitmapWidth, const uint32_t bitmapHeight,
@@ -187,5 +186,3 @@ private:
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_PATCH_CACHE_H
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 6f68c2bdff80..93b2e15a6590 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -63,8 +63,10 @@ int Properties::overrideSpotShadowStrength = -1;
ProfileType Properties::sProfileType = ProfileType::None;
bool Properties::sDisableProfileBars = false;
+RenderPipelineType Properties::sRenderPipelineType = RenderPipelineType::NotInitialized;
bool Properties::waitForGpuCompletion = false;
+bool Properties::forceDrawFrame = false;
bool Properties::filterOutTestOverhead = false;
@@ -204,5 +206,21 @@ ProfileType Properties::getProfileType() {
return sProfileType;
}
+RenderPipelineType Properties::getRenderPipelineType() {
+ if (RenderPipelineType::NotInitialized != sRenderPipelineType) {
+ return sRenderPipelineType;
+ }
+ char prop[PROPERTY_VALUE_MAX];
+ property_get(PROPERTY_DEFAULT_RENDERER, prop, "opengl");
+ if (!strcmp(prop, "skiagl") ) {
+ sRenderPipelineType = RenderPipelineType::SkiaGL;
+ } else if (!strcmp(prop, "skiavulkan") ) {
+ sRenderPipelineType = RenderPipelineType::SkiaVulkan;
+ } else { //"opengl"
+ sRenderPipelineType = RenderPipelineType::OpenGL;
+ }
+ return sRenderPipelineType;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 8fec42972c2f..133ae809ab2c 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -20,8 +20,7 @@
#include <cutils/properties.h>
/**
- * This file contains the list of system properties used to configure
- * the OpenGLRenderer.
+ * This file contains the list of system properties used to configure libhwui.
*/
namespace android {
@@ -153,6 +152,12 @@ enum DebugLevel {
#define PROPERTY_FILTER_TEST_OVERHEAD "debug.hwui.filter_test_overhead"
+/**
+ * Allows to set rendering pipeline mode to OpenGL (default), Skia OpenGL
+ * or Vulkan.
+ */
+#define PROPERTY_DEFAULT_RENDERER "debug.hwui.default_renderer"
+
///////////////////////////////////////////////////////////////////////////////
// Runtime configuration properties
///////////////////////////////////////////////////////////////////////////////
@@ -161,7 +166,7 @@ enum DebugLevel {
* Used to enable/disable scissor optimization. The accepted values are
* "true" and "false". The default value is "false".
*
- * When scissor optimization is enabled, OpenGLRenderer will attempt to
+ * When scissor optimization is enabled, libhwui will attempt to
* minimize the use of scissor by selectively enabling and disabling the
* GL scissor test.
* When the optimization is disabled, OpenGLRenderer will keep the GL
@@ -245,6 +250,13 @@ enum class StencilClipDebug {
ShowRegion
};
+enum class RenderPipelineType {
+ OpenGL = 0,
+ SkiaGL,
+ SkiaVulkan,
+ NotInitialized = 128
+};
+
/**
* Renderthread-only singleton which manages several static rendering properties. Most of these
* are driven by system properties which are queried once at initialization, and again if init()
@@ -292,9 +304,11 @@ public:
static int overrideSpotShadowStrength;
static ProfileType getProfileType();
+ static RenderPipelineType getRenderPipelineType();
// Should be used only by test apps
static bool waitForGpuCompletion;
+ static bool forceDrawFrame;
// Should only be set by automated tests to try and filter out
// any overhead they add
@@ -303,6 +317,7 @@ public:
private:
static ProfileType sProfileType;
static bool sDisableProfileBars;
+ static RenderPipelineType sRenderPipelineType;
}; // class Caches
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 55f823dfe226..60eadff66ad1 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -19,6 +19,7 @@
#include "Caches.h"
#include "Image.h"
#include "GlopBuilder.h"
+#include "Layer.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "utils/GLUtils.h"
@@ -30,14 +31,8 @@
namespace android {
namespace uirenderer {
-CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
- Surface& surface, SkBitmap* bitmap) {
- // TODO: Clean this up and unify it with LayerRenderer::copyLayer,
- // of which most of this is copied from.
- renderThread.eglManager().initialize();
-
- Caches& caches = Caches::getInstance();
- RenderState& renderState = renderThread.renderState();
+static CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
+ Texture& sourceTexture, Matrix4& texTransform, SkBitmap* bitmap) {
int destWidth = bitmap->width();
int destHeight = bitmap->height();
if (destWidth > caches.maxTextureSize
@@ -98,6 +93,44 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
+ {
+ // Draw & readback
+ renderState.setViewport(destWidth, destHeight);
+ renderState.scissor().setEnabled(false);
+ renderState.blend().syncEnabled();
+ renderState.stencil().disable();
+
+ Glop glop;
+ GlopBuilder(renderState, caches, &glop)
+ .setRoundRectClipState(nullptr)
+ .setMeshTexturedUnitQuad(nullptr)
+ .setFillExternalTexture(sourceTexture, texTransform)
+ .setTransform(Matrix4::identity(), TransformFlags::None)
+ .setModelViewMapUnitToRect(Rect(destWidth, destHeight))
+ .build();
+ Matrix4 ortho;
+ ortho.loadOrtho(destWidth, destHeight);
+ renderState.render(glop, ortho);
+
+ glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
+ type, bitmap->getPixels());
+ }
+
+ // Cleanup
+ caches.textureState().deleteTexture(texture);
+ renderState.deleteFramebuffer(fbo);
+
+ GL_CHECKPOINT(MODERATE);
+
+ return CopyResult::Success;
+}
+
+CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
+ Surface& surface, SkBitmap* bitmap) {
+ renderThread.eglManager().initialize();
+
+ Caches& caches = Caches::getInstance();
+
// Setup the source
sp<GraphicBuffer> sourceBuffer;
sp<Fence> sourceFence;
@@ -142,7 +175,7 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
GLuint sourceTexId;
// Create a 2D texture to sample from the EGLImage
glGenTextures(1, &sourceTexId);
- Caches::getInstance().textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
+ caches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, sourceImage);
GLenum status = GL_NO_ERROR;
@@ -155,37 +188,13 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
sourceTexture.wrap(sourceTexId,
sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);
- {
- // Draw & readback
- renderState.setViewport(destWidth, destHeight);
- renderState.scissor().setEnabled(false);
- renderState.blend().syncEnabled();
- renderState.stencil().disable();
-
- Rect destRect(destWidth, destHeight);
- Glop glop;
- GlopBuilder(renderState, caches, &glop)
- .setRoundRectClipState(nullptr)
- .setMeshTexturedUnitQuad(nullptr)
- .setFillExternalTexture(sourceTexture, texTransform)
- .setTransform(Matrix4::identity(), TransformFlags::None)
- .setModelViewMapUnitToRect(destRect)
- .build();
- Matrix4 ortho;
- ortho.loadOrtho(destWidth, destHeight);
- renderState.render(glop, ortho);
-
- glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
- type, bitmap->getPixels());
- }
-
- // Cleanup
- caches.textureState().deleteTexture(texture);
- renderState.deleteFramebuffer(fbo);
-
- GL_CHECKPOINT(MODERATE);
+ return copyTextureInto(caches, renderThread.renderState(), sourceTexture, texTransform, bitmap);
+}
- return CopyResult::Success;
+CopyResult Readback::copyTextureLayerInto(renderthread::RenderThread& renderThread,
+ Layer& layer, SkBitmap* bitmap) {
+ return copyTextureInto(Caches::getInstance(), renderThread.renderState(),
+ layer.getTexture(), layer.getTexTransform(), bitmap);
}
} // namespace uirenderer
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index a112c42988c0..bd73734949f3 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -24,6 +24,8 @@
namespace android {
namespace uirenderer {
+class Layer;
+
// Keep in sync with PixelCopy.java codes
enum class CopyResult {
Success = 0,
@@ -36,8 +38,18 @@ enum class CopyResult {
class Readback {
public:
+ /**
+ * Copies the surface's most recently queued buffer into the provided bitmap.
+ */
static CopyResult copySurfaceInto(renderthread::RenderThread& renderThread,
Surface& surface, SkBitmap* bitmap);
+
+ /**
+ * Copies the TextureLayer's texture content (thus, the currently rendering buffer) into the
+ * provided bitmap.
+ */
+ static CopyResult copyTextureLayerInto(renderthread::RenderThread& renderThread,
+ Layer& layer, SkBitmap* bitmap);
};
} // namespace uirenderer
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index aee9d6370083..f3078ce58503 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_RECORDED_OP_H
-#define ANDROID_HWUI_RECORDED_OP_H
+#pragma once
-#include "RecordedOp.h"
#include "font/FontUtil.h"
#include "Matrix.h"
#include "Rect.h"
#include "RenderNode.h"
#include "TessellationCache.h"
#include "utils/LinearAllocator.h"
+#include "utils/PaintUtils.h"
#include "Vector.h"
#include <androidfw/ResourceTypes.h>
@@ -529,5 +528,3 @@ struct LayerOp : RecordedOp {
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_RECORDED_OP_H
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index cbefccb955de..4528a3876177 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -43,7 +43,6 @@ void RecordingCanvas::resetRecording(int width, int height) {
mState.initializeRecordingSaveStack(width, height);
mDeferredBarrierType = DeferredBarrierType::InOrder;
- mState.setDirtyClip(false);
}
DisplayList* RecordingCanvas::finishRecording() {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6facf20b025c..ff277d111197 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -16,19 +16,17 @@
#include "RenderNode.h"
+#include "BakedOpRenderer.h"
#include "DamageAccumulator.h"
#include "Debug.h"
-#if HWUI_NEW_OPS
-#include "BakedOpRenderer.h"
-#include "RecordedOp.h"
-#include "OpDumper.h"
-#endif
-#include "DisplayListOp.h"
#include "LayerRenderer.h"
-#include "OpenGLRenderer.h"
+#include "OpDumper.h"
+#include "RecordedOp.h"
#include "TreeInfo.h"
#include "utils/MathUtils.h"
#include "utils/TraceUtils.h"
+#include "VectorDrawable.h"
+#include "renderstate/RenderState.h"
#include "renderthread/CanvasContext.h"
#include "protos/hwui.pb.h"
@@ -41,23 +39,6 @@
namespace android {
namespace uirenderer {
-void RenderNode::debugDumpLayers(const char* prefix) {
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("TODO: dump layer");
-#else
- if (mLayer) {
- ALOGD("%sNode %p (%s) has layer %p (fbo = %u, wasBuildLayered = %s)",
- prefix, this, getName(), mLayer, mLayer->getFbo(),
- mLayer->wasBuildLayered ? "true" : "false");
- }
-#endif
- if (mDisplayList) {
- for (auto&& child : mDisplayList->getChildren()) {
- child->renderNode->debugDumpLayers(prefix);
- }
- }
-}
-
RenderNode::RenderNode()
: mDirtyPropertyFields(0)
, mNeedsDisplayListSync(false)
@@ -70,15 +51,7 @@ RenderNode::RenderNode()
RenderNode::~RenderNode() {
deleteDisplayList(nullptr);
delete mStagingDisplayList;
-#if HWUI_NEW_OPS
LOG_ALWAYS_FATAL_IF(mLayer, "layer missed detachment!");
-#else
- if (mLayer) {
- ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer);
- mLayer->postDecStrong();
- mLayer = nullptr;
- }
-#endif
}
void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
@@ -96,7 +69,6 @@ void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* o
* This function is a simplified version of replay(), where we simply retrieve and log the
* display list. This function should remain in sync with the replay() function.
*/
-#if HWUI_NEW_OPS
void RenderNode::output(uint32_t level, const char* label) {
ALOGD("%s (%s %p%s%s%s%s%s)",
label,
@@ -123,26 +95,6 @@ void RenderNode::output(uint32_t level, const char* label) {
}
ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this);
}
-#else
-void RenderNode::output(uint32_t level) {
- ALOGD("%*sStart display list (%p, %s%s%s%s%s%s)", (level - 1) * 2, "", this,
- getName(),
- (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""),
- (properties().hasShadow() ? ", casting shadow" : ""),
- (isRenderable() ? "" : ", empty"),
- (properties().getProjectBackwards() ? ", projected" : ""),
- (mLayer != nullptr ? ", on HW Layer" : ""));
- ALOGD("%*s%s %d", level * 2, "", "Save", SaveFlags::MatrixClip);
- properties().debugOutputProperties(level);
- if (mDisplayList) {
- // TODO: consider printing the chunk boundaries here
- for (auto&& op : mDisplayList->getOps()) {
- op->output(level, DisplayListOp::kOpLogFlag_Recurse);
- }
- }
- ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
- }
-#endif
void RenderNode::copyTo(proto::RenderNode *pnode) {
pnode->set_id(static_cast<uint64_t>(
@@ -272,29 +224,17 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) {
}
}
-static layer_t* createLayer(RenderState& renderState, uint32_t width, uint32_t height) {
-#if HWUI_NEW_OPS
+static OffscreenBuffer* createLayer(RenderState& renderState, uint32_t width, uint32_t height) {
return renderState.layerPool().get(renderState, width, height);
-#else
- return LayerRenderer::createRenderLayer(renderState, width, height);
-#endif
}
-static void destroyLayer(layer_t* layer) {
-#if HWUI_NEW_OPS
+static void destroyLayer(OffscreenBuffer* layer) {
RenderState& renderState = layer->renderState;
renderState.layerPool().putOrDelete(layer);
-#else
- LayerRenderer::destroyLayer(layer);
-#endif
}
-static bool layerMatchesWidthAndHeight(layer_t* layer, int width, int height) {
-#if HWUI_NEW_OPS
+static bool layerMatchesWidthAndHeight(OffscreenBuffer* layer, int width, int height) {
return layer->viewportWidth == (uint32_t) width && layer->viewportHeight == (uint32_t)height;
-#else
- return layer->layer.getWidth() == width && layer->layer.getHeight() == height;
-#endif
}
void RenderNode::pushLayerUpdate(TreeInfo& info) {
@@ -315,22 +255,15 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
bool transformUpdateNeeded = false;
if (!mLayer) {
mLayer = createLayer(info.canvasContext.getRenderState(), getWidth(), getHeight());
-#if !HWUI_NEW_OPS
- applyLayerPropertiesToLayer(info);
-#endif
damageSelf(info);
transformUpdateNeeded = true;
} else if (!layerMatchesWidthAndHeight(mLayer, getWidth(), getHeight())) {
-#if HWUI_NEW_OPS
// TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering)
// Or, ideally, maintain damage between frames on node/layer so ordering is always correct
RenderState& renderState = mLayer->renderState;
if (properties().fitsOnLayer()) {
mLayer = renderState.layerPool().resize(mLayer, getWidth(), getHeight());
} else {
-#else
- if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) {
-#endif
destroyLayer(mLayer);
mLayer = nullptr;
}
@@ -365,19 +298,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
mLayer->setWindowTransform(windowTransform);
}
-#if HWUI_NEW_OPS
info.layerUpdateQueue->enqueueLayerWithDamage(this, dirty);
-#else
- if (dirty.intersect(0, 0, getWidth(), getHeight())) {
- dirty.roundOut(&dirty);
- mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom);
- }
- // This is not inside the above if because we may have called
- // updateDeferred on a previous prepare pass that didn't have a renderer
- if (info.renderer && mLayer->deferredUpdateScheduled) {
- info.renderer->pushLayerUpdate(mLayer);
- }
-#endif
// There might be prefetched layers that need to be accounted for.
// That might be us, so tell CanvasContext that this layer is in the
@@ -453,9 +374,6 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
damageSelf(info);
info.damageAccumulator->popTransform();
syncProperties();
-#if !HWUI_NEW_OPS
- applyLayerPropertiesToLayer(info);
-#endif
// We could try to be clever and only re-damage if the matrix changed.
// However, we don't need to worry about that. The cost of over-damaging
// here is only going to be a single additional map rect of this node
@@ -466,17 +384,6 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
}
}
-#if !HWUI_NEW_OPS
-void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) {
- if (CC_LIKELY(!mLayer)) return;
-
- const LayerProperties& props = properties().layerProperties();
- mLayer->setAlpha(props.alpha(), props.xferMode());
- mLayer->setColorFilter(props.colorFilter());
- mLayer->setBlend(props.needsBlending());
-}
-#endif
-
void RenderNode::syncDisplayList(TreeInfo* info) {
// Make sure we inc first so that we don't fluctuate between 0 and 1,
// which would thrash the layer cache
@@ -529,15 +436,8 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL
}
for (auto&& op : subtree->getChildren()) {
RenderNode* childNode = op->renderNode;
-#if HWUI_NEW_OPS
info.damageAccumulator->pushTransform(&op->localMatrix);
bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
-#else
- info.damageAccumulator->pushTransform(&op->localMatrix);
- bool childFunctorsNeedLayer = functorsNeedLayer
- // Recorded with non-rect clip, or canvas-rotated by parent
- || op->mRecordedWithPotentialStencilClip;
-#endif
childNode->prepareTreeImpl(info, childFunctorsNeedLayer);
info.damageAccumulator->popTransform();
}
@@ -579,84 +479,6 @@ void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) {
}
}
-/*
- * For property operations, we pass a savecount of 0, since the operations aren't part of the
- * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
- * base saveCount (i.e., how RestoreToCount uses saveCount + properties().getCount())
- */
-#define PROPERTY_SAVECOUNT 0
-
-template <class T>
-void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
-#if DEBUG_DISPLAY_LIST
- properties().debugOutputProperties(handler.level() + 1);
-#endif
- if (properties().getLeft() != 0 || properties().getTop() != 0) {
- renderer.translate(properties().getLeft(), properties().getTop());
- }
- if (properties().getStaticMatrix()) {
- renderer.concatMatrix(*properties().getStaticMatrix());
- } else if (properties().getAnimationMatrix()) {
- renderer.concatMatrix(*properties().getAnimationMatrix());
- }
- if (properties().hasTransformMatrix()) {
- if (properties().isTransformTranslateOnly()) {
- renderer.translate(properties().getTranslationX(), properties().getTranslationY());
- } else {
- renderer.concatMatrix(*properties().getTransformMatrix());
- }
- }
- const bool isLayer = properties().effectiveLayerType() != LayerType::None;
- int clipFlags = properties().getClippingFlags();
- if (properties().getAlpha() < 1) {
- if (isLayer) {
- clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
- }
- if (CC_LIKELY(isLayer || !properties().getHasOverlappingRendering())) {
- // simply scale rendering content's alpha
- renderer.scaleAlpha(properties().getAlpha());
- } else {
- // savelayer needed to create an offscreen buffer
- Rect layerBounds(0, 0, getWidth(), getHeight());
- if (clipFlags) {
- properties().getClippingRectForFlags(clipFlags, &layerBounds);
- clipFlags = 0; // all clipping done by savelayer
- }
- SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
- layerBounds.left, layerBounds.top,
- layerBounds.right, layerBounds.bottom,
- (int) (properties().getAlpha() * 255),
- SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer);
- handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
- }
-
- if (CC_UNLIKELY(ATRACE_ENABLED() && properties().promotedToLayer())) {
- // pretend alpha always causes savelayer to warn about
- // performance problem affecting old versions
- ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", getName(),
- static_cast<int>(getWidth()),
- static_cast<int>(getHeight()));
- }
- }
- if (clipFlags) {
- Rect clipRect;
- properties().getClippingRectForFlags(clipFlags, &clipRect);
- ClipRectOp* op = new (handler.allocator()) ClipRectOp(
- clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkRegion::kIntersect_Op);
- handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
- }
-
- // TODO: support nesting round rect clips
- if (mProperties.getRevealClip().willClip()) {
- Rect bounds;
- mProperties.getRevealClip().getBounds(&bounds);
- renderer.setClippingRoundRect(handler.allocator(), bounds, mProperties.getRevealClip().getRadius());
- } else if (mProperties.getOutline().willClip()) {
- renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline()));
- }
-}
-
/**
* Apply property-based transformations to input matrix
*
@@ -717,14 +539,14 @@ void RenderNode::computeOrdering() {
// transform properties are applied correctly to top level children
if (mDisplayList == nullptr) return;
for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
- renderNodeOp_t* childOp = mDisplayList->getChildren()[i];
+ RenderNodeOp* childOp = mDisplayList->getChildren()[i];
childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
}
}
void RenderNode::computeOrderingImpl(
- renderNodeOp_t* opState,
- std::vector<renderNodeOp_t*>* compositedChildrenOfProjectionSurface,
+ RenderNodeOp* opState,
+ std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
const mat4* transformFromProjectionSurface) {
mProjectedNodes.clear();
if (mDisplayList == nullptr || mDisplayList->isEmpty()) return;
@@ -748,10 +570,10 @@ void RenderNode::computeOrderingImpl(
const bool isProjectionReceiver = mDisplayList->projectionReceiveIndex >= 0;
bool haveAppliedPropertiesToProjection = false;
for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
- renderNodeOp_t* childOp = mDisplayList->getChildren()[i];
+ RenderNodeOp* childOp = mDisplayList->getChildren()[i];
RenderNode* child = childOp->renderNode;
- std::vector<renderNodeOp_t*>* projectionChildren = nullptr;
+ std::vector<RenderNodeOp*>* projectionChildren = nullptr;
const mat4* projectionTransform = nullptr;
if (isProjectionReceiver && !child->properties().getProjectBackwards()) {
// if receiving projections, collect projecting descendant
@@ -774,372 +596,5 @@ void RenderNode::computeOrderingImpl(
}
}
-class DeferOperationHandler {
-public:
- DeferOperationHandler(DeferStateStruct& deferStruct, int level)
- : mDeferStruct(deferStruct), mLevel(level) {}
- inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
- operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds);
- }
- inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); }
- inline void startMark(const char* name) {} // do nothing
- inline void endMark() {}
- inline int level() { return mLevel; }
- inline int replayFlags() { return mDeferStruct.mReplayFlags; }
- inline SkPath* allocPathForFrame() { return mDeferStruct.allocPathForFrame(); }
-
-private:
- DeferStateStruct& mDeferStruct;
- const int mLevel;
-};
-
-void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
- DeferOperationHandler handler(deferStruct, level);
- issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
-}
-
-class ReplayOperationHandler {
-public:
- ReplayOperationHandler(ReplayStateStruct& replayStruct, int level)
- : mReplayStruct(replayStruct), mLevel(level) {}
- inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
- mReplayStruct.mRenderer.eventMark(operation->name());
-#endif
- operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
- }
- inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); }
- inline void startMark(const char* name) {
- mReplayStruct.mRenderer.startMark(name);
- }
- inline void endMark() {
- mReplayStruct.mRenderer.endMark();
- }
- inline int level() { return mLevel; }
- inline int replayFlags() { return mReplayStruct.mReplayFlags; }
- inline SkPath* allocPathForFrame() { return mReplayStruct.allocPathForFrame(); }
-
-private:
- ReplayStateStruct& mReplayStruct;
- const int mLevel;
-};
-
-void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
- ReplayOperationHandler handler(replayStruct, level);
- issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
-}
-
-void RenderNode::buildZSortedChildList(const DisplayList::Chunk& chunk,
- std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
-#if !HWUI_NEW_OPS
- if (chunk.beginChildIndex == chunk.endChildIndex) return;
-
- for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
- DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
- RenderNode* child = childOp->renderNode;
- float childZ = child->properties().getZ();
-
- if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
- zTranslatedNodes.push_back(ZDrawRenderNodeOpPair(childZ, childOp));
- childOp->skipInOrderDraw = true;
- } else if (!child->properties().getProjectBackwards()) {
- // regular, in order drawing DisplayList
- childOp->skipInOrderDraw = false;
- }
- }
-
- // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
- std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
-#endif
-}
-
-template <class T>
-void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
- if (properties().getAlpha() <= 0.0f
- || properties().getOutline().getAlpha() <= 0.0f
- || !properties().getOutline().getPath()
- || properties().getScaleX() == 0
- || properties().getScaleY() == 0) {
- // no shadow to draw
- return;
- }
-
- mat4 shadowMatrixXY(transformFromParent);
- applyViewPropertyTransforms(shadowMatrixXY);
-
- // Z matrix needs actual 3d transformation, so mapped z values will be correct
- mat4 shadowMatrixZ(transformFromParent);
- applyViewPropertyTransforms(shadowMatrixZ, true);
-
- const SkPath* casterOutlinePath = properties().getOutline().getPath();
- const SkPath* revealClipPath = properties().getRevealClip().getPath();
- if (revealClipPath && revealClipPath->isEmpty()) return;
-
- float casterAlpha = properties().getAlpha() * properties().getOutline().getAlpha();
-
-
- // holds temporary SkPath to store the result of intersections
- SkPath* frameAllocatedPath = nullptr;
- const SkPath* outlinePath = casterOutlinePath;
-
- // intersect the outline with the reveal clip, if present
- if (revealClipPath) {
- frameAllocatedPath = handler.allocPathForFrame();
-
- Op(*outlinePath, *revealClipPath, kIntersect_SkPathOp, frameAllocatedPath);
- outlinePath = frameAllocatedPath;
- }
-
- // intersect the outline with the clipBounds, if present
- if (properties().getClippingFlags() & CLIP_TO_CLIP_BOUNDS) {
- if (!frameAllocatedPath) {
- frameAllocatedPath = handler.allocPathForFrame();
- }
-
- Rect clipBounds;
- properties().getClippingRectForFlags(CLIP_TO_CLIP_BOUNDS, &clipBounds);
- SkPath clipBoundsPath;
- clipBoundsPath.addRect(clipBounds.left, clipBounds.top,
- clipBounds.right, clipBounds.bottom);
-
- Op(*outlinePath, clipBoundsPath, kIntersect_SkPathOp, frameAllocatedPath);
- outlinePath = frameAllocatedPath;
- }
-
- DisplayListOp* shadowOp = new (handler.allocator()) DrawShadowOp(
- shadowMatrixXY, shadowMatrixZ, casterAlpha, outlinePath);
- handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-}
-
-#define SHADOW_DELTA 0.1f
-
-template <class T>
-void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode,
- const Matrix4& initialTransform, const std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
- OpenGLRenderer& renderer, T& handler) {
- const int size = zTranslatedNodes.size();
- if (size == 0
- || (mode == ChildrenSelectMode::NegativeZChildren && zTranslatedNodes[0].key > 0.0f)
- || (mode == ChildrenSelectMode::PositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) {
- // no 3d children to draw
- return;
- }
-
- // Apply the base transform of the parent of the 3d children. This isolates
- // 3d children of the current chunk from transformations made in previous chunks.
- int rootRestoreTo = renderer.save(SaveFlags::Matrix);
- renderer.setGlobalMatrix(initialTransform);
-
- /**
- * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
- * with very similar Z heights to draw together.
- *
- * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are
- * underneath both, and neither's shadow is drawn on top of the other.
- */
- const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes);
- size_t drawIndex, shadowIndex, endIndex;
- if (mode == ChildrenSelectMode::NegativeZChildren) {
- drawIndex = 0;
- endIndex = nonNegativeIndex;
- shadowIndex = endIndex; // draw no shadows
- } else {
- drawIndex = nonNegativeIndex;
- endIndex = size;
- shadowIndex = drawIndex; // potentially draw shadow for each pos Z child
- }
-
- DISPLAY_LIST_LOGD("%*s%d %s 3d children:", (handler.level() + 1) * 2, "",
- endIndex - drawIndex, mode == kNegativeZChildren ? "negative" : "positive");
-
- float lastCasterZ = 0.0f;
- while (shadowIndex < endIndex || drawIndex < endIndex) {
- if (shadowIndex < endIndex) {
- DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value;
- RenderNode* caster = casterOp->renderNode;
- const float casterZ = zTranslatedNodes[shadowIndex].key;
- // attempt to render the shadow if the caster about to be drawn is its caster,
- // OR if its caster's Z value is similar to the previous potential caster
- if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
- caster->issueDrawShadowOperation(casterOp->localMatrix, handler);
-
- lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
- shadowIndex++;
- continue;
- }
- }
-
- // only the actual child DL draw needs to be in save/restore,
- // since it modifies the renderer's matrix
- int restoreTo = renderer.save(SaveFlags::Matrix);
-
- DrawRenderNodeOp* childOp = zTranslatedNodes[drawIndex].value;
-
- renderer.concatMatrix(childOp->localMatrix);
- childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone
- handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds());
- childOp->skipInOrderDraw = true;
-
- renderer.restoreToCount(restoreTo);
- drawIndex++;
- }
- renderer.restoreToCount(rootRestoreTo);
-}
-
-template <class T>
-void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
- DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size());
- const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
- int restoreTo = renderer.getSaveCount();
-
- LinearAllocator& alloc = handler.allocator();
- handler(new (alloc) SaveOp(SaveFlags::MatrixClip),
- PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
- // Transform renderer to match background we're projecting onto
- // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
- const DisplayListOp* op =
-#if HWUI_NEW_OPS
- nullptr;
- LOG_ALWAYS_FATAL("unsupported");
-#else
- (mDisplayList->getOps()[mDisplayList->projectionReceiveIndex]);
-#endif
- const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
- const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
- renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
-
- // If the projection receiver has an outline, we mask projected content to it
- // (which we know, apriori, are all tessellated paths)
- renderer.setProjectionPathMask(alloc, projectionReceiverOutline);
-
- // draw projected nodes
- for (size_t i = 0; i < mProjectedNodes.size(); i++) {
- renderNodeOp_t* childOp = mProjectedNodes[i];
-
- // matrix save, concat, and restore can be done safely without allocating operations
- int restoreTo = renderer.save(SaveFlags::Matrix);
- renderer.concatMatrix(childOp->transformFromCompositingAncestor);
- childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone
- handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds());
- childOp->skipInOrderDraw = true;
- renderer.restoreToCount(restoreTo);
- }
-
- handler(new (alloc) RestoreToCountOp(restoreTo),
- PROPERTY_SAVECOUNT, properties().getClipToBounds());
-}
-
-/**
- * This function serves both defer and replay modes, and will organize the displayList's component
- * operations for a single frame:
- *
- * Every 'simple' state operation that affects just the matrix and alpha (or other factors of
- * DeferredDisplayState) may be issued directly to the renderer, but complex operations (with custom
- * defer logic) and operations in displayListOps are issued through the 'handler' which handles the
- * defer vs replay logic, per operation
- */
-template <class T>
-void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
- if (mDisplayList->isEmpty()) {
- DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", handler.level() * 2, "",
- this, getName());
- return;
- }
-
-#if HWUI_NEW_OPS
- const bool drawLayer = false;
-#else
- const bool drawLayer = (mLayer && (&renderer != mLayer->renderer.get()));
-#endif
- // If we are updating the contents of mLayer, we don't want to apply any of
- // the RenderNode's properties to this issueOperations pass. Those will all
- // be applied when the layer is drawn, aka when this is true.
- const bool useViewProperties = (!mLayer || drawLayer);
- if (useViewProperties) {
- const Outline& outline = properties().getOutline();
- if (properties().getAlpha() <= 0
- || (outline.getShouldClip() && outline.isEmpty())
- || properties().getScaleX() == 0
- || properties().getScaleY() == 0) {
- DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", handler.level() * 2, "",
- this, getName());
- return;
- }
- }
-
- handler.startMark(getName());
-
-#if DEBUG_DISPLAY_LIST
- const Rect& clipRect = renderer.getLocalClipBounds();
- DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), localClipBounds: %.0f, %.0f, %.0f, %.0f",
- handler.level() * 2, "", this, getName(),
- clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-#endif
-
- LinearAllocator& alloc = handler.allocator();
- int restoreTo = renderer.getSaveCount();
- handler(new (alloc) SaveOp(SaveFlags::MatrixClip),
- PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
- DISPLAY_LIST_LOGD("%*sSave %d %d", (handler.level() + 1) * 2, "",
- SaveFlags::MatrixClip, restoreTo);
-
- if (useViewProperties) {
- setViewProperties<T>(renderer, handler);
- }
-
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("legacy op traversal not supported");
-#else
- bool quickRejected = properties().getClipToBounds()
- && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
- if (!quickRejected) {
- Matrix4 initialTransform(*(renderer.currentTransform()));
- renderer.setBaseTransform(initialTransform);
-
- if (drawLayer) {
- handler(new (alloc) DrawLayerOp(mLayer),
- renderer.getSaveCount() - 1, properties().getClipToBounds());
- } else {
- const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionReceiveIndex = mDisplayList->projectionReceiveIndex;
- for (size_t chunkIndex = 0; chunkIndex < mDisplayList->getChunks().size(); chunkIndex++) {
- const DisplayList::Chunk& chunk = mDisplayList->getChunks()[chunkIndex];
-
- std::vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
- buildZSortedChildList(chunk, zTranslatedNodes);
-
- issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren,
- initialTransform, zTranslatedNodes, renderer, handler);
-
- for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
- DisplayListOp *op = mDisplayList->getOps()[opIndex];
-#if DEBUG_DISPLAY_LIST
- op->output(handler.level() + 1);
-#endif
- handler(op, saveCountOffset, properties().getClipToBounds());
-
- if (CC_UNLIKELY(!mProjectedNodes.empty() && projectionReceiveIndex >= 0 &&
- opIndex == static_cast<size_t>(projectionReceiveIndex))) {
- issueOperationsOfProjectedChildren(renderer, handler);
- }
- }
-
- issueOperationsOf3dChildren(ChildrenSelectMode::PositiveZChildren,
- initialTransform, zTranslatedNodes, renderer, handler);
- }
- }
- }
-#endif
-
- DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo);
- handler(new (alloc) RestoreToCountOp(restoreTo),
- PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
- DISPLAY_LIST_LOGD("%*sDone (%p, %s)", handler.level() * 2, "", this, getName());
- handler.endMark();
-}
-
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index f9735a231d7a..ee045aaae0a4 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef RENDERNODE_H
-#define RENDERNODE_H
+
+#pragma once
#include <SkCamera.h>
#include <SkMatrix.h>
@@ -44,29 +44,13 @@ namespace android {
namespace uirenderer {
class CanvasState;
-class DisplayListCanvas;
class DisplayListOp;
-class OpenGLRenderer;
-class Rect;
-class SkiaShader;
-
-#if HWUI_NEW_OPS
class FrameBuilder;
class OffscreenBuffer;
+class Rect;
+class SkiaShader;
struct RenderNodeOp;
-typedef OffscreenBuffer layer_t;
-typedef RenderNodeOp renderNodeOp_t;
-#else
-class Layer;
-typedef Layer layer_t;
-typedef DrawRenderNodeOp renderNodeOp_t;
-#endif
-
-class ClipRectOp;
-class DrawRenderNodeOp;
-class SaveLayerOp;
-class SaveOp;
-class RestoreToCountOp;
+
class TreeInfo;
class TreeObserver;
@@ -78,9 +62,8 @@ class RenderNode;
* Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
*
* Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
- * functionality is split between DisplayListCanvas (which manages the recording), DisplayList
- * (which holds the actual data), and DisplayList (which holds properties and performs playback onto
- * a renderer).
+ * functionality is split between RecordingCanvas (which manages the recording), DisplayList
+ * (which holds the actual data), and RenderNode (which holds properties used for render playback).
*
* Note that DisplayList is swapped out from beneath an individual RenderNode when a view's
* recorded stream of canvas operations is refreshed. The RenderNode (and its properties) stay
@@ -115,20 +98,11 @@ public:
kReplayFlag_ClipChildren = 0x1
};
- void debugDumpLayers(const char* prefix);
-
ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
void computeOrdering();
- void defer(DeferStateStruct& deferStruct, const int level);
- void replay(ReplayStateStruct& replayStruct, const int level);
-
-#if HWUI_NEW_OPS
ANDROID_API void output(uint32_t level = 0, const char* label = "Root");
-#else
- ANDROID_API void output(uint32_t level = 1);
-#endif
ANDROID_API int getDebugSize();
void copyTo(proto::RenderNode* node);
@@ -223,10 +197,8 @@ public:
const DisplayList* getDisplayList() const {
return mDisplayList;
}
-#if HWUI_NEW_OPS
OffscreenBuffer* getLayer() const { return mLayer; }
OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
-#endif
// Note: The position callbacks are relying on the listener using
// the frameNumber to appropriately batch/synchronize these transactions.
@@ -257,63 +229,10 @@ public:
}
private:
- typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
-
- static size_t findNonNegativeIndex(const std::vector<ZDrawRenderNodeOpPair>& nodes) {
- for (size_t i = 0; i < nodes.size(); i++) {
- if (nodes[i].key >= 0.0f) return i;
- }
- return nodes.size();
- }
-
- enum class ChildrenSelectMode {
- NegativeZChildren,
- PositiveZChildren
- };
-
- void computeOrderingImpl(renderNodeOp_t* opState,
- std::vector<renderNodeOp_t*>* compositedChildrenOfProjectionSurface,
+ void computeOrderingImpl(RenderNodeOp* opState,
+ std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
const mat4* transformFromProjectionSurface);
- template <class T>
- inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
-
- void buildZSortedChildList(const DisplayList::Chunk& chunk,
- std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
-
- template<class T>
- inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
-
- template <class T>
- inline void issueOperationsOf3dChildren(ChildrenSelectMode mode,
- const Matrix4& initialTransform, const std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
- OpenGLRenderer& renderer, T& handler);
-
- template <class T>
- inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
-
- /**
- * Issue the RenderNode's operations into a handler, recursing for subtrees through
- * DrawRenderNodeOp's defer() or replay() methods
- */
- template <class T>
- inline void issueOperations(OpenGLRenderer& renderer, T& handler);
-
- class TextContainer {
- public:
- size_t length() const {
- return mByteLength;
- }
-
- const char* text() const {
- return (const char*) mText;
- }
-
- size_t mByteLength;
- const char* mText;
- };
-
-
void syncProperties();
void syncDisplayList(TreeInfo* info);
@@ -321,9 +240,6 @@ private:
void pushStagingPropertiesChanges(TreeInfo& info);
void pushStagingDisplayListChanges(TreeInfo& info);
void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree);
-#if !HWUI_NEW_OPS
- void applyLayerPropertiesToLayer(TreeInfo& info);
-#endif
void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
void pushLayerUpdate(TreeInfo& info);
void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
@@ -349,14 +265,14 @@ private:
// Owned by RT. Lifecycle is managed by prepareTree(), with the exception
// being in ~RenderNode() which may happen on any thread.
- layer_t* mLayer = nullptr;
+ OffscreenBuffer* mLayer = nullptr;
/**
* Draw time state - these properties are only set and used during rendering
*/
// for projection surfaces, contains a list of all children items
- std::vector<renderNodeOp_t*> mProjectedNodes;
+ std::vector<RenderNodeOp*> mProjectedNodes;
// How many references our parent(s) have to us. Typically this should alternate
// between 2 and 1 (when a staging push happens we inc first then dec)
@@ -371,5 +287,3 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* RENDERNODE_H */
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 5ebf5458da18..7e3cad4ca9d0 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -24,7 +24,6 @@
#include <SkPathOps.h>
#include "Matrix.h"
-#include "OpenGLRenderer.h"
#include "hwui/Canvas.h"
#include "utils/MathUtils.h"
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 6a6e8dbb3fcd..00494a12b808 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef RENDERNODEPROPERTIES_H
-#define RENDERNODEPROPERTIES_H
+
+#pragma once
#include "Caches.h"
#include "DeviceInfo.h"
@@ -22,6 +22,7 @@
#include "RevealClip.h"
#include "Outline.h"
#include "utils/MathUtils.h"
+#include "utils/PaintUtils.h"
#include <SkCamera.h>
#include <SkMatrix.h>
@@ -678,5 +679,3 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* RENDERNODEPROPERTIES_H */
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 0693804d5770..600707ab86ac 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -29,7 +29,6 @@
#include <SkImage.h>
#include <SkShader.h>
#include <SkTArray.h>
-#include <SkTLazy.h>
#include <SkTemplates.h>
#include "VectorDrawable.h"
@@ -352,13 +351,12 @@ int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
int alpha, SaveFlags::Flags flags) {
- SkTLazy<SkPaint> alphaPaint;
if (static_cast<unsigned>(alpha) < 0xFF) {
- alphaPaint.init()->setAlpha(alpha);
+ SkPaint alphaPaint;
+ alphaPaint.setAlpha(alpha);
+ return this->saveLayer(left, top, right, bottom, &alphaPaint, flags);
}
-
- return this->saveLayer(left, top, right, bottom, alphaPaint.getMaybeNull(),
- flags);
+ return this->saveLayer(left, top, right, bottom, nullptr, flags);
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 9df32b28bf3b..f264a3597ef2 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -23,6 +23,7 @@
#include <SkPixelRef.h>
#include <SkRect.h>
#include <SkRRect.h>
+#include <SkSurface.h>
#include <memory>
@@ -153,7 +154,7 @@ void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkP
mCanvas->drawVertices(mode, floatCount, vArray, tArray, cArray, indices, indexCount, paint);
}
-SkSurface* SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
+sk_sp<SkSurface> SkiaCanvasProxy::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
SkDEBUGFAIL("SkiaCanvasProxy::onNewSurface is not supported");
return NULL;
}
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 973c55fe2236..d1c9c6b2ad70 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -44,7 +44,7 @@ public:
protected:
- virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
+ virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
virtual void willSave() override;
virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 2c9c9d90f686..21c26f7a1d44 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -30,14 +30,11 @@ Snapshot::Snapshot()
, previous(nullptr)
, layer(nullptr)
, fbo(0)
- , invisible(false)
- , empty(false)
, alpha(1.0f)
, roundRectClipState(nullptr)
, projectionPathMask(nullptr)
, mClipArea(&mClipAreaRoot) {
transform = &mTransformRoot;
- region = nullptr;
}
/**
@@ -49,8 +46,6 @@ Snapshot::Snapshot(Snapshot* s, int saveFlags)
, previous(s)
, layer(s->layer)
, fbo(s->fbo)
- , invisible(s->invisible)
- , empty(false)
, alpha(s->alpha)
, roundRectClipState(s->roundRectClipState)
, projectionPathMask(s->projectionPathMask)
@@ -70,13 +65,6 @@ Snapshot::Snapshot(Snapshot* s, int saveFlags)
} else {
mClipArea = s->mClipArea;
}
-
- if (s->flags & Snapshot::kFlagFboTarget) {
- flags |= Snapshot::kFlagFboTarget;
- region = s->region;
- } else {
- region = nullptr;
- }
}
///////////////////////////////////////////////////////////////////////////////
@@ -126,58 +114,6 @@ void Snapshot::resetClip(float left, float top, float right, float bottom) {
}
///////////////////////////////////////////////////////////////////////////////
-// Transforms
-///////////////////////////////////////////////////////////////////////////////
-
-void Snapshot::resetTransform(float x, float y, float z) {
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("not supported - light center managed differently");
-#else
- // before resetting, map current light pos with inverse of current transform
- Vector3 center = mRelativeLightCenter;
- mat4 inverse;
- inverse.loadInverse(*transform);
- inverse.mapPoint3d(center);
- mRelativeLightCenter = center;
-
- transform = &mTransformRoot;
- transform->loadTranslate(x, y, z);
-#endif
-}
-
-void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("not supported - not needed by new ops");
-#else
- // build (reverse ordered) list of the stack of snapshots, terminated with a NULL
- Vector<const Snapshot*> snapshotList;
- snapshotList.push(nullptr);
- const Snapshot* current = this;
- do {
- snapshotList.push(current);
- current = current->previous;
- } while (current);
-
- // traverse the list, adding in each transform that contributes to the total transform
- outTransform->loadIdentity();
- for (size_t i = snapshotList.size() - 1; i > 0; i--) {
- // iterate down the stack
- const Snapshot* current = snapshotList[i];
- const Snapshot* next = snapshotList[i - 1];
- if (current->flags & kFlagIsFboLayer) {
- // if we've hit a layer, translate by the layer's draw offset
- outTransform->translate(current->layer->layer.left, current->layer->layer.top);
- }
- if (!next || (next->flags & kFlagIsFboLayer)) {
- // if this snapshot is last, or if this snapshot is last before an
- // FBO layer (which reset the transform), apply it
- outTransform->multiply(*(current->transform));
- }
- }
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Clipping round rect
///////////////////////////////////////////////////////////////////////////////
@@ -226,20 +162,8 @@ void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& boun
roundRectClipState = state;
}
-void Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
-#if HWUI_NEW_OPS
- // TODO: remove allocator param for HWUI_NEW_OPS
+void Snapshot::setProjectionPathMask(const SkPath* path) {
projectionPathMask = path;
-#else
- if (path) {
- ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
- mask->projectionMask = path;
- buildScreenSpaceTransform(&(mask->projectionMaskTransform));
- projectionPathMask = mask;
- } else {
- projectionPathMask = nullptr;
- }
-#endif
}
static Snapshot* getClipRoot(Snapshot* target) {
@@ -273,13 +197,9 @@ void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform)
// Queries
///////////////////////////////////////////////////////////////////////////////
-bool Snapshot::isIgnored() const {
- return invisible || empty;
-}
-
void Snapshot::dump() const {
- ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
- this, flags, previous, getViewportHeight(), isIgnored(), !mClipArea->isSimple());
+ ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d",
+ this, flags, previous, getViewportHeight(), !mClipArea->isSimple());
const Rect& clipRect(mClipArea->getClipRect());
ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d",
clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple());
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index d8f926ef3925..4ab58302df8f 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_SNAPSHOT_H
-#define ANDROID_HWUI_SNAPSHOT_H
+#pragma once
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -63,18 +62,6 @@ public:
float radius;
};
-// TODO: remove for HWUI_NEW_OPS
-class ProjectionPathMask {
-public:
- static void* operator new(size_t size) = delete;
- static void* operator new(size_t size, LinearAllocator& allocator) {
- return allocator.alloc<ProjectionPathMask>(size);
- }
-
- const SkPath* projectionMask;
- Matrix4 projectionMaskTransform;
-};
-
/**
* A snapshot holds information about the current state of the rendering
* surface. A snapshot is usually created whenever the user calls save()
@@ -113,11 +100,6 @@ public:
* restored when this snapshot is restored.
*/
kFlagIsFboLayer = 0x4,
- /**
- * Indicates that this snapshot or an ancestor snapshot is
- * an FBO layer.
- */
- kFlagFboTarget = 0x8, // TODO: remove for HWUI_NEW_OPS
};
/**
@@ -179,11 +161,6 @@ public:
*/
void resetClip(float left, float top, float right, float bottom);
- /**
- * Resets the current transform to a pure 3D translation.
- */
- void resetTransform(float x, float y, float z);
-
void initializeViewport(int width, int height) {
mViewportData.initialize(width, height);
mClipAreaRoot.setViewportDimensions(width, height);
@@ -207,13 +184,7 @@ public:
/**
* Sets (and replaces) the current projection mask
*/
- void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
-
- /**
- * Indicates whether this snapshot should be ignored. A snapshot
- * is typically ignored if its layer is invisible or empty.
- */
- bool isIgnored() const;
+ void setProjectionPathMask(const SkPath* path);
/**
* Indicates whether the current transform has perspective components.
@@ -221,13 +192,6 @@ public:
bool hasPerspectiveTransform() const;
/**
- * Fills outTransform with the current, total transform to screen space,
- * across layer boundaries.
- */
- // TODO: remove for HWUI_NEW_OPS
- void buildScreenSpaceTransform(Matrix4* outTransform) const;
-
- /**
* Dirty flags.
*/
int flags;
@@ -251,19 +215,6 @@ public:
GLuint fbo;
/**
- * Indicates that this snapshot is invisible and nothing should be drawn
- * inside it. This flag is set only when the layer clips drawing to its
- * bounds and is passed to subsequent snapshots.
- */
- bool invisible;
-
- /**
- * If set to true, the layer will not be composited. This is similar to
- * invisible but this flag is not passed to subsequent snapshots.
- */
- bool empty;
-
- /**
* Local transformation. Holds the current translation, scale and
* rotation values.
*
@@ -273,14 +224,6 @@ public:
mat4* transform;
/**
- * The ancestor layer's dirty region.
- *
- * This is a reference to a region owned by a layer. This pointer must
- * not be freed.
- */
- Region* region;
-
- /**
* Current alpha value. This value is 1 by default, but may be set by a DisplayList which
* has translucent rendering in a non-overlapping View. This value will be used by
* the renderer to set the alpha in the current color being used for ensuing drawing
@@ -302,11 +245,7 @@ public:
/**
* Current projection masking path - used exclusively to mask projected, tessellated circles.
*/
-#if HWUI_NEW_OPS
const SkPath* projectionPathMask;
-#else
- const ProjectionPathMask* projectionPathMask;
-#endif
void dump() const;
@@ -345,5 +284,3 @@ private:
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_SNAPSHOT_H
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index d9e811684610..91e7ac39af90 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -18,7 +18,6 @@
#include <utils/Trace.h>
#include "Caches.h"
-#include "OpenGLRenderer.h"
#include "PathTessellator.h"
#include "ShadowTessellator.h"
#include "TessellationCache.h"
@@ -369,21 +368,6 @@ void TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect
mShadowCache.put(key, task.get());
}
-void TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius, vertexBuffer_pair_t& outBuffers) {
- ShadowDescription key(casterPerimeter, drawTransform);
- ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
- if (!task) {
- precacheShadows(drawTransform, localClip, opaque, casterPerimeter,
- transformXY, transformZ, lightCenter, lightRadius);
- task = static_cast<ShadowTask*>(mShadowCache.get(key));
- }
- LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
- outBuffers = task->getResult();
-}
-
sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 6141b4ef63d7..ccad1b7bd415 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_TESSELLATION_CACHE_H
-#define ANDROID_HWUI_TESSELLATION_CACHE_H
+#pragma once
#include "Debug.h"
#include "Matrix.h"
@@ -161,17 +160,6 @@ public:
const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry);
- // TODO: delete these when switching to HWUI_NEW_OPS
- void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius);
- void getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
- bool opaque, const SkPath* casterPerimeter,
- const Matrix4* transformXY, const Matrix4* transformZ,
- const Vector3& lightCenter, float lightRadius,
- vertexBuffer_pair_t& outBuffers);
-
sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip,
bool opaque, const SkPath* casterPerimeter,
const Matrix4* transformXY, const Matrix4* transformZ,
@@ -184,6 +172,11 @@ private:
typedef VertexBuffer* (*Tessellator)(const Description&);
+ void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
+ bool opaque, const SkPath* casterPerimeter,
+ const Matrix4* transformXY, const Matrix4* transformZ,
+ const Vector3& lightCenter, float lightRadius);
+
Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
float width, float height);
Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
@@ -232,5 +225,3 @@ void tessellateShadows(
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_PATH_CACHE_H
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index ac2bdccf5255..2087fca205da 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef TREEINFO_H
-#define TREEINFO_H
+
+#pragma once
#include "utils/Macros.h"
@@ -31,7 +31,6 @@ class CanvasContext;
class DamageAccumulator;
class LayerUpdateQueue;
-class OpenGLRenderer;
class RenderNode;
class RenderState;
@@ -89,13 +88,7 @@ public:
// Must not be null during actual usage
DamageAccumulator* damageAccumulator = nullptr;
-#if HWUI_NEW_OPS
LayerUpdateQueue* layerUpdateQueue = nullptr;
-#else
- // The renderer that will be drawing the next frame. Use this to push any
- // layer updates or similar. May be NULL.
- OpenGLRenderer* renderer = nullptr;
-#endif
ErrorHandler* errorHandler = nullptr;
// Optional, may be nullptr. Used to allow things to observe interesting
@@ -128,5 +121,3 @@ public:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* TREEINFO_H */
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e67dfdd15703..940b1ca84dc1 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -39,6 +39,13 @@
namespace android {
namespace uirenderer {
+// Debug
+#if DEBUG_VECTOR_DRAWABLE
+ #define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__)
+#else
+ #define VECTOR_DRAWABLE_LOGD(...)
+#endif
+
namespace VectorDrawable {
#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
#define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false)
diff --git a/libs/hwui/debug/DefaultGlesDriver.cpp b/libs/hwui/debug/DefaultGlesDriver.cpp
new file mode 100644
index 000000000000..4515ec1f25a5
--- /dev/null
+++ b/libs/hwui/debug/DefaultGlesDriver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DefaultGlesDriver.h"
+
+#include "gles_undefine.h"
+
+#include <EGL/egl.h>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+// Generate the proxy
+#define API_ENTRY(x) DefaultGlesDriver::x##_
+#define CALL_GL_API(x, ...) x(__VA_ARGS__);
+#define CALL_GL_API_RETURN(x, ...) return x(__VA_ARGS__);
+
+#include "gles_stubs.in"
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/DefaultGlesDriver.h b/libs/hwui/debug/DefaultGlesDriver.h
new file mode 100644
index 000000000000..3eab97077004
--- /dev/null
+++ b/libs/hwui/debug/DefaultGlesDriver.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "GlesDriver.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+class DefaultGlesDriver : public GlesDriver {
+public:
+#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
+ #include "gles_decls.in"
+#undef GL_ENTRY
+
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/FatalBaseDriver.cpp b/libs/hwui/debug/FatalBaseDriver.cpp
new file mode 100644
index 000000000000..99ac358163ff
--- /dev/null
+++ b/libs/hwui/debug/FatalBaseDriver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FatalBaseDriver.h"
+
+#include <cutils/log.h>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+// Generate the proxy
+#define API_ENTRY(x) FatalBaseDriver::x##_
+#define CALL_GL_API(x, ...) LOG_ALWAYS_FATAL("Not Implemented");
+#define CALL_GL_API_RETURN(x, ...) \
+ LOG_ALWAYS_FATAL("Not Implemented"); \
+ return static_cast<decltype(x(__VA_ARGS__))>(0);
+
+#include "gles_stubs.in"
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/FatalBaseDriver.h b/libs/hwui/debug/FatalBaseDriver.h
new file mode 100644
index 000000000000..76c30e90bd39
--- /dev/null
+++ b/libs/hwui/debug/FatalBaseDriver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "GlesDriver.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+// A base driver that implements all the pure virtuals in the form of
+// LOG_ALWAYS_FATALS. Suitable for selective-override implementations
+// where only a known subset of methods need to be overridden
+class FatalBaseDriver : public GlesDriver {
+public:
+#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
+ #include "gles_decls.in"
+#undef GL_ENTRY
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesDriver.cpp b/libs/hwui/debug/GlesDriver.cpp
new file mode 100644
index 000000000000..b8ef639074de
--- /dev/null
+++ b/libs/hwui/debug/GlesDriver.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlesDriver.h"
+#include "DefaultGlesDriver.h"
+#include "GlesErrorCheckWrapper.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+static DefaultGlesDriver sDefaultDriver;
+
+static std::unique_ptr<GlesDriver> sGlesDriver(new GlesErrorCheckWrapper(sDefaultDriver));
+
+GlesDriver* GlesDriver::get() {
+ return sGlesDriver.get();
+}
+
+std::unique_ptr<GlesDriver> GlesDriver::replace(std::unique_ptr<GlesDriver>&& driver) {
+ std::unique_ptr<GlesDriver> ret = std::move(sGlesDriver);
+ sGlesDriver = std::move(driver);
+ return ret;
+}
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesDriver.h b/libs/hwui/debug/GlesDriver.h
new file mode 100644
index 000000000000..ca6f4b628eab
--- /dev/null
+++ b/libs/hwui/debug/GlesDriver.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#ifndef HWUI_GLES_WRAP_ENABLED
+#error Wrapping wasn't enabled, can't use this!
+#endif
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+#include <GLES3/gl32.h>
+
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+// All the gl methods on GlesDriver have a trailing underscore
+// This is to avoid collision with gles_redefine/gles_undefine
+class GlesDriver {
+public:
+ virtual ~GlesDriver() {}
+
+#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) = 0;
+ #include "gles_decls.in"
+#undef GL_ENTRY
+
+ static GlesDriver* get();
+ static std::unique_ptr<GlesDriver> replace(std::unique_ptr<GlesDriver>&& driver);
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesErrorCheckWrapper.cpp b/libs/hwui/debug/GlesErrorCheckWrapper.cpp
new file mode 100644
index 000000000000..8366387b6d98
--- /dev/null
+++ b/libs/hwui/debug/GlesErrorCheckWrapper.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlesErrorCheckWrapper.h"
+
+#include <cutils/log.h>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+void GlesErrorCheckWrapper::assertNoErrors(const char* apicall) {
+ GLenum status = GL_NO_ERROR;
+ GLenum lastError = GL_NO_ERROR;
+ const char* lastErrorName = nullptr;
+ while ((status = mBase.glGetError_()) != GL_NO_ERROR) {
+ lastError = status;
+ switch (status) {
+ case GL_INVALID_ENUM:
+ ALOGE("GL error: GL_INVALID_ENUM");
+ lastErrorName = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ ALOGE("GL error: GL_INVALID_VALUE");
+ lastErrorName = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ ALOGE("GL error: GL_INVALID_OPERATION");
+ lastErrorName = "GL_INVALID_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ ALOGE("GL error: Out of memory!");
+ lastErrorName = "GL_OUT_OF_MEMORY";
+ break;
+ default:
+ ALOGE("GL error: 0x%x", status);
+ lastErrorName = "UNKNOWN";
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(lastError != GL_NO_ERROR,
+ "%s error! %s (0x%x)", apicall, lastErrorName, lastError);
+}
+
+#define API_ENTRY(x) GlesErrorCheckWrapper::x##_
+#define CALL_GL_API(x, ...) \
+ mBase.x##_(__VA_ARGS__); assertNoErrors(#x)
+
+#define CALL_GL_API_RETURN(x, ...) \
+ auto ret = mBase.x##_(__VA_ARGS__); \
+ assertNoErrors(#x); \
+ return ret
+
+#include "gles_stubs.in"
+
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/GlesErrorCheckWrapper.h b/libs/hwui/debug/GlesErrorCheckWrapper.h
new file mode 100644
index 000000000000..fd45fc0184a1
--- /dev/null
+++ b/libs/hwui/debug/GlesErrorCheckWrapper.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "GlesDriver.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+class GlesErrorCheckWrapper : public GlesDriver {
+public:
+ GlesErrorCheckWrapper(GlesDriver& base) : mBase(base) {}
+
+#define GL_ENTRY(ret, api, ...) virtual ret api##_(__VA_ARGS__) override;
+ #include "gles_decls.in"
+#undef GL_ENTRY
+
+private:
+ void assertNoErrors(const char* apicall);
+
+ GlesDriver& mBase;
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/MockGlesDriver.h b/libs/hwui/debug/MockGlesDriver.h
new file mode 100644
index 000000000000..e0bfc5780b21
--- /dev/null
+++ b/libs/hwui/debug/MockGlesDriver.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "FatalBaseDriver.h"
+
+#include <gmock/gmock.h>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+class MockGlesDriver : public FatalBaseDriver {
+public:
+ MOCK_METHOD2(glBindBuffer_, void(GLenum target, GLuint buffer));
+ MOCK_METHOD4(glBufferData_, void(GLenum target, GLsizeiptr size, const void *data, GLenum usage));
+ MOCK_METHOD2(glGenBuffers_, void(GLsizei n, GLuint *buffers));
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/NullGlesDriver.cpp b/libs/hwui/debug/NullGlesDriver.cpp
new file mode 100644
index 000000000000..e9dbc7446f4e
--- /dev/null
+++ b/libs/hwui/debug/NullGlesDriver.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <debug/NullGlesDriver.h>
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+struct {
+ GLboolean scissorEnabled;
+} gState;
+
+static void nullglGenCommon(GLsizei n, GLuint *buffers) {
+ static GLuint nextId = 0;
+ int i;
+ for(i = 0; i < n; i++) {
+ buffers[i] = ++nextId;
+ }
+}
+
+void NullGlesDriver::glGenBuffers_(GLsizei n, GLuint *buffers) {
+ nullglGenCommon(n, buffers);
+}
+
+void NullGlesDriver::glGenFramebuffers_(GLsizei n, GLuint *framebuffers) {
+ nullglGenCommon(n, framebuffers);
+}
+
+void NullGlesDriver::glGenRenderbuffers_(GLsizei n, GLuint *renderbuffers) {
+ nullglGenCommon(n, renderbuffers);
+}
+
+void NullGlesDriver::glGenTextures_(GLsizei n, GLuint *textures) {
+ nullglGenCommon(n, textures);
+}
+
+GLuint NullGlesDriver::glCreateProgram_(void) {
+ static GLuint nextProgram = 0;
+ return ++nextProgram;
+}
+
+GLuint NullGlesDriver::glCreateShader_(GLenum type) {
+ static GLuint nextShader = 0;
+ return ++nextShader;
+}
+
+void NullGlesDriver::glGetProgramiv_(GLuint program, GLenum pname, GLint *params) {
+ switch (pname) {
+ case GL_DELETE_STATUS:
+ case GL_LINK_STATUS:
+ case GL_VALIDATE_STATUS:
+ *params = GL_TRUE;
+ break;
+ case GL_INFO_LOG_LENGTH:
+ *params = 16;
+ break;
+ }
+}
+
+void NullGlesDriver::glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ *length = snprintf(infoLog, bufSize, "success");
+ if (*length >= bufSize) {
+ *length = bufSize - 1;
+ }
+}
+
+void NullGlesDriver::glGetShaderiv_(GLuint shader, GLenum pname, GLint *params) {
+ switch (pname) {
+ case GL_COMPILE_STATUS:
+ case GL_DELETE_STATUS:
+ *params = GL_TRUE;
+ }
+}
+
+void NullGlesDriver::glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ *length = snprintf(infoLog, bufSize, "success");
+ if (*length >= bufSize) {
+ *length = bufSize - 1;
+ }
+}
+
+void setBooleanState(GLenum cap, GLboolean value) {
+ switch (cap) {
+ case GL_SCISSOR_TEST:
+ gState.scissorEnabled = value;
+ break;
+ }
+}
+
+void NullGlesDriver::glEnable_(GLenum cap) {
+ setBooleanState(cap, GL_TRUE);
+}
+
+void NullGlesDriver::glDisable_(GLenum cap) {
+ setBooleanState(cap, GL_FALSE);
+}
+
+GLboolean NullGlesDriver::glIsEnabled_(GLenum cap) {
+ switch (cap) {
+ case GL_SCISSOR_TEST:
+ return gState.scissorEnabled;
+ default:
+ return GL_FALSE;
+ }
+}
+
+void NullGlesDriver::glGetIntegerv_(GLenum pname, GLint *data) {
+ switch (pname) {
+ case GL_MAX_TEXTURE_SIZE:
+ *data = 2048;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ *data = 4;
+ break;
+ default:
+ *data = 0;
+ }
+}
+
+GLenum NullGlesDriver::glCheckFramebufferStatus_(GLenum target) {
+ switch (target) {
+ case GL_FRAMEBUFFER:
+ return GL_FRAMEBUFFER_COMPLETE;
+ default:
+ return 0; // error case
+ }
+}
+
+static const char* getString(GLenum name) {
+ switch (name) {
+ case GL_VENDOR:
+ return "android";
+ case GL_RENDERER:
+ return "null";
+ case GL_VERSION:
+ return "OpenGL ES 2.0 rev1";
+ case GL_SHADING_LANGUAGE_VERSION:
+ return "OpenGL ES GLSL ES 2.0 rev1";
+ case GL_EXTENSIONS:
+ default:
+ return "";
+ }
+}
+
+const GLubyte* NullGlesDriver::glGetString_(GLenum name) {
+ return (GLubyte*) getString(name);
+}
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/NullGlesDriver.h b/libs/hwui/debug/NullGlesDriver.h
new file mode 100644
index 000000000000..d73137983940
--- /dev/null
+++ b/libs/hwui/debug/NullGlesDriver.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "FatalBaseDriver.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+class NullGlesDriver : public FatalBaseDriver {
+public:
+ virtual void glGenBuffers_(GLsizei n, GLuint *buffers) override;
+ virtual void glGenFramebuffers_(GLsizei n, GLuint *framebuffers) override;
+ virtual void glGenRenderbuffers_(GLsizei n, GLuint *renderbuffers) override;
+ virtual void glGenTextures_(GLsizei n, GLuint *textures) override;
+ virtual GLuint glCreateProgram_(void) override;
+ virtual GLuint glCreateShader_(GLenum type) override;
+ virtual void glGetProgramiv_(GLuint program, GLenum pname, GLint *params) override;
+ virtual void glGetProgramInfoLog_(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) override;
+ virtual void glGetShaderiv_(GLuint shader, GLenum pname, GLint *params) override;
+ virtual void glGetShaderInfoLog_(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) override;
+ virtual void glEnable_(GLenum cap) override;
+ virtual void glDisable_(GLenum cap) override;
+ virtual GLboolean glIsEnabled_(GLenum cap) override;
+ virtual void glGetIntegerv_(GLenum pname, GLint *data) override;
+ virtual const GLubyte* glGetString_(GLenum name) override;
+ virtual GLenum glCheckFramebufferStatus_(GLenum target) override;
+
+ virtual void glActiveTexture_(GLenum texture) override {}
+ virtual void glAttachShader_(GLuint program, GLuint shader) override {}
+ virtual void glBindAttribLocation_(GLuint program, GLuint index, const GLchar *name) override {}
+ virtual void glBindBuffer_(GLenum target, GLuint buffer) override {}
+ virtual void glBindFramebuffer_(GLenum target, GLuint framebuffer) override {}
+ virtual void glBindRenderbuffer_(GLenum target, GLuint renderbuffer) override {}
+ virtual void glBindTexture_(GLenum target, GLuint texture) override {}
+ virtual void glBlendColor_(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) override {}
+ virtual void glBlendEquation_(GLenum mode) override {}
+ virtual void glBlendEquationSeparate_(GLenum modeRGB, GLenum modeAlpha) override {}
+ virtual void glBlendFunc_(GLenum sfactor, GLenum dfactor) override {}
+ virtual void glBlendFuncSeparate_(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) override {}
+ virtual void glBufferData_(GLenum target, GLsizeiptr size, const void *data, GLenum usage) override {}
+ virtual void glBufferSubData_(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) override {}
+ virtual void glClear_(GLbitfield mask) override {}
+ virtual void glClearColor_(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) override {}
+ virtual void glClearDepthf_(GLfloat d) override {}
+ virtual void glClearStencil_(GLint s) override {}
+ virtual void glColorMask_(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) override {}
+ virtual void glCompileShader_(GLuint shader) override {}
+ virtual void glCompressedTexImage2D_(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) override {}
+ virtual void glCompressedTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) override {}
+ virtual void glCopyTexImage2D_(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) override {}
+ virtual void glCopyTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) override {}
+ virtual void glCullFace_(GLenum mode) override {}
+ virtual void glDeleteBuffers_(GLsizei n, const GLuint *buffers) override {}
+ virtual void glDeleteFramebuffers_(GLsizei n, const GLuint *framebuffers) override {}
+ virtual void glDeleteProgram_(GLuint program) override {}
+ virtual void glDeleteRenderbuffers_(GLsizei n, const GLuint *renderbuffers) override {}
+ virtual void glDeleteShader_(GLuint shader) override {}
+ virtual void glDeleteTextures_(GLsizei n, const GLuint *textures) override {}
+ virtual void glDepthFunc_(GLenum func) override {}
+ virtual void glDepthMask_(GLboolean flag) override {}
+ virtual void glDepthRangef_(GLfloat n, GLfloat f) override {}
+ virtual void glDetachShader_(GLuint program, GLuint shader) override {}
+ virtual void glDisableVertexAttribArray_(GLuint index) override {}
+ virtual void glDrawArrays_(GLenum mode, GLint first, GLsizei count) override {}
+ virtual void glDrawElements_(GLenum mode, GLsizei count, GLenum type, const void *indices) override {}
+ virtual void glEnableVertexAttribArray_(GLuint index) override {}
+ virtual void glFinish_(void) override {}
+ virtual void glFlush_(void) override {}
+ virtual void glFramebufferRenderbuffer_(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) override {}
+ virtual void glFramebufferTexture2D_(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override {}
+ virtual void glFrontFace_(GLenum mode) override {}
+ virtual void glGenerateMipmap_(GLenum target) override {}
+ virtual GLint glGetAttribLocation_(GLuint program, const GLchar *name) override { return 1; }
+ virtual GLenum glGetError_(void) override { return GL_NO_ERROR; }
+ virtual GLint glGetUniformLocation_(GLuint program, const GLchar *name) override { return 2; }
+ virtual void glHint_(GLenum target, GLenum mode) override {}
+ virtual void glLineWidth_(GLfloat width) override {}
+ virtual void glLinkProgram_(GLuint program) override {}
+ virtual void glPixelStorei_(GLenum pname, GLint param) override {}
+ virtual void glPolygonOffset_(GLfloat factor, GLfloat units) override {}
+ virtual void glReadPixels_(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) override {}
+ virtual void glReleaseShaderCompiler_(void) override {}
+ virtual void glRenderbufferStorage_(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) override {}
+ virtual void glSampleCoverage_(GLfloat value, GLboolean invert) override {}
+ virtual void glScissor_(GLint x, GLint y, GLsizei width, GLsizei height) override {}
+ virtual void glShaderBinary_(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) override {}
+ virtual void glShaderSource_(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) override {}
+ virtual void glStencilFunc_(GLenum func, GLint ref, GLuint mask) override {}
+ virtual void glStencilFuncSeparate_(GLenum face, GLenum func, GLint ref, GLuint mask) override {}
+ virtual void glStencilMask_(GLuint mask) override {}
+ virtual void glStencilMaskSeparate_(GLenum face, GLuint mask) override {}
+ virtual void glStencilOp_(GLenum fail, GLenum zfail, GLenum zpass) override {}
+ virtual void glStencilOpSeparate_(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) override {}
+ virtual void glTexImage2D_(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) override {}
+ virtual void glTexParameterf_(GLenum target, GLenum pname, GLfloat param) override {}
+ virtual void glTexParameterfv_(GLenum target, GLenum pname, const GLfloat *params) override {}
+ virtual void glTexParameteri_(GLenum target, GLenum pname, GLint param) override {}
+ virtual void glTexParameteriv_(GLenum target, GLenum pname, const GLint *params) override {}
+ virtual void glTexSubImage2D_(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) override {}
+ virtual void glUniform1f_(GLint location, GLfloat v0) override {}
+ virtual void glUniform1fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform1i_(GLint location, GLint v0) override {}
+ virtual void glUniform1iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniform2f_(GLint location, GLfloat v0, GLfloat v1) override {}
+ virtual void glUniform2fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform2i_(GLint location, GLint v0, GLint v1) override {}
+ virtual void glUniform2iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniform3f_(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) override {}
+ virtual void glUniform3fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform3i_(GLint location, GLint v0, GLint v1, GLint v2) override {}
+ virtual void glUniform3iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniform4f_(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) override {}
+ virtual void glUniform4fv_(GLint location, GLsizei count, const GLfloat *value) override {}
+ virtual void glUniform4i_(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) override {}
+ virtual void glUniform4iv_(GLint location, GLsizei count, const GLint *value) override {}
+ virtual void glUniformMatrix2fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
+ virtual void glUniformMatrix3fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
+ virtual void glUniformMatrix4fv_(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override {}
+ virtual void glUseProgram_(GLuint program) override {}
+ virtual void glValidateProgram_(GLuint program) override {}
+ virtual void glVertexAttrib1f_(GLuint index, GLfloat x) override {}
+ virtual void glVertexAttrib1fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttrib2f_(GLuint index, GLfloat x, GLfloat y) override {}
+ virtual void glVertexAttrib2fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttrib3f_(GLuint index, GLfloat x, GLfloat y, GLfloat z) override {}
+ virtual void glVertexAttrib3fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttrib4f_(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) override {}
+ virtual void glVertexAttrib4fv_(GLuint index, const GLfloat *v) override {}
+ virtual void glVertexAttribPointer_(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) override {}
+ virtual void glViewport_(GLint x, GLint y, GLsizei width, GLsizei height) override {}
+
+ // gles2 ext
+ virtual void glInsertEventMarkerEXT_(GLsizei length, const GLchar *marker) override {}
+ virtual void glPushGroupMarkerEXT_(GLsizei length, const GLchar *marker) override {}
+ virtual void glPopGroupMarkerEXT_(void) override {}
+ virtual void glDiscardFramebufferEXT_(GLenum target, GLsizei numAttachments, const GLenum *attachments) override {}
+ virtual void glEGLImageTargetTexture2DOES_(GLenum target, GLeglImageOES image) override {}
+
+ // GLES3
+ virtual void* glMapBufferRange_(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) override {
+ return 0;
+ }
+
+ virtual GLboolean glUnmapBuffer_(GLenum target) override {
+ return GL_FALSE;
+ }
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/ScopedReplaceDriver.h b/libs/hwui/debug/ScopedReplaceDriver.h
new file mode 100644
index 000000000000..342c9d223727
--- /dev/null
+++ b/libs/hwui/debug/ScopedReplaceDriver.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "GlesDriver.h"
+
+namespace android {
+namespace uirenderer {
+namespace debug {
+
+template <typename Driver>
+class ScopedReplaceDriver {
+public:
+ ScopedReplaceDriver() {
+ std::unique_ptr<Driver> glDriver = std::make_unique<Driver>();
+ mCurrentDriver = glDriver.get();
+ mOldDriver = GlesDriver::replace(std::move(glDriver));
+ }
+
+ Driver& get() { return *mCurrentDriver; }
+
+ ~ScopedReplaceDriver() {
+ GlesDriver::replace(std::move(mOldDriver));
+ }
+private:
+ std::unique_ptr<GlesDriver> mOldDriver;
+ Driver* mCurrentDriver;
+};
+
+} // namespace debug
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/debug/gles_decls.in b/libs/hwui/debug/gles_decls.in
new file mode 100644
index 000000000000..16574a7fb074
--- /dev/null
+++ b/libs/hwui/debug/gles_decls.in
@@ -0,0 +1,544 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar *name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glBlendEquation, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glClearDepthf, GLfloat d)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint *framebuffers)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint *renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLfloat n, GLfloat f)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void *indices)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint *framebuffers)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint *renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders)
+GL_ENTRY(GLint, glGetAttribLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *data)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *data)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *data)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat *params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint *params)
+GL_ENTRY(GLint, glGetUniformLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void **pointer)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSampleCoverage, GLfloat value, GLboolean invert)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glShaderBinary, GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat v0)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glUniform1i, GLint location, GLint v0)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat v0, GLfloat v1)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glUniform2i, GLint location, GLint v0, GLint v1)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glUniform3i, GLint location, GLint v0, GLint v1, GLint v2)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glUniform4i, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint index, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint index, const GLfloat *v)
+GL_ENTRY(void, glVertexAttrib2f, GLuint index, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint index, const GLfloat *v)
+GL_ENTRY(void, glVertexAttrib3f, GLuint index, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint index, const GLfloat *v)
+GL_ENTRY(void, glVertexAttrib4f, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint index, const GLfloat *v)
+GL_ENTRY(void, glVertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glReadBuffer, GLenum src)
+GL_ENTRY(void, glDrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)
+GL_ENTRY(void, glTexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glCopyTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCompressedTexImage3D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glGenQueries, GLsizei n, GLuint *ids)
+GL_ENTRY(void, glDeleteQueries, GLsizei n, const GLuint *ids)
+GL_ENTRY(GLboolean, glIsQuery, GLuint id)
+GL_ENTRY(void, glBeginQuery, GLenum target, GLuint id)
+GL_ENTRY(void, glEndQuery, GLenum target)
+GL_ENTRY(void, glGetQueryiv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params)
+GL_ENTRY(GLboolean, glUnmapBuffer, GLenum target)
+GL_ENTRY(void, glGetBufferPointerv, GLenum target, GLenum pname, void **params)
+GL_ENTRY(void, glDrawBuffers, GLsizei n, const GLenum *bufs)
+GL_ENTRY(void, glUniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glBlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+GL_ENTRY(void, glRenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glFramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+GL_ENTRY(void *, glMapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+GL_ENTRY(void, glFlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length)
+GL_ENTRY(void, glBindVertexArray, GLuint array)
+GL_ENTRY(void, glDeleteVertexArrays, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glGenVertexArrays, GLsizei n, GLuint *arrays)
+GL_ENTRY(GLboolean, glIsVertexArray, GLuint array)
+GL_ENTRY(void, glGetIntegeri_v, GLenum target, GLuint index, GLint *data)
+GL_ENTRY(void, glBeginTransformFeedback, GLenum primitiveMode)
+GL_ENTRY(void, glEndTransformFeedback, void)
+GL_ENTRY(void, glBindBufferRange, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glBindBufferBase, GLenum target, GLuint index, GLuint buffer)
+GL_ENTRY(void, glTransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
+GL_ENTRY(void, glGetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glVertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glGetVertexAttribIiv, GLuint index, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetVertexAttribIuiv, GLuint index, GLenum pname, GLuint *params)
+GL_ENTRY(void, glVertexAttribI4i, GLuint index, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glVertexAttribI4ui, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+GL_ENTRY(void, glVertexAttribI4iv, GLuint index, const GLint *v)
+GL_ENTRY(void, glVertexAttribI4uiv, GLuint index, const GLuint *v)
+GL_ENTRY(void, glGetUniformuiv, GLuint program, GLint location, GLuint *params)
+GL_ENTRY(GLint, glGetFragDataLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glUniform1ui, GLint location, GLuint v0)
+GL_ENTRY(void, glUniform2ui, GLint location, GLuint v0, GLuint v1)
+GL_ENTRY(void, glUniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2)
+GL_ENTRY(void, glUniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+GL_ENTRY(void, glUniform1uiv, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glUniform2uiv, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glUniform3uiv, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glUniform4uiv, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint *value)
+GL_ENTRY(void, glClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint *value)
+GL_ENTRY(void, glClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat *value)
+GL_ENTRY(void, glClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+GL_ENTRY(const GLubyte *, glGetStringi, GLenum name, GLuint index)
+GL_ENTRY(void, glCopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+GL_ENTRY(void, glGetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
+GL_ENTRY(void, glGetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
+GL_ENTRY(GLuint, glGetUniformBlockIndex, GLuint program, const GLchar *uniformBlockName)
+GL_ENTRY(void, glGetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetActiveUniformBlockName, GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
+GL_ENTRY(void, glUniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+GL_ENTRY(void, glDrawArraysInstanced, GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
+GL_ENTRY(void, glDrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount)
+GL_ENTRY(GLsync, glFenceSync, GLenum condition, GLbitfield flags)
+GL_ENTRY(GLboolean, glIsSync, GLsync sync)
+GL_ENTRY(void, glDeleteSync, GLsync sync)
+GL_ENTRY(GLenum, glClientWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout)
+GL_ENTRY(void, glWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout)
+GL_ENTRY(void, glGetInteger64v, GLenum pname, GLint64 *data)
+GL_ENTRY(void, glGetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+GL_ENTRY(void, glGetInteger64i_v, GLenum target, GLuint index, GLint64 *data)
+GL_ENTRY(void, glGetBufferParameteri64v, GLenum target, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGenSamplers, GLsizei count, GLuint *samplers)
+GL_ENTRY(void, glDeleteSamplers, GLsizei count, const GLuint *samplers)
+GL_ENTRY(GLboolean, glIsSampler, GLuint sampler)
+GL_ENTRY(void, glBindSampler, GLuint unit, GLuint sampler)
+GL_ENTRY(void, glSamplerParameteri, GLuint sampler, GLenum pname, GLint param)
+GL_ENTRY(void, glSamplerParameteriv, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterf, GLuint sampler, GLenum pname, GLfloat param)
+GL_ENTRY(void, glSamplerParameterfv, GLuint sampler, GLenum pname, const GLfloat *param)
+GL_ENTRY(void, glGetSamplerParameteriv, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterfv, GLuint sampler, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glVertexAttribDivisor, GLuint index, GLuint divisor)
+GL_ENTRY(void, glBindTransformFeedback, GLenum target, GLuint id)
+GL_ENTRY(void, glDeleteTransformFeedbacks, GLsizei n, const GLuint *ids)
+GL_ENTRY(void, glGenTransformFeedbacks, GLsizei n, GLuint *ids)
+GL_ENTRY(GLboolean, glIsTransformFeedback, GLuint id)
+GL_ENTRY(void, glPauseTransformFeedback, void)
+GL_ENTRY(void, glResumeTransformFeedback, void)
+GL_ENTRY(void, glGetProgramBinary, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glProgramBinary, GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
+GL_ENTRY(void, glProgramParameteri, GLuint program, GLenum pname, GLint value)
+GL_ENTRY(void, glInvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glInvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glGetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glDispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
+GL_ENTRY(void, glDispatchComputeIndirect, GLintptr indirect)
+GL_ENTRY(void, glDrawArraysIndirect, GLenum mode, const void *indirect)
+GL_ENTRY(void, glDrawElementsIndirect, GLenum mode, GLenum type, const void *indirect)
+GL_ENTRY(void, glFramebufferParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glGetFramebufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint *params)
+GL_ENTRY(GLuint, glGetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(void, glGetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name)
+GL_ENTRY(void, glGetProgramResourceiv, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params)
+GL_ENTRY(GLint, glGetProgramResourceLocation, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(void, glUseProgramStages, GLuint pipeline, GLbitfield stages, GLuint program)
+GL_ENTRY(void, glActiveShaderProgram, GLuint pipeline, GLuint program)
+GL_ENTRY(GLuint, glCreateShaderProgramv, GLenum type, GLsizei count, const GLchar *const*strings)
+GL_ENTRY(void, glBindProgramPipeline, GLuint pipeline)
+GL_ENTRY(void, glDeleteProgramPipelines, GLsizei n, const GLuint *pipelines)
+GL_ENTRY(void, glGenProgramPipelines, GLsizei n, GLuint *pipelines)
+GL_ENTRY(GLboolean, glIsProgramPipeline, GLuint pipeline)
+GL_ENTRY(void, glGetProgramPipelineiv, GLuint pipeline, GLenum pname, GLint *params)
+GL_ENTRY(void, glProgramUniform1i, GLuint program, GLint location, GLint v0)
+GL_ENTRY(void, glProgramUniform2i, GLuint program, GLint location, GLint v0, GLint v1)
+GL_ENTRY(void, glProgramUniform3i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+GL_ENTRY(void, glProgramUniform4i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+GL_ENTRY(void, glProgramUniform1ui, GLuint program, GLint location, GLuint v0)
+GL_ENTRY(void, glProgramUniform2ui, GLuint program, GLint location, GLuint v0, GLuint v1)
+GL_ENTRY(void, glProgramUniform3ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+GL_ENTRY(void, glProgramUniform4ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+GL_ENTRY(void, glProgramUniform1f, GLuint program, GLint location, GLfloat v0)
+GL_ENTRY(void, glProgramUniform2f, GLuint program, GLint location, GLfloat v0, GLfloat v1)
+GL_ENTRY(void, glProgramUniform3f, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+GL_ENTRY(void, glProgramUniform4f, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+GL_ENTRY(void, glProgramUniform1iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform2iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform3iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform4iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform1uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform2uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform3uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform4uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform1fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform2fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform3fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform4fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glValidateProgramPipeline, GLuint pipeline)
+GL_ENTRY(void, glGetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glBindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)
+GL_ENTRY(void, glGetBooleani_v, GLenum target, GLuint index, GLboolean *data)
+GL_ENTRY(void, glMemoryBarrier, GLbitfield barriers)
+GL_ENTRY(void, glMemoryBarrierByRegion, GLbitfield barriers)
+GL_ENTRY(void, glTexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)
+GL_ENTRY(void, glGetMultisamplefv, GLenum pname, GLuint index, GLfloat *val)
+GL_ENTRY(void, glSampleMaski, GLuint maskNumber, GLbitfield mask)
+GL_ENTRY(void, glGetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glBindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
+GL_ENTRY(void, glVertexAttribFormat, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
+GL_ENTRY(void, glVertexAttribIFormat, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
+GL_ENTRY(void, glVertexAttribBinding, GLuint attribindex, GLuint bindingindex)
+GL_ENTRY(void, glVertexBindingDivisor, GLuint bindingindex, GLuint divisor)
+GL_ENTRY(void, glBlendBarrier, void)
+GL_ENTRY(void, glCopyImageSubData, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+GL_ENTRY(void, glDebugMessageControl, GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
+GL_ENTRY(void, glDebugMessageInsert, GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)
+GL_ENTRY(void, glDebugMessageCallback, GLDEBUGPROC callback, const void *userParam)
+GL_ENTRY(GLuint, glGetDebugMessageLog, GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog)
+GL_ENTRY(void, glPushDebugGroup, GLenum source, GLuint id, GLsizei length, const GLchar *message)
+GL_ENTRY(void, glPopDebugGroup, void)
+GL_ENTRY(void, glObjectLabel, GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glGetObjectLabel, GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glObjectPtrLabel, const void *ptr, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glGetObjectPtrLabel, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glEnablei, GLenum target, GLuint index)
+GL_ENTRY(void, glDisablei, GLenum target, GLuint index)
+GL_ENTRY(void, glBlendEquationi, GLuint buf, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparatei, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunci, GLuint buf, GLenum src, GLenum dst)
+GL_ENTRY(void, glBlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+GL_ENTRY(GLboolean, glIsEnabledi, GLenum target, GLuint index)
+GL_ENTRY(void, glDrawElementsBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawRangeElementsBaseVertex, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glFramebufferTexture, GLenum target, GLenum attachment, GLuint texture, GLint level)
+GL_ENTRY(void, glPrimitiveBoundingBox, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+GL_ENTRY(GLenum, glGetGraphicsResetStatus, void)
+GL_ENTRY(void, glReadnPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glGetnUniformfv, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformiv, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetnUniformuiv, GLuint program, GLint location, GLsizei bufSize, GLuint *params)
+GL_ENTRY(void, glMinSampleShading, GLfloat value)
+GL_ENTRY(void, glPatchParameteri, GLenum pname, GLint value)
+GL_ENTRY(void, glTexParameterIiv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIuiv, GLenum target, GLenum pname, const GLuint *params)
+GL_ENTRY(void, glGetTexParameterIiv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIuiv, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glSamplerParameterIiv, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIuiv, GLuint sampler, GLenum pname, const GLuint *param)
+GL_ENTRY(void, glGetSamplerParameterIiv, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIuiv, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glTexBuffer, GLenum target, GLenum internalformat, GLuint buffer)
+GL_ENTRY(void, glTexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glTexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
+GL_ENTRY(void, glBlendBarrierKHR, void)
+GL_ENTRY(void, glDebugMessageControlKHR, GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
+GL_ENTRY(void, glDebugMessageInsertKHR, GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)
+GL_ENTRY(void, glDebugMessageCallbackKHR, GLDEBUGPROCKHR callback, const void *userParam)
+GL_ENTRY(GLuint, glGetDebugMessageLogKHR, GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog)
+GL_ENTRY(void, glPushDebugGroupKHR, GLenum source, GLuint id, GLsizei length, const GLchar *message)
+GL_ENTRY(void, glPopDebugGroupKHR, void)
+GL_ENTRY(void, glObjectLabelKHR, GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glGetObjectLabelKHR, GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glObjectPtrLabelKHR, const void *ptr, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glGetObjectPtrLabelKHR, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetPointervKHR, GLenum pname, void **params)
+GL_ENTRY(GLenum, glGetGraphicsResetStatusKHR, void)
+GL_ENTRY(void, glReadnPixelsKHR, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glGetnUniformfvKHR, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformivKHR, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetnUniformuivKHR, GLuint program, GLint location, GLsizei bufSize, GLuint *params)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glCopyImageSubDataOES, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+GL_ENTRY(void, glEnableiOES, GLenum target, GLuint index)
+GL_ENTRY(void, glDisableiOES, GLenum target, GLuint index)
+GL_ENTRY(void, glBlendEquationiOES, GLuint buf, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparateiOES, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunciOES, GLuint buf, GLenum src, GLenum dst)
+GL_ENTRY(void, glBlendFuncSeparateiOES, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glColorMaskiOES, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+GL_ENTRY(GLboolean, glIsEnablediOES, GLenum target, GLuint index)
+GL_ENTRY(void, glDrawElementsBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawRangeElementsBaseVertexOES, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glMultiDrawElementsBaseVertexOES, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex)
+GL_ENTRY(void, glFramebufferTextureOES, GLenum target, GLenum attachment, GLuint texture, GLint level)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void *, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void **params)
+GL_ENTRY(void, glPrimitiveBoundingBoxOES, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+GL_ENTRY(void, glMinSampleShadingOES, GLfloat value)
+GL_ENTRY(void, glPatchParameteriOES, GLenum pname, GLint value)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glTexParameterIivOES, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIuivOES, GLenum target, GLenum pname, const GLuint *params)
+GL_ENTRY(void, glGetTexParameterIivOES, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIuivOES, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glSamplerParameterIivOES, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIuivOES, GLuint sampler, GLenum pname, const GLuint *param)
+GL_ENTRY(void, glGetSamplerParameterIivOES, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIuivOES, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glTexBufferOES, GLenum target, GLenum internalformat, GLuint buffer)
+GL_ENTRY(void, glTexBufferRangeOES, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glTexStorage3DMultisampleOES, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
+GL_ENTRY(void, glTextureViewOES, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
+GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
+GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
+GL_ENTRY(void, glDrawArraysInstancedBaseInstanceEXT, GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance)
+GL_ENTRY(void, glDrawElementsInstancedBaseInstanceEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexBaseInstanceEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance)
+GL_ENTRY(void, glBindFragDataLocationIndexedEXT, GLuint program, GLuint colorNumber, GLuint index, const GLchar *name)
+GL_ENTRY(void, glBindFragDataLocationEXT, GLuint program, GLuint color, const GLchar *name)
+GL_ENTRY(GLint, glGetProgramResourceLocationIndexEXT, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(GLint, glGetFragDataIndexEXT, GLuint program, const GLchar *name)
+GL_ENTRY(void, glBufferStorageEXT, GLenum target, GLsizeiptr size, const void *data, GLbitfield flags)
+GL_ENTRY(void, glCopyImageSubDataEXT, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+GL_ENTRY(void, glLabelObjectEXT, GLenum type, GLuint object, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glGetObjectLabelEXT, GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glInsertEventMarkerEXT, GLsizei length, const GLchar *marker)
+GL_ENTRY(void, glPushGroupMarkerEXT, GLsizei length, const GLchar *marker)
+GL_ENTRY(void, glPopGroupMarkerEXT, void)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glGenQueriesEXT, GLsizei n, GLuint *ids)
+GL_ENTRY(void, glDeleteQueriesEXT, GLsizei n, const GLuint *ids)
+GL_ENTRY(GLboolean, glIsQueryEXT, GLuint id)
+GL_ENTRY(void, glBeginQueryEXT, GLenum target, GLuint id)
+GL_ENTRY(void, glEndQueryEXT, GLenum target)
+GL_ENTRY(void, glQueryCounterEXT, GLuint id, GLenum target)
+GL_ENTRY(void, glGetQueryivEXT, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryObjectivEXT, GLuint id, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryObjectuivEXT, GLuint id, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64 *params)
+GL_ENTRY(void, glDrawBuffersEXT, GLsizei n, const GLenum *bufs)
+GL_ENTRY(void, glEnableiEXT, GLenum target, GLuint index)
+GL_ENTRY(void, glDisableiEXT, GLenum target, GLuint index)
+GL_ENTRY(void, glBlendEquationiEXT, GLuint buf, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparateiEXT, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunciEXT, GLuint buf, GLenum src, GLenum dst)
+GL_ENTRY(void, glBlendFuncSeparateiEXT, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glColorMaskiEXT, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+GL_ENTRY(GLboolean, glIsEnablediEXT, GLenum target, GLuint index)
+GL_ENTRY(void, glDrawElementsBaseVertexEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawRangeElementsBaseVertexEXT, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glMultiDrawElementsBaseVertexEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex)
+GL_ENTRY(void, glDrawArraysInstancedEXT, GLenum mode, GLint start, GLsizei count, GLsizei primcount)
+GL_ENTRY(void, glDrawElementsInstancedEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
+GL_ENTRY(void, glFramebufferTextureEXT, GLenum target, GLenum attachment, GLuint texture, GLint level)
+GL_ENTRY(void, glVertexAttribDivisorEXT, GLuint index, GLuint divisor)
+GL_ENTRY(void *, glMapBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+GL_ENTRY(void, glFlushMappedBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawArraysIndirectEXT, GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride)
+GL_ENTRY(void, glMultiDrawElementsIndirectEXT, GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride)
+GL_ENTRY(void, glRenderbufferStorageMultisampleEXT, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
+GL_ENTRY(void, glReadBufferIndexedEXT, GLenum src, GLint index)
+GL_ENTRY(void, glDrawBuffersIndexedEXT, GLint n, const GLenum *location, const GLint *indices)
+GL_ENTRY(void, glGetIntegeri_vEXT, GLenum target, GLuint index, GLint *data)
+GL_ENTRY(void, glPrimitiveBoundingBoxEXT, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+GL_ENTRY(void, glRasterSamplesEXT, GLuint samples, GLboolean fixedsamplelocations)
+GL_ENTRY(GLenum, glGetGraphicsResetStatusEXT, void)
+GL_ENTRY(void, glReadnPixelsEXT, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glGetnUniformfvEXT, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformivEXT, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glActiveShaderProgramEXT, GLuint pipeline, GLuint program)
+GL_ENTRY(void, glBindProgramPipelineEXT, GLuint pipeline)
+GL_ENTRY(GLuint, glCreateShaderProgramvEXT, GLenum type, GLsizei count, const GLchar **strings)
+GL_ENTRY(void, glDeleteProgramPipelinesEXT, GLsizei n, const GLuint *pipelines)
+GL_ENTRY(void, glGenProgramPipelinesEXT, GLsizei n, GLuint *pipelines)
+GL_ENTRY(void, glGetProgramPipelineInfoLogEXT, GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetProgramPipelineivEXT, GLuint pipeline, GLenum pname, GLint *params)
+GL_ENTRY(GLboolean, glIsProgramPipelineEXT, GLuint pipeline)
+GL_ENTRY(void, glProgramParameteriEXT, GLuint program, GLenum pname, GLint value)
+GL_ENTRY(void, glProgramUniform1fEXT, GLuint program, GLint location, GLfloat v0)
+GL_ENTRY(void, glProgramUniform1fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform1iEXT, GLuint program, GLint location, GLint v0)
+GL_ENTRY(void, glProgramUniform1ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform2fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1)
+GL_ENTRY(void, glProgramUniform2fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform2iEXT, GLuint program, GLint location, GLint v0, GLint v1)
+GL_ENTRY(void, glProgramUniform2ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform3fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+GL_ENTRY(void, glProgramUniform3fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform3iEXT, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+GL_ENTRY(void, glProgramUniform3ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform4fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+GL_ENTRY(void, glProgramUniform4fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform4iEXT, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+GL_ENTRY(void, glProgramUniform4ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniformMatrix2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUseProgramStagesEXT, GLuint pipeline, GLbitfield stages, GLuint program)
+GL_ENTRY(void, glValidateProgramPipelineEXT, GLuint pipeline)
+GL_ENTRY(void, glProgramUniform1uiEXT, GLuint program, GLint location, GLuint v0)
+GL_ENTRY(void, glProgramUniform2uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1)
+GL_ENTRY(void, glProgramUniform3uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+GL_ENTRY(void, glProgramUniform4uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+GL_ENTRY(void, glProgramUniform1uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform2uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform3uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform4uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniformMatrix2x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glTexPageCommitmentEXT, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit)
+GL_ENTRY(void, glPatchParameteriEXT, GLenum pname, GLint value)
+GL_ENTRY(void, glTexParameterIivEXT, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIuivEXT, GLenum target, GLenum pname, const GLuint *params)
+GL_ENTRY(void, glGetTexParameterIivEXT, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIuivEXT, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glSamplerParameterIivEXT, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIuivEXT, GLuint sampler, GLenum pname, const GLuint *param)
+GL_ENTRY(void, glGetSamplerParameterIivEXT, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIuivEXT, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glTexBufferEXT, GLenum target, GLenum internalformat, GLuint buffer)
+GL_ENTRY(void, glTexBufferRangeEXT, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glTexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
+GL_ENTRY(void, glTexStorage2DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTexStorage3DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glTextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
+GL_ENTRY(void, glTextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glTextureViewEXT, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) \ No newline at end of file
diff --git a/libs/hwui/debug/gles_stubs.in b/libs/hwui/debug/gles_stubs.in
new file mode 100644
index 000000000000..4064a391a71d
--- /dev/null
+++ b/libs/hwui/debug/gles_stubs.in
@@ -0,0 +1,1632 @@
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+ CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
+ CALL_GL_API(glAttachShader, program, shader);
+}
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar *name) {
+ CALL_GL_API(glBindAttribLocation, program, index, name);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+ CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer) {
+ CALL_GL_API(glBindFramebuffer, target, framebuffer);
+}
+void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer) {
+ CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+ CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+ CALL_GL_API(glBlendColor, red, green, blue, alpha);
+}
+void API_ENTRY(glBlendEquation)(GLenum mode) {
+ CALL_GL_API(glBlendEquation, mode);
+}
+void API_ENTRY(glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) {
+ CALL_GL_API(glBlendEquationSeparate, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+ CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
+ CALL_GL_API(glBlendFuncSeparate, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
+ CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
+ CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
+ CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+ CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+ CALL_GL_API(glClearColor, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthf)(GLfloat d) {
+ CALL_GL_API(glClearDepthf, d);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+ CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+ CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glCompileShader)(GLuint shader) {
+ CALL_GL_API(glCompileShader, shader);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+ CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border);
+}
+void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint API_ENTRY(glCreateProgram)(void) {
+ CALL_GL_API_RETURN(glCreateProgram);
+}
+GLuint API_ENTRY(glCreateShader)(GLenum type) {
+ CALL_GL_API_RETURN(glCreateShader, type);
+}
+void API_ENTRY(glCullFace)(GLenum mode) {
+ CALL_GL_API(glCullFace, mode);
+}
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint *buffers) {
+ CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers) {
+ CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glDeleteProgram)(GLuint program) {
+ CALL_GL_API(glDeleteProgram, program);
+}
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers) {
+ CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glDeleteShader)(GLuint shader) {
+ CALL_GL_API(glDeleteShader, shader);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
+ CALL_GL_API(glDeleteTextures, n, textures);
+}
+void API_ENTRY(glDepthFunc)(GLenum func) {
+ CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag) {
+ CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangef)(GLfloat n, GLfloat f) {
+ CALL_GL_API(glDepthRangef, n, f);
+}
+void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) {
+ CALL_GL_API(glDetachShader, program, shader);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+ CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableVertexAttribArray)(GLuint index) {
+ CALL_GL_API(glDisableVertexAttribArray, index);
+}
+void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
+ CALL_GL_API(glDrawArrays, mode, first, count);
+}
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void *indices) {
+ CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+ CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableVertexAttribArray)(GLuint index) {
+ CALL_GL_API(glEnableVertexAttribArray, index);
+}
+void API_ENTRY(glFinish)(void) {
+ CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+ CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+ CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+ CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+ CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) {
+ CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenerateMipmap)(GLenum target) {
+ CALL_GL_API(glGenerateMipmap, target);
+}
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint *framebuffers) {
+ CALL_GL_API(glGenFramebuffers, n, framebuffers);
+}
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint *renderbuffers) {
+ CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
+ CALL_GL_API(glGenTextures, n, textures);
+}
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
+ CALL_GL_API(glGetActiveAttrib, program, index, bufSize, length, size, type, name);
+}
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
+ CALL_GL_API(glGetActiveUniform, program, index, bufSize, length, size, type, name);
+}
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) {
+ CALL_GL_API(glGetAttachedShaders, program, maxCount, count, shaders);
+}
+GLint API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetAttribLocation, program, name);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *data) {
+ CALL_GL_API(glGetBooleanv, pname, data);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+GLenum API_ENTRY(glGetError)(void) {
+ CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *data) {
+ CALL_GL_API(glGetFloatv, pname, data);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *data) {
+ CALL_GL_API(glGetIntegerv, pname, data);
+}
+void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetProgramiv, program, pname, params);
+}
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ CALL_GL_API(glGetProgramInfoLog, program, bufSize, length, infoLog);
+}
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetShaderiv, shader, pname, params);
+}
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ CALL_GL_API(glGetShaderInfoLog, shader, bufSize, length, infoLog);
+}
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) {
+ CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
+}
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) {
+ CALL_GL_API(glGetShaderSource, shader, bufSize, length, source);
+}
+const GLubyte * API_ENTRY(glGetString)(GLenum name) {
+ CALL_GL_API_RETURN(glGetString, name);
+}
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
+ CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat *params) {
+ CALL_GL_API(glGetUniformfv, program, location, params);
+}
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint *params) {
+ CALL_GL_API(glGetUniformiv, program, location, params);
+}
+GLint API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetUniformLocation, program, name);
+}
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat *params) {
+ CALL_GL_API(glGetVertexAttribfv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetVertexAttribiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void **pointer) {
+ CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
+}
+void API_ENTRY(glHint)(GLenum target, GLenum mode) {
+ CALL_GL_API(glHint, target, mode);
+}
+GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
+ CALL_GL_API_RETURN(glIsBuffer, buffer);
+}
+GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
+ CALL_GL_API_RETURN(glIsEnabled, cap);
+}
+GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer) {
+ CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
+}
+GLboolean API_ENTRY(glIsProgram)(GLuint program) {
+ CALL_GL_API_RETURN(glIsProgram, program);
+}
+GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer) {
+ CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
+}
+GLboolean API_ENTRY(glIsShader)(GLuint shader) {
+ CALL_GL_API_RETURN(glIsShader, shader);
+}
+GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
+ CALL_GL_API_RETURN(glIsTexture, texture);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+ CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLinkProgram)(GLuint program) {
+ CALL_GL_API(glLinkProgram, program);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+ CALL_GL_API(glPixelStorei, pname, param);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+ CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {
+ CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glReleaseShaderCompiler)(void) {
+ CALL_GL_API(glReleaseShaderCompiler);
+}
+void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
+}
+void API_ENTRY(glSampleCoverage)(GLfloat value, GLboolean invert) {
+ CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShaderBinary)(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) {
+ CALL_GL_API(glShaderBinary, count, shaders, binaryformat, binary, length);
+}
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) {
+ CALL_GL_API(glShaderSource, shader, count, string, length);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+ CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) {
+ CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+ CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask) {
+ CALL_GL_API(glStencilMaskSeparate, face, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+ CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
+ CALL_GL_API(glStencilOpSeparate, face, sfail, dpfail, dppass);
+}
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
+}
+void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
+ CALL_GL_API(glTexParameterf, target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
+ CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
+ CALL_GL_API(glTexParameteri, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
+ CALL_GL_API(glTexParameteriv, target, pname, params);
+}
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glUniform1f)(GLint location, GLfloat v0) {
+ CALL_GL_API(glUniform1f, location, v0);
+}
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glUniform1fv, location, count, value);
+}
+void API_ENTRY(glUniform1i)(GLint location, GLint v0) {
+ CALL_GL_API(glUniform1i, location, v0);
+}
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glUniform1iv, location, count, value);
+}
+void API_ENTRY(glUniform2f)(GLint location, GLfloat v0, GLfloat v1) {
+ CALL_GL_API(glUniform2f, location, v0, v1);
+}
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glUniform2fv, location, count, value);
+}
+void API_ENTRY(glUniform2i)(GLint location, GLint v0, GLint v1) {
+ CALL_GL_API(glUniform2i, location, v0, v1);
+}
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glUniform2iv, location, count, value);
+}
+void API_ENTRY(glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ CALL_GL_API(glUniform3f, location, v0, v1, v2);
+}
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glUniform3fv, location, count, value);
+}
+void API_ENTRY(glUniform3i)(GLint location, GLint v0, GLint v1, GLint v2) {
+ CALL_GL_API(glUniform3i, location, v0, v1, v2);
+}
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glUniform3iv, location, count, value);
+}
+void API_ENTRY(glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
+ CALL_GL_API(glUniform4f, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glUniform4fv, location, count, value);
+}
+void API_ENTRY(glUniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
+ CALL_GL_API(glUniform4i, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glUniform4iv, location, count, value);
+}
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUseProgram)(GLuint program) {
+ CALL_GL_API(glUseProgram, program);
+}
+void API_ENTRY(glValidateProgram)(GLuint program) {
+ CALL_GL_API(glValidateProgram, program);
+}
+void API_ENTRY(glVertexAttrib1f)(GLuint index, GLfloat x) {
+ CALL_GL_API(glVertexAttrib1f, index, x);
+}
+void API_ENTRY(glVertexAttrib1fv)(GLuint index, const GLfloat *v) {
+ CALL_GL_API(glVertexAttrib1fv, index, v);
+}
+void API_ENTRY(glVertexAttrib2f)(GLuint index, GLfloat x, GLfloat y) {
+ CALL_GL_API(glVertexAttrib2f, index, x, y);
+}
+void API_ENTRY(glVertexAttrib2fv)(GLuint index, const GLfloat *v) {
+ CALL_GL_API(glVertexAttrib2fv, index, v);
+}
+void API_ENTRY(glVertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
+ CALL_GL_API(glVertexAttrib3f, index, x, y, z);
+}
+void API_ENTRY(glVertexAttrib3fv)(GLuint index, const GLfloat *v) {
+ CALL_GL_API(glVertexAttrib3fv, index, v);
+}
+void API_ENTRY(glVertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ CALL_GL_API(glVertexAttrib4f, index, x, y, z, w);
+}
+void API_ENTRY(glVertexAttrib4fv)(GLuint index, const GLfloat *v) {
+ CALL_GL_API(glVertexAttrib4fv, index, v);
+}
+void API_ENTRY(glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
+ CALL_GL_API(glVertexAttribPointer, index, size, type, normalized, stride, pointer);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glViewport, x, y, width, height);
+}
+void API_ENTRY(glReadBuffer)(GLenum src) {
+ CALL_GL_API(glReadBuffer, src);
+}
+void API_ENTRY(glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) {
+ CALL_GL_API(glDrawRangeElements, mode, start, end, count, type, indices);
+}
+void API_ENTRY(glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexImage3D, target, level, internalformat, width, height, depth, border, format, type, pixels);
+}
+void API_ENTRY(glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexSubImage3D, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+void API_ENTRY(glCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glCopyTexSubImage3D, target, level, xoffset, yoffset, zoffset, x, y, width, height);
+}
+void API_ENTRY(glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexImage3D, target, level, internalformat, width, height, depth, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexSubImage3D, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+}
+void API_ENTRY(glGenQueries)(GLsizei n, GLuint *ids) {
+ CALL_GL_API(glGenQueries, n, ids);
+}
+void API_ENTRY(glDeleteQueries)(GLsizei n, const GLuint *ids) {
+ CALL_GL_API(glDeleteQueries, n, ids);
+}
+GLboolean API_ENTRY(glIsQuery)(GLuint id) {
+ CALL_GL_API_RETURN(glIsQuery, id);
+}
+void API_ENTRY(glBeginQuery)(GLenum target, GLuint id) {
+ CALL_GL_API(glBeginQuery, target, id);
+}
+void API_ENTRY(glEndQuery)(GLenum target) {
+ CALL_GL_API(glEndQuery, target);
+}
+void API_ENTRY(glGetQueryiv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetQueryiv, target, pname, params);
+}
+void API_ENTRY(glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetQueryObjectuiv, id, pname, params);
+}
+GLboolean API_ENTRY(glUnmapBuffer)(GLenum target) {
+ CALL_GL_API_RETURN(glUnmapBuffer, target);
+}
+void API_ENTRY(glGetBufferPointerv)(GLenum target, GLenum pname, void **params) {
+ CALL_GL_API(glGetBufferPointerv, target, pname, params);
+}
+void API_ENTRY(glDrawBuffers)(GLsizei n, const GLenum *bufs) {
+ CALL_GL_API(glDrawBuffers, n, bufs);
+}
+void API_ENTRY(glUniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix2x3fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix3x2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix2x4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix4x2fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix3x4fv, location, count, transpose, value);
+}
+void API_ENTRY(glUniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glUniformMatrix4x3fv, location, count, transpose, value);
+}
+void API_ENTRY(glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
+ CALL_GL_API(glBlitFramebuffer, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+void API_ENTRY(glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glRenderbufferStorageMultisample, target, samples, internalformat, width, height);
+}
+void API_ENTRY(glFramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
+ CALL_GL_API(glFramebufferTextureLayer, target, attachment, texture, level, layer);
+}
+void * API_ENTRY(glMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
+ CALL_GL_API_RETURN(glMapBufferRange, target, offset, length, access);
+}
+void API_ENTRY(glFlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length) {
+ CALL_GL_API(glFlushMappedBufferRange, target, offset, length);
+}
+void API_ENTRY(glBindVertexArray)(GLuint array) {
+ CALL_GL_API(glBindVertexArray, array);
+}
+void API_ENTRY(glDeleteVertexArrays)(GLsizei n, const GLuint *arrays) {
+ CALL_GL_API(glDeleteVertexArrays, n, arrays);
+}
+void API_ENTRY(glGenVertexArrays)(GLsizei n, GLuint *arrays) {
+ CALL_GL_API(glGenVertexArrays, n, arrays);
+}
+GLboolean API_ENTRY(glIsVertexArray)(GLuint array) {
+ CALL_GL_API_RETURN(glIsVertexArray, array);
+}
+void API_ENTRY(glGetIntegeri_v)(GLenum target, GLuint index, GLint *data) {
+ CALL_GL_API(glGetIntegeri_v, target, index, data);
+}
+void API_ENTRY(glBeginTransformFeedback)(GLenum primitiveMode) {
+ CALL_GL_API(glBeginTransformFeedback, primitiveMode);
+}
+void API_ENTRY(glEndTransformFeedback)(void) {
+ CALL_GL_API(glEndTransformFeedback);
+}
+void API_ENTRY(glBindBufferRange)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+ CALL_GL_API(glBindBufferRange, target, index, buffer, offset, size);
+}
+void API_ENTRY(glBindBufferBase)(GLenum target, GLuint index, GLuint buffer) {
+ CALL_GL_API(glBindBufferBase, target, index, buffer);
+}
+void API_ENTRY(glTransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode) {
+ CALL_GL_API(glTransformFeedbackVaryings, program, count, varyings, bufferMode);
+}
+void API_ENTRY(glGetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) {
+ CALL_GL_API(glGetTransformFeedbackVarying, program, index, bufSize, length, size, type, name);
+}
+void API_ENTRY(glVertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer) {
+ CALL_GL_API(glVertexAttribIPointer, index, size, type, stride, pointer);
+}
+void API_ENTRY(glGetVertexAttribIiv)(GLuint index, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetVertexAttribIiv, index, pname, params);
+}
+void API_ENTRY(glGetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetVertexAttribIuiv, index, pname, params);
+}
+void API_ENTRY(glVertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w) {
+ CALL_GL_API(glVertexAttribI4i, index, x, y, z, w);
+}
+void API_ENTRY(glVertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
+ CALL_GL_API(glVertexAttribI4ui, index, x, y, z, w);
+}
+void API_ENTRY(glVertexAttribI4iv)(GLuint index, const GLint *v) {
+ CALL_GL_API(glVertexAttribI4iv, index, v);
+}
+void API_ENTRY(glVertexAttribI4uiv)(GLuint index, const GLuint *v) {
+ CALL_GL_API(glVertexAttribI4uiv, index, v);
+}
+void API_ENTRY(glGetUniformuiv)(GLuint program, GLint location, GLuint *params) {
+ CALL_GL_API(glGetUniformuiv, program, location, params);
+}
+GLint API_ENTRY(glGetFragDataLocation)(GLuint program, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetFragDataLocation, program, name);
+}
+void API_ENTRY(glUniform1ui)(GLint location, GLuint v0) {
+ CALL_GL_API(glUniform1ui, location, v0);
+}
+void API_ENTRY(glUniform2ui)(GLint location, GLuint v0, GLuint v1) {
+ CALL_GL_API(glUniform2ui, location, v0, v1);
+}
+void API_ENTRY(glUniform3ui)(GLint location, GLuint v0, GLuint v1, GLuint v2) {
+ CALL_GL_API(glUniform3ui, location, v0, v1, v2);
+}
+void API_ENTRY(glUniform4ui)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
+ CALL_GL_API(glUniform4ui, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glUniform1uiv)(GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glUniform1uiv, location, count, value);
+}
+void API_ENTRY(glUniform2uiv)(GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glUniform2uiv, location, count, value);
+}
+void API_ENTRY(glUniform3uiv)(GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glUniform3uiv, location, count, value);
+}
+void API_ENTRY(glUniform4uiv)(GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glUniform4uiv, location, count, value);
+}
+void API_ENTRY(glClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint *value) {
+ CALL_GL_API(glClearBufferiv, buffer, drawbuffer, value);
+}
+void API_ENTRY(glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint *value) {
+ CALL_GL_API(glClearBufferuiv, buffer, drawbuffer, value);
+}
+void API_ENTRY(glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat *value) {
+ CALL_GL_API(glClearBufferfv, buffer, drawbuffer, value);
+}
+void API_ENTRY(glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
+ CALL_GL_API(glClearBufferfi, buffer, drawbuffer, depth, stencil);
+}
+const GLubyte * API_ENTRY(glGetStringi)(GLenum name, GLuint index) {
+ CALL_GL_API_RETURN(glGetStringi, name, index);
+}
+void API_ENTRY(glCopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
+ CALL_GL_API(glCopyBufferSubData, readTarget, writeTarget, readOffset, writeOffset, size);
+}
+void API_ENTRY(glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices) {
+ CALL_GL_API(glGetUniformIndices, program, uniformCount, uniformNames, uniformIndices);
+}
+void API_ENTRY(glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params);
+}
+GLuint API_ENTRY(glGetUniformBlockIndex)(GLuint program, const GLchar *uniformBlockName) {
+ CALL_GL_API_RETURN(glGetUniformBlockIndex, program, uniformBlockName);
+}
+void API_ENTRY(glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetActiveUniformBlockiv, program, uniformBlockIndex, pname, params);
+}
+void API_ENTRY(glGetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) {
+ CALL_GL_API(glGetActiveUniformBlockName, program, uniformBlockIndex, bufSize, length, uniformBlockName);
+}
+void API_ENTRY(glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
+ CALL_GL_API(glUniformBlockBinding, program, uniformBlockIndex, uniformBlockBinding);
+}
+void API_ENTRY(glDrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
+ CALL_GL_API(glDrawArraysInstanced, mode, first, count, instancecount);
+}
+void API_ENTRY(glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount) {
+ CALL_GL_API(glDrawElementsInstanced, mode, count, type, indices, instancecount);
+}
+GLsync API_ENTRY(glFenceSync)(GLenum condition, GLbitfield flags) {
+ CALL_GL_API_RETURN(glFenceSync, condition, flags);
+}
+GLboolean API_ENTRY(glIsSync)(GLsync sync) {
+ CALL_GL_API_RETURN(glIsSync, sync);
+}
+void API_ENTRY(glDeleteSync)(GLsync sync) {
+ CALL_GL_API(glDeleteSync, sync);
+}
+GLenum API_ENTRY(glClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ CALL_GL_API_RETURN(glClientWaitSync, sync, flags, timeout);
+}
+void API_ENTRY(glWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ CALL_GL_API(glWaitSync, sync, flags, timeout);
+}
+void API_ENTRY(glGetInteger64v)(GLenum pname, GLint64 *data) {
+ CALL_GL_API(glGetInteger64v, pname, data);
+}
+void API_ENTRY(glGetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
+ CALL_GL_API(glGetSynciv, sync, pname, bufSize, length, values);
+}
+void API_ENTRY(glGetInteger64i_v)(GLenum target, GLuint index, GLint64 *data) {
+ CALL_GL_API(glGetInteger64i_v, target, index, data);
+}
+void API_ENTRY(glGetBufferParameteri64v)(GLenum target, GLenum pname, GLint64 *params) {
+ CALL_GL_API(glGetBufferParameteri64v, target, pname, params);
+}
+void API_ENTRY(glGenSamplers)(GLsizei count, GLuint *samplers) {
+ CALL_GL_API(glGenSamplers, count, samplers);
+}
+void API_ENTRY(glDeleteSamplers)(GLsizei count, const GLuint *samplers) {
+ CALL_GL_API(glDeleteSamplers, count, samplers);
+}
+GLboolean API_ENTRY(glIsSampler)(GLuint sampler) {
+ CALL_GL_API_RETURN(glIsSampler, sampler);
+}
+void API_ENTRY(glBindSampler)(GLuint unit, GLuint sampler) {
+ CALL_GL_API(glBindSampler, unit, sampler);
+}
+void API_ENTRY(glSamplerParameteri)(GLuint sampler, GLenum pname, GLint param) {
+ CALL_GL_API(glSamplerParameteri, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameteriv)(GLuint sampler, GLenum pname, const GLint *param) {
+ CALL_GL_API(glSamplerParameteriv, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterf)(GLuint sampler, GLenum pname, GLfloat param) {
+ CALL_GL_API(glSamplerParameterf, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterfv)(GLuint sampler, GLenum pname, const GLfloat *param) {
+ CALL_GL_API(glSamplerParameterfv, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameteriv)(GLuint sampler, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetSamplerParameteriv, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterfv)(GLuint sampler, GLenum pname, GLfloat *params) {
+ CALL_GL_API(glGetSamplerParameterfv, sampler, pname, params);
+}
+void API_ENTRY(glVertexAttribDivisor)(GLuint index, GLuint divisor) {
+ CALL_GL_API(glVertexAttribDivisor, index, divisor);
+}
+void API_ENTRY(glBindTransformFeedback)(GLenum target, GLuint id) {
+ CALL_GL_API(glBindTransformFeedback, target, id);
+}
+void API_ENTRY(glDeleteTransformFeedbacks)(GLsizei n, const GLuint *ids) {
+ CALL_GL_API(glDeleteTransformFeedbacks, n, ids);
+}
+void API_ENTRY(glGenTransformFeedbacks)(GLsizei n, GLuint *ids) {
+ CALL_GL_API(glGenTransformFeedbacks, n, ids);
+}
+GLboolean API_ENTRY(glIsTransformFeedback)(GLuint id) {
+ CALL_GL_API_RETURN(glIsTransformFeedback, id);
+}
+void API_ENTRY(glPauseTransformFeedback)(void) {
+ CALL_GL_API(glPauseTransformFeedback);
+}
+void API_ENTRY(glResumeTransformFeedback)(void) {
+ CALL_GL_API(glResumeTransformFeedback);
+}
+void API_ENTRY(glGetProgramBinary)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+ CALL_GL_API(glGetProgramBinary, program, bufSize, length, binaryFormat, binary);
+}
+void API_ENTRY(glProgramBinary)(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) {
+ CALL_GL_API(glProgramBinary, program, binaryFormat, binary, length);
+}
+void API_ENTRY(glProgramParameteri)(GLuint program, GLenum pname, GLint value) {
+ CALL_GL_API(glProgramParameteri, program, pname, value);
+}
+void API_ENTRY(glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
+ CALL_GL_API(glInvalidateFramebuffer, target, numAttachments, attachments);
+}
+void API_ENTRY(glInvalidateSubFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glInvalidateSubFramebuffer, target, numAttachments, attachments, x, y, width, height);
+}
+void API_ENTRY(glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glTexStorage2D, target, levels, internalformat, width, height);
+}
+void API_ENTRY(glTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
+ CALL_GL_API(glTexStorage3D, target, levels, internalformat, width, height, depth);
+}
+void API_ENTRY(glGetInternalformativ)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
+ CALL_GL_API(glGetInternalformativ, target, internalformat, pname, bufSize, params);
+}
+void API_ENTRY(glDispatchCompute)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
+ CALL_GL_API(glDispatchCompute, num_groups_x, num_groups_y, num_groups_z);
+}
+void API_ENTRY(glDispatchComputeIndirect)(GLintptr indirect) {
+ CALL_GL_API(glDispatchComputeIndirect, indirect);
+}
+void API_ENTRY(glDrawArraysIndirect)(GLenum mode, const void *indirect) {
+ CALL_GL_API(glDrawArraysIndirect, mode, indirect);
+}
+void API_ENTRY(glDrawElementsIndirect)(GLenum mode, GLenum type, const void *indirect) {
+ CALL_GL_API(glDrawElementsIndirect, mode, type, indirect);
+}
+void API_ENTRY(glFramebufferParameteri)(GLenum target, GLenum pname, GLint param) {
+ CALL_GL_API(glFramebufferParameteri, target, pname, param);
+}
+void API_ENTRY(glGetFramebufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetFramebufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetProgramInterfaceiv, program, programInterface, pname, params);
+}
+GLuint API_ENTRY(glGetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetProgramResourceIndex, program, programInterface, name);
+}
+void API_ENTRY(glGetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) {
+ CALL_GL_API(glGetProgramResourceName, program, programInterface, index, bufSize, length, name);
+}
+void API_ENTRY(glGetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params) {
+ CALL_GL_API(glGetProgramResourceiv, program, programInterface, index, propCount, props, bufSize, length, params);
+}
+GLint API_ENTRY(glGetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetProgramResourceLocation, program, programInterface, name);
+}
+void API_ENTRY(glUseProgramStages)(GLuint pipeline, GLbitfield stages, GLuint program) {
+ CALL_GL_API(glUseProgramStages, pipeline, stages, program);
+}
+void API_ENTRY(glActiveShaderProgram)(GLuint pipeline, GLuint program) {
+ CALL_GL_API(glActiveShaderProgram, pipeline, program);
+}
+GLuint API_ENTRY(glCreateShaderProgramv)(GLenum type, GLsizei count, const GLchar *const*strings) {
+ CALL_GL_API_RETURN(glCreateShaderProgramv, type, count, strings);
+}
+void API_ENTRY(glBindProgramPipeline)(GLuint pipeline) {
+ CALL_GL_API(glBindProgramPipeline, pipeline);
+}
+void API_ENTRY(glDeleteProgramPipelines)(GLsizei n, const GLuint *pipelines) {
+ CALL_GL_API(glDeleteProgramPipelines, n, pipelines);
+}
+void API_ENTRY(glGenProgramPipelines)(GLsizei n, GLuint *pipelines) {
+ CALL_GL_API(glGenProgramPipelines, n, pipelines);
+}
+GLboolean API_ENTRY(glIsProgramPipeline)(GLuint pipeline) {
+ CALL_GL_API_RETURN(glIsProgramPipeline, pipeline);
+}
+void API_ENTRY(glGetProgramPipelineiv)(GLuint pipeline, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetProgramPipelineiv, pipeline, pname, params);
+}
+void API_ENTRY(glProgramUniform1i)(GLuint program, GLint location, GLint v0) {
+ CALL_GL_API(glProgramUniform1i, program, location, v0);
+}
+void API_ENTRY(glProgramUniform2i)(GLuint program, GLint location, GLint v0, GLint v1) {
+ CALL_GL_API(glProgramUniform2i, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform3i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {
+ CALL_GL_API(glProgramUniform3i, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform4i)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
+ CALL_GL_API(glProgramUniform4i, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform1ui)(GLuint program, GLint location, GLuint v0) {
+ CALL_GL_API(glProgramUniform1ui, program, location, v0);
+}
+void API_ENTRY(glProgramUniform2ui)(GLuint program, GLint location, GLuint v0, GLuint v1) {
+ CALL_GL_API(glProgramUniform2ui, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform3ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) {
+ CALL_GL_API(glProgramUniform3ui, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform4ui)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
+ CALL_GL_API(glProgramUniform4ui, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform1f)(GLuint program, GLint location, GLfloat v0) {
+ CALL_GL_API(glProgramUniform1f, program, location, v0);
+}
+void API_ENTRY(glProgramUniform2f)(GLuint program, GLint location, GLfloat v0, GLfloat v1) {
+ CALL_GL_API(glProgramUniform2f, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform3f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ CALL_GL_API(glProgramUniform3f, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform4f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
+ CALL_GL_API(glProgramUniform4f, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform1iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform1iv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform2iv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform3iv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform4iv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform1uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform1uiv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform2uiv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform3uiv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform4uiv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform1fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform1fv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform2fv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform3fv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform4fv, program, location, count, value);
+}
+void API_ENTRY(glProgramUniformMatrix2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix2x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2x3fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3x2fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix2x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2x4fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4x2fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3x4fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4x3fv, program, location, count, transpose, value);
+}
+void API_ENTRY(glValidateProgramPipeline)(GLuint pipeline) {
+ CALL_GL_API(glValidateProgramPipeline, pipeline);
+}
+void API_ENTRY(glGetProgramPipelineInfoLog)(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ CALL_GL_API(glGetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog);
+}
+void API_ENTRY(glBindImageTexture)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) {
+ CALL_GL_API(glBindImageTexture, unit, texture, level, layered, layer, access, format);
+}
+void API_ENTRY(glGetBooleani_v)(GLenum target, GLuint index, GLboolean *data) {
+ CALL_GL_API(glGetBooleani_v, target, index, data);
+}
+void API_ENTRY(glMemoryBarrier)(GLbitfield barriers) {
+ CALL_GL_API(glMemoryBarrier, barriers);
+}
+void API_ENTRY(glMemoryBarrierByRegion)(GLbitfield barriers) {
+ CALL_GL_API(glMemoryBarrierByRegion, barriers);
+}
+void API_ENTRY(glTexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
+ CALL_GL_API(glTexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations);
+}
+void API_ENTRY(glGetMultisamplefv)(GLenum pname, GLuint index, GLfloat *val) {
+ CALL_GL_API(glGetMultisamplefv, pname, index, val);
+}
+void API_ENTRY(glSampleMaski)(GLuint maskNumber, GLbitfield mask) {
+ CALL_GL_API(glSampleMaski, maskNumber, mask);
+}
+void API_ENTRY(glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetTexLevelParameteriv, target, level, pname, params);
+}
+void API_ENTRY(glGetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat *params) {
+ CALL_GL_API(glGetTexLevelParameterfv, target, level, pname, params);
+}
+void API_ENTRY(glBindVertexBuffer)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) {
+ CALL_GL_API(glBindVertexBuffer, bindingindex, buffer, offset, stride);
+}
+void API_ENTRY(glVertexAttribFormat)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
+ CALL_GL_API(glVertexAttribFormat, attribindex, size, type, normalized, relativeoffset);
+}
+void API_ENTRY(glVertexAttribIFormat)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
+ CALL_GL_API(glVertexAttribIFormat, attribindex, size, type, relativeoffset);
+}
+void API_ENTRY(glVertexAttribBinding)(GLuint attribindex, GLuint bindingindex) {
+ CALL_GL_API(glVertexAttribBinding, attribindex, bindingindex);
+}
+void API_ENTRY(glVertexBindingDivisor)(GLuint bindingindex, GLuint divisor) {
+ CALL_GL_API(glVertexBindingDivisor, bindingindex, divisor);
+}
+void API_ENTRY(glBlendBarrier)(void) {
+ CALL_GL_API(glBlendBarrier);
+}
+void API_ENTRY(glCopyImageSubData)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
+ CALL_GL_API(glCopyImageSubData, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+}
+void API_ENTRY(glDebugMessageControl)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled) {
+ CALL_GL_API(glDebugMessageControl, source, type, severity, count, ids, enabled);
+}
+void API_ENTRY(glDebugMessageInsert)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf) {
+ CALL_GL_API(glDebugMessageInsert, source, type, id, severity, length, buf);
+}
+void API_ENTRY(glDebugMessageCallback)(GLDEBUGPROC callback, const void *userParam) {
+ CALL_GL_API(glDebugMessageCallback, callback, userParam);
+}
+GLuint API_ENTRY(glGetDebugMessageLog)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog) {
+ CALL_GL_API_RETURN(glGetDebugMessageLog, count, bufSize, sources, types, ids, severities, lengths, messageLog);
+}
+void API_ENTRY(glPushDebugGroup)(GLenum source, GLuint id, GLsizei length, const GLchar *message) {
+ CALL_GL_API(glPushDebugGroup, source, id, length, message);
+}
+void API_ENTRY(glPopDebugGroup)(void) {
+ CALL_GL_API(glPopDebugGroup);
+}
+void API_ENTRY(glObjectLabel)(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) {
+ CALL_GL_API(glObjectLabel, identifier, name, length, label);
+}
+void API_ENTRY(glGetObjectLabel)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label) {
+ CALL_GL_API(glGetObjectLabel, identifier, name, bufSize, length, label);
+}
+void API_ENTRY(glObjectPtrLabel)(const void *ptr, GLsizei length, const GLchar *label) {
+ CALL_GL_API(glObjectPtrLabel, ptr, length, label);
+}
+void API_ENTRY(glGetObjectPtrLabel)(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) {
+ CALL_GL_API(glGetObjectPtrLabel, ptr, bufSize, length, label);
+}
+void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
+ CALL_GL_API(glGetPointerv, pname, params);
+}
+void API_ENTRY(glEnablei)(GLenum target, GLuint index) {
+ CALL_GL_API(glEnablei, target, index);
+}
+void API_ENTRY(glDisablei)(GLenum target, GLuint index) {
+ CALL_GL_API(glDisablei, target, index);
+}
+void API_ENTRY(glBlendEquationi)(GLuint buf, GLenum mode) {
+ CALL_GL_API(glBlendEquationi, buf, mode);
+}
+void API_ENTRY(glBlendEquationSeparatei)(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
+ CALL_GL_API(glBlendEquationSeparatei, buf, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunci)(GLuint buf, GLenum src, GLenum dst) {
+ CALL_GL_API(glBlendFunci, buf, src, dst);
+}
+void API_ENTRY(glBlendFuncSeparatei)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+ CALL_GL_API(glBlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glColorMaski)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
+ CALL_GL_API(glColorMaski, index, r, g, b, a);
+}
+GLboolean API_ENTRY(glIsEnabledi)(GLenum target, GLuint index) {
+ CALL_GL_API_RETURN(glIsEnabledi, target, index);
+}
+void API_ENTRY(glDrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawElementsBaseVertex, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawRangeElementsBaseVertex, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+ CALL_GL_API(glDrawElementsInstancedBaseVertex, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glFramebufferTexture)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
+ CALL_GL_API(glFramebufferTexture, target, attachment, texture, level);
+}
+void API_ENTRY(glPrimitiveBoundingBox)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
+ CALL_GL_API(glPrimitiveBoundingBox, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+}
+GLenum API_ENTRY(glGetGraphicsResetStatus)(void) {
+ CALL_GL_API_RETURN(glGetGraphicsResetStatus);
+}
+void API_ENTRY(glReadnPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
+ CALL_GL_API(glReadnPixels, x, y, width, height, format, type, bufSize, data);
+}
+void API_ENTRY(glGetnUniformfv)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
+ CALL_GL_API(glGetnUniformfv, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformiv)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
+ CALL_GL_API(glGetnUniformiv, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformuiv)(GLuint program, GLint location, GLsizei bufSize, GLuint *params) {
+ CALL_GL_API(glGetnUniformuiv, program, location, bufSize, params);
+}
+void API_ENTRY(glMinSampleShading)(GLfloat value) {
+ CALL_GL_API(glMinSampleShading, value);
+}
+void API_ENTRY(glPatchParameteri)(GLenum pname, GLint value) {
+ CALL_GL_API(glPatchParameteri, pname, value);
+}
+void API_ENTRY(glTexParameterIiv)(GLenum target, GLenum pname, const GLint *params) {
+ CALL_GL_API(glTexParameterIiv, target, pname, params);
+}
+void API_ENTRY(glTexParameterIuiv)(GLenum target, GLenum pname, const GLuint *params) {
+ CALL_GL_API(glTexParameterIuiv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIiv)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetTexParameterIiv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIuiv)(GLenum target, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetTexParameterIuiv, target, pname, params);
+}
+void API_ENTRY(glSamplerParameterIiv)(GLuint sampler, GLenum pname, const GLint *param) {
+ CALL_GL_API(glSamplerParameterIiv, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterIuiv)(GLuint sampler, GLenum pname, const GLuint *param) {
+ CALL_GL_API(glSamplerParameterIuiv, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameterIiv)(GLuint sampler, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetSamplerParameterIiv, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterIuiv)(GLuint sampler, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetSamplerParameterIuiv, sampler, pname, params);
+}
+void API_ENTRY(glTexBuffer)(GLenum target, GLenum internalformat, GLuint buffer) {
+ CALL_GL_API(glTexBuffer, target, internalformat, buffer);
+}
+void API_ENTRY(glTexBufferRange)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+ CALL_GL_API(glTexBufferRange, target, internalformat, buffer, offset, size);
+}
+void API_ENTRY(glTexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
+ CALL_GL_API(glTexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations);
+}
+void API_ENTRY(glBlendBarrierKHR)(void) {
+ CALL_GL_API(glBlendBarrierKHR);
+}
+void API_ENTRY(glDebugMessageControlKHR)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled) {
+ CALL_GL_API(glDebugMessageControlKHR, source, type, severity, count, ids, enabled);
+}
+void API_ENTRY(glDebugMessageInsertKHR)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf) {
+ CALL_GL_API(glDebugMessageInsertKHR, source, type, id, severity, length, buf);
+}
+void API_ENTRY(glDebugMessageCallbackKHR)(GLDEBUGPROCKHR callback, const void *userParam) {
+ CALL_GL_API(glDebugMessageCallbackKHR, callback, userParam);
+}
+GLuint API_ENTRY(glGetDebugMessageLogKHR)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog) {
+ CALL_GL_API_RETURN(glGetDebugMessageLogKHR, count, bufSize, sources, types, ids, severities, lengths, messageLog);
+}
+void API_ENTRY(glPushDebugGroupKHR)(GLenum source, GLuint id, GLsizei length, const GLchar *message) {
+ CALL_GL_API(glPushDebugGroupKHR, source, id, length, message);
+}
+void API_ENTRY(glPopDebugGroupKHR)(void) {
+ CALL_GL_API(glPopDebugGroupKHR);
+}
+void API_ENTRY(glObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) {
+ CALL_GL_API(glObjectLabelKHR, identifier, name, length, label);
+}
+void API_ENTRY(glGetObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label) {
+ CALL_GL_API(glGetObjectLabelKHR, identifier, name, bufSize, length, label);
+}
+void API_ENTRY(glObjectPtrLabelKHR)(const void *ptr, GLsizei length, const GLchar *label) {
+ CALL_GL_API(glObjectPtrLabelKHR, ptr, length, label);
+}
+void API_ENTRY(glGetObjectPtrLabelKHR)(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) {
+ CALL_GL_API(glGetObjectPtrLabelKHR, ptr, bufSize, length, label);
+}
+void API_ENTRY(glGetPointervKHR)(GLenum pname, void **params) {
+ CALL_GL_API(glGetPointervKHR, pname, params);
+}
+GLenum API_ENTRY(glGetGraphicsResetStatusKHR)(void) {
+ CALL_GL_API_RETURN(glGetGraphicsResetStatusKHR);
+}
+void API_ENTRY(glReadnPixelsKHR)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
+ CALL_GL_API(glReadnPixelsKHR, x, y, width, height, format, type, bufSize, data);
+}
+void API_ENTRY(glGetnUniformfvKHR)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
+ CALL_GL_API(glGetnUniformfvKHR, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformivKHR)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
+ CALL_GL_API(glGetnUniformivKHR, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformuivKHR)(GLuint program, GLint location, GLsizei bufSize, GLuint *params) {
+ CALL_GL_API(glGetnUniformuivKHR, program, location, bufSize, params);
+}
+void API_ENTRY(glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) {
+ CALL_GL_API(glEGLImageTargetTexture2DOES, target, image);
+}
+void API_ENTRY(glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
+ CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
+}
+void API_ENTRY(glCopyImageSubDataOES)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
+ CALL_GL_API(glCopyImageSubDataOES, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+}
+void API_ENTRY(glEnableiOES)(GLenum target, GLuint index) {
+ CALL_GL_API(glEnableiOES, target, index);
+}
+void API_ENTRY(glDisableiOES)(GLenum target, GLuint index) {
+ CALL_GL_API(glDisableiOES, target, index);
+}
+void API_ENTRY(glBlendEquationiOES)(GLuint buf, GLenum mode) {
+ CALL_GL_API(glBlendEquationiOES, buf, mode);
+}
+void API_ENTRY(glBlendEquationSeparateiOES)(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
+ CALL_GL_API(glBlendEquationSeparateiOES, buf, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunciOES)(GLuint buf, GLenum src, GLenum dst) {
+ CALL_GL_API(glBlendFunciOES, buf, src, dst);
+}
+void API_ENTRY(glBlendFuncSeparateiOES)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+ CALL_GL_API(glBlendFuncSeparateiOES, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glColorMaskiOES)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
+ CALL_GL_API(glColorMaskiOES, index, r, g, b, a);
+}
+GLboolean API_ENTRY(glIsEnablediOES)(GLenum target, GLuint index) {
+ CALL_GL_API_RETURN(glIsEnablediOES, target, index);
+}
+void API_ENTRY(glDrawElementsBaseVertexOES)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawElementsBaseVertexOES, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertexOES)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawRangeElementsBaseVertexOES, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexOES)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+ CALL_GL_API(glDrawElementsInstancedBaseVertexOES, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glMultiDrawElementsBaseVertexOES)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex) {
+ CALL_GL_API(glMultiDrawElementsBaseVertexOES, mode, count, type, indices, primcount, basevertex);
+}
+void API_ENTRY(glFramebufferTextureOES)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
+ CALL_GL_API(glFramebufferTextureOES, target, attachment, texture, level);
+}
+void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+ CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary);
+}
+void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) {
+ CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length);
+}
+void * API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
+ CALL_GL_API_RETURN(glMapBufferOES, target, access);
+}
+GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
+ CALL_GL_API_RETURN(glUnmapBufferOES, target);
+}
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void **params) {
+ CALL_GL_API(glGetBufferPointervOES, target, pname, params);
+}
+void API_ENTRY(glPrimitiveBoundingBoxOES)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
+ CALL_GL_API(glPrimitiveBoundingBoxOES, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+}
+void API_ENTRY(glMinSampleShadingOES)(GLfloat value) {
+ CALL_GL_API(glMinSampleShadingOES, value);
+}
+void API_ENTRY(glPatchParameteriOES)(GLenum pname, GLint value) {
+ CALL_GL_API(glPatchParameteriOES, pname, value);
+}
+void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels);
+}
+void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) {
+ CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+ CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height);
+}
+void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {
+ CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+}
+void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
+ CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset);
+}
+void API_ENTRY(glTexParameterIivOES)(GLenum target, GLenum pname, const GLint *params) {
+ CALL_GL_API(glTexParameterIivOES, target, pname, params);
+}
+void API_ENTRY(glTexParameterIuivOES)(GLenum target, GLenum pname, const GLuint *params) {
+ CALL_GL_API(glTexParameterIuivOES, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIivOES)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetTexParameterIivOES, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIuivOES)(GLenum target, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetTexParameterIuivOES, target, pname, params);
+}
+void API_ENTRY(glSamplerParameterIivOES)(GLuint sampler, GLenum pname, const GLint *param) {
+ CALL_GL_API(glSamplerParameterIivOES, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterIuivOES)(GLuint sampler, GLenum pname, const GLuint *param) {
+ CALL_GL_API(glSamplerParameterIuivOES, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameterIivOES)(GLuint sampler, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetSamplerParameterIivOES, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterIuivOES)(GLuint sampler, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetSamplerParameterIuivOES, sampler, pname, params);
+}
+void API_ENTRY(glTexBufferOES)(GLenum target, GLenum internalformat, GLuint buffer) {
+ CALL_GL_API(glTexBufferOES, target, internalformat, buffer);
+}
+void API_ENTRY(glTexBufferRangeOES)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+ CALL_GL_API(glTexBufferRangeOES, target, internalformat, buffer, offset, size);
+}
+void API_ENTRY(glTexStorage3DMultisampleOES)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
+ CALL_GL_API(glTexStorage3DMultisampleOES, target, samples, internalformat, width, height, depth, fixedsamplelocations);
+}
+void API_ENTRY(glTextureViewOES)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
+ CALL_GL_API(glTextureViewOES, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
+}
+void API_ENTRY(glBindVertexArrayOES)(GLuint array) {
+ CALL_GL_API(glBindVertexArrayOES, array);
+}
+void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint *arrays) {
+ CALL_GL_API(glDeleteVertexArraysOES, n, arrays);
+}
+void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint *arrays) {
+ CALL_GL_API(glGenVertexArraysOES, n, arrays);
+}
+GLboolean API_ENTRY(glIsVertexArrayOES)(GLuint array) {
+ CALL_GL_API_RETURN(glIsVertexArrayOES, array);
+}
+void API_ENTRY(glDrawArraysInstancedBaseInstanceEXT)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance) {
+ CALL_GL_API(glDrawArraysInstancedBaseInstanceEXT, mode, first, count, instancecount, baseinstance);
+}
+void API_ENTRY(glDrawElementsInstancedBaseInstanceEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance) {
+ CALL_GL_API(glDrawElementsInstancedBaseInstanceEXT, mode, count, type, indices, instancecount, baseinstance);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexBaseInstanceEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
+ CALL_GL_API(glDrawElementsInstancedBaseVertexBaseInstanceEXT, mode, count, type, indices, instancecount, basevertex, baseinstance);
+}
+void API_ENTRY(glBindFragDataLocationIndexedEXT)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name) {
+ CALL_GL_API(glBindFragDataLocationIndexedEXT, program, colorNumber, index, name);
+}
+void API_ENTRY(glBindFragDataLocationEXT)(GLuint program, GLuint color, const GLchar *name) {
+ CALL_GL_API(glBindFragDataLocationEXT, program, color, name);
+}
+GLint API_ENTRY(glGetProgramResourceLocationIndexEXT)(GLuint program, GLenum programInterface, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetProgramResourceLocationIndexEXT, program, programInterface, name);
+}
+GLint API_ENTRY(glGetFragDataIndexEXT)(GLuint program, const GLchar *name) {
+ CALL_GL_API_RETURN(glGetFragDataIndexEXT, program, name);
+}
+void API_ENTRY(glBufferStorageEXT)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags) {
+ CALL_GL_API(glBufferStorageEXT, target, size, data, flags);
+}
+void API_ENTRY(glCopyImageSubDataEXT)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
+ CALL_GL_API(glCopyImageSubDataEXT, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+}
+void API_ENTRY(glLabelObjectEXT)(GLenum type, GLuint object, GLsizei length, const GLchar *label) {
+ CALL_GL_API(glLabelObjectEXT, type, object, length, label);
+}
+void API_ENTRY(glGetObjectLabelEXT)(GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label) {
+ CALL_GL_API(glGetObjectLabelEXT, type, object, bufSize, length, label);
+}
+void API_ENTRY(glInsertEventMarkerEXT)(GLsizei length, const GLchar *marker) {
+ CALL_GL_API(glInsertEventMarkerEXT, length, marker);
+}
+void API_ENTRY(glPushGroupMarkerEXT)(GLsizei length, const GLchar *marker) {
+ CALL_GL_API(glPushGroupMarkerEXT, length, marker);
+}
+void API_ENTRY(glPopGroupMarkerEXT)(void) {
+ CALL_GL_API(glPopGroupMarkerEXT);
+}
+void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
+ CALL_GL_API(glDiscardFramebufferEXT, target, numAttachments, attachments);
+}
+void API_ENTRY(glGenQueriesEXT)(GLsizei n, GLuint *ids) {
+ CALL_GL_API(glGenQueriesEXT, n, ids);
+}
+void API_ENTRY(glDeleteQueriesEXT)(GLsizei n, const GLuint *ids) {
+ CALL_GL_API(glDeleteQueriesEXT, n, ids);
+}
+GLboolean API_ENTRY(glIsQueryEXT)(GLuint id) {
+ CALL_GL_API_RETURN(glIsQueryEXT, id);
+}
+void API_ENTRY(glBeginQueryEXT)(GLenum target, GLuint id) {
+ CALL_GL_API(glBeginQueryEXT, target, id);
+}
+void API_ENTRY(glEndQueryEXT)(GLenum target) {
+ CALL_GL_API(glEndQueryEXT, target);
+}
+void API_ENTRY(glQueryCounterEXT)(GLuint id, GLenum target) {
+ CALL_GL_API(glQueryCounterEXT, id, target);
+}
+void API_ENTRY(glGetQueryivEXT)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetQueryivEXT, target, pname, params);
+}
+void API_ENTRY(glGetQueryObjectivEXT)(GLuint id, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetQueryObjectivEXT, id, pname, params);
+}
+void API_ENTRY(glGetQueryObjectuivEXT)(GLuint id, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetQueryObjectuivEXT, id, pname, params);
+}
+void API_ENTRY(glGetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64 *params) {
+ CALL_GL_API(glGetQueryObjecti64vEXT, id, pname, params);
+}
+void API_ENTRY(glGetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64 *params) {
+ CALL_GL_API(glGetQueryObjectui64vEXT, id, pname, params);
+}
+void API_ENTRY(glDrawBuffersEXT)(GLsizei n, const GLenum *bufs) {
+ CALL_GL_API(glDrawBuffersEXT, n, bufs);
+}
+void API_ENTRY(glEnableiEXT)(GLenum target, GLuint index) {
+ CALL_GL_API(glEnableiEXT, target, index);
+}
+void API_ENTRY(glDisableiEXT)(GLenum target, GLuint index) {
+ CALL_GL_API(glDisableiEXT, target, index);
+}
+void API_ENTRY(glBlendEquationiEXT)(GLuint buf, GLenum mode) {
+ CALL_GL_API(glBlendEquationiEXT, buf, mode);
+}
+void API_ENTRY(glBlendEquationSeparateiEXT)(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
+ CALL_GL_API(glBlendEquationSeparateiEXT, buf, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunciEXT)(GLuint buf, GLenum src, GLenum dst) {
+ CALL_GL_API(glBlendFunciEXT, buf, src, dst);
+}
+void API_ENTRY(glBlendFuncSeparateiEXT)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+ CALL_GL_API(glBlendFuncSeparateiEXT, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glColorMaskiEXT)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
+ CALL_GL_API(glColorMaskiEXT, index, r, g, b, a);
+}
+GLboolean API_ENTRY(glIsEnablediEXT)(GLenum target, GLuint index) {
+ CALL_GL_API_RETURN(glIsEnablediEXT, target, index);
+}
+void API_ENTRY(glDrawElementsBaseVertexEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawElementsBaseVertexEXT, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertexEXT)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+ CALL_GL_API(glDrawRangeElementsBaseVertexEXT, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+ CALL_GL_API(glDrawElementsInstancedBaseVertexEXT, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glMultiDrawElementsBaseVertexEXT)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex) {
+ CALL_GL_API(glMultiDrawElementsBaseVertexEXT, mode, count, type, indices, primcount, basevertex);
+}
+void API_ENTRY(glDrawArraysInstancedEXT)(GLenum mode, GLint start, GLsizei count, GLsizei primcount) {
+ CALL_GL_API(glDrawArraysInstancedEXT, mode, start, count, primcount);
+}
+void API_ENTRY(glDrawElementsInstancedEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) {
+ CALL_GL_API(glDrawElementsInstancedEXT, mode, count, type, indices, primcount);
+}
+void API_ENTRY(glFramebufferTextureEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
+ CALL_GL_API(glFramebufferTextureEXT, target, attachment, texture, level);
+}
+void API_ENTRY(glVertexAttribDivisorEXT)(GLuint index, GLuint divisor) {
+ CALL_GL_API(glVertexAttribDivisorEXT, index, divisor);
+}
+void * API_ENTRY(glMapBufferRangeEXT)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
+ CALL_GL_API_RETURN(glMapBufferRangeEXT, target, offset, length, access);
+}
+void API_ENTRY(glFlushMappedBufferRangeEXT)(GLenum target, GLintptr offset, GLsizeiptr length) {
+ CALL_GL_API(glFlushMappedBufferRangeEXT, target, offset, length);
+}
+void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawArraysEXT, mode, first, count, primcount);
+}
+void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawElementsEXT, mode, count, type, indices, primcount);
+}
+void API_ENTRY(glMultiDrawArraysIndirectEXT)(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride) {
+ CALL_GL_API(glMultiDrawArraysIndirectEXT, mode, indirect, drawcount, stride);
+}
+void API_ENTRY(glMultiDrawElementsIndirectEXT)(GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride) {
+ CALL_GL_API(glMultiDrawElementsIndirectEXT, mode, type, indirect, drawcount, stride);
+}
+void API_ENTRY(glRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glRenderbufferStorageMultisampleEXT, target, samples, internalformat, width, height);
+}
+void API_ENTRY(glFramebufferTexture2DMultisampleEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
+ CALL_GL_API(glFramebufferTexture2DMultisampleEXT, target, attachment, textarget, texture, level, samples);
+}
+void API_ENTRY(glReadBufferIndexedEXT)(GLenum src, GLint index) {
+ CALL_GL_API(glReadBufferIndexedEXT, src, index);
+}
+void API_ENTRY(glDrawBuffersIndexedEXT)(GLint n, const GLenum *location, const GLint *indices) {
+ CALL_GL_API(glDrawBuffersIndexedEXT, n, location, indices);
+}
+void API_ENTRY(glGetIntegeri_vEXT)(GLenum target, GLuint index, GLint *data) {
+ CALL_GL_API(glGetIntegeri_vEXT, target, index, data);
+}
+void API_ENTRY(glPrimitiveBoundingBoxEXT)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
+ CALL_GL_API(glPrimitiveBoundingBoxEXT, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+}
+void API_ENTRY(glRasterSamplesEXT)(GLuint samples, GLboolean fixedsamplelocations) {
+ CALL_GL_API(glRasterSamplesEXT, samples, fixedsamplelocations);
+}
+GLenum API_ENTRY(glGetGraphicsResetStatusEXT)(void) {
+ CALL_GL_API_RETURN(glGetGraphicsResetStatusEXT);
+}
+void API_ENTRY(glReadnPixelsEXT)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
+ CALL_GL_API(glReadnPixelsEXT, x, y, width, height, format, type, bufSize, data);
+}
+void API_ENTRY(glGetnUniformfvEXT)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
+ CALL_GL_API(glGetnUniformfvEXT, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformivEXT)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
+ CALL_GL_API(glGetnUniformivEXT, program, location, bufSize, params);
+}
+void API_ENTRY(glActiveShaderProgramEXT)(GLuint pipeline, GLuint program) {
+ CALL_GL_API(glActiveShaderProgramEXT, pipeline, program);
+}
+void API_ENTRY(glBindProgramPipelineEXT)(GLuint pipeline) {
+ CALL_GL_API(glBindProgramPipelineEXT, pipeline);
+}
+GLuint API_ENTRY(glCreateShaderProgramvEXT)(GLenum type, GLsizei count, const GLchar **strings) {
+ CALL_GL_API_RETURN(glCreateShaderProgramvEXT, type, count, strings);
+}
+void API_ENTRY(glDeleteProgramPipelinesEXT)(GLsizei n, const GLuint *pipelines) {
+ CALL_GL_API(glDeleteProgramPipelinesEXT, n, pipelines);
+}
+void API_ENTRY(glGenProgramPipelinesEXT)(GLsizei n, GLuint *pipelines) {
+ CALL_GL_API(glGenProgramPipelinesEXT, n, pipelines);
+}
+void API_ENTRY(glGetProgramPipelineInfoLogEXT)(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ CALL_GL_API(glGetProgramPipelineInfoLogEXT, pipeline, bufSize, length, infoLog);
+}
+void API_ENTRY(glGetProgramPipelineivEXT)(GLuint pipeline, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetProgramPipelineivEXT, pipeline, pname, params);
+}
+GLboolean API_ENTRY(glIsProgramPipelineEXT)(GLuint pipeline) {
+ CALL_GL_API_RETURN(glIsProgramPipelineEXT, pipeline);
+}
+void API_ENTRY(glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value) {
+ CALL_GL_API(glProgramParameteriEXT, program, pname, value);
+}
+void API_ENTRY(glProgramUniform1fEXT)(GLuint program, GLint location, GLfloat v0) {
+ CALL_GL_API(glProgramUniform1fEXT, program, location, v0);
+}
+void API_ENTRY(glProgramUniform1fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform1fvEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform1iEXT)(GLuint program, GLint location, GLint v0) {
+ CALL_GL_API(glProgramUniform1iEXT, program, location, v0);
+}
+void API_ENTRY(glProgramUniform1ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform1ivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1) {
+ CALL_GL_API(glProgramUniform2fEXT, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform2fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform2fvEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2iEXT)(GLuint program, GLint location, GLint v0, GLint v1) {
+ CALL_GL_API(glProgramUniform2iEXT, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform2ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform2ivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ CALL_GL_API(glProgramUniform3fEXT, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform3fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform3fvEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3iEXT)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {
+ CALL_GL_API(glProgramUniform3iEXT, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform3ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform3ivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
+ CALL_GL_API(glProgramUniform4fEXT, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform4fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
+ CALL_GL_API(glProgramUniform4fvEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4iEXT)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
+ CALL_GL_API(glProgramUniform4iEXT, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform4ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
+ CALL_GL_API(glProgramUniform4ivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniformMatrix2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glUseProgramStagesEXT)(GLuint pipeline, GLbitfield stages, GLuint program) {
+ CALL_GL_API(glUseProgramStagesEXT, pipeline, stages, program);
+}
+void API_ENTRY(glValidateProgramPipelineEXT)(GLuint pipeline) {
+ CALL_GL_API(glValidateProgramPipelineEXT, pipeline);
+}
+void API_ENTRY(glProgramUniform1uiEXT)(GLuint program, GLint location, GLuint v0) {
+ CALL_GL_API(glProgramUniform1uiEXT, program, location, v0);
+}
+void API_ENTRY(glProgramUniform2uiEXT)(GLuint program, GLint location, GLuint v0, GLuint v1) {
+ CALL_GL_API(glProgramUniform2uiEXT, program, location, v0, v1);
+}
+void API_ENTRY(glProgramUniform3uiEXT)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) {
+ CALL_GL_API(glProgramUniform3uiEXT, program, location, v0, v1, v2);
+}
+void API_ENTRY(glProgramUniform4uiEXT)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
+ CALL_GL_API(glProgramUniform4uiEXT, program, location, v0, v1, v2, v3);
+}
+void API_ENTRY(glProgramUniform1uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform1uivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform2uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform2uivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform3uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform3uivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniform4uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
+ CALL_GL_API(glProgramUniform4uivEXT, program, location, count, value);
+}
+void API_ENTRY(glProgramUniformMatrix2x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2x3fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3x2fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix2x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix2x4fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4x2fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix3x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix3x4fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glProgramUniformMatrix4x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
+ CALL_GL_API(glProgramUniformMatrix4x3fvEXT, program, location, count, transpose, value);
+}
+void API_ENTRY(glTexPageCommitmentEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit) {
+ CALL_GL_API(glTexPageCommitmentEXT, target, level, xoffset, yoffset, zoffset, width, height, depth, commit);
+}
+void API_ENTRY(glPatchParameteriEXT)(GLenum pname, GLint value) {
+ CALL_GL_API(glPatchParameteriEXT, pname, value);
+}
+void API_ENTRY(glTexParameterIivEXT)(GLenum target, GLenum pname, const GLint *params) {
+ CALL_GL_API(glTexParameterIivEXT, target, pname, params);
+}
+void API_ENTRY(glTexParameterIuivEXT)(GLenum target, GLenum pname, const GLuint *params) {
+ CALL_GL_API(glTexParameterIuivEXT, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIivEXT)(GLenum target, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetTexParameterIivEXT, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIuivEXT)(GLenum target, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetTexParameterIuivEXT, target, pname, params);
+}
+void API_ENTRY(glSamplerParameterIivEXT)(GLuint sampler, GLenum pname, const GLint *param) {
+ CALL_GL_API(glSamplerParameterIivEXT, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, const GLuint *param) {
+ CALL_GL_API(glSamplerParameterIuivEXT, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameterIivEXT)(GLuint sampler, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetSamplerParameterIivEXT, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, GLuint *params) {
+ CALL_GL_API(glGetSamplerParameterIuivEXT, sampler, pname, params);
+}
+void API_ENTRY(glTexBufferEXT)(GLenum target, GLenum internalformat, GLuint buffer) {
+ CALL_GL_API(glTexBufferEXT, target, internalformat, buffer);
+}
+void API_ENTRY(glTexBufferRangeEXT)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+ CALL_GL_API(glTexBufferRangeEXT, target, internalformat, buffer, offset, size);
+}
+void API_ENTRY(glTexStorage1DEXT)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) {
+ CALL_GL_API(glTexStorage1DEXT, target, levels, internalformat, width);
+}
+void API_ENTRY(glTexStorage2DEXT)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glTexStorage2DEXT, target, levels, internalformat, width, height);
+}
+void API_ENTRY(glTexStorage3DEXT)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
+ CALL_GL_API(glTexStorage3DEXT, target, levels, internalformat, width, height, depth);
+}
+void API_ENTRY(glTextureStorage1DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) {
+ CALL_GL_API(glTextureStorage1DEXT, texture, target, levels, internalformat, width);
+}
+void API_ENTRY(glTextureStorage2DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glTextureStorage2DEXT, texture, target, levels, internalformat, width, height);
+}
+void API_ENTRY(glTextureStorage3DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
+ CALL_GL_API(glTextureStorage3DEXT, texture, target, levels, internalformat, width, height, depth);
+}
+void API_ENTRY(glTextureViewEXT)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
+ CALL_GL_API(glTextureViewEXT, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
+} \ No newline at end of file
diff --git a/libs/hwui/debug/unwrap_gles.h b/libs/hwui/debug/gles_undefine.h
index 7716a735a63b..e43829d98e38 100644
--- a/libs/hwui/debug/unwrap_gles.h
+++ b/libs/hwui/debug/gles_undefine.h
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-#ifdef HWUI_GLES_WRAP_ENABLED
-#undef HWUI_GLES_WRAP_ENABLED
-
#undef glActiveShaderProgram
#undef glActiveShaderProgramEXT
#undef glActiveTexture
@@ -914,5 +911,3 @@
#undef glWaitSyncAPPLE
#undef glWeightPathsNV
#undef glWeightPointerOES
-
-#endif // HWUI_GLES_WRAP_ENABLED
diff --git a/libs/hwui/debug/nullegl.cpp b/libs/hwui/debug/nullegl.cpp
index b6cc2f247627..1ce180dd7543 100644
--- a/libs/hwui/debug/nullegl.cpp
+++ b/libs/hwui/debug/nullegl.cpp
@@ -68,6 +68,9 @@ EGLBoolean eglTerminate(EGLDisplay dpy) {
}
const char * eglQueryString(EGLDisplay dpy, EGLint name) {
+ if (name == EGL_EXTENSIONS) {
+ return "EGL_KHR_swap_buffers_with_damage";
+ }
return "";
}
@@ -148,6 +151,10 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
return EGL_TRUE;
}
+EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint rectCount) {
+ return EGL_TRUE;
+}
+
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) {
return (EGLImageKHR) malloc(sizeof(EGLImageKHR));
}
diff --git a/libs/hwui/debug/nullgles.cpp b/libs/hwui/debug/nullgles.cpp
deleted file mode 100644
index 8689f9814f7b..000000000000
--- a/libs/hwui/debug/nullgles.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright(C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0(the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "unwrap_gles.h"
-
-#include <GLES3/gl3.h>
-#include <GLES2/gl2ext.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-struct {
- GLboolean scissorEnabled;
-} gState;
-
-void glGenCommon(GLsizei n, GLuint *buffers) {
- static GLuint nextId = 0;
- int i;
- for(i = 0; i < n; i++) {
- buffers[i] = ++nextId;
- }
-}
-
-void glGenBuffers(GLsizei n, GLuint *buffers) {
- glGenCommon(n, buffers);
-}
-
-void glGenFramebuffers(GLsizei n, GLuint *framebuffers) {
- glGenCommon(n, framebuffers);
-}
-
-void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers) {
- glGenCommon(n, renderbuffers);
-}
-
-void glGenTextures(GLsizei n, GLuint *textures) {
- glGenCommon(n, textures);
-}
-
-GLuint glCreateProgram(void) {
- static GLuint nextProgram = 0;
- return ++nextProgram;
-}
-
-GLuint glCreateShader(GLenum type) {
- static GLuint nextShader = 0;
- return ++nextShader;
-}
-
-void glGetProgramiv(GLuint program, GLenum pname, GLint *params) {
- switch (pname) {
- case GL_DELETE_STATUS:
- case GL_LINK_STATUS:
- case GL_VALIDATE_STATUS:
- *params = GL_TRUE;
- break;
- case GL_INFO_LOG_LENGTH:
- *params = 16;
- break;
- }
-}
-
-void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
- *length = snprintf(infoLog, bufSize, "success");
- if (*length >= bufSize) {
- *length = bufSize - 1;
- }
-}
-
-void glGetShaderiv(GLuint shader, GLenum pname, GLint *params) {
- switch (pname) {
- case GL_COMPILE_STATUS:
- case GL_DELETE_STATUS:
- *params = GL_TRUE;
- }
-}
-
-void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
- *length = snprintf(infoLog, bufSize, "success");
- if (*length >= bufSize) {
- *length = bufSize - 1;
- }
-}
-
-void setBooleanState(GLenum cap, GLboolean value) {
- switch (cap) {
- case GL_SCISSOR_TEST:
- gState.scissorEnabled = value;
- break;
- }
-}
-
-void glEnable(GLenum cap) {
- setBooleanState(cap, GL_TRUE);
-}
-
-void glDisable(GLenum cap) {
- setBooleanState(cap, GL_FALSE);
-}
-
-GLboolean glIsEnabled(GLenum cap) {
- switch (cap) {
- case GL_SCISSOR_TEST:
- return gState.scissorEnabled;
- default:
- return GL_FALSE;
- }
-}
-
-void glGetIntegerv(GLenum pname, GLint *data) {
- switch (pname) {
- case GL_MAX_TEXTURE_SIZE:
- *data = 2048;
- break;
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
- *data = 4;
- break;
- default:
- *data = 0;
- }
-}
-
-GLenum glCheckFramebufferStatus(GLenum target) {
- switch (target) {
- case GL_FRAMEBUFFER:
- return GL_FRAMEBUFFER_COMPLETE;
- default:
- return 0; // error case
- }
-}
-
-const char* getString(GLenum name) {
- switch (name) {
- case GL_VENDOR:
- return "android";
- case GL_RENDERER:
- return "null";
- case GL_VERSION:
- return "OpenGL ES 2.0 rev1";
- case GL_SHADING_LANGUAGE_VERSION:
- return "OpenGL ES GLSL ES 2.0 rev1";
- case GL_EXTENSIONS:
- default:
- return "";
- }
-}
-
-const GLubyte* glGetString(GLenum name) {
- return (GLubyte*) getString(name);
-}
-
-void glActiveTexture(GLenum texture) {}
-void glAttachShader(GLuint program, GLuint shader) {}
-void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name) {}
-void glBindBuffer(GLenum target, GLuint buffer) {}
-void glBindFramebuffer(GLenum target, GLuint framebuffer) {}
-void glBindRenderbuffer(GLenum target, GLuint renderbuffer) {}
-void glBindTexture(GLenum target, GLuint texture) {}
-void glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {}
-void glBlendEquation(GLenum mode) {}
-void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {}
-void glBlendFunc(GLenum sfactor, GLenum dfactor) {}
-void glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {}
-void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {}
-void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {}
-void glClear(GLbitfield mask) {}
-void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {}
-void glClearDepthf(GLfloat d) {}
-void glClearStencil(GLint s) {}
-void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {}
-void glCompileShader(GLuint shader) {}
-void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {}
-void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {}
-void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {}
-void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {}
-void glCullFace(GLenum mode) {}
-void glDeleteBuffers(GLsizei n, const GLuint *buffers) {}
-void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) {}
-void glDeleteProgram(GLuint program) {}
-void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) {}
-void glDeleteShader(GLuint shader) {}
-void glDeleteTextures(GLsizei n, const GLuint *textures) {}
-void glDepthFunc(GLenum func) {}
-void glDepthMask(GLboolean flag) {}
-void glDepthRangef(GLfloat n, GLfloat f) {}
-void glDetachShader(GLuint program, GLuint shader) {}
-void glDisableVertexAttribArray(GLuint index) {}
-void glDrawArrays(GLenum mode, GLint first, GLsizei count) {}
-void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) {}
-void glEnableVertexAttribArray(GLuint index) {}
-void glFinish(void) {}
-void glFlush(void) {}
-void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {}
-void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {}
-void glFrontFace(GLenum mode) {}
-void glGenerateMipmap(GLenum target) {}
-GLint glGetAttribLocation(GLuint program, const GLchar *name) { return 1; }
-GLenum glGetError(void) { return GL_NO_ERROR; }
-GLint glGetUniformLocation(GLuint program, const GLchar *name) { return 2; }
-void glHint(GLenum target, GLenum mode) {}
-void glLineWidth(GLfloat width) {}
-void glLinkProgram(GLuint program) {}
-void glPixelStorei(GLenum pname, GLint param) {}
-void glPolygonOffset(GLfloat factor, GLfloat units) {}
-void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {}
-void glReleaseShaderCompiler(void) {}
-void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {}
-void glSampleCoverage(GLfloat value, GLboolean invert) {}
-void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {}
-void glShaderBinary(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) {}
-void glShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) {}
-void glStencilFunc(GLenum func, GLint ref, GLuint mask) {}
-void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {}
-void glStencilMask(GLuint mask) {}
-void glStencilMaskSeparate(GLenum face, GLuint mask) {}
-void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {}
-void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {}
-void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {}
-void glTexParameterf(GLenum target, GLenum pname, GLfloat param) {}
-void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {}
-void glTexParameteri(GLenum target, GLenum pname, GLint param) {}
-void glTexParameteriv(GLenum target, GLenum pname, const GLint *params) {}
-void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {}
-void glUniform1f(GLint location, GLfloat v0) {}
-void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) {}
-void glUniform1i(GLint location, GLint v0) {}
-void glUniform1iv(GLint location, GLsizei count, const GLint *value) {}
-void glUniform2f(GLint location, GLfloat v0, GLfloat v1) {}
-void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) {}
-void glUniform2i(GLint location, GLint v0, GLint v1) {}
-void glUniform2iv(GLint location, GLsizei count, const GLint *value) {}
-void glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {}
-void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) {}
-void glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {}
-void glUniform3iv(GLint location, GLsizei count, const GLint *value) {}
-void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {}
-void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) {}
-void glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {}
-void glUniform4iv(GLint location, GLsizei count, const GLint *value) {}
-void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {}
-void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {}
-void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {}
-void glUseProgram(GLuint program) {}
-void glValidateProgram(GLuint program) {}
-void glVertexAttrib1f(GLuint index, GLfloat x) {}
-void glVertexAttrib1fv(GLuint index, const GLfloat *v) {}
-void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {}
-void glVertexAttrib2fv(GLuint index, const GLfloat *v) {}
-void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {}
-void glVertexAttrib3fv(GLuint index, const GLfloat *v) {}
-void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {}
-void glVertexAttrib4fv(GLuint index, const GLfloat *v) {}
-void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {}
-void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {}
-
-
-// gles2 ext
-void glInsertEventMarkerEXT(GLsizei length, const GLchar *marker) {}
-void glPushGroupMarkerEXT(GLsizei length, const GLchar *marker) {}
-void glPopGroupMarkerEXT(void) {}
-void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments) {}
-void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) {}
-
-// GLES3
-void* glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
- return 0;
-}
-
-GLboolean glUnmapBuffer(GLenum target) {
- return GL_FALSE;
-}
diff --git a/libs/hwui/debug/wrap_gles.cpp b/libs/hwui/debug/wrap_gles.cpp
index c4f2e3537fe8..8dc946e5667b 100644
--- a/libs/hwui/debug/wrap_gles.cpp
+++ b/libs/hwui/debug/wrap_gles.cpp
@@ -14,80 +14,20 @@
* limitations under the License.
*/
-#include "unwrap_gles.h"
+#include "GlesDriver.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES3/gl3.h>
-#include <GLES3/gl31.h>
-#include <GLES3/gl32.h>
+using namespace android::uirenderer::debug;
-#include <cutils/log.h>
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
-void assertNoGlErrors(const char* apicall) {
- GLenum status = GL_NO_ERROR;
- GLenum lastError = GL_NO_ERROR;
- const char* lastErrorName = nullptr;
- while ((status = glGetError()) != GL_NO_ERROR) {
- lastError = status;
- switch (status) {
- case GL_INVALID_ENUM:
- ALOGE("GL error: GL_INVALID_ENUM");
- lastErrorName = "GL_INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- ALOGE("GL error: GL_INVALID_VALUE");
- lastErrorName = "GL_INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- ALOGE("GL error: GL_INVALID_OPERATION");
- lastErrorName = "GL_INVALID_OPERATION";
- break;
- case GL_OUT_OF_MEMORY:
- ALOGE("GL error: Out of memory!");
- lastErrorName = "GL_OUT_OF_MEMORY";
- break;
- default:
- ALOGE("GL error: 0x%x", status);
- lastErrorName = "UNKNOWN";
- }
- }
- LOG_ALWAYS_FATAL_IF(lastError != GL_NO_ERROR,
- "%s error! %s (0x%x)", apicall, lastErrorName, lastError);
-}
+#define API_ENTRY(x) x
+#define CALL_GL_API(api, ...) GlesDriver::get()->api##_(__VA_ARGS__)
+#define CALL_GL_API_RETURN(api, ...) return GlesDriver::get()->api##_(__VA_ARGS__)
-#define API_ENTRY(x) wrap_##x
-#define CALL_GL_API(x, ...) x(__VA_ARGS__); assertNoGlErrors(#x)
-#define CALL_GL_API_RETURN(x, ...) auto ret = x(__VA_ARGS__);\
- assertNoGlErrors(#x);\
- return ret
+#include "gles_stubs.in"
-extern "C" {
-#include <gl2_api.in>
-#include <gl2ext_api.in>
-
-// libGLESv2 handles these specially, so they are not in gl2_api.in
-
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *data) {
- CALL_GL_API(glGetBooleanv, pname, data);
-}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *data) {
- CALL_GL_API(glGetFloatv, pname, data);
-}
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *data) {
- CALL_GL_API(glGetIntegerv, pname, data);
-}
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
- CALL_GL_API_RETURN(glGetString, name);
-}
-const GLubyte * API_ENTRY(glGetStringi)(GLenum name, GLuint index) {
- CALL_GL_API_RETURN(glGetStringi, name, index);
-}
-void API_ENTRY(glGetInteger64v)(GLenum pname, GLint64 *data) {
- CALL_GL_API(glGetInteger64v, pname, data);
-}
-}
+#undef API_ENTRY
+#undef CALL_GL_API
+#undef CALL_GL_API_RETURN
diff --git a/libs/hwui/debug/wrap_gles.h b/libs/hwui/debug/wrap_gles.h
index 4a3537442e73..ecd46e249969 100644
--- a/libs/hwui/debug/wrap_gles.h
+++ b/libs/hwui/debug/wrap_gles.h
@@ -14,905 +14,15 @@
* limitations under the License.
*/
-#ifndef HWUI_GLES_WRAP_ENABLED
+// #include'ing this file is bad, bad things should be compile errors
+#ifdef HWUI_GLES_WRAP_ENABLED
+#error wrap_gles.h should only be used as an auto-included header, don't directly #include it
+#endif
#define HWUI_GLES_WRAP_ENABLED
-#define glActiveShaderProgram wrap_glActiveShaderProgram
-#define glActiveShaderProgramEXT wrap_glActiveShaderProgramEXT
-#define glActiveTexture wrap_glActiveTexture
-#define glAlphaFunc wrap_glAlphaFunc
-#define glAlphaFuncQCOM wrap_glAlphaFuncQCOM
-#define glAlphaFuncx wrap_glAlphaFuncx
-#define glAlphaFuncxOES wrap_glAlphaFuncxOES
-#define glApplyFramebufferAttachmentCMAAINTEL wrap_glApplyFramebufferAttachmentCMAAINTEL
-#define glAttachShader wrap_glAttachShader
-#define glBeginConditionalRenderNV wrap_glBeginConditionalRenderNV
-#define glBeginPerfMonitorAMD wrap_glBeginPerfMonitorAMD
-#define glBeginPerfQueryINTEL wrap_glBeginPerfQueryINTEL
-#define glBeginQuery wrap_glBeginQuery
-#define glBeginQueryEXT wrap_glBeginQueryEXT
-#define glBeginTransformFeedback wrap_glBeginTransformFeedback
-#define glBindAttribLocation wrap_glBindAttribLocation
-#define glBindBuffer wrap_glBindBuffer
-#define glBindBufferBase wrap_glBindBufferBase
-#define glBindBufferRange wrap_glBindBufferRange
-#define glBindFragDataLocationEXT wrap_glBindFragDataLocationEXT
-#define glBindFragDataLocationIndexedEXT wrap_glBindFragDataLocationIndexedEXT
-#define glBindFramebuffer wrap_glBindFramebuffer
-#define glBindFramebufferOES wrap_glBindFramebufferOES
-#define glBindImageTexture wrap_glBindImageTexture
-#define glBindProgramPipeline wrap_glBindProgramPipeline
-#define glBindProgramPipelineEXT wrap_glBindProgramPipelineEXT
-#define glBindRenderbuffer wrap_glBindRenderbuffer
-#define glBindRenderbufferOES wrap_glBindRenderbufferOES
-#define glBindSampler wrap_glBindSampler
-#define glBindTexture wrap_glBindTexture
-#define glBindTransformFeedback wrap_glBindTransformFeedback
-#define glBindVertexArray wrap_glBindVertexArray
-#define glBindVertexArrayOES wrap_glBindVertexArrayOES
-#define glBindVertexBuffer wrap_glBindVertexBuffer
-#define glBlendBarrier wrap_glBlendBarrier
-#define glBlendBarrierKHR wrap_glBlendBarrierKHR
-#define glBlendBarrierNV wrap_glBlendBarrierNV
-#define glBlendColor wrap_glBlendColor
-#define glBlendEquation wrap_glBlendEquation
-#define glBlendEquationOES wrap_glBlendEquationOES
-#define glBlendEquationSeparate wrap_glBlendEquationSeparate
-#define glBlendEquationSeparateOES wrap_glBlendEquationSeparateOES
-#define glBlendEquationSeparatei wrap_glBlendEquationSeparatei
-#define glBlendEquationSeparateiEXT wrap_glBlendEquationSeparateiEXT
-#define glBlendEquationSeparateiOES wrap_glBlendEquationSeparateiOES
-#define glBlendEquationi wrap_glBlendEquationi
-#define glBlendEquationiEXT wrap_glBlendEquationiEXT
-#define glBlendEquationiOES wrap_glBlendEquationiOES
-#define glBlendFunc wrap_glBlendFunc
-#define glBlendFuncSeparate wrap_glBlendFuncSeparate
-#define glBlendFuncSeparateOES wrap_glBlendFuncSeparateOES
-#define glBlendFuncSeparatei wrap_glBlendFuncSeparatei
-#define glBlendFuncSeparateiEXT wrap_glBlendFuncSeparateiEXT
-#define glBlendFuncSeparateiOES wrap_glBlendFuncSeparateiOES
-#define glBlendFunci wrap_glBlendFunci
-#define glBlendFunciEXT wrap_glBlendFunciEXT
-#define glBlendFunciOES wrap_glBlendFunciOES
-#define glBlendParameteriNV wrap_glBlendParameteriNV
-#define glBlitFramebuffer wrap_glBlitFramebuffer
-#define glBlitFramebufferANGLE wrap_glBlitFramebufferANGLE
-#define glBlitFramebufferNV wrap_glBlitFramebufferNV
-#define glBufferData wrap_glBufferData
-#define glBufferStorageEXT wrap_glBufferStorageEXT
-#define glBufferSubData wrap_glBufferSubData
-#define glCheckFramebufferStatus wrap_glCheckFramebufferStatus
-#define glCheckFramebufferStatusOES wrap_glCheckFramebufferStatusOES
-#define glClear wrap_glClear
-#define glClearBufferfi wrap_glClearBufferfi
-#define glClearBufferfv wrap_glClearBufferfv
-#define glClearBufferiv wrap_glClearBufferiv
-#define glClearBufferuiv wrap_glClearBufferuiv
-#define glClearColor wrap_glClearColor
-#define glClearColorx wrap_glClearColorx
-#define glClearColorxOES wrap_glClearColorxOES
-#define glClearDepthf wrap_glClearDepthf
-#define glClearDepthfOES wrap_glClearDepthfOES
-#define glClearDepthx wrap_glClearDepthx
-#define glClearDepthxOES wrap_glClearDepthxOES
-#define glClearStencil wrap_glClearStencil
-#define glClientActiveTexture wrap_glClientActiveTexture
-#define glClientWaitSync wrap_glClientWaitSync
-#define glClientWaitSyncAPPLE wrap_glClientWaitSyncAPPLE
-#define glClipPlanef wrap_glClipPlanef
-#define glClipPlanefIMG wrap_glClipPlanefIMG
-#define glClipPlanefOES wrap_glClipPlanefOES
-#define glClipPlanex wrap_glClipPlanex
-#define glClipPlanexIMG wrap_glClipPlanexIMG
-#define glClipPlanexOES wrap_glClipPlanexOES
-#define glColor4f wrap_glColor4f
-#define glColor4ub wrap_glColor4ub
-#define glColor4x wrap_glColor4x
-#define glColor4xOES wrap_glColor4xOES
-#define glColorMask wrap_glColorMask
-#define glColorMaski wrap_glColorMaski
-#define glColorMaskiEXT wrap_glColorMaskiEXT
-#define glColorMaskiOES wrap_glColorMaskiOES
-#define glColorPointer wrap_glColorPointer
-#define glCompileShader wrap_glCompileShader
-#define glCompressedTexImage2D wrap_glCompressedTexImage2D
-#define glCompressedTexImage3D wrap_glCompressedTexImage3D
-#define glCompressedTexImage3DOES wrap_glCompressedTexImage3DOES
-#define glCompressedTexSubImage2D wrap_glCompressedTexSubImage2D
-#define glCompressedTexSubImage3D wrap_glCompressedTexSubImage3D
-#define glCompressedTexSubImage3DOES wrap_glCompressedTexSubImage3DOES
-#define glCopyBufferSubData wrap_glCopyBufferSubData
-#define glCopyBufferSubDataNV wrap_glCopyBufferSubDataNV
-#define glCopyImageSubData wrap_glCopyImageSubData
-#define glCopyImageSubDataEXT wrap_glCopyImageSubDataEXT
-#define glCopyImageSubDataOES wrap_glCopyImageSubDataOES
-#define glCopyPathNV wrap_glCopyPathNV
-#define glCopyTexImage2D wrap_glCopyTexImage2D
-#define glCopyTexSubImage2D wrap_glCopyTexSubImage2D
-#define glCopyTexSubImage3D wrap_glCopyTexSubImage3D
-#define glCopyTexSubImage3DOES wrap_glCopyTexSubImage3DOES
-#define glCopyTextureLevelsAPPLE wrap_glCopyTextureLevelsAPPLE
-#define glCoverFillPathInstancedNV wrap_glCoverFillPathInstancedNV
-#define glCoverFillPathNV wrap_glCoverFillPathNV
-#define glCoverStrokePathInstancedNV wrap_glCoverStrokePathInstancedNV
-#define glCoverStrokePathNV wrap_glCoverStrokePathNV
-#define glCoverageMaskNV wrap_glCoverageMaskNV
-#define glCoverageModulationNV wrap_glCoverageModulationNV
-#define glCoverageModulationTableNV wrap_glCoverageModulationTableNV
-#define glCoverageOperationNV wrap_glCoverageOperationNV
-#define glCreatePerfQueryINTEL wrap_glCreatePerfQueryINTEL
-#define glCreateProgram wrap_glCreateProgram
-#define glCreateShader wrap_glCreateShader
-#define glCreateShaderProgramv wrap_glCreateShaderProgramv
-#define glCreateShaderProgramvEXT wrap_glCreateShaderProgramvEXT
-#define glCullFace wrap_glCullFace
-#define glCurrentPaletteMatrixOES wrap_glCurrentPaletteMatrixOES
-#define glDebugMessageCallback wrap_glDebugMessageCallback
-#define glDebugMessageCallbackKHR wrap_glDebugMessageCallbackKHR
-#define glDebugMessageControl wrap_glDebugMessageControl
-#define glDebugMessageControlKHR wrap_glDebugMessageControlKHR
-#define glDebugMessageInsert wrap_glDebugMessageInsert
-#define glDebugMessageInsertKHR wrap_glDebugMessageInsertKHR
-#define glDeleteBuffers wrap_glDeleteBuffers
-#define glDeleteFencesNV wrap_glDeleteFencesNV
-#define glDeleteFramebuffers wrap_glDeleteFramebuffers
-#define glDeleteFramebuffersOES wrap_glDeleteFramebuffersOES
-#define glDeletePathsNV wrap_glDeletePathsNV
-#define glDeletePerfMonitorsAMD wrap_glDeletePerfMonitorsAMD
-#define glDeletePerfQueryINTEL wrap_glDeletePerfQueryINTEL
-#define glDeleteProgram wrap_glDeleteProgram
-#define glDeleteProgramPipelines wrap_glDeleteProgramPipelines
-#define glDeleteProgramPipelinesEXT wrap_glDeleteProgramPipelinesEXT
-#define glDeleteQueries wrap_glDeleteQueries
-#define glDeleteQueriesEXT wrap_glDeleteQueriesEXT
-#define glDeleteRenderbuffers wrap_glDeleteRenderbuffers
-#define glDeleteRenderbuffersOES wrap_glDeleteRenderbuffersOES
-#define glDeleteSamplers wrap_glDeleteSamplers
-#define glDeleteShader wrap_glDeleteShader
-#define glDeleteSync wrap_glDeleteSync
-#define glDeleteSyncAPPLE wrap_glDeleteSyncAPPLE
-#define glDeleteTextures wrap_glDeleteTextures
-#define glDeleteTransformFeedbacks wrap_glDeleteTransformFeedbacks
-#define glDeleteVertexArrays wrap_glDeleteVertexArrays
-#define glDeleteVertexArraysOES wrap_glDeleteVertexArraysOES
-#define glDepthFunc wrap_glDepthFunc
-#define glDepthMask wrap_glDepthMask
-#define glDepthRangeArrayfvNV wrap_glDepthRangeArrayfvNV
-#define glDepthRangeIndexedfNV wrap_glDepthRangeIndexedfNV
-#define glDepthRangef wrap_glDepthRangef
-#define glDepthRangefOES wrap_glDepthRangefOES
-#define glDepthRangex wrap_glDepthRangex
-#define glDepthRangexOES wrap_glDepthRangexOES
-#define glDetachShader wrap_glDetachShader
-#define glDisable wrap_glDisable
-#define glDisableClientState wrap_glDisableClientState
-#define glDisableDriverControlQCOM wrap_glDisableDriverControlQCOM
-#define glDisableVertexAttribArray wrap_glDisableVertexAttribArray
-#define glDisablei wrap_glDisablei
-#define glDisableiEXT wrap_glDisableiEXT
-#define glDisableiNV wrap_glDisableiNV
-#define glDisableiOES wrap_glDisableiOES
-#define glDiscardFramebufferEXT wrap_glDiscardFramebufferEXT
-#define glDispatchCompute wrap_glDispatchCompute
-#define glDispatchComputeIndirect wrap_glDispatchComputeIndirect
-#define glDrawArrays wrap_glDrawArrays
-#define glDrawArraysIndirect wrap_glDrawArraysIndirect
-#define glDrawArraysInstanced wrap_glDrawArraysInstanced
-#define glDrawArraysInstancedANGLE wrap_glDrawArraysInstancedANGLE
-#define glDrawArraysInstancedBaseInstanceEXT wrap_glDrawArraysInstancedBaseInstanceEXT
-#define glDrawArraysInstancedEXT wrap_glDrawArraysInstancedEXT
-#define glDrawArraysInstancedNV wrap_glDrawArraysInstancedNV
-#define glDrawBuffers wrap_glDrawBuffers
-#define glDrawBuffersEXT wrap_glDrawBuffersEXT
-#define glDrawBuffersIndexedEXT wrap_glDrawBuffersIndexedEXT
-#define glDrawBuffersNV wrap_glDrawBuffersNV
-#define glDrawElements wrap_glDrawElements
-#define glDrawElementsBaseVertex wrap_glDrawElementsBaseVertex
-#define glDrawElementsBaseVertexEXT wrap_glDrawElementsBaseVertexEXT
-#define glDrawElementsBaseVertexOES wrap_glDrawElementsBaseVertexOES
-#define glDrawElementsIndirect wrap_glDrawElementsIndirect
-#define glDrawElementsInstanced wrap_glDrawElementsInstanced
-#define glDrawElementsInstancedANGLE wrap_glDrawElementsInstancedANGLE
-#define glDrawElementsInstancedBaseInstanceEXT wrap_glDrawElementsInstancedBaseInstanceEXT
-#define glDrawElementsInstancedBaseVertex wrap_glDrawElementsInstancedBaseVertex
-#define glDrawElementsInstancedBaseVertexBaseInstanceEXT wrap_glDrawElementsInstancedBaseVertexBaseInstanceEXT
-#define glDrawElementsInstancedBaseVertexEXT wrap_glDrawElementsInstancedBaseVertexEXT
-#define glDrawElementsInstancedBaseVertexOES wrap_glDrawElementsInstancedBaseVertexOES
-#define glDrawElementsInstancedEXT wrap_glDrawElementsInstancedEXT
-#define glDrawElementsInstancedNV wrap_glDrawElementsInstancedNV
-#define glDrawRangeElements wrap_glDrawRangeElements
-#define glDrawRangeElementsBaseVertex wrap_glDrawRangeElementsBaseVertex
-#define glDrawRangeElementsBaseVertexEXT wrap_glDrawRangeElementsBaseVertexEXT
-#define glDrawRangeElementsBaseVertexOES wrap_glDrawRangeElementsBaseVertexOES
-#define glDrawTexfOES wrap_glDrawTexfOES
-#define glDrawTexfvOES wrap_glDrawTexfvOES
-#define glDrawTexiOES wrap_glDrawTexiOES
-#define glDrawTexivOES wrap_glDrawTexivOES
-#define glDrawTexsOES wrap_glDrawTexsOES
-#define glDrawTexsvOES wrap_glDrawTexsvOES
-#define glDrawTexxOES wrap_glDrawTexxOES
-#define glDrawTexxvOES wrap_glDrawTexxvOES
-#define glEGLImageTargetRenderbufferStorageOES wrap_glEGLImageTargetRenderbufferStorageOES
-#define glEGLImageTargetTexture2DOES wrap_glEGLImageTargetTexture2DOES
-#define glEnable wrap_glEnable
-#define glEnableClientState wrap_glEnableClientState
-#define glEnableDriverControlQCOM wrap_glEnableDriverControlQCOM
-#define glEnableVertexAttribArray wrap_glEnableVertexAttribArray
-#define glEnablei wrap_glEnablei
-#define glEnableiEXT wrap_glEnableiEXT
-#define glEnableiNV wrap_glEnableiNV
-#define glEnableiOES wrap_glEnableiOES
-#define glEndConditionalRenderNV wrap_glEndConditionalRenderNV
-#define glEndPerfMonitorAMD wrap_glEndPerfMonitorAMD
-#define glEndPerfQueryINTEL wrap_glEndPerfQueryINTEL
-#define glEndQuery wrap_glEndQuery
-#define glEndQueryEXT wrap_glEndQueryEXT
-#define glEndTilingQCOM wrap_glEndTilingQCOM
-#define glEndTransformFeedback wrap_glEndTransformFeedback
-#define glExtGetBufferPointervQCOM wrap_glExtGetBufferPointervQCOM
-#define glExtGetBuffersQCOM wrap_glExtGetBuffersQCOM
-#define glExtGetFramebuffersQCOM wrap_glExtGetFramebuffersQCOM
-#define glExtGetProgramBinarySourceQCOM wrap_glExtGetProgramBinarySourceQCOM
-#define glExtGetProgramsQCOM wrap_glExtGetProgramsQCOM
-#define glExtGetRenderbuffersQCOM wrap_glExtGetRenderbuffersQCOM
-#define glExtGetShadersQCOM wrap_glExtGetShadersQCOM
-#define glExtGetTexLevelParameterivQCOM wrap_glExtGetTexLevelParameterivQCOM
-#define glExtGetTexSubImageQCOM wrap_glExtGetTexSubImageQCOM
-#define glExtGetTexturesQCOM wrap_glExtGetTexturesQCOM
-#define glExtIsProgramBinaryQCOM wrap_glExtIsProgramBinaryQCOM
-#define glExtTexObjectStateOverrideiQCOM wrap_glExtTexObjectStateOverrideiQCOM
-#define glFenceSync wrap_glFenceSync
-#define glFenceSyncAPPLE wrap_glFenceSyncAPPLE
-#define glFinish wrap_glFinish
-#define glFinishFenceNV wrap_glFinishFenceNV
-#define glFlush wrap_glFlush
-#define glFlushMappedBufferRange wrap_glFlushMappedBufferRange
-#define glFlushMappedBufferRangeEXT wrap_glFlushMappedBufferRangeEXT
-#define glFogf wrap_glFogf
-#define glFogfv wrap_glFogfv
-#define glFogx wrap_glFogx
-#define glFogxOES wrap_glFogxOES
-#define glFogxv wrap_glFogxv
-#define glFogxvOES wrap_glFogxvOES
-#define glFragmentCoverageColorNV wrap_glFragmentCoverageColorNV
-#define glFramebufferParameteri wrap_glFramebufferParameteri
-#define glFramebufferRenderbuffer wrap_glFramebufferRenderbuffer
-#define glFramebufferRenderbufferOES wrap_glFramebufferRenderbufferOES
-#define glFramebufferSampleLocationsfvNV wrap_glFramebufferSampleLocationsfvNV
-#define glFramebufferTexture wrap_glFramebufferTexture
-#define glFramebufferTexture2D wrap_glFramebufferTexture2D
-#define glFramebufferTexture2DMultisampleEXT wrap_glFramebufferTexture2DMultisampleEXT
-#define glFramebufferTexture2DMultisampleIMG wrap_glFramebufferTexture2DMultisampleIMG
-#define glFramebufferTexture2DOES wrap_glFramebufferTexture2DOES
-#define glFramebufferTexture3DOES wrap_glFramebufferTexture3DOES
-#define glFramebufferTextureEXT wrap_glFramebufferTextureEXT
-#define glFramebufferTextureLayer wrap_glFramebufferTextureLayer
-#define glFramebufferTextureMultisampleMultiviewOVR wrap_glFramebufferTextureMultisampleMultiviewOVR
-#define glFramebufferTextureMultiviewOVR wrap_glFramebufferTextureMultiviewOVR
-#define glFramebufferTextureOES wrap_glFramebufferTextureOES
-#define glFrontFace wrap_glFrontFace
-#define glFrustumf wrap_glFrustumf
-#define glFrustumfOES wrap_glFrustumfOES
-#define glFrustumx wrap_glFrustumx
-#define glFrustumxOES wrap_glFrustumxOES
-#define glGenBuffers wrap_glGenBuffers
-#define glGenFencesNV wrap_glGenFencesNV
-#define glGenFramebuffers wrap_glGenFramebuffers
-#define glGenFramebuffersOES wrap_glGenFramebuffersOES
-#define glGenPathsNV wrap_glGenPathsNV
-#define glGenPerfMonitorsAMD wrap_glGenPerfMonitorsAMD
-#define glGenProgramPipelines wrap_glGenProgramPipelines
-#define glGenProgramPipelinesEXT wrap_glGenProgramPipelinesEXT
-#define glGenQueries wrap_glGenQueries
-#define glGenQueriesEXT wrap_glGenQueriesEXT
-#define glGenRenderbuffers wrap_glGenRenderbuffers
-#define glGenRenderbuffersOES wrap_glGenRenderbuffersOES
-#define glGenSamplers wrap_glGenSamplers
-#define glGenTextures wrap_glGenTextures
-#define glGenTransformFeedbacks wrap_glGenTransformFeedbacks
-#define glGenVertexArrays wrap_glGenVertexArrays
-#define glGenVertexArraysOES wrap_glGenVertexArraysOES
-#define glGenerateMipmap wrap_glGenerateMipmap
-#define glGenerateMipmapOES wrap_glGenerateMipmapOES
-#define glGetActiveAttrib wrap_glGetActiveAttrib
-#define glGetActiveUniform wrap_glGetActiveUniform
-#define glGetActiveUniformBlockName wrap_glGetActiveUniformBlockName
-#define glGetActiveUniformBlockiv wrap_glGetActiveUniformBlockiv
-#define glGetActiveUniformsiv wrap_glGetActiveUniformsiv
-#define glGetAttachedShaders wrap_glGetAttachedShaders
-#define glGetAttribLocation wrap_glGetAttribLocation
-#define glGetBooleani_v wrap_glGetBooleani_v
-#define glGetBooleanv wrap_glGetBooleanv
-#define glGetBufferParameteri64v wrap_glGetBufferParameteri64v
-#define glGetBufferParameteriv wrap_glGetBufferParameteriv
-#define glGetBufferPointerv wrap_glGetBufferPointerv
-#define glGetBufferPointervOES wrap_glGetBufferPointervOES
-#define glGetClipPlanef wrap_glGetClipPlanef
-#define glGetClipPlanefOES wrap_glGetClipPlanefOES
-#define glGetClipPlanex wrap_glGetClipPlanex
-#define glGetClipPlanexOES wrap_glGetClipPlanexOES
-#define glGetCoverageModulationTableNV wrap_glGetCoverageModulationTableNV
-#define glGetDebugMessageLog wrap_glGetDebugMessageLog
-#define glGetDebugMessageLogKHR wrap_glGetDebugMessageLogKHR
-#define glGetDriverControlStringQCOM wrap_glGetDriverControlStringQCOM
-#define glGetDriverControlsQCOM wrap_glGetDriverControlsQCOM
-#define glGetError wrap_glGetError
-#define glGetFenceivNV wrap_glGetFenceivNV
-#define glGetFirstPerfQueryIdINTEL wrap_glGetFirstPerfQueryIdINTEL
-#define glGetFixedv wrap_glGetFixedv
-#define glGetFixedvOES wrap_glGetFixedvOES
-#define glGetFloati_vNV wrap_glGetFloati_vNV
-#define glGetFloatv wrap_glGetFloatv
-#define glGetFragDataIndexEXT wrap_glGetFragDataIndexEXT
-#define glGetFragDataLocation wrap_glGetFragDataLocation
-#define glGetFramebufferAttachmentParameteriv wrap_glGetFramebufferAttachmentParameteriv
-#define glGetFramebufferAttachmentParameterivOES wrap_glGetFramebufferAttachmentParameterivOES
-#define glGetFramebufferParameteriv wrap_glGetFramebufferParameteriv
-#define glGetGraphicsResetStatus wrap_glGetGraphicsResetStatus
-#define glGetGraphicsResetStatusEXT wrap_glGetGraphicsResetStatusEXT
-#define glGetGraphicsResetStatusKHR wrap_glGetGraphicsResetStatusKHR
-#define glGetImageHandleNV wrap_glGetImageHandleNV
-#define glGetInteger64i_v wrap_glGetInteger64i_v
-#define glGetInteger64v wrap_glGetInteger64v
-#define glGetInteger64vAPPLE wrap_glGetInteger64vAPPLE
-#define glGetIntegeri_v wrap_glGetIntegeri_v
-#define glGetIntegeri_vEXT wrap_glGetIntegeri_vEXT
-#define glGetIntegerv wrap_glGetIntegerv
-#define glGetInternalformatSampleivNV wrap_glGetInternalformatSampleivNV
-#define glGetInternalformativ wrap_glGetInternalformativ
-#define glGetLightfv wrap_glGetLightfv
-#define glGetLightxv wrap_glGetLightxv
-#define glGetLightxvOES wrap_glGetLightxvOES
-#define glGetMaterialfv wrap_glGetMaterialfv
-#define glGetMaterialxv wrap_glGetMaterialxv
-#define glGetMaterialxvOES wrap_glGetMaterialxvOES
-#define glGetMultisamplefv wrap_glGetMultisamplefv
-#define glGetNextPerfQueryIdINTEL wrap_glGetNextPerfQueryIdINTEL
-#define glGetObjectLabel wrap_glGetObjectLabel
-#define glGetObjectLabelEXT wrap_glGetObjectLabelEXT
-#define glGetObjectLabelKHR wrap_glGetObjectLabelKHR
-#define glGetObjectPtrLabel wrap_glGetObjectPtrLabel
-#define glGetObjectPtrLabelKHR wrap_glGetObjectPtrLabelKHR
-#define glGetPathCommandsNV wrap_glGetPathCommandsNV
-#define glGetPathCoordsNV wrap_glGetPathCoordsNV
-#define glGetPathDashArrayNV wrap_glGetPathDashArrayNV
-#define glGetPathLengthNV wrap_glGetPathLengthNV
-#define glGetPathMetricRangeNV wrap_glGetPathMetricRangeNV
-#define glGetPathMetricsNV wrap_glGetPathMetricsNV
-#define glGetPathParameterfvNV wrap_glGetPathParameterfvNV
-#define glGetPathParameterivNV wrap_glGetPathParameterivNV
-#define glGetPathSpacingNV wrap_glGetPathSpacingNV
-#define glGetPerfCounterInfoINTEL wrap_glGetPerfCounterInfoINTEL
-#define glGetPerfMonitorCounterDataAMD wrap_glGetPerfMonitorCounterDataAMD
-#define glGetPerfMonitorCounterInfoAMD wrap_glGetPerfMonitorCounterInfoAMD
-#define glGetPerfMonitorCounterStringAMD wrap_glGetPerfMonitorCounterStringAMD
-#define glGetPerfMonitorCountersAMD wrap_glGetPerfMonitorCountersAMD
-#define glGetPerfMonitorGroupStringAMD wrap_glGetPerfMonitorGroupStringAMD
-#define glGetPerfMonitorGroupsAMD wrap_glGetPerfMonitorGroupsAMD
-#define glGetPerfQueryDataINTEL wrap_glGetPerfQueryDataINTEL
-#define glGetPerfQueryIdByNameINTEL wrap_glGetPerfQueryIdByNameINTEL
-#define glGetPerfQueryInfoINTEL wrap_glGetPerfQueryInfoINTEL
-#define glGetPointerv wrap_glGetPointerv
-#define glGetPointervKHR wrap_glGetPointervKHR
-#define glGetProgramBinary wrap_glGetProgramBinary
-#define glGetProgramBinaryOES wrap_glGetProgramBinaryOES
-#define glGetProgramInfoLog wrap_glGetProgramInfoLog
-#define glGetProgramInterfaceiv wrap_glGetProgramInterfaceiv
-#define glGetProgramPipelineInfoLog wrap_glGetProgramPipelineInfoLog
-#define glGetProgramPipelineInfoLogEXT wrap_glGetProgramPipelineInfoLogEXT
-#define glGetProgramPipelineiv wrap_glGetProgramPipelineiv
-#define glGetProgramPipelineivEXT wrap_glGetProgramPipelineivEXT
-#define glGetProgramResourceIndex wrap_glGetProgramResourceIndex
-#define glGetProgramResourceLocation wrap_glGetProgramResourceLocation
-#define glGetProgramResourceLocationIndexEXT wrap_glGetProgramResourceLocationIndexEXT
-#define glGetProgramResourceName wrap_glGetProgramResourceName
-#define glGetProgramResourcefvNV wrap_glGetProgramResourcefvNV
-#define glGetProgramResourceiv wrap_glGetProgramResourceiv
-#define glGetProgramiv wrap_glGetProgramiv
-#define glGetQueryObjecti64vEXT wrap_glGetQueryObjecti64vEXT
-#define glGetQueryObjectivEXT wrap_glGetQueryObjectivEXT
-#define glGetQueryObjectui64vEXT wrap_glGetQueryObjectui64vEXT
-#define glGetQueryObjectuiv wrap_glGetQueryObjectuiv
-#define glGetQueryObjectuivEXT wrap_glGetQueryObjectuivEXT
-#define glGetQueryiv wrap_glGetQueryiv
-#define glGetQueryivEXT wrap_glGetQueryivEXT
-#define glGetRenderbufferParameteriv wrap_glGetRenderbufferParameteriv
-#define glGetRenderbufferParameterivOES wrap_glGetRenderbufferParameterivOES
-#define glGetSamplerParameterIiv wrap_glGetSamplerParameterIiv
-#define glGetSamplerParameterIivEXT wrap_glGetSamplerParameterIivEXT
-#define glGetSamplerParameterIivOES wrap_glGetSamplerParameterIivOES
-#define glGetSamplerParameterIuiv wrap_glGetSamplerParameterIuiv
-#define glGetSamplerParameterIuivEXT wrap_glGetSamplerParameterIuivEXT
-#define glGetSamplerParameterIuivOES wrap_glGetSamplerParameterIuivOES
-#define glGetSamplerParameterfv wrap_glGetSamplerParameterfv
-#define glGetSamplerParameteriv wrap_glGetSamplerParameteriv
-#define glGetShaderInfoLog wrap_glGetShaderInfoLog
-#define glGetShaderPrecisionFormat wrap_glGetShaderPrecisionFormat
-#define glGetShaderSource wrap_glGetShaderSource
-#define glGetShaderiv wrap_glGetShaderiv
-#define glGetString wrap_glGetString
-#define glGetStringi wrap_glGetStringi
-#define glGetSynciv wrap_glGetSynciv
-#define glGetSyncivAPPLE wrap_glGetSyncivAPPLE
-#define glGetTexEnvfv wrap_glGetTexEnvfv
-#define glGetTexEnviv wrap_glGetTexEnviv
-#define glGetTexEnvxv wrap_glGetTexEnvxv
-#define glGetTexEnvxvOES wrap_glGetTexEnvxvOES
-#define glGetTexGenfvOES wrap_glGetTexGenfvOES
-#define glGetTexGenivOES wrap_glGetTexGenivOES
-#define glGetTexGenxvOES wrap_glGetTexGenxvOES
-#define glGetTexLevelParameterfv wrap_glGetTexLevelParameterfv
-#define glGetTexLevelParameteriv wrap_glGetTexLevelParameteriv
-#define glGetTexParameterIiv wrap_glGetTexParameterIiv
-#define glGetTexParameterIivEXT wrap_glGetTexParameterIivEXT
-#define glGetTexParameterIivOES wrap_glGetTexParameterIivOES
-#define glGetTexParameterIuiv wrap_glGetTexParameterIuiv
-#define glGetTexParameterIuivEXT wrap_glGetTexParameterIuivEXT
-#define glGetTexParameterIuivOES wrap_glGetTexParameterIuivOES
-#define glGetTexParameterfv wrap_glGetTexParameterfv
-#define glGetTexParameteriv wrap_glGetTexParameteriv
-#define glGetTexParameterxv wrap_glGetTexParameterxv
-#define glGetTexParameterxvOES wrap_glGetTexParameterxvOES
-#define glGetTextureHandleNV wrap_glGetTextureHandleNV
-#define glGetTextureSamplerHandleNV wrap_glGetTextureSamplerHandleNV
-#define glGetTransformFeedbackVarying wrap_glGetTransformFeedbackVarying
-#define glGetTranslatedShaderSourceANGLE wrap_glGetTranslatedShaderSourceANGLE
-#define glGetUniformBlockIndex wrap_glGetUniformBlockIndex
-#define glGetUniformIndices wrap_glGetUniformIndices
-#define glGetUniformLocation wrap_glGetUniformLocation
-#define glGetUniformfv wrap_glGetUniformfv
-#define glGetUniformiv wrap_glGetUniformiv
-#define glGetUniformuiv wrap_glGetUniformuiv
-#define glGetVertexAttribIiv wrap_glGetVertexAttribIiv
-#define glGetVertexAttribIuiv wrap_glGetVertexAttribIuiv
-#define glGetVertexAttribPointerv wrap_glGetVertexAttribPointerv
-#define glGetVertexAttribfv wrap_glGetVertexAttribfv
-#define glGetVertexAttribiv wrap_glGetVertexAttribiv
-#define glGetnUniformfv wrap_glGetnUniformfv
-#define glGetnUniformfvEXT wrap_glGetnUniformfvEXT
-#define glGetnUniformfvKHR wrap_glGetnUniformfvKHR
-#define glGetnUniformiv wrap_glGetnUniformiv
-#define glGetnUniformivEXT wrap_glGetnUniformivEXT
-#define glGetnUniformivKHR wrap_glGetnUniformivKHR
-#define glGetnUniformuiv wrap_glGetnUniformuiv
-#define glGetnUniformuivKHR wrap_glGetnUniformuivKHR
-#define glHint wrap_glHint
-#define glInsertEventMarkerEXT wrap_glInsertEventMarkerEXT
-#define glInterpolatePathsNV wrap_glInterpolatePathsNV
-#define glInvalidateFramebuffer wrap_glInvalidateFramebuffer
-#define glInvalidateSubFramebuffer wrap_glInvalidateSubFramebuffer
-#define glIsBuffer wrap_glIsBuffer
-#define glIsEnabled wrap_glIsEnabled
-#define glIsEnabledi wrap_glIsEnabledi
-#define glIsEnablediEXT wrap_glIsEnablediEXT
-#define glIsEnablediNV wrap_glIsEnablediNV
-#define glIsEnablediOES wrap_glIsEnablediOES
-#define glIsFenceNV wrap_glIsFenceNV
-#define glIsFramebuffer wrap_glIsFramebuffer
-#define glIsFramebufferOES wrap_glIsFramebufferOES
-#define glIsImageHandleResidentNV wrap_glIsImageHandleResidentNV
-#define glIsPathNV wrap_glIsPathNV
-#define glIsPointInFillPathNV wrap_glIsPointInFillPathNV
-#define glIsPointInStrokePathNV wrap_glIsPointInStrokePathNV
-#define glIsProgram wrap_glIsProgram
-#define glIsProgramPipeline wrap_glIsProgramPipeline
-#define glIsProgramPipelineEXT wrap_glIsProgramPipelineEXT
-#define glIsQuery wrap_glIsQuery
-#define glIsQueryEXT wrap_glIsQueryEXT
-#define glIsRenderbuffer wrap_glIsRenderbuffer
-#define glIsRenderbufferOES wrap_glIsRenderbufferOES
-#define glIsSampler wrap_glIsSampler
-#define glIsShader wrap_glIsShader
-#define glIsSync wrap_glIsSync
-#define glIsSyncAPPLE wrap_glIsSyncAPPLE
-#define glIsTexture wrap_glIsTexture
-#define glIsTextureHandleResidentNV wrap_glIsTextureHandleResidentNV
-#define glIsTransformFeedback wrap_glIsTransformFeedback
-#define glIsVertexArray wrap_glIsVertexArray
-#define glIsVertexArrayOES wrap_glIsVertexArrayOES
-#define glLabelObjectEXT wrap_glLabelObjectEXT
-#define glLightModelf wrap_glLightModelf
-#define glLightModelfv wrap_glLightModelfv
-#define glLightModelx wrap_glLightModelx
-#define glLightModelxOES wrap_glLightModelxOES
-#define glLightModelxv wrap_glLightModelxv
-#define glLightModelxvOES wrap_glLightModelxvOES
-#define glLightf wrap_glLightf
-#define glLightfv wrap_glLightfv
-#define glLightx wrap_glLightx
-#define glLightxOES wrap_glLightxOES
-#define glLightxv wrap_glLightxv
-#define glLightxvOES wrap_glLightxvOES
-#define glLineWidth wrap_glLineWidth
-#define glLineWidthx wrap_glLineWidthx
-#define glLineWidthxOES wrap_glLineWidthxOES
-#define glLinkProgram wrap_glLinkProgram
-#define glLoadIdentity wrap_glLoadIdentity
-#define glLoadMatrixf wrap_glLoadMatrixf
-#define glLoadMatrixx wrap_glLoadMatrixx
-#define glLoadMatrixxOES wrap_glLoadMatrixxOES
-#define glLoadPaletteFromModelViewMatrixOES wrap_glLoadPaletteFromModelViewMatrixOES
-#define glLogicOp wrap_glLogicOp
-#define glMakeImageHandleNonResidentNV wrap_glMakeImageHandleNonResidentNV
-#define glMakeImageHandleResidentNV wrap_glMakeImageHandleResidentNV
-#define glMakeTextureHandleNonResidentNV wrap_glMakeTextureHandleNonResidentNV
-#define glMakeTextureHandleResidentNV wrap_glMakeTextureHandleResidentNV
-#define glMapBufferOES wrap_glMapBufferOES
-#define glMapBufferRange wrap_glMapBufferRange
-#define glMapBufferRangeEXT wrap_glMapBufferRangeEXT
-#define glMaterialf wrap_glMaterialf
-#define glMaterialfv wrap_glMaterialfv
-#define glMaterialx wrap_glMaterialx
-#define glMaterialxOES wrap_glMaterialxOES
-#define glMaterialxv wrap_glMaterialxv
-#define glMaterialxvOES wrap_glMaterialxvOES
-#define glMatrixIndexPointerOES wrap_glMatrixIndexPointerOES
-#define glMatrixLoad3x2fNV wrap_glMatrixLoad3x2fNV
-#define glMatrixLoad3x3fNV wrap_glMatrixLoad3x3fNV
-#define glMatrixLoadTranspose3x3fNV wrap_glMatrixLoadTranspose3x3fNV
-#define glMatrixMode wrap_glMatrixMode
-#define glMatrixMult3x2fNV wrap_glMatrixMult3x2fNV
-#define glMatrixMult3x3fNV wrap_glMatrixMult3x3fNV
-#define glMatrixMultTranspose3x3fNV wrap_glMatrixMultTranspose3x3fNV
-#define glMemoryBarrier wrap_glMemoryBarrier
-#define glMemoryBarrierByRegion wrap_glMemoryBarrierByRegion
-#define glMinSampleShading wrap_glMinSampleShading
-#define glMinSampleShadingOES wrap_glMinSampleShadingOES
-#define glMultMatrixf wrap_glMultMatrixf
-#define glMultMatrixx wrap_glMultMatrixx
-#define glMultMatrixxOES wrap_glMultMatrixxOES
-#define glMultiDrawArraysEXT wrap_glMultiDrawArraysEXT
-#define glMultiDrawArraysIndirectEXT wrap_glMultiDrawArraysIndirectEXT
-#define glMultiDrawElementsBaseVertexEXT wrap_glMultiDrawElementsBaseVertexEXT
-#define glMultiDrawElementsBaseVertexOES wrap_glMultiDrawElementsBaseVertexOES
-#define glMultiDrawElementsEXT wrap_glMultiDrawElementsEXT
-#define glMultiDrawElementsIndirectEXT wrap_glMultiDrawElementsIndirectEXT
-#define glMultiTexCoord4f wrap_glMultiTexCoord4f
-#define glMultiTexCoord4x wrap_glMultiTexCoord4x
-#define glMultiTexCoord4xOES wrap_glMultiTexCoord4xOES
-#define glNamedFramebufferSampleLocationsfvNV wrap_glNamedFramebufferSampleLocationsfvNV
-#define glNormal3f wrap_glNormal3f
-#define glNormal3x wrap_glNormal3x
-#define glNormal3xOES wrap_glNormal3xOES
-#define glNormalPointer wrap_glNormalPointer
-#define glObjectLabel wrap_glObjectLabel
-#define glObjectLabelKHR wrap_glObjectLabelKHR
-#define glObjectPtrLabel wrap_glObjectPtrLabel
-#define glObjectPtrLabelKHR wrap_glObjectPtrLabelKHR
-#define glOrthof wrap_glOrthof
-#define glOrthofOES wrap_glOrthofOES
-#define glOrthox wrap_glOrthox
-#define glOrthoxOES wrap_glOrthoxOES
-#define glPatchParameteri wrap_glPatchParameteri
-#define glPatchParameteriEXT wrap_glPatchParameteriEXT
-#define glPatchParameteriOES wrap_glPatchParameteriOES
-#define glPathCommandsNV wrap_glPathCommandsNV
-#define glPathCoordsNV wrap_glPathCoordsNV
-#define glPathCoverDepthFuncNV wrap_glPathCoverDepthFuncNV
-#define glPathDashArrayNV wrap_glPathDashArrayNV
-#define glPathGlyphIndexArrayNV wrap_glPathGlyphIndexArrayNV
-#define glPathGlyphIndexRangeNV wrap_glPathGlyphIndexRangeNV
-#define glPathGlyphRangeNV wrap_glPathGlyphRangeNV
-#define glPathGlyphsNV wrap_glPathGlyphsNV
-#define glPathMemoryGlyphIndexArrayNV wrap_glPathMemoryGlyphIndexArrayNV
-#define glPathParameterfNV wrap_glPathParameterfNV
-#define glPathParameterfvNV wrap_glPathParameterfvNV
-#define glPathParameteriNV wrap_glPathParameteriNV
-#define glPathParameterivNV wrap_glPathParameterivNV
-#define glPathStencilDepthOffsetNV wrap_glPathStencilDepthOffsetNV
-#define glPathStencilFuncNV wrap_glPathStencilFuncNV
-#define glPathStringNV wrap_glPathStringNV
-#define glPathSubCommandsNV wrap_glPathSubCommandsNV
-#define glPathSubCoordsNV wrap_glPathSubCoordsNV
-#define glPauseTransformFeedback wrap_glPauseTransformFeedback
-#define glPixelStorei wrap_glPixelStorei
-#define glPointAlongPathNV wrap_glPointAlongPathNV
-#define glPointParameterf wrap_glPointParameterf
-#define glPointParameterfv wrap_glPointParameterfv
-#define glPointParameterx wrap_glPointParameterx
-#define glPointParameterxOES wrap_glPointParameterxOES
-#define glPointParameterxv wrap_glPointParameterxv
-#define glPointParameterxvOES wrap_glPointParameterxvOES
-#define glPointSize wrap_glPointSize
-#define glPointSizePointerOES wrap_glPointSizePointerOES
-#define glPointSizex wrap_glPointSizex
-#define glPointSizexOES wrap_glPointSizexOES
-#define glPolygonModeNV wrap_glPolygonModeNV
-#define glPolygonOffset wrap_glPolygonOffset
-#define glPolygonOffsetx wrap_glPolygonOffsetx
-#define glPolygonOffsetxOES wrap_glPolygonOffsetxOES
-#define glPopDebugGroup wrap_glPopDebugGroup
-#define glPopDebugGroupKHR wrap_glPopDebugGroupKHR
-#define glPopGroupMarkerEXT wrap_glPopGroupMarkerEXT
-#define glPopMatrix wrap_glPopMatrix
-#define glPrimitiveBoundingBox wrap_glPrimitiveBoundingBox
-#define glPrimitiveBoundingBoxEXT wrap_glPrimitiveBoundingBoxEXT
-#define glPrimitiveBoundingBoxOES wrap_glPrimitiveBoundingBoxOES
-#define glProgramBinary wrap_glProgramBinary
-#define glProgramBinaryOES wrap_glProgramBinaryOES
-#define glProgramParameteri wrap_glProgramParameteri
-#define glProgramParameteriEXT wrap_glProgramParameteriEXT
-#define glProgramPathFragmentInputGenNV wrap_glProgramPathFragmentInputGenNV
-#define glProgramUniform1f wrap_glProgramUniform1f
-#define glProgramUniform1fEXT wrap_glProgramUniform1fEXT
-#define glProgramUniform1fv wrap_glProgramUniform1fv
-#define glProgramUniform1fvEXT wrap_glProgramUniform1fvEXT
-#define glProgramUniform1i wrap_glProgramUniform1i
-#define glProgramUniform1iEXT wrap_glProgramUniform1iEXT
-#define glProgramUniform1iv wrap_glProgramUniform1iv
-#define glProgramUniform1ivEXT wrap_glProgramUniform1ivEXT
-#define glProgramUniform1ui wrap_glProgramUniform1ui
-#define glProgramUniform1uiEXT wrap_glProgramUniform1uiEXT
-#define glProgramUniform1uiv wrap_glProgramUniform1uiv
-#define glProgramUniform1uivEXT wrap_glProgramUniform1uivEXT
-#define glProgramUniform2f wrap_glProgramUniform2f
-#define glProgramUniform2fEXT wrap_glProgramUniform2fEXT
-#define glProgramUniform2fv wrap_glProgramUniform2fv
-#define glProgramUniform2fvEXT wrap_glProgramUniform2fvEXT
-#define glProgramUniform2i wrap_glProgramUniform2i
-#define glProgramUniform2iEXT wrap_glProgramUniform2iEXT
-#define glProgramUniform2iv wrap_glProgramUniform2iv
-#define glProgramUniform2ivEXT wrap_glProgramUniform2ivEXT
-#define glProgramUniform2ui wrap_glProgramUniform2ui
-#define glProgramUniform2uiEXT wrap_glProgramUniform2uiEXT
-#define glProgramUniform2uiv wrap_glProgramUniform2uiv
-#define glProgramUniform2uivEXT wrap_glProgramUniform2uivEXT
-#define glProgramUniform3f wrap_glProgramUniform3f
-#define glProgramUniform3fEXT wrap_glProgramUniform3fEXT
-#define glProgramUniform3fv wrap_glProgramUniform3fv
-#define glProgramUniform3fvEXT wrap_glProgramUniform3fvEXT
-#define glProgramUniform3i wrap_glProgramUniform3i
-#define glProgramUniform3iEXT wrap_glProgramUniform3iEXT
-#define glProgramUniform3iv wrap_glProgramUniform3iv
-#define glProgramUniform3ivEXT wrap_glProgramUniform3ivEXT
-#define glProgramUniform3ui wrap_glProgramUniform3ui
-#define glProgramUniform3uiEXT wrap_glProgramUniform3uiEXT
-#define glProgramUniform3uiv wrap_glProgramUniform3uiv
-#define glProgramUniform3uivEXT wrap_glProgramUniform3uivEXT
-#define glProgramUniform4f wrap_glProgramUniform4f
-#define glProgramUniform4fEXT wrap_glProgramUniform4fEXT
-#define glProgramUniform4fv wrap_glProgramUniform4fv
-#define glProgramUniform4fvEXT wrap_glProgramUniform4fvEXT
-#define glProgramUniform4i wrap_glProgramUniform4i
-#define glProgramUniform4iEXT wrap_glProgramUniform4iEXT
-#define glProgramUniform4iv wrap_glProgramUniform4iv
-#define glProgramUniform4ivEXT wrap_glProgramUniform4ivEXT
-#define glProgramUniform4ui wrap_glProgramUniform4ui
-#define glProgramUniform4uiEXT wrap_glProgramUniform4uiEXT
-#define glProgramUniform4uiv wrap_glProgramUniform4uiv
-#define glProgramUniform4uivEXT wrap_glProgramUniform4uivEXT
-#define glProgramUniformHandleui64NV wrap_glProgramUniformHandleui64NV
-#define glProgramUniformHandleui64vNV wrap_glProgramUniformHandleui64vNV
-#define glProgramUniformMatrix2fv wrap_glProgramUniformMatrix2fv
-#define glProgramUniformMatrix2fvEXT wrap_glProgramUniformMatrix2fvEXT
-#define glProgramUniformMatrix2x3fv wrap_glProgramUniformMatrix2x3fv
-#define glProgramUniformMatrix2x3fvEXT wrap_glProgramUniformMatrix2x3fvEXT
-#define glProgramUniformMatrix2x4fv wrap_glProgramUniformMatrix2x4fv
-#define glProgramUniformMatrix2x4fvEXT wrap_glProgramUniformMatrix2x4fvEXT
-#define glProgramUniformMatrix3fv wrap_glProgramUniformMatrix3fv
-#define glProgramUniformMatrix3fvEXT wrap_glProgramUniformMatrix3fvEXT
-#define glProgramUniformMatrix3x2fv wrap_glProgramUniformMatrix3x2fv
-#define glProgramUniformMatrix3x2fvEXT wrap_glProgramUniformMatrix3x2fvEXT
-#define glProgramUniformMatrix3x4fv wrap_glProgramUniformMatrix3x4fv
-#define glProgramUniformMatrix3x4fvEXT wrap_glProgramUniformMatrix3x4fvEXT
-#define glProgramUniformMatrix4fv wrap_glProgramUniformMatrix4fv
-#define glProgramUniformMatrix4fvEXT wrap_glProgramUniformMatrix4fvEXT
-#define glProgramUniformMatrix4x2fv wrap_glProgramUniformMatrix4x2fv
-#define glProgramUniformMatrix4x2fvEXT wrap_glProgramUniformMatrix4x2fvEXT
-#define glProgramUniformMatrix4x3fv wrap_glProgramUniformMatrix4x3fv
-#define glProgramUniformMatrix4x3fvEXT wrap_glProgramUniformMatrix4x3fvEXT
-#define glPushDebugGroup wrap_glPushDebugGroup
-#define glPushDebugGroupKHR wrap_glPushDebugGroupKHR
-#define glPushGroupMarkerEXT wrap_glPushGroupMarkerEXT
-#define glPushMatrix wrap_glPushMatrix
-#define glQueryCounterEXT wrap_glQueryCounterEXT
-#define glQueryMatrixxOES wrap_glQueryMatrixxOES
-#define glRasterSamplesEXT wrap_glRasterSamplesEXT
-#define glReadBuffer wrap_glReadBuffer
-#define glReadBufferIndexedEXT wrap_glReadBufferIndexedEXT
-#define glReadBufferNV wrap_glReadBufferNV
-#define glReadPixels wrap_glReadPixels
-#define glReadnPixels wrap_glReadnPixels
-#define glReadnPixelsEXT wrap_glReadnPixelsEXT
-#define glReadnPixelsKHR wrap_glReadnPixelsKHR
-#define glReleaseShaderCompiler wrap_glReleaseShaderCompiler
-#define glRenderbufferStorage wrap_glRenderbufferStorage
-#define glRenderbufferStorageMultisample wrap_glRenderbufferStorageMultisample
-#define glRenderbufferStorageMultisampleANGLE wrap_glRenderbufferStorageMultisampleANGLE
-#define glRenderbufferStorageMultisampleAPPLE wrap_glRenderbufferStorageMultisampleAPPLE
-#define glRenderbufferStorageMultisampleEXT wrap_glRenderbufferStorageMultisampleEXT
-#define glRenderbufferStorageMultisampleIMG wrap_glRenderbufferStorageMultisampleIMG
-#define glRenderbufferStorageMultisampleNV wrap_glRenderbufferStorageMultisampleNV
-#define glRenderbufferStorageOES wrap_glRenderbufferStorageOES
-#define glResolveDepthValuesNV wrap_glResolveDepthValuesNV
-#define glResolveMultisampleFramebufferAPPLE wrap_glResolveMultisampleFramebufferAPPLE
-#define glResumeTransformFeedback wrap_glResumeTransformFeedback
-#define glRotatef wrap_glRotatef
-#define glRotatex wrap_glRotatex
-#define glRotatexOES wrap_glRotatexOES
-#define glSampleCoverage wrap_glSampleCoverage
-#define glSampleCoveragex wrap_glSampleCoveragex
-#define glSampleCoveragexOES wrap_glSampleCoveragexOES
-#define glSampleMaski wrap_glSampleMaski
-#define glSamplerParameterIiv wrap_glSamplerParameterIiv
-#define glSamplerParameterIivEXT wrap_glSamplerParameterIivEXT
-#define glSamplerParameterIivOES wrap_glSamplerParameterIivOES
-#define glSamplerParameterIuiv wrap_glSamplerParameterIuiv
-#define glSamplerParameterIuivEXT wrap_glSamplerParameterIuivEXT
-#define glSamplerParameterIuivOES wrap_glSamplerParameterIuivOES
-#define glSamplerParameterf wrap_glSamplerParameterf
-#define glSamplerParameterfv wrap_glSamplerParameterfv
-#define glSamplerParameteri wrap_glSamplerParameteri
-#define glSamplerParameteriv wrap_glSamplerParameteriv
-#define glScalef wrap_glScalef
-#define glScalex wrap_glScalex
-#define glScalexOES wrap_glScalexOES
-#define glScissor wrap_glScissor
-#define glScissorArrayvNV wrap_glScissorArrayvNV
-#define glScissorIndexedNV wrap_glScissorIndexedNV
-#define glScissorIndexedvNV wrap_glScissorIndexedvNV
-#define glSelectPerfMonitorCountersAMD wrap_glSelectPerfMonitorCountersAMD
-#define glSetFenceNV wrap_glSetFenceNV
-#define glShadeModel wrap_glShadeModel
-#define glShaderBinary wrap_glShaderBinary
-#define glShaderSource wrap_glShaderSource
-#define glStartTilingQCOM wrap_glStartTilingQCOM
-#define glStencilFillPathInstancedNV wrap_glStencilFillPathInstancedNV
-#define glStencilFillPathNV wrap_glStencilFillPathNV
-#define glStencilFunc wrap_glStencilFunc
-#define glStencilFuncSeparate wrap_glStencilFuncSeparate
-#define glStencilMask wrap_glStencilMask
-#define glStencilMaskSeparate wrap_glStencilMaskSeparate
-#define glStencilOp wrap_glStencilOp
-#define glStencilOpSeparate wrap_glStencilOpSeparate
-#define glStencilStrokePathInstancedNV wrap_glStencilStrokePathInstancedNV
-#define glStencilStrokePathNV wrap_glStencilStrokePathNV
-#define glStencilThenCoverFillPathInstancedNV wrap_glStencilThenCoverFillPathInstancedNV
-#define glStencilThenCoverFillPathNV wrap_glStencilThenCoverFillPathNV
-#define glStencilThenCoverStrokePathInstancedNV wrap_glStencilThenCoverStrokePathInstancedNV
-#define glStencilThenCoverStrokePathNV wrap_glStencilThenCoverStrokePathNV
-#define glSubpixelPrecisionBiasNV wrap_glSubpixelPrecisionBiasNV
-#define glTestFenceNV wrap_glTestFenceNV
-#define glTexBuffer wrap_glTexBuffer
-#define glTexBufferEXT wrap_glTexBufferEXT
-#define glTexBufferOES wrap_glTexBufferOES
-#define glTexBufferRange wrap_glTexBufferRange
-#define glTexBufferRangeEXT wrap_glTexBufferRangeEXT
-#define glTexBufferRangeOES wrap_glTexBufferRangeOES
-#define glTexCoordPointer wrap_glTexCoordPointer
-#define glTexEnvf wrap_glTexEnvf
-#define glTexEnvfv wrap_glTexEnvfv
-#define glTexEnvi wrap_glTexEnvi
-#define glTexEnviv wrap_glTexEnviv
-#define glTexEnvx wrap_glTexEnvx
-#define glTexEnvxOES wrap_glTexEnvxOES
-#define glTexEnvxv wrap_glTexEnvxv
-#define glTexEnvxvOES wrap_glTexEnvxvOES
-#define glTexGenfOES wrap_glTexGenfOES
-#define glTexGenfvOES wrap_glTexGenfvOES
-#define glTexGeniOES wrap_glTexGeniOES
-#define glTexGenivOES wrap_glTexGenivOES
-#define glTexGenxOES wrap_glTexGenxOES
-#define glTexGenxvOES wrap_glTexGenxvOES
-#define glTexImage2D wrap_glTexImage2D
-#define glTexImage3D wrap_glTexImage3D
-#define glTexImage3DOES wrap_glTexImage3DOES
-#define glTexPageCommitmentEXT wrap_glTexPageCommitmentEXT
-#define glTexParameterIiv wrap_glTexParameterIiv
-#define glTexParameterIivEXT wrap_glTexParameterIivEXT
-#define glTexParameterIivOES wrap_glTexParameterIivOES
-#define glTexParameterIuiv wrap_glTexParameterIuiv
-#define glTexParameterIuivEXT wrap_glTexParameterIuivEXT
-#define glTexParameterIuivOES wrap_glTexParameterIuivOES
-#define glTexParameterf wrap_glTexParameterf
-#define glTexParameterfv wrap_glTexParameterfv
-#define glTexParameteri wrap_glTexParameteri
-#define glTexParameteriv wrap_glTexParameteriv
-#define glTexParameterx wrap_glTexParameterx
-#define glTexParameterxOES wrap_glTexParameterxOES
-#define glTexParameterxv wrap_glTexParameterxv
-#define glTexParameterxvOES wrap_glTexParameterxvOES
-#define glTexStorage1DEXT wrap_glTexStorage1DEXT
-#define glTexStorage2D wrap_glTexStorage2D
-#define glTexStorage2DEXT wrap_glTexStorage2DEXT
-#define glTexStorage2DMultisample wrap_glTexStorage2DMultisample
-#define glTexStorage3D wrap_glTexStorage3D
-#define glTexStorage3DEXT wrap_glTexStorage3DEXT
-#define glTexStorage3DMultisample wrap_glTexStorage3DMultisample
-#define glTexStorage3DMultisampleOES wrap_glTexStorage3DMultisampleOES
-#define glTexSubImage2D wrap_glTexSubImage2D
-#define glTexSubImage3D wrap_glTexSubImage3D
-#define glTexSubImage3DOES wrap_glTexSubImage3DOES
-#define glTextureStorage1DEXT wrap_glTextureStorage1DEXT
-#define glTextureStorage2DEXT wrap_glTextureStorage2DEXT
-#define glTextureStorage3DEXT wrap_glTextureStorage3DEXT
-#define glTextureViewEXT wrap_glTextureViewEXT
-#define glTextureViewOES wrap_glTextureViewOES
-#define glTransformFeedbackVaryings wrap_glTransformFeedbackVaryings
-#define glTransformPathNV wrap_glTransformPathNV
-#define glTranslatef wrap_glTranslatef
-#define glTranslatex wrap_glTranslatex
-#define glTranslatexOES wrap_glTranslatexOES
-#define glUniform1f wrap_glUniform1f
-#define glUniform1fv wrap_glUniform1fv
-#define glUniform1i wrap_glUniform1i
-#define glUniform1iv wrap_glUniform1iv
-#define glUniform1ui wrap_glUniform1ui
-#define glUniform1uiv wrap_glUniform1uiv
-#define glUniform2f wrap_glUniform2f
-#define glUniform2fv wrap_glUniform2fv
-#define glUniform2i wrap_glUniform2i
-#define glUniform2iv wrap_glUniform2iv
-#define glUniform2ui wrap_glUniform2ui
-#define glUniform2uiv wrap_glUniform2uiv
-#define glUniform3f wrap_glUniform3f
-#define glUniform3fv wrap_glUniform3fv
-#define glUniform3i wrap_glUniform3i
-#define glUniform3iv wrap_glUniform3iv
-#define glUniform3ui wrap_glUniform3ui
-#define glUniform3uiv wrap_glUniform3uiv
-#define glUniform4f wrap_glUniform4f
-#define glUniform4fv wrap_glUniform4fv
-#define glUniform4i wrap_glUniform4i
-#define glUniform4iv wrap_glUniform4iv
-#define glUniform4ui wrap_glUniform4ui
-#define glUniform4uiv wrap_glUniform4uiv
-#define glUniformBlockBinding wrap_glUniformBlockBinding
-#define glUniformHandleui64NV wrap_glUniformHandleui64NV
-#define glUniformHandleui64vNV wrap_glUniformHandleui64vNV
-#define glUniformMatrix2fv wrap_glUniformMatrix2fv
-#define glUniformMatrix2x3fv wrap_glUniformMatrix2x3fv
-#define glUniformMatrix2x3fvNV wrap_glUniformMatrix2x3fvNV
-#define glUniformMatrix2x4fv wrap_glUniformMatrix2x4fv
-#define glUniformMatrix2x4fvNV wrap_glUniformMatrix2x4fvNV
-#define glUniformMatrix3fv wrap_glUniformMatrix3fv
-#define glUniformMatrix3x2fv wrap_glUniformMatrix3x2fv
-#define glUniformMatrix3x2fvNV wrap_glUniformMatrix3x2fvNV
-#define glUniformMatrix3x4fv wrap_glUniformMatrix3x4fv
-#define glUniformMatrix3x4fvNV wrap_glUniformMatrix3x4fvNV
-#define glUniformMatrix4fv wrap_glUniformMatrix4fv
-#define glUniformMatrix4x2fv wrap_glUniformMatrix4x2fv
-#define glUniformMatrix4x2fvNV wrap_glUniformMatrix4x2fvNV
-#define glUniformMatrix4x3fv wrap_glUniformMatrix4x3fv
-#define glUniformMatrix4x3fvNV wrap_glUniformMatrix4x3fvNV
-#define glUnmapBuffer wrap_glUnmapBuffer
-#define glUnmapBufferOES wrap_glUnmapBufferOES
-#define glUseProgram wrap_glUseProgram
-#define glUseProgramStages wrap_glUseProgramStages
-#define glUseProgramStagesEXT wrap_glUseProgramStagesEXT
-#define glValidateProgram wrap_glValidateProgram
-#define glValidateProgramPipeline wrap_glValidateProgramPipeline
-#define glValidateProgramPipelineEXT wrap_glValidateProgramPipelineEXT
-#define glVertexAttrib1f wrap_glVertexAttrib1f
-#define glVertexAttrib1fv wrap_glVertexAttrib1fv
-#define glVertexAttrib2f wrap_glVertexAttrib2f
-#define glVertexAttrib2fv wrap_glVertexAttrib2fv
-#define glVertexAttrib3f wrap_glVertexAttrib3f
-#define glVertexAttrib3fv wrap_glVertexAttrib3fv
-#define glVertexAttrib4f wrap_glVertexAttrib4f
-#define glVertexAttrib4fv wrap_glVertexAttrib4fv
-#define glVertexAttribBinding wrap_glVertexAttribBinding
-#define glVertexAttribDivisor wrap_glVertexAttribDivisor
-#define glVertexAttribDivisorANGLE wrap_glVertexAttribDivisorANGLE
-#define glVertexAttribDivisorEXT wrap_glVertexAttribDivisorEXT
-#define glVertexAttribDivisorNV wrap_glVertexAttribDivisorNV
-#define glVertexAttribFormat wrap_glVertexAttribFormat
-#define glVertexAttribI4i wrap_glVertexAttribI4i
-#define glVertexAttribI4iv wrap_glVertexAttribI4iv
-#define glVertexAttribI4ui wrap_glVertexAttribI4ui
-#define glVertexAttribI4uiv wrap_glVertexAttribI4uiv
-#define glVertexAttribIFormat wrap_glVertexAttribIFormat
-#define glVertexAttribIPointer wrap_glVertexAttribIPointer
-#define glVertexAttribPointer wrap_glVertexAttribPointer
-#define glVertexBindingDivisor wrap_glVertexBindingDivisor
-#define glVertexPointer wrap_glVertexPointer
-#define glViewport wrap_glViewport
-#define glViewportArrayvNV wrap_glViewportArrayvNV
-#define glViewportIndexedfNV wrap_glViewportIndexedfNV
-#define glViewportIndexedfvNV wrap_glViewportIndexedfvNV
-#define glWaitSync wrap_glWaitSync
-#define glWaitSyncAPPLE wrap_glWaitSyncAPPLE
-#define glWeightPathsNV wrap_glWeightPathsNV
-#define glWeightPointerOES wrap_glWeightPointerOES
+#include "GlesDriver.h"
-#endif // HWUI_GLES_WRAP_ENABLED
+#define GL_ENTRY(ret, api, ...) ret api(__VA_ARGS__);
+
+#include "gles_decls.in"
+#undef GL_ENTRY
diff --git a/libs/hwui/font/CachedGlyphInfo.h b/libs/hwui/font/CachedGlyphInfo.h
index 0642d59d9b16..073d59bdea3f 100644
--- a/libs/hwui/font/CachedGlyphInfo.h
+++ b/libs/hwui/font/CachedGlyphInfo.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_HWUI_CACHED_GLYPH_INFO_H
#define ANDROID_HWUI_CACHED_GLYPH_INFO_H
-#include <SkFixed.h>
-
namespace android {
namespace uirenderer {
@@ -41,14 +39,14 @@ struct CachedGlyphInfo {
float mBitmapMaxV;
// Minimize how much we call freetype
uint32_t mGlyphIndex;
- uint32_t mAdvanceX;
- uint32_t mAdvanceY;
+ float mAdvanceX;
+ float mAdvanceY;
// Values below contain a glyph's origin in the bitmap
int32_t mBitmapLeft;
int32_t mBitmapTop;
- // Auto-kerning
- SkFixed mLsbDelta;
- SkFixed mRsbDelta;
+ // Auto-kerning; represents a 2.6 fixed-point value with range [-1, 1].
+ int8_t mLsbDelta;
+ int8_t mRsbDelta;
CacheTexture* mCacheTexture;
};
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 8e04c8715f62..9c812bc33e46 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -304,7 +304,7 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
}
int glyphsCount = 0;
- SkFixed prevRsbDelta = 0;
+ int prevRsbDelta = 0;
float penX = 0.0f;
@@ -332,14 +332,14 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
}
CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
- penX += SkFixedToFloat(AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta));
+ penX += AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta);
prevRsbDelta = cachedGlyph->mRsbDelta;
if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) {
drawCachedGlyph(cachedGlyph, penX, hOffset, vOffset, measure, &position, &tangent);
}
- penX += SkFixedToFloat(cachedGlyph->mAdvanceX);
+ penX += cachedGlyph->mAdvanceX;
glyphsCount++;
}
diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h
index aa77d98c9343..07e8b34ac66f 100644
--- a/libs/hwui/font/FontUtil.h
+++ b/libs/hwui/font/FontUtil.h
@@ -44,6 +44,8 @@ typedef uint16_t glyph_t;
#define GET_METRICS(cache, glyph) cache->getGlyphIDMetrics(glyph)
#define IS_END_OF_STRING(glyph) false
-#define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
+// prev, next are assumed to be signed x.6 fixed-point numbers with range
+// [-1, 1]. Result is an integral float.
+#define AUTO_KERN(prev, next) static_cast<float>(((next) - (prev) + 32) >> 6)
#endif // ANDROID_HWUI_FONT_UTIL_H
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 7bfa15a26d56..461363f5e8d8 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -16,7 +16,6 @@
#include "Canvas.h"
-#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include "MinikinUtils.h"
#include "Paint.h"
@@ -27,11 +26,7 @@
namespace android {
Canvas* Canvas::create_recording_canvas(int width, int height) {
-#if HWUI_NEW_OPS
return new uirenderer::RecordingCanvas(width, height);
-#else
- return new uirenderer::DisplayListCanvas(width, height);
-#endif
}
void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
@@ -79,8 +74,9 @@ static void simplifyPaint(int color, SkPaint* paint) {
class DrawTextFunctor {
public:
- DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
- const SkPaint& paint, float x, float y, MinikinRect& bounds, float totalAdvance)
+ DrawTextFunctor(const minikin::Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
+ const SkPaint& paint, float x, float y, minikin::MinikinRect& bounds,
+ float totalAdvance)
: layout(layout)
, canvas(canvas)
, glyphs(glyphs)
@@ -135,14 +131,14 @@ public:
}
}
private:
- const Layout& layout;
+ const minikin::Layout& layout;
Canvas* canvas;
uint16_t* glyphs;
float* pos;
const SkPaint& paint;
float x;
float y;
- MinikinRect& bounds;
+ minikin::MinikinRect& bounds;
float totalAdvance;
};
@@ -151,7 +147,7 @@ void Canvas::drawText(const uint16_t* text, int start, int count, int contextCou
// minikin may modify the original paint
Paint paint(origPaint);
- Layout layout;
+ minikin::Layout layout;
MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
size_t nGlyphs = layout.nGlyphs();
@@ -160,7 +156,7 @@ void Canvas::drawText(const uint16_t* text, int start, int count, int contextCou
x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
- MinikinRect bounds;
+ minikin::MinikinRect bounds;
layout.getBounds(&bounds);
if (!drawTextAbsolutePos()) {
bounds.offset(x, y);
@@ -178,7 +174,7 @@ void Canvas::drawText(const uint16_t* text, int start, int count, int contextCou
class DrawTextOnPathFunctor {
public:
- DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
+ DrawTextOnPathFunctor(const minikin::Layout& layout, Canvas* canvas, float hOffset,
float vOffset, const Paint& paint, const SkPath& path)
: layout(layout)
, canvas(canvas)
@@ -198,7 +194,7 @@ public:
}
}
private:
- const Layout& layout;
+ const minikin::Layout& layout;
Canvas* canvas;
float hOffset;
float vOffset;
@@ -209,7 +205,7 @@ private:
void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
float hOffset, float vOffset, const Paint& paint, Typeface* typeface) {
Paint paintCopy(paint);
- Layout layout;
+ minikin::Layout layout;
MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 55af33e80256..0b4209925bd4 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_GRAPHICS_CANVAS_H
-#define ANDROID_GRAPHICS_CANVAS_H
+#pragma once
#include <cutils/compiler.h>
#include <utils/Functor.h>
@@ -220,7 +219,7 @@ public:
/**
* Draws a VectorDrawable onto the canvas.
*/
- virtual void drawVectorDrawable(VectorDrawableRoot* tree);
+ virtual void drawVectorDrawable(VectorDrawableRoot* tree) = 0;
/**
* Converts utf16 text to glyphs, calculating position and boundary,
@@ -253,4 +252,3 @@ protected:
};
}; // namespace android
-#endif // ANDROID_GRAPHICS_CANVAS_H
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index a455f576e38d..d16b64415f52 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -24,7 +24,7 @@ namespace android {
MinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize,
int ttcIndex) :
- MinikinFont(typeface->uniqueID()), mTypeface(typeface), mFontData(fontData),
+ minikin::MinikinFont(typeface->uniqueID()), mTypeface(typeface), mFontData(fontData),
mFontSize(fontSize), mTtcIndex(ttcIndex) {
}
@@ -32,7 +32,8 @@ MinikinFontSkia::~MinikinFontSkia() {
SkSafeUnref(mTypeface);
}
-static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
+static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint,
+ const minikin::MinikinPaint& paint) {
skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
skPaint->setTextSize(paint.size);
skPaint->setTextScaleX(paint.scaleX);
@@ -43,7 +44,7 @@ static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPai
}
float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
- const MinikinPaint &paint) const {
+ const minikin::MinikinPaint &paint) const {
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkScalar skWidth;
@@ -55,8 +56,8 @@ float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
return skWidth;
}
-void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
- const MinikinPaint& paint) const {
+void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
+ const minikin::MinikinPaint& paint) const {
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkRect skBounds;
@@ -68,7 +69,8 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
bounds->mBottom = skBounds.fBottom;
}
-const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) {
+const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size,
+ minikin::MinikinDestroyFunc* destroy) {
// we don't have a buffer to the font data, copy to own buffer
const size_t tableSize = mTypeface->getTableSize(tag);
*size = tableSize;
@@ -117,7 +119,8 @@ void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
}
-void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) {
+void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font,
+ minikin::FontFakery fakery) {
paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface());
paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold());
if (fakery.isFakeItalic()) {
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index a7c9fb0b09d4..96b256d1b8af 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -25,7 +25,7 @@ class SkTypeface;
namespace android {
-class ANDROID_API MinikinFontSkia : public MinikinFont {
+class ANDROID_API MinikinFontSkia : public minikin::MinikinFont {
public:
// Note: this takes ownership of the reference (will unref on dtor)
explicit MinikinFontSkia(SkTypeface *typeface, const void* fontData, size_t fontSize,
@@ -34,12 +34,12 @@ public:
~MinikinFontSkia();
float GetHorizontalAdvance(uint32_t glyph_id,
- const MinikinPaint &paint) const;
+ const minikin::MinikinPaint &paint) const;
- void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
- const MinikinPaint &paint) const;
+ void GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
+ const minikin::MinikinPaint &paint) const;
- const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
+ const void* GetTable(uint32_t tag, size_t* size, minikin::MinikinDestroyFunc* destroy);
SkTypeface* GetSkTypeface() const;
@@ -52,7 +52,8 @@ public:
static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
// set typeface and fake bold/italic parameters
- static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery);
+ static void populateSkPaint(SkPaint* paint, const minikin::MinikinFont* font,
+ minikin::FontFakery fakery);
private:
SkTypeface* mTypeface;
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 67b775d98356..a06cc37f944e 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -24,17 +24,18 @@
namespace android {
-FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
- const Paint* paint, Typeface* typeface) {
+minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
+ minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
*pFont = resolvedFace->fFontCollection;
- FontStyle resolved = resolvedFace->fStyle;
+ minikin::FontStyle resolved = resolvedFace->fStyle;
/* Prepare minikin FontStyle */
- FontVariant minikinVariant = (paint->getFontVariant() == VARIANT_ELEGANT) ? VARIANT_ELEGANT
- : VARIANT_COMPACT;
+ minikin::FontVariant minikinVariant = (paint->getFontVariant() == minikin::VARIANT_ELEGANT) ?
+ minikin::VARIANT_ELEGANT : minikin::VARIANT_COMPACT;
const uint32_t langListId = paint->getMinikinLangListId();
- FontStyle minikinStyle(langListId, minikinVariant, resolved.getWeight(), resolved.getItalic());
+ minikin::FontStyle minikinStyle(langListId, minikinVariant, resolved.getWeight(),
+ resolved.getItalic());
/* Prepare minikin Paint */
// Note: it would be nice to handle fractional size values (it would improve smooth zoom
@@ -46,27 +47,27 @@ FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontColl
minikinPaint->letterSpacing = paint->getLetterSpacing();
minikinPaint->paintFlags = MinikinFontSkia::packPaintFlags(paint);
minikinPaint->fontFeatureSettings = paint->getFontFeatureSettings();
- minikinPaint->hyphenEdit = HyphenEdit(paint->getHyphenEdit());
+ minikinPaint->hyphenEdit = minikin::HyphenEdit(paint->getHyphenEdit());
return minikinStyle;
}
-void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
+void MinikinUtils::doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize) {
- FontCollection *font;
- MinikinPaint minikinPaint;
- FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+ minikin::FontCollection *font;
+ minikin::MinikinPaint minikinPaint;
+ minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
layout->setFontCollection(font);
layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
}
float MinikinUtils::measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
- FontCollection *font;
- MinikinPaint minikinPaint;
- FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
- return Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint,
- font, advances);
+ minikin::FontCollection *font;
+ minikin::MinikinPaint minikinPaint;
+ minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+ return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
+ minikinPaint, font, advances);
}
bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs) {
@@ -74,7 +75,7 @@ bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint,
return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
}
-float MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
+float MinikinUtils::xOffsetForTextAlign(Paint* paint, const minikin::Layout& layout) {
switch (paint->getTextAlign()) {
case Paint::kCenter_Align:
return layout.getAdvance() * -0.5f;
@@ -88,7 +89,8 @@ float MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
return 0;
}
-float MinikinUtils::hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path) {
+float MinikinUtils::hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout,
+ const SkPath& path) {
float align = 0;
switch (paint->getTextAlign()) {
case Paint::kCenter_Align:
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index cfaa961ac1fc..d6f64d2418d5 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -34,31 +34,33 @@ namespace android {
class MinikinUtils {
public:
- ANDROID_API static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
- const Paint* paint, Typeface* typeface);
+ ANDROID_API static minikin::FontStyle prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
+ minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface);
- ANDROID_API static void doLayout(Layout* layout, const Paint* paint, int bidiFlags,
+ ANDROID_API static void doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize);
ANDROID_API static float measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances);
- ANDROID_API static bool hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs);
+ ANDROID_API static bool hasVariationSelector(Typeface* typeface, uint32_t codepoint,
+ uint32_t vs);
- ANDROID_API static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
+ ANDROID_API static float xOffsetForTextAlign(Paint* paint, const minikin::Layout& layout);
- ANDROID_API static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
+ ANDROID_API static float hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout,
+ const SkPath& path);
// f is a functor of type void f(size_t start, size_t end);
template <typename F>
- ANDROID_API static void forFontRun(const Layout& layout, Paint* paint, F& f) {
+ ANDROID_API static void forFontRun(const minikin::Layout& layout, Paint* paint, F& f) {
float saveSkewX = paint->getTextSkewX();
bool savefakeBold = paint->isFakeBoldText();
- MinikinFont* curFont = NULL;
+ minikin::MinikinFont* curFont = NULL;
size_t start = 0;
size_t nGlyphs = layout.nGlyphs();
for (size_t i = 0; i < nGlyphs; i++) {
- MinikinFont* nextFont = layout.getFont(i);
+ minikin::MinikinFont* nextFont = layout.getFont(i);
if (i > 0 && nextFont != curFont) {
MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
f(start, i);
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 9599c30c639b..6307926ec43e 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -64,11 +64,11 @@ public:
return mMinikinLangListId;
}
- void setFontVariant(FontVariant variant) {
+ void setFontVariant(minikin::FontVariant variant) {
mFontVariant = variant;
}
- FontVariant getFontVariant() const {
+ minikin::FontVariant getFontVariant() const {
return mFontVariant;
}
@@ -84,7 +84,7 @@ private:
float mLetterSpacing = 0;
std::string mFontFeatureSettings;
uint32_t mMinikinLangListId;
- FontVariant mFontVariant;
+ minikin::FontVariant mFontVariant;
uint32_t mHyphenEdit = 0;
};
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index b27672ce16a0..84122d768089 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -20,7 +20,7 @@ namespace android {
Paint::Paint() :
SkPaint(), mLetterSpacing(0), mFontFeatureSettings(), mMinikinLangListId(0),
- mFontVariant(VARIANT_DEFAULT) {
+ mFontVariant(minikin::VARIANT_DEFAULT) {
}
Paint::Paint(const Paint& paint) : SkPaint(paint),
@@ -31,7 +31,7 @@ Paint::Paint(const Paint& paint) : SkPaint(paint),
Paint::Paint(const SkPaint& paint) : SkPaint(paint),
mLetterSpacing(0), mFontFeatureSettings(), mMinikinLangListId(0),
- mFontVariant(VARIANT_DEFAULT) {
+ mFontVariant(minikin::VARIANT_DEFAULT) {
}
Paint::~Paint() {
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index c583988554c7..b5c5ef9a5915 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -43,7 +43,7 @@ static void resolveStyle(Typeface* typeface) {
weight = 9;
}
bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
- typeface->fStyle = FontStyle(weight, italic);
+ typeface->fStyle = minikin::FontStyle(weight, italic);
}
Typeface* gDefaultTypeface = NULL;
@@ -54,13 +54,13 @@ pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
// typeface is set.
// TODO: investigate why layouts are being created before Typeface.java
// class initialization.
-static FontCollection *makeFontCollection() {
- std::vector<FontFamily *>typefaces;
+static minikin::FontCollection *makeFontCollection() {
+ std::vector<minikin::FontFamily *>typefaces;
const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf",
};
- FontFamily *family = new FontFamily();
+ minikin::FontFamily *family = new minikin::FontFamily();
for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
const char *fn = fns[i];
ALOGD("makeFontCollection adding %s", fn);
@@ -69,7 +69,7 @@ static FontCollection *makeFontCollection() {
// TODO: might be a nice optimization to get access to the underlying font
// data, but would require us opening the file ourselves and passing that
// to the appropriate Create method of SkTypeface.
- MinikinFont *font = new MinikinFontSkia(skFace, NULL, 0, 0);
+ minikin::MinikinFont *font = new MinikinFontSkia(skFace, NULL, 0, 0);
family->addFont(font);
font->Unref();
} else {
@@ -78,13 +78,13 @@ static FontCollection *makeFontCollection() {
}
typefaces.push_back(family);
- FontCollection *result = new FontCollection(typefaces);
+ minikin::FontCollection *result = new minikin::FontCollection(typefaces);
family->Unref();
return result;
}
static void getDefaultTypefaceOnce() {
- Layout::init();
+ minikin::Layout::init();
if (gDefaultTypeface == NULL) {
// We expect the client to set a default typeface, but provide a
// default so we can make progress before that happens.
@@ -131,16 +131,16 @@ Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
return result;
}
-Typeface* Typeface::createFromFamilies(const std::vector<FontFamily*>& families) {
+Typeface* Typeface::createFromFamilies(const std::vector<minikin::FontFamily*>& families) {
Typeface* result = new Typeface;
- result->fFontCollection = new FontCollection(families);
+ result->fFontCollection = new minikin::FontCollection(families);
if (families.empty()) {
ALOGW("createFromFamilies creating empty collection");
result->fSkiaStyle = SkTypeface::kNormal;
} else {
- const FontStyle defaultStyle;
- FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
- MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
+ const minikin::FontStyle defaultStyle;
+ minikin::FontFamily* firstFamily = reinterpret_cast<minikin::FontFamily*>(families[0]);
+ minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
if (mf != NULL) {
SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
// TODO: probably better to query more precise style from family, will be important
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 8862e5a5a911..ed0a7ebd56ae 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -27,7 +27,7 @@
namespace android {
struct ANDROID_API Typeface {
- FontCollection *fFontCollection;
+ minikin::FontCollection *fFontCollection;
// style used for constructing and querying Typeface objects
SkTypeface::Style fSkiaStyle;
@@ -35,7 +35,7 @@ struct ANDROID_API Typeface {
int fBaseWeight;
// resolved style actually used for rendering
- FontStyle fStyle;
+ minikin::FontStyle fStyle;
void unref();
@@ -45,7 +45,7 @@ struct ANDROID_API Typeface {
static Typeface* createWeightAlias(Typeface* src, int baseweight);
- static Typeface* createFromFamilies(const std::vector<FontFamily*>& families);
+ static Typeface* createFromFamilies(const std::vector<minikin::FontFamily*>& families);
static void setDefault(Typeface* face);
};
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index b575c696586e..6d0293695412 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -17,8 +17,6 @@
#include "Program.h"
-#include "ShadowTessellator.h"
-
namespace android {
namespace uirenderer {
@@ -100,6 +98,12 @@ void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
glBufferData(GL_ARRAY_BUFFER, size, data, usage);
}
+void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const void* data) {
+ bindMeshBuffer(buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
+}
+
void MeshState::deleteMeshBuffer(GLuint buffer) {
if (buffer == mCurrentBuffer) {
// GL defines that deleting the currently bound VBO rebinds to 0 (no VBO).
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index dd684686f584..17ad4622e44a 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -72,6 +72,7 @@ public:
void unbindMeshBuffer();
void genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data, GLenum usage);
+ void updateMeshBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data);
void deleteMeshBuffer(GLuint);
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 5e600644ca19..ee4619d2c222 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -60,38 +60,6 @@ static void layerLostGlContext(Layer* layer) {
}
void RenderState::onGLContextDestroyed() {
-/*
- size_t size = mActiveLayers.size();
- if (CC_UNLIKELY(size != 0)) {
- ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
- mRegisteredContexts.size(), size, mActiveLayers.empty());
- mCaches->dumpMemoryUsage();
- for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
- cit != mRegisteredContexts.end(); cit++) {
- renderthread::CanvasContext* context = *cit;
- ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get());
- ALOGE(" Prefeteched layers: %zu", context->mPrefetechedLayers.size());
- for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
- pit != context->mPrefetechedLayers.end(); pit++) {
- (*pit)->debugDumpLayers(" ");
- }
- context->mRootRenderNode->debugDumpLayers(" ");
- }
-
-
- if (mActiveLayers.begin() == mActiveLayers.end()) {
- ALOGE("set has become empty. wat.");
- }
- for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
- lit != mActiveLayers.end(); lit++) {
- const Layer* layer = *(lit);
- ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d",
- layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered);
- }
- LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
- }
-*/
-
mLayerPool.clear();
// TODO: reset all cached state in state objects
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5003c6aefb8b..2eccca9fee37 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -21,15 +21,16 @@
#include "Caches.h"
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
-#include "LayerUpdateQueue.h"
#include "LayerRenderer.h"
-#include "OpenGLRenderer.h"
+#include "LayerUpdateQueue.h"
#include "Properties.h"
+#include "Readback.h"
#include "RenderThread.h"
#include "hwui/Canvas.h"
#include "renderstate/RenderState.h"
#include "renderstate/Stencil.h"
#include "protos/hwui.pb.h"
+#include "OpenGLPipeline.h"
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
@@ -61,15 +62,40 @@ namespace android {
namespace uirenderer {
namespace renderthread {
+CanvasContext* CanvasContext::create(RenderThread& thread,
+ bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) {
+
+ auto renderType = Properties::getRenderPipelineType();
+
+ switch (renderType) {
+ case RenderPipelineType::OpenGL:
+ return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
+ std::make_unique<OpenGLPipeline>(thread));
+ case RenderPipelineType::SkiaGL:
+ //TODO: implement SKIA GL
+ LOG_ALWAYS_FATAL("skiaGL canvas type not implemented.");
+ break;
+ case RenderPipelineType::SkiaVulkan:
+ //TODO: implement Vulkan
+ LOG_ALWAYS_FATAL("Vulkan canvas type not implemented.");
+ break;
+ default:
+ LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
+ break;
+ }
+ return nullptr;
+}
+
CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory)
+ RenderNode* rootRenderNode, IContextFactory* contextFactory,
+ std::unique_ptr<IRenderPipeline> renderPipeline)
: mRenderThread(thread)
- , mEglManager(thread.eglManager())
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
, mJankTracker(thread.timeLord().frameIntervalNanos())
, mProfiler(mFrames)
- , mContentDrawBounds(0, 0, 0, 0) {
+ , mContentDrawBounds(0, 0, 0, 0)
+ , mRenderPipeline(std::move(renderPipeline)) {
mRenderNodes.emplace_back(rootRenderNode);
mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
@@ -86,12 +112,6 @@ void CanvasContext::destroy(TreeObserver* observer) {
freePrefetchedLayers(observer);
destroyHardwareResources(observer);
mAnimationContext->destroy();
-#if !HWUI_NEW_OPS
- if (mCanvas) {
- delete mCanvas;
- mCanvas = nullptr;
- }
-#endif
}
void CanvasContext::setSurface(Surface* surface) {
@@ -99,24 +119,15 @@ void CanvasContext::setSurface(Surface* surface) {
mNativeSurface = surface;
- if (mEglSurface != EGL_NO_SURFACE) {
- mEglManager.destroySurface(mEglSurface);
- mEglSurface = EGL_NO_SURFACE;
- }
-
- if (surface) {
- mEglSurface = mEglManager.createSurface(surface);
- }
+ bool hasSurface = mRenderPipeline->setSurface(surface, mSwapBehavior);
mFrameNumber = -1;
- if (mEglSurface != EGL_NO_SURFACE) {
- const bool preserveBuffer = (mSwapBehavior != kSwap_discardBuffer);
- mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
- mHaveNewSurface = true;
- mSwapHistory.clear();
+ if (hasSurface) {
+ mHaveNewSurface = true;
+ mSwapHistory.clear();
} else {
- mRenderThread.removeFrameCallback(this);
+ mRenderThread.removeFrameCallback(this);
}
}
@@ -126,11 +137,6 @@ void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
void CanvasContext::initialize(Surface* surface) {
setSurface(surface);
-#if !HWUI_NEW_OPS
- if (mCanvas) return;
- mCanvas = new OpenGLRenderer(mRenderThread.renderState());
- mCanvas->initProperties();
-#endif
}
void CanvasContext::updateSurface(Surface* surface) {
@@ -146,35 +152,22 @@ void CanvasContext::setStopped(bool stopped) {
mStopped = stopped;
if (mStopped) {
mRenderThread.removeFrameCallback(this);
- if (mEglManager.isCurrent(mEglSurface)) {
- mEglManager.makeCurrent(EGL_NO_SURFACE);
- }
+ mRenderPipeline->onStop();
} else if (mIsDirty && hasSurface()) {
mRenderThread.postFrameCallback(this);
}
}
}
-// TODO: don't pass viewport size, it's automatic via EGL
-void CanvasContext::setup(int width, int height, float lightRadius,
+void CanvasContext::setup(float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
-#if HWUI_NEW_OPS
mLightGeometry.radius = lightRadius;
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
-#else
- if (!mCanvas) return;
- mCanvas->initLight(lightRadius, ambientShadowAlpha, spotShadowAlpha);
-#endif
}
void CanvasContext::setLightCenter(const Vector3& lightCenter) {
-#if HWUI_NEW_OPS
mLightGeometry.center = lightCenter;
-#else
- if (!mCanvas) return;
- mCanvas->setLightCenter(lightCenter);
-#endif
}
void CanvasContext::setOpaque(bool opaque) {
@@ -184,14 +177,23 @@ void CanvasContext::setOpaque(bool opaque) {
bool CanvasContext::makeCurrent() {
if (mStopped) return false;
- // TODO: Figure out why this workaround is needed, see b/13913604
- // In the meantime this matches the behavior of GLRenderer, so it is not a regression
- EGLint error = 0;
- mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface, &error);
- if (error) {
- setSurface(nullptr);
+ auto result = mRenderPipeline->makeCurrent();
+ switch (result) {
+ case MakeCurrentResult::AlreadyCurrent:
+ return true;
+ case MakeCurrentResult::Failed:
+ mHaveNewSurface = true;
+ setSurface(nullptr);
+ return false;
+ case MakeCurrentResult::Succeeded:
+ mHaveNewSurface = true;
+ return true;
+ default:
+ LOG_ALWAYS_FATAL("unexpected result %d from IRenderPipeline::makeCurrent",
+ (int32_t) result);
}
- return !error;
+
+ return true;
}
static bool wasSkipped(FrameInfo* info) {
@@ -251,11 +253,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
mCurrentFrameInfo->markSyncStart();
info.damageAccumulator = &mDamageAccumulator;
-#if HWUI_NEW_OPS
info.layerUpdateQueue = &mLayerUpdateQueue;
-#else
- info.renderer = mCanvas;
-#endif
mAnimationContext->startFrame(info.mode);
for (const sp<RenderNode>& node : mRenderNodes) {
@@ -280,7 +278,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
return;
}
- if (CC_LIKELY(mSwapHistory.size())) {
+ if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
SwapHistory& lastSwap = mSwapHistory.back();
int durationUs;
@@ -332,11 +330,6 @@ void CanvasContext::notifyFramePending() {
}
void CanvasContext::draw() {
-#if !HWUI_NEW_OPS
- LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
- "drawRenderNode called on a context with no canvas or surface!");
-#endif
-
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -348,215 +341,27 @@ void CanvasContext::draw() {
mCurrentFrameInfo->markIssueDrawCommandsStart();
- Frame frame = mEglManager.beginFrame(mEglSurface);
-
- if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
- // can't rely on prior content of window if viewport size changes
- dirty.setEmpty();
- mLastFrameWidth = frame.width();
- mLastFrameHeight = frame.height();
- } else if (mHaveNewSurface || frame.bufferAge() == 0) {
- // New surface needs a full draw
- dirty.setEmpty();
- } else {
- if (!dirty.isEmpty() && !dirty.intersect(0, 0, frame.width(), frame.height())) {
- ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?",
- SK_RECT_ARGS(dirty), frame.width(), frame.height());
- dirty.setEmpty();
- }
- profiler().unionDirty(&dirty);
- }
-
- if (dirty.isEmpty()) {
- dirty.set(0, 0, frame.width(), frame.height());
- }
-
- // At this point dirty is the area of the screen to update. However,
- // the area of the frame we need to repaint is potentially different, so
- // stash the screen area for later
- SkRect screenDirty(dirty);
-
- // If the buffer age is 0 we do a full-screen repaint (handled above)
- // If the buffer age is 1 the buffer contents are the same as they were
- // last frame so there's nothing to union() against
- // Therefore we only care about the > 1 case.
- if (frame.bufferAge() > 1) {
- if (frame.bufferAge() > (int) mSwapHistory.size()) {
- // We don't have enough history to handle this old of a buffer
- // Just do a full-draw
- dirty.set(0, 0, frame.width(), frame.height());
- } else {
- // At this point we haven't yet added the latest frame
- // to the damage history (happens below)
- // So we need to damage
- for (int i = mSwapHistory.size() - 1;
- i > ((int) mSwapHistory.size()) - frame.bufferAge(); i--) {
- dirty.join(mSwapHistory[i].damage);
- }
- }
- }
-
- mEglManager.damageFrame(frame, dirty);
-
-#if HWUI_NEW_OPS
- auto& caches = Caches::getInstance();
- FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), mLightGeometry, caches);
+ Frame frame = mRenderPipeline->getFrame();
- frameBuilder.deferLayers(mLayerUpdateQueue);
- mLayerUpdateQueue.clear();
+ SkRect windowDirty = computeDirtyRect(frame, &dirty);
- frameBuilder.deferRenderNodeScene(mRenderNodes, mContentDrawBounds);
-
- BakedOpRenderer renderer(caches, mRenderThread.renderState(),
- mOpaque, mLightInfo);
- frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
- profiler().draw(&renderer);
- bool drew = renderer.didDraw();
-
- // post frame cleanup
- caches.clearGarbage();
- caches.pathCache.trim();
- caches.tessellationCache.trim();
-
-#if DEBUG_MEMORY_USAGE
- mCaches.dumpMemoryUsage();
-#else
- if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) {
- caches.dumpMemoryUsage();
- }
-#endif
-
-#else
- mCanvas->prepareDirty(frame.width(), frame.height(),
- dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
-
- Rect outBounds;
- // It there are multiple render nodes, they are laid out as follows:
- // #0 - backdrop (content + caption)
- // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
- // #2 - additional overlay nodes
- // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
- // resizing however it might become partially visible. The following render loop will crop the
- // backdrop against the content and draw the remaining part of it. It will then draw the content
- // cropped to the backdrop (since that indicates a shrinking of the window).
- //
- // Additional nodes will be drawn on top with no particular clipping semantics.
-
- // The bounds of the backdrop against which the content should be clipped.
- Rect backdropBounds = mContentDrawBounds;
- // Usually the contents bounds should be mContentDrawBounds - however - we will
- // move it towards the fixed edge to give it a more stable appearance (for the moment).
- Rect contentBounds;
- // If there is no content bounds we ignore the layering as stated above and start with 2.
- int layer = (mContentDrawBounds.isEmpty() || mRenderNodes.size() == 1) ? 2 : 0;
- // Draw all render nodes. Note that
- for (const sp<RenderNode>& node : mRenderNodes) {
- if (layer == 0) { // Backdrop.
- // Draw the backdrop clipped to the inverse content bounds, but assume that the content
- // was moved to the upper left corner.
- const RenderProperties& properties = node->properties();
- Rect targetBounds(properties.getLeft(), properties.getTop(),
- properties.getRight(), properties.getBottom());
- // Move the content bounds towards the fixed corner of the backdrop.
- const int x = targetBounds.left;
- const int y = targetBounds.top;
- contentBounds.set(x, y, x + mContentDrawBounds.getWidth(),
- y + mContentDrawBounds.getHeight());
- // Remember the intersection of the target bounds and the intersection bounds against
- // which we have to crop the content.
- backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
- backdropBounds.doIntersect(targetBounds);
- // Check if we have to draw something on the left side ...
- if (targetBounds.left < contentBounds.left) {
- mCanvas->save(SaveFlags::Clip);
- if (mCanvas->clipRect(targetBounds.left, targetBounds.top,
- contentBounds.left, targetBounds.bottom,
- SkRegion::kIntersect_Op)) {
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- // Reduce the target area by the area we have just painted.
- targetBounds.left = std::min(contentBounds.left, targetBounds.right);
- mCanvas->restore();
- }
- // ... or on the right side ...
- if (targetBounds.right > contentBounds.right &&
- !targetBounds.isEmpty()) {
- mCanvas->save(SaveFlags::Clip);
- if (mCanvas->clipRect(contentBounds.right, targetBounds.top,
- targetBounds.right, targetBounds.bottom,
- SkRegion::kIntersect_Op)) {
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- // Reduce the target area by the area we have just painted.
- targetBounds.right = std::max(targetBounds.left, contentBounds.right);
- mCanvas->restore();
- }
- // ... or at the top ...
- if (targetBounds.top < contentBounds.top &&
- !targetBounds.isEmpty()) {
- mCanvas->save(SaveFlags::Clip);
- if (mCanvas->clipRect(targetBounds.left, targetBounds.top, targetBounds.right,
- contentBounds.top,
- SkRegion::kIntersect_Op)) {
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- // Reduce the target area by the area we have just painted.
- targetBounds.top = std::min(contentBounds.top, targetBounds.bottom);
- mCanvas->restore();
- }
- // ... or at the bottom.
- if (targetBounds.bottom > contentBounds.bottom &&
- !targetBounds.isEmpty()) {
- mCanvas->save(SaveFlags::Clip);
- if (mCanvas->clipRect(targetBounds.left, contentBounds.bottom, targetBounds.right,
- targetBounds.bottom, SkRegion::kIntersect_Op)) {
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- mCanvas->restore();
- }
- } else if (layer == 1) { // Content
- // It gets cropped against the bounds of the backdrop to stay inside.
- mCanvas->save(SaveFlags::MatrixClip);
-
- // We shift and clip the content to match its final location in the window.
- const float left = mContentDrawBounds.left;
- const float top = mContentDrawBounds.top;
- const float dx = backdropBounds.left - left;
- const float dy = backdropBounds.top - top;
- const float width = backdropBounds.getWidth();
- const float height = backdropBounds.getHeight();
-
- mCanvas->translate(dx, dy);
- if (mCanvas->clipRect(left, top, left + width, top + height, SkRegion::kIntersect_Op)) {
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- mCanvas->restore();
- } else { // draw the rest on top at will!
- mCanvas->drawRenderNode(node.get(), outBounds);
- }
- layer++;
- }
-
- profiler().draw(mCanvas);
-
- bool drew = mCanvas->finish();
-#endif
+ bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
+ mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes, &(profiler()));
waitOnFences();
- GL_CHECKPOINT(LOW);
+ bool requireSwap = false;
+ bool didSwap = mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo,
+ &requireSwap);
- // Even if we decided to cancel the frame, from the perspective of jank
- // metrics the frame was swapped at this point
- mCurrentFrameInfo->markSwapBuffers();
mIsDirty = false;
- if (drew || mEglManager.damageRequiresSwap()) {
- if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) {
+ if (requireSwap) {
+ if (!didSwap) { //some error happened
setSurface(nullptr);
}
SwapHistory& swap = mSwapHistory.next();
- swap.damage = screenDirty;
+ swap.damage = windowDirty;
swap.swapCompletedTime = systemTime(CLOCK_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
mHaveNewSurface = false;
@@ -592,11 +397,7 @@ void CanvasContext::draw() {
// Called by choreographer to do an RT-driven animation
void CanvasContext::doFrame() {
-#if HWUI_NEW_OPS
- if (CC_UNLIKELY(mEglSurface == EGL_NO_SURFACE)) return;
-#else
- if (CC_UNLIKELY(!mCanvas || mEglSurface == EGL_NO_SURFACE)) return;
-#endif
+ if (!mRenderPipeline->isSurfaceReady()) return;
prepareAndDraw(nullptr);
}
@@ -646,10 +447,7 @@ void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
ATRACE_CALL();
- if (!mEglManager.hasEglContext()) return;
-#if !HWUI_NEW_OPS
- if (!mCanvas) return;
-#endif
+ if (!mRenderPipeline->isContextReady()) return;
// buildLayer() will leave the tree in an unknown state, so we must stop drawing
stopDrawing();
@@ -657,11 +455,7 @@ void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
TreeInfo info(TreeInfo::MODE_FULL, *this);
info.damageAccumulator = &mDamageAccumulator;
info.observer = observer;
-#if HWUI_NEW_OPS
info.layerUpdateQueue = &mLayerUpdateQueue;
-#else
- info.renderer = mCanvas;
-#endif
info.runAnimations = false;
node->prepareTree(info);
SkRect ignore;
@@ -670,41 +464,24 @@ void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
// purposes when the frame is actually drawn
node->setPropertyFieldsDirty(RenderNode::GENERIC);
-#if HWUI_NEW_OPS
- static const std::vector< sp<RenderNode> > emptyNodeList;
- auto& caches = Caches::getInstance();
- FrameBuilder frameBuilder(mLayerUpdateQueue, mLightGeometry, caches);
- mLayerUpdateQueue.clear();
- BakedOpRenderer renderer(caches, mRenderThread.renderState(),
- mOpaque, mLightInfo);
- LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case");
- frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
-#else
- mCanvas->markLayersAsBuildLayers();
- mCanvas->flushLayerUpdates();
-#endif
+ mRenderPipeline->renderLayers(mLightGeometry, &mLayerUpdateQueue, mOpaque, mLightInfo);
node->incStrong(nullptr);
mPrefetchedLayers.insert(node);
}
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
- layer->apply();
- return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
+ return mRenderPipeline->copyLayerInto(layer, bitmap);
}
void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
stopDrawing();
- if (mEglManager.hasEglContext()) {
+ if (mRenderPipeline->isContextReady()) {
freePrefetchedLayers(observer);
for (const sp<RenderNode>& node : mRenderNodes) {
node->destroyHardwareResources(observer);
}
- Caches& caches = Caches::getInstance();
- // Make sure to release all the textures we were owning as there won't
- // be another draw
- caches.textureCache.resetMarkInUse(this);
- mRenderThread.renderState().flush(Caches::FlushMode::Layers);
+ mRenderPipeline->onDestroyHardwareResources();
}
}
@@ -721,15 +498,8 @@ void CanvasContext::trimMemory(RenderThread& thread, int level) {
}
}
-void CanvasContext::runWithGlContext(RenderTask* task) {
- LOG_ALWAYS_FATAL_IF(!mEglManager.hasEglContext(),
- "GL context not initialized!");
- task->run();
-}
-
Layer* CanvasContext::createTextureLayer() {
- mEglManager.initialize();
- return LayerRenderer::createTextureLayer(mRenderThread.renderState());
+ return mRenderPipeline->createTextureLayer();
}
void CanvasContext::setTextureAtlas(RenderThread& thread,
@@ -809,8 +579,8 @@ void CanvasContext::waitOnFences() {
class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
public:
- FuncTaskProcessor(Caches& caches)
- : TaskProcessor<bool>(&caches.tasks) {}
+ explicit FuncTaskProcessor(TaskManager* taskManager)
+ : TaskProcessor<bool>(taskManager) {}
virtual void onProcess(const sp<Task<bool> >& task) override {
FuncTask* t = static_cast<FuncTask*>(task.get());
@@ -821,7 +591,7 @@ public:
void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
if (!mFrameWorkProcessor.get()) {
- mFrameWorkProcessor = new FuncTaskProcessor(Caches::getInstance());
+ mFrameWorkProcessor = new FuncTaskProcessor(mRenderPipeline->getTaskManager());
}
sp<FuncTask> task(new FuncTask());
task->func = func;
@@ -837,6 +607,56 @@ int64_t CanvasContext::getFrameNumber() {
return mFrameNumber;
}
+SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
+ if (frame.width() != mLastFrameWidth || frame.height() != mLastFrameHeight) {
+ // can't rely on prior content of window if viewport size changes
+ dirty->setEmpty();
+ mLastFrameWidth = frame.width();
+ mLastFrameHeight = frame.height();
+ } else if (mHaveNewSurface || frame.bufferAge() == 0) {
+ // New surface needs a full draw
+ dirty->setEmpty();
+ } else {
+ if (!dirty->isEmpty() && !dirty->intersect(0, 0, frame.width(), frame.height())) {
+ ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?",
+ SK_RECT_ARGS(*dirty), frame.width(), frame.height());
+ dirty->setEmpty();
+ }
+ profiler().unionDirty(dirty);
+ }
+
+ if (dirty->isEmpty()) {
+ dirty->set(0, 0, frame.width(), frame.height());
+ }
+
+ // At this point dirty is the area of the window to update. However,
+ // the area of the frame we need to repaint is potentially different, so
+ // stash the screen area for later
+ SkRect windowDirty(*dirty);
+
+ // If the buffer age is 0 we do a full-screen repaint (handled above)
+ // If the buffer age is 1 the buffer contents are the same as they were
+ // last frame so there's nothing to union() against
+ // Therefore we only care about the > 1 case.
+ if (frame.bufferAge() > 1) {
+ if (frame.bufferAge() > (int) mSwapHistory.size()) {
+ // We don't have enough history to handle this old of a buffer
+ // Just do a full-draw
+ dirty->set(0, 0, frame.width(), frame.height());
+ } else {
+ // At this point we haven't yet added the latest frame
+ // to the damage history (happens below)
+ // So we need to damage
+ for (int i = mSwapHistory.size() - 1;
+ i > ((int) mSwapHistory.size()) - frame.bufferAge(); i--) {
+ dirty->join(mSwapHistory[i].damage);
+ }
+ }
+ }
+
+ return windowDirty;
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b0d980b94308..42e9be33d4ea 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -14,14 +14,17 @@
* limitations under the License.
*/
-#ifndef CANVASCONTEXT_H_
-#define CANVASCONTEXT_H_
+#pragma once
+#include "BakedOpDispatcher.h"
+#include "BakedOpRenderer.h"
#include "DamageAccumulator.h"
+#include "FrameBuilder.h"
#include "FrameInfo.h"
#include "FrameInfoVisualizer.h"
#include "FrameMetricsReporter.h"
#include "IContextFactory.h"
+#include "IRenderPipeline.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "thread/Task.h"
@@ -30,12 +33,6 @@
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
-#if HWUI_NEW_OPS
-#include "BakedOpDispatcher.h"
-#include "BakedOpRenderer.h"
-#include "FrameBuilder.h"
-#endif
-
#include <cutils/compiler.h>
#include <EGL/egl.h>
#include <SkBitmap.h>
@@ -53,27 +50,22 @@ namespace uirenderer {
class AnimationContext;
class DeferredLayerUpdater;
-class OpenGLRenderer;
-class Rect;
class Layer;
+class Rect;
class RenderState;
namespace renderthread {
class EglManager;
-
-enum SwapBehavior {
- kSwap_default,
- kSwap_discardBuffer,
-};
+class Frame;
// This per-renderer class manages the bridge between the global EGL context
// and the render surface.
// TODO: Rename to Renderer or some other per-window, top-level manager
class CanvasContext : public IFrameCallback {
public:
- CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory);
+ static CanvasContext* create(RenderThread& thread, bool translucent,
+ RenderNode* rootRenderNode, IContextFactory* contextFactory);
virtual ~CanvasContext();
// Won't take effect until next EGLSurface creation
@@ -85,7 +77,7 @@ public:
void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
- void setup(int width, int height, float lightRadius,
+ void setup(float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightCenter(const Vector3& lightCenter);
void setOpaque(bool opaque);
@@ -108,8 +100,6 @@ public:
static void invokeFunctor(RenderThread& thread, Functor* functor);
- void runWithGlContext(RenderTask* task);
-
Layer* createTextureLayer();
ANDROID_API static void setTextureAtlas(RenderThread& thread,
@@ -169,6 +159,9 @@ public:
ANDROID_API int64_t getFrameNumber();
private:
+ CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
+ IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
+
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
// lifecycle tracking
@@ -182,21 +175,20 @@ private:
bool isSwapChainStuffed();
+ SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
+
EGLint mLastFrameWidth = 0;
EGLint mLastFrameHeight = 0;
RenderThread& mRenderThread;
- EglManager& mEglManager;
sp<Surface> mNativeSurface;
- EGLSurface mEglSurface = EGL_NO_SURFACE;
// stopped indicates the CanvasContext will reject actual redraw operations,
// and defer repaint until it is un-stopped
bool mStopped = false;
// CanvasContext is dirty if it has received an update that it has not
// painted onto its surface.
bool mIsDirty = false;
- bool mBufferPreserved = false;
- SwapBehavior mSwapBehavior = kSwap_default;
+ SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
struct SwapHistory {
SkRect damage;
nsecs_t vsyncTime;
@@ -209,12 +201,8 @@ private:
int64_t mFrameNumber = -1;
bool mOpaque;
-#if HWUI_NEW_OPS
BakedOpRenderer::LightInfo mLightInfo;
FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
-#else
- OpenGLRenderer* mCanvas = nullptr;
-#endif
bool mHaveNewSurface = false;
DamageAccumulator mDamageAccumulator;
@@ -245,9 +233,9 @@ private:
std::vector< sp<FuncTask> > mFrameFences;
sp<TaskProcessor<bool> > mFrameWorkProcessor;
+ std::unique_ptr<IRenderPipeline> mRenderPipeline;
};
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
-#endif /* CANVASCONTEXT_H_ */
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
new file mode 100644
index 000000000000..0c0fbe9d716c
--- /dev/null
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "FrameInfoVisualizer.h"
+#include "EglManager.h"
+
+#include <SkRect.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class Surface;
+
+namespace uirenderer {
+
+class DeferredLayerUpdater;
+
+namespace renderthread {
+
+enum class SwapBehavior {
+ kSwap_default,
+ kSwap_discardBuffer,
+};
+
+enum class MakeCurrentResult {
+ AlreadyCurrent,
+ Failed,
+ Succeeded
+};
+
+class IRenderPipeline {
+public:
+ virtual MakeCurrentResult makeCurrent() = 0;
+ virtual Frame getFrame() = 0;
+ virtual bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector< sp<RenderNode> >& renderNodes,
+ FrameInfoVisualizer* profiler) = 0;
+ virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+ FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
+ virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
+ virtual Layer* createTextureLayer() = 0;
+ virtual bool setSurface(Surface* window, SwapBehavior swapBehavior) = 0;
+ virtual void onStop() = 0;
+ virtual bool isSurfaceReady() = 0;
+ virtual bool isContextReady() = 0;
+ virtual void onDestroyHardwareResources() = 0;
+ virtual void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo) = 0;
+ virtual TaskManager* getTaskManager() = 0;
+
+ virtual ~IRenderPipeline() {}
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
new file mode 100644
index 000000000000..3a2b15584d50
--- /dev/null
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OpenGLPipeline.h"
+
+#include "DeferredLayerUpdater.h"
+#include "EglManager.h"
+#include "LayerRenderer.h"
+#include "renderstate/RenderState.h"
+#include "Readback.h"
+
+#include <android/native_window.h>
+#include <cutils/properties.h>
+#include <strings.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+OpenGLPipeline::OpenGLPipeline(RenderThread& thread)
+ : mEglManager(thread.eglManager()), mRenderThread(thread) {
+}
+
+MakeCurrentResult OpenGLPipeline::makeCurrent() {
+ // TODO: Figure out why this workaround is needed, see b/13913604
+ // In the meantime this matches the behavior of GLRenderer, so it is not a regression
+ EGLint error = 0;
+ bool haveNewSurface = mEglManager.makeCurrent(mEglSurface, &error);
+
+ Caches::getInstance().textureCache.resetMarkInUse(this);
+ if (!haveNewSurface) {
+ return MakeCurrentResult::AlreadyCurrent;
+ }
+ return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
+}
+
+Frame OpenGLPipeline::getFrame() {
+ LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
+ "drawRenderNode called on a context with no surface!");
+ return mEglManager.beginFrame(mEglSurface);
+}
+
+bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector< sp<RenderNode> >& renderNodes,
+ FrameInfoVisualizer* profiler) {
+
+ mEglManager.damageFrame(frame, dirty);
+
+ bool drew = false;
+
+
+ auto& caches = Caches::getInstance();
+ FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), lightGeometry, caches);
+
+ frameBuilder.deferLayers(*layerUpdateQueue);
+ layerUpdateQueue->clear();
+
+ frameBuilder.deferRenderNodeScene(renderNodes, contentDrawBounds);
+
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(),
+ opaque, lightInfo);
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+ profiler->draw(&renderer);
+ drew = renderer.didDraw();
+
+ // post frame cleanup
+ caches.clearGarbage();
+ caches.pathCache.trim();
+ caches.tessellationCache.trim();
+
+#if DEBUG_MEMORY_USAGE
+ mCaches.dumpMemoryUsage();
+#else
+ if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) {
+ caches.dumpMemoryUsage();
+ }
+#endif
+
+ return drew;
+}
+
+bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+ FrameInfo* currentFrameInfo, bool* requireSwap) {
+
+ GL_CHECKPOINT(LOW);
+
+ // Even if we decided to cancel the frame, from the perspective of jank
+ // metrics the frame was swapped at this point
+ currentFrameInfo->markSwapBuffers();
+
+ *requireSwap = drew || mEglManager.damageRequiresSwap();
+
+ if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) {
+ return false;
+ }
+
+ return *requireSwap;
+}
+
+bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
+ layer->apply();
+ return Readback::copyTextureLayerInto(mRenderThread, *(layer->backingLayer()), bitmap)
+ == CopyResult::Success;
+}
+
+Layer* OpenGLPipeline::createTextureLayer() {
+ mEglManager.initialize();
+ return LayerRenderer::createTextureLayer(mRenderThread.renderState());
+}
+
+void OpenGLPipeline::onStop() {
+ if (mEglManager.isCurrent(mEglSurface)) {
+ mEglManager.makeCurrent(EGL_NO_SURFACE);
+ }
+}
+
+bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) {
+
+ if (mEglSurface != EGL_NO_SURFACE) {
+ mEglManager.destroySurface(mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+ }
+
+ if (surface) {
+ mEglSurface = mEglManager.createSurface(surface);
+ }
+
+ if (mEglSurface != EGL_NO_SURFACE) {
+ const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
+ mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
+ return true;
+ }
+
+ return false;
+}
+
+bool OpenGLPipeline::isSurfaceReady() {
+ return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE);
+}
+
+bool OpenGLPipeline::isContextReady() {
+ return CC_LIKELY(mEglManager.hasEglContext());
+}
+
+void OpenGLPipeline::onDestroyHardwareResources() {
+ Caches& caches = Caches::getInstance();
+ // Make sure to release all the textures we were owning as there won't
+ // be another draw
+ caches.textureCache.resetMarkInUse(this);
+ mRenderThread.renderState().flush(Caches::FlushMode::Layers);
+}
+
+void OpenGLPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo) {
+ static const std::vector< sp<RenderNode> > emptyNodeList;
+ auto& caches = Caches::getInstance();
+ FrameBuilder frameBuilder(*layerUpdateQueue, lightGeometry, caches);
+ layerUpdateQueue->clear();
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(),
+ opaque, lightInfo);
+ LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case");
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+}
+
+TaskManager* OpenGLPipeline::getTaskManager() {
+ return &Caches::getInstance().tasks;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h
new file mode 100644
index 000000000000..a6d22ee8b34f
--- /dev/null
+++ b/libs/hwui/renderthread/OpenGLPipeline.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include "CanvasContext.h"
+#include "BakedOpDispatcher.h"
+#include "BakedOpRenderer.h"
+#include "FrameBuilder.h"
+#include "IRenderPipeline.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class Frame;
+
+
+class OpenGLPipeline : public IRenderPipeline {
+public:
+ OpenGLPipeline(RenderThread& thread);
+ virtual ~OpenGLPipeline() {}
+
+ MakeCurrentResult makeCurrent() override;
+ Frame getFrame() override;
+ bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
+ const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue,
+ const Rect& contentDrawBounds, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo,
+ const std::vector< sp<RenderNode> >& renderNodes,
+ FrameInfoVisualizer* profiler) override;
+ bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+ FrameInfo* currentFrameInfo, bool* requireSwap) override;
+ bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
+ Layer* createTextureLayer() override;
+ bool setSurface(Surface* window, SwapBehavior swapBehavior) override;
+ void onStop() override;
+ bool isSurfaceReady() override;
+ bool isContextReady() override;
+ void onDestroyHardwareResources() override;
+ void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
+ LayerUpdateQueue* layerUpdateQueue, bool opaque,
+ const BakedOpRenderer::LightInfo& lightInfo) override;
+ TaskManager* getTaskManager() override;
+
+private:
+ EglManager& mEglManager;
+ EGLSurface mEglSurface = EGL_NO_SURFACE;
+ bool mBufferPreserved = false;
+ RenderThread& mRenderThread;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 06a24b248bf6..d860acd1edd1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -55,7 +55,7 @@ namespace renderthread {
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
- return new CanvasContext(*args->thread, args->translucent,
+ return CanvasContext::create(*args->thread, args->translucent,
args->rootRenderNode, args->contextFactory);
}
@@ -180,19 +180,17 @@ void RenderProxy::setStopped(bool stopped) {
postAndWait(task);
}
-CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height,
+CREATE_BRIDGE4(setup, CanvasContext* context,
float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- args->context->setup(args->width, args->height, args->lightRadius,
+ args->context->setup(args->lightRadius,
args->ambientShadowAlpha, args->spotShadowAlpha);
return nullptr;
}
-void RenderProxy::setup(int width, int height, float lightRadius,
+void RenderProxy::setup(float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
SETUP_TASK(setup);
args->context = mContext;
- args->width = width;
- args->height = height;
args->lightRadius = lightRadius;
args->ambientShadowAlpha = ambientShadowAlpha;
args->spotShadowAlpha = spotShadowAlpha;
@@ -267,18 +265,6 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
}
}
-CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
- args->context->runWithGlContext(args->task);
- return nullptr;
-}
-
-void RenderProxy::runWithGlContext(RenderTask* gltask) {
- SETUP_TASK(runWithGlContext);
- args->context = mContext;
- args->task = gltask;
- postAndWait(task);
-}
-
CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
Layer* layer = args->context->createTextureLayer();
if (!layer) return nullptr;
@@ -456,6 +442,19 @@ void RenderProxy::resetProfileInfo() {
postAndWait(task);
}
+CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) {
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(
+ args->thread->jankTracker().findPercentile(args->percentile)));
+}
+
+uint32_t RenderProxy::frameTimePercentile(int p) {
+ SETUP_TASK(frameTimePercentile);
+ args->thread = &mRenderThread;
+ args->percentile = p;
+ return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
+ postAndWait(task)));
+}
+
CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
args->thread->jankTracker().dump(args->fd);
@@ -467,11 +466,7 @@ CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
} else {
fprintf(file, "\nNo caches instance.\n");
}
-#if HWUI_NEW_OPS
fprintf(file, "\nPipeline=FrameBuilder\n");
-#else
- fprintf(file, "\nPipeline=OpenGLRenderer\n");
-#endif
fflush(file);
return nullptr;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index e31062c83734..0bee858a84fa 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -80,7 +80,7 @@ public:
ANDROID_API void updateSurface(const sp<Surface>& surface);
ANDROID_API bool pauseSurface(const sp<Surface>& surface);
ANDROID_API void setStopped(bool stopped);
- ANDROID_API void setup(int width, int height, float lightRadius,
+ ANDROID_API void setup(float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
ANDROID_API void setLightCenter(const Vector3& lightCenter);
ANDROID_API void setOpaque(bool opaque);
@@ -90,8 +90,6 @@ public:
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
- ANDROID_API void runWithGlContext(RenderTask* task);
-
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
@@ -111,6 +109,7 @@ public:
ANDROID_API void dumpProfileInfo(int fd, int dumpFlags);
// Not exported, only used for testing
void resetProfileInfo();
+ uint32_t frameTimePercentile(int p);
ANDROID_API static void dumpGraphicsMemory(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
diff --git a/libs/hwui/tests/common/LeakChecker.cpp b/libs/hwui/tests/common/LeakChecker.cpp
new file mode 100644
index 000000000000..d935382cc9a4
--- /dev/null
+++ b/libs/hwui/tests/common/LeakChecker.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LeakChecker.h"
+
+#include "Caches.h"
+#include "TestUtils.h"
+
+#include <cstdio>
+#include <iostream>
+#include <memunreachable/memunreachable.h>
+#include <unistd.h>
+#include <unordered_set>
+
+using namespace std;
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+static void logUnreachable(initializer_list<UnreachableMemoryInfo> infolist) {
+ // merge them all
+ UnreachableMemoryInfo merged;
+ unordered_set<uintptr_t> addrs;
+ merged.allocation_bytes = 0;
+ merged.leak_bytes = 0;
+ merged.num_allocations = 0;
+ merged.num_leaks = 0;
+ for (auto& info : infolist) {
+ // We'll be a little hazzy about these ones and just hope the biggest
+ // is the most accurate
+ merged.allocation_bytes = max(merged.allocation_bytes, info.allocation_bytes);
+ merged.num_allocations = max(merged.num_allocations, info.num_allocations);
+ for (auto& leak : info.leaks) {
+ if (addrs.find(leak.begin) == addrs.end()) {
+ merged.leaks.push_back(leak);
+ merged.num_leaks++;
+ merged.leak_bytes += leak.size;
+ addrs.insert(leak.begin);
+ }
+ }
+ }
+
+ // Now log the result
+ if (merged.num_leaks) {
+ cout << endl << "Leaked memory!" << endl;
+ if (!merged.leaks[0].backtrace.num_frames) {
+ cout << "Re-run with 'setprop libc.debug.malloc.program hwui_unit_test'"
+ << endl << "and 'setprop libc.debug.malloc.options backtrace=8'"
+ << " to get backtraces" << endl;
+ }
+ cout << merged.ToString(false);
+ }
+}
+
+void LeakChecker::checkForLeaks() {
+ // TODO: Until we can shutdown the RT thread we need to do this in
+ // two passes as GetUnreachableMemory has limited insight into
+ // thread-local caches so some leaks will not be properly tagged as leaks
+ UnreachableMemoryInfo rtMemInfo;
+ TestUtils::runOnRenderThread([&rtMemInfo](renderthread::RenderThread& thread) {
+ if (Caches::hasInstance()) {
+ Caches::getInstance().tasks.stop();
+ }
+ // Check for leaks
+ if (!GetUnreachableMemory(rtMemInfo)) {
+ cerr << "Failed to get unreachable memory!" << endl;
+ return;
+ }
+ });
+ UnreachableMemoryInfo uiMemInfo;
+ if (!GetUnreachableMemory(uiMemInfo)) {
+ cerr << "Failed to get unreachable memory!" << endl;
+ return;
+ }
+ logUnreachable({rtMemInfo, uiMemInfo});
+}
+
+} /* namespace test */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/tests/common/LeakChecker.h b/libs/hwui/tests/common/LeakChecker.h
new file mode 100644
index 000000000000..cdf47d6bda80
--- /dev/null
+++ b/libs/hwui/tests/common/LeakChecker.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+#pragma once
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+class LeakChecker {
+public:
+ static void checkForLeaks();
+}; // class TestUtils
+
+} /* namespace test */
+} /* namespace uirenderer */
+} /* namespace android */ \ No newline at end of file
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 146e735839d1..1c7e7eef7626 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -62,20 +62,53 @@ TestContext::TestContext() {
TestContext::~TestContext() {}
sp<Surface> TestContext::surface() {
- if (!mSurfaceControl.get()) {
- mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"),
- gDisplay.w, gDisplay.h, PIXEL_FORMAT_RGBX_8888);
-
- SurfaceComposerClient::openGlobalTransaction();
- mSurfaceControl->setLayer(0x7FFFFFF);
- mSurfaceControl->show();
- SurfaceComposerClient::closeGlobalTransaction();
+ if (!mSurface.get()) {
+ createSurface();
}
+ return mSurface;
+}
+
+void TestContext::createSurface() {
+ if (mRenderOffscreen) {
+ createOffscreenSurface();
+ } else {
+ createWindowSurface();
+ }
+}
- return mSurfaceControl->getSurface();
+void TestContext::createWindowSurface() {
+ mSurfaceControl = mSurfaceComposerClient->createSurface(String8("HwuiTest"),
+ gDisplay.w, gDisplay.h, PIXEL_FORMAT_RGBX_8888);
+
+ SurfaceComposerClient::openGlobalTransaction();
+ mSurfaceControl->setLayer(0x7FFFFFF);
+ mSurfaceControl->show();
+ SurfaceComposerClient::closeGlobalTransaction();
+ mSurface = mSurfaceControl->getSurface();
+}
+
+void TestContext::createOffscreenSurface() {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ producer->setMaxDequeuedBufferCount(3);
+ producer->setAsyncMode(true);
+ mConsumer = new BufferItemConsumer(consumer, GRALLOC_USAGE_HW_COMPOSER, 4);
+ mConsumer->setDefaultBufferSize(gDisplay.w, gDisplay.h);
+ mSurface = new Surface(producer);
}
void TestContext::waitForVsync() {
+ if (mConsumer.get()) {
+ BufferItem buffer;
+ if (mConsumer->acquireBuffer(&buffer, 0, false) == OK) {
+ // We assume the producer is internally ordered enough such that
+ // it is unneccessary to set a release fence
+ mConsumer->releaseBuffer(buffer);
+ }
+ // We running free, go go go!
+ return;
+ }
#if !HWUI_NULL_GPU
// Request vsync
mDisplayEventReceiver.requestNextVsync();
diff --git a/libs/hwui/tests/common/TestContext.h b/libs/hwui/tests/common/TestContext.h
index 2bbe5dffd9b8..312988b968de 100644
--- a/libs/hwui/tests/common/TestContext.h
+++ b/libs/hwui/tests/common/TestContext.h
@@ -19,12 +19,16 @@
#include <gui/DisplayEventReceiver.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/BufferItemConsumer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
#include <gui/Surface.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
+#include <thread>
+#include <atomic>
+
namespace android {
namespace uirenderer {
namespace test {
@@ -39,15 +43,29 @@ public:
TestContext();
~TestContext();
+ // Must be called before surface();
+ void setRenderOffscreen(bool renderOffscreen) {
+ LOG_ALWAYS_FATAL_IF(mSurface.get(),
+ "Must be called before surface is created");
+ mRenderOffscreen = renderOffscreen;
+ }
+
sp<Surface> surface();
void waitForVsync();
private:
+ void createSurface();
+ void createWindowSurface();
+ void createOffscreenSurface();
+
sp<SurfaceComposerClient> mSurfaceComposerClient;
sp<SurfaceControl> mSurfaceControl;
+ sp<BufferItemConsumer> mConsumer;
DisplayEventReceiver mDisplayEventReceiver;
sp<Looper> mLooper;
+ sp<Surface> mSurface;
+ bool mRenderOffscreen;
};
} // namespace test
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
new file mode 100644
index 000000000000..847a6ff1181d
--- /dev/null
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestListViewSceneBase.h"
+
+#include "TestContext.h"
+#include "TestUtils.h"
+
+#include <utils/Color.h>
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+void TestListViewSceneBase::createContent(int width, int height, TestCanvas& canvas) {
+ srand(0);
+ mItemHeight = dp(60);
+ mItemSpacing = dp(16);
+ mItemWidth = std::min((height - mItemSpacing * 2), (int)dp(300));
+ mItemLeft = (width - mItemWidth) / 2;
+ int heightWithSpacing = mItemHeight + mItemSpacing;
+ for (int y = 0; y < height + (heightWithSpacing - 1); y += heightWithSpacing) {
+ int id = mListItems.size();
+ auto setup = std::bind(&TestListViewSceneBase::createListItem, this, std::placeholders::_1,
+ std::placeholders::_2, id, mItemWidth, mItemHeight);
+ auto node = TestUtils::createNode(mItemLeft, y, mItemLeft + mItemWidth,
+ y + mItemHeight, setup);
+ mListItems.push_back(node);
+ }
+ mListView = TestUtils::createNode(0, 0, width, height,
+ [this](RenderProperties& props, TestCanvas& canvas) {
+ for (size_t ci = 0; ci < mListItems.size(); ci++) {
+ canvas.drawRenderNode(mListItems[ci].get());
+ }
+ });
+
+ canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode);
+ canvas.drawRenderNode(mListView.get());
+}
+
+void TestListViewSceneBase::doFrame(int frameNr) {
+ int scrollPx = dp(frameNr) * 3;
+ int itemIndexOffset = scrollPx / (mItemSpacing + mItemHeight);
+ int pxOffset = -(scrollPx % (mItemSpacing + mItemHeight));
+
+ TestCanvas canvas(
+ mListView->stagingProperties().getWidth(),
+ mListView->stagingProperties().getHeight());
+ for (size_t ci = 0; ci < mListItems.size(); ci++) {
+ // update item position
+ auto listItem = mListItems[(ci + itemIndexOffset) % mListItems.size()];
+ int top = ((int)ci) * (mItemSpacing + mItemHeight) + pxOffset;
+ listItem->mutateStagingProperties().setLeftTopRightBottom(
+ mItemLeft, top, mItemLeft + mItemWidth, top + mItemHeight);
+ listItem->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+ // draw it to parent DisplayList
+ canvas.drawRenderNode(mListItems[ci].get());
+ }
+ mListView->setStagingDisplayList(canvas.finishRecording(), nullptr);
+}
+
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.h b/libs/hwui/tests/common/TestListViewSceneBase.h
new file mode 100644
index 000000000000..8ffe9929bbd9
--- /dev/null
+++ b/libs/hwui/tests/common/TestListViewSceneBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+#pragma once
+
+#include "TestScene.h"
+#include <RenderNode.h>
+#include <RenderProperties.h>
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+class TestListViewSceneBase : public TestScene {
+public:
+ virtual void createListItem(RenderProperties& props, TestCanvas& canvas, int id,
+ int itemWidth, int itemHeight) = 0;
+private:
+ int mItemHeight;
+ int mItemSpacing;
+ int mItemWidth;
+ int mItemLeft;
+ sp<RenderNode> mListView;
+ std::vector< sp<RenderNode> > mListItems;
+
+ void createContent(int width, int height, TestCanvas& canvas) override;
+ void doFrame(int frameNr) override;
+};
+
+} // namespace test
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/tests/common/TestScene.h b/libs/hwui/tests/common/TestScene.h
index 706f2ff75222..4813ff0de174 100644
--- a/libs/hwui/tests/common/TestScene.h
+++ b/libs/hwui/tests/common/TestScene.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef TESTS_TESTSCENE_H
-#define TESTS_TESTSCENE_H
+
+#pragma once
#include <string>
#include <unordered_map>
@@ -22,14 +22,9 @@
namespace android {
namespace uirenderer {
class RenderNode;
-
-#if HWUI_NEW_OPS
class RecordingCanvas;
+
typedef RecordingCanvas TestCanvas;
-#else
-class DisplayListCanvas;
-typedef DisplayListCanvas TestCanvas;
-#endif
namespace test {
@@ -38,6 +33,7 @@ public:
struct Options {
int count = 0;
int reportFrametimeWeight = 0;
+ bool renderOffscreen = false;
};
template <class T>
@@ -75,5 +71,3 @@ public:
} // namespace test
} // namespace uirenderer
} // namespace android
-
-#endif /* TESTS_TESTSCENE_H */
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index c762eed616e4..930067a9b2cc 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -20,6 +20,9 @@
#include "DeferredLayerUpdater.h"
#include "LayerRenderer.h"
+#include <renderthread/EglManager.h>
+#include <utils/Unicode.h>
+
namespace android {
namespace uirenderer {
@@ -68,7 +71,10 @@ void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
while (*text != '\0') {
- SkUnichar unichar = SkUTF8_NextUnichar(&text);
+ size_t nextIndex = 0;
+ int32_t unichar = utf32_from_utf8_at(text, 4, 0, &nextIndex);
+ text += nextIndex;
+
glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar);
autoCache.getCache()->unicharToGlyph(unichar);
@@ -107,12 +113,18 @@ void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text,
void TestUtils::TestTask::run() {
// RenderState only valid once RenderThread is running, so queried here
- RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
+ renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance();
+ bool hasEglContext = renderThread.eglManager().hasEglContext();
+ RenderState& renderState = renderThread.renderState();
+ if (!hasEglContext) {
+ renderState.onGLContextCreated();
+ }
- renderState.onGLContextCreated();
- rtCallback(renderthread::RenderThread::getInstance());
- renderState.flush(Caches::FlushMode::Full);
- renderState.onGLContextDestroyed();
+ rtCallback(renderThread);
+ if (!hasEglContext) {
+ renderState.flush(Caches::FlushMode::Full);
+ renderState.onGLContextDestroyed();
+ }
}
std::unique_ptr<uint16_t[]> TestUtils::asciiToUtf16(const char* str) {
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 4536bef6d391..9f7fee262acf 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef TEST_UTILS_H
-#define TEST_UTILS_H
+
+#pragma once
#include <DeviceInfo.h>
#include <DisplayList.h>
@@ -25,24 +25,15 @@
#include <renderthread/RenderThread.h>
#include <Snapshot.h>
-#if HWUI_NEW_OPS
#include <RecordedOp.h>
#include <RecordingCanvas.h>
-#else
-#include <DisplayListOp.h>
-#include <DisplayListCanvas.h>
-#endif
#include <memory>
namespace android {
namespace uirenderer {
-#if HWUI_NEW_OPS
typedef RecordingCanvas TestCanvas;
-#else
-typedef DisplayListCanvas TestCanvas;
-#endif
#define EXPECT_MATRIX_APPROX_EQ(a, b) \
EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
@@ -251,5 +242,3 @@ private:
} /* namespace uirenderer */
} /* namespace android */
-
-#endif /* TEST_UTILS_H */
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index f184411b4139..a61f6d0f1e7c 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -17,8 +17,8 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
-#include <minikin/Layout.h>
#include <hwui/Paint.h>
+#include <minikin/Layout.h>
#include <cstdio>
@@ -56,7 +56,7 @@ public:
for (int i = 0; i < 5; i++) {
paint.setTextSize(10 + (frameNr % 20) + i * 20);
canvas.drawText(text.get(), 0, textLength, textLength,
- 0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr);
+ 0, 100 * (i + 2), minikin::kBidi_Force_LTR, paint, nullptr);
}
container->setStagingDisplayList(canvas.finishRecording(), nullptr);
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
new file mode 100644
index 000000000000..ba6074fa7840
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+#include "tests/common/TestListViewSceneBase.h"
+
+#include <SkGradientShader.h>
+
+class ListOfFadedTextAnimation;
+
+static TestScene::Registrar _ListOfFadedTextAnimation(TestScene::Info{
+ "fadingedges",
+ "A mock ListView of scrolling text with faded edge. Doesn't re-bind/re-record views"
+ "as they are recycled, so won't upload much content (either glyphs, or bitmaps).",
+ TestScene::simpleCreateScene<ListOfFadedTextAnimation>
+});
+
+class ListOfFadedTextAnimation : public TestListViewSceneBase {
+ void createListItem(RenderProperties& props, TestCanvas& canvas, int id,
+ int itemWidth, int itemHeight) override {
+ canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+ int length = dp(100);
+ canvas.saveLayer(0, 0, length, itemHeight, nullptr, SaveFlags::HasAlphaLayer);
+ SkPaint textPaint;
+ textPaint.setTextSize(dp(20));
+ textPaint.setAntiAlias(true);
+ TestUtils::drawUtf8ToCanvas(&canvas, "not that long long text", textPaint, dp(10), dp(30));
+
+ SkPoint pts[2];
+ pts[0].set(0, 0);
+ pts[1].set(0, 1);
+
+ SkColor colors[2] = {Color::Black, Color::Transparent};
+ SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
+ SkShader::kClamp_TileMode));
+
+ SkMatrix matrix;
+ matrix.setScale(1, length);
+ matrix.postRotate(-90);
+ SkPaint fadingPaint;
+ fadingPaint.setShader(s->newWithLocalMatrix(matrix))->unref();
+ SkXfermode* mode = SkXfermode::Create(SkXfermode::kDstOut_Mode);
+ fadingPaint.setXfermode(mode);
+ canvas.drawRect(0, 0, length, itemHeight, fadingPaint);
+ canvas.restore();
+ }
+};
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index 8035dc45f23c..a614044b2468 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -15,7 +15,7 @@
*/
#include "TestSceneBase.h"
-#include "utils/Color.h"
+#include "tests/common/TestListViewSceneBase.h"
#include <cstdio>
@@ -28,58 +28,8 @@ static TestScene::Registrar _ListView(TestScene::Info{
TestScene::simpleCreateScene<ListViewAnimation>
});
-class ListViewAnimation : public TestScene {
-public:
- int cardHeight;
- int cardSpacing;
- int cardWidth;
- int cardLeft;
- sp<RenderNode> listView;
- std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, TestCanvas& canvas) override {
- srand(0);
- cardHeight = dp(60);
- cardSpacing = dp(16);
- cardWidth = std::min((height - cardSpacing * 2), (int)dp(300));
- cardLeft = (width - cardWidth) / 2;
-
- for (int y = 0; y < height + (cardHeight + cardSpacing - 1); y += (cardHeight + cardSpacing)) {
- cards.push_back(createCard(cards.size(), y));
- }
- listView = TestUtils::createNode(0, 0, width, height,
- [this](RenderProperties& props, TestCanvas& canvas) {
- for (size_t ci = 0; ci < cards.size(); ci++) {
- canvas.drawRenderNode(cards[ci].get());
- }
- });
-
- canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode);
- canvas.drawRenderNode(listView.get());
- }
-
- void doFrame(int frameNr) override {
- int scrollPx = dp(frameNr) * 3;
- int cardIndexOffset = scrollPx / (cardSpacing + cardHeight);
- int pxOffset = -(scrollPx % (cardSpacing + cardHeight));
-
- TestCanvas canvas(
- listView->stagingProperties().getWidth(),
- listView->stagingProperties().getHeight());
- for (size_t ci = 0; ci < cards.size(); ci++) {
- // update card position
- auto card = cards[(ci + cardIndexOffset) % cards.size()];
- int top = ((int)ci) * (cardSpacing + cardHeight) + pxOffset;
- card->mutateStagingProperties().setLeftTopRightBottom(
- cardLeft, top, cardLeft + cardWidth, top + cardHeight);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
-
- // draw it to parent DisplayList
- canvas.drawRenderNode(cards[ci].get());
- }
- listView->setStagingDisplayList(canvas.finishRecording(), nullptr);
- }
-private:
- SkBitmap createRandomCharIcon() {
+class ListViewAnimation : public TestListViewSceneBase {
+ SkBitmap createRandomCharIcon(int cardHeight) {
int size = cardHeight - (dp(10) * 2);
SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
SkCanvas canvas(bitmap);
@@ -97,7 +47,10 @@ private:
paint.setTextAlign(SkPaint::kCenter_Align);
paint.setTextSize(size / 2);
char charToShow = 'A' + (rand() % 26);
- canvas.drawText(&charToShow, 1, size / 2, /*approximate centering*/ size * 0.7, paint);
+ const SkPoint pos[] = {{
+ SkIntToScalar(size / 2),
+ /*approximate centering*/ SkFloatToScalar(size * 0.7f)}};
+ canvas.drawPosText(&charToShow, 1, pos, paint);
return bitmap;
}
@@ -117,34 +70,31 @@ private:
return bitmap;
}
- sp<RenderNode> createCard(int cardId, int top) {
- return TestUtils::createNode(cardLeft, top, cardLeft + cardWidth, top + cardHeight,
- [this, cardId](RenderProperties& props, TestCanvas& canvas) {
- static SkBitmap filledBox = createBoxBitmap(true);
- static SkBitmap strokedBox = createBoxBitmap(false);
-
- // TODO: switch to using round rect clipping, once merging correctly handles that
- SkPaint roundRectPaint;
- roundRectPaint.setAntiAlias(true);
- roundRectPaint.setColor(Color::White);
- canvas.drawRoundRect(0, 0, cardWidth, cardHeight, dp(6), dp(6), roundRectPaint);
-
- SkPaint textPaint;
- textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
- textPaint.setTextSize(dp(20));
- textPaint.setAntiAlias(true);
- char buf[256];
- snprintf(buf, sizeof(buf), "This card is #%d", cardId);
- TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
- textPaint.setTextSize(dp(15));
- TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
- cardHeight, dp(45));
-
- canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);
-
- const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox;
- canvas.drawBitmap(boxBitmap, cardWidth - dp(10) - boxBitmap.width(), dp(10), nullptr);
- });
+ void createListItem(RenderProperties& props, TestCanvas& canvas, int cardId,
+ int itemWidth, int itemHeight) override {
+ static SkBitmap filledBox = createBoxBitmap(true);
+ static SkBitmap strokedBox = createBoxBitmap(false);
+ // TODO: switch to using round rect clipping, once merging correctly handles that
+ SkPaint roundRectPaint;
+ roundRectPaint.setAntiAlias(true);
+ roundRectPaint.setColor(Color::White);
+ canvas.drawRoundRect(0, 0, itemWidth, itemHeight, dp(6), dp(6), roundRectPaint);
+
+ SkPaint textPaint;
+ textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
+ textPaint.setTextSize(dp(20));
+ textPaint.setAntiAlias(true);
+ char buf[256];
+ snprintf(buf, sizeof(buf), "This card is #%d", cardId);
+ TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, itemHeight, dp(25));
+ textPaint.setTextSize(dp(15));
+ TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
+ itemHeight, dp(45));
+
+ canvas.drawBitmap(createRandomCharIcon(itemHeight), dp(10), dp(10), nullptr);
+
+ const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox;
+ canvas.drawBitmap(boxBitmap, itemWidth - dp(10) - boxBitmap.width(), dp(10), nullptr);
}
};
diff --git a/libs/hwui/tests/common/scenes/TestSceneBase.h b/libs/hwui/tests/common/scenes/TestSceneBase.h
index 935ddcf9212d..792312a6a7a4 100644
--- a/libs/hwui/tests/common/scenes/TestSceneBase.h
+++ b/libs/hwui/tests/common/scenes/TestSceneBase.h
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef TESTS_SCENES_TESTSCENEBASE_H
-#define TESTS_SCENES_TESTSCENEBASE_H
-#include "DisplayListCanvas.h"
+#pragma once
+
#include "RecordingCanvas.h"
#include "RenderNode.h"
#include "tests/common/TestContext.h"
@@ -30,5 +29,3 @@ using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::test;
-
-#endif /* TESTS_SCENES_TESTSCENEBASE_H_ */
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index c5af06160b62..f03dcbf4c24c 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -22,6 +22,7 @@
#include "renderthread/RenderProxy.h"
#include "renderthread/RenderTask.h"
+#include <benchmark/benchmark.h>
#include <cutils/log.h>
#include <gui/Surface.h>
#include <ui/PixelFormat.h>
@@ -41,7 +42,7 @@ public:
template<class T>
class ModifiedMovingAverage {
public:
- ModifiedMovingAverage(int weight) : mWeight(weight) {}
+ explicit ModifiedMovingAverage(int weight) : mWeight(weight) {}
T add(T today) {
if (!mHasValue) {
@@ -62,13 +63,62 @@ private:
T mAverage;
};
-void run(const TestScene::Info& info, const TestScene::Options& opts) {
+void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts,
+ benchmark::BenchmarkReporter* reporter, RenderProxy* proxy,
+ double durationInS) {
+ using namespace benchmark;
+
+ struct ReportInfo {
+ int percentile;
+ const char* suffix;
+ };
+
+ static std::array<ReportInfo, 4> REPORTS = {
+ ReportInfo { 50, "_50th" },
+ ReportInfo { 90, "_90th" },
+ ReportInfo { 95, "_95th" },
+ ReportInfo { 99, "_99th" },
+ };
+
+ // Although a vector is used, it must stay with only a single element
+ // otherwise the BenchmarkReporter will automatically compute
+ // mean and stddev which doesn't make sense for our usage
+ std::vector<BenchmarkReporter::Run> reports;
+ BenchmarkReporter::Run report;
+ report.benchmark_name = info.name;
+ report.iterations = static_cast<int64_t>(opts.count);
+ report.real_accumulated_time = durationInS;
+ report.cpu_accumulated_time = durationInS;
+ report.items_per_second = opts.count / durationInS;
+ reports.push_back(report);
+ reporter->ReportRuns(reports);
+
+ // Pretend the percentiles are single-iteration runs of the test
+ // If rendering offscreen skip this as it's fps that's more interesting
+ // in that test case than percentiles.
+ if (!opts.renderOffscreen) {
+ for (auto& ri : REPORTS) {
+ reports[0].benchmark_name = info.name;
+ reports[0].benchmark_name += ri.suffix;
+ durationInS = proxy->frameTimePercentile(ri.percentile) / 1000.0;
+ reports[0].real_accumulated_time = durationInS;
+ reports[0].cpu_accumulated_time = durationInS;
+ reports[0].iterations = 1;
+ reports[0].items_per_second = 0;
+ reporter->ReportRuns(reports);
+ }
+ }
+}
+
+void run(const TestScene::Info& info, const TestScene::Options& opts,
+ benchmark::BenchmarkReporter* reporter) {
// Switch to the real display
gDisplay = getBuiltInDisplay();
std::unique_ptr<TestScene> scene(info.createScene(opts));
TestContext testContext;
+ testContext.setRenderOffscreen(opts.renderOffscreen);
// create the native surface
const int width = gDisplay.w;
@@ -87,11 +137,16 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
proxy->loadSystemProperties();
proxy->initialize(surface);
float lightX = width / 2.0;
- proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
+ proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
// Do a few cold runs then reset the stats so that the caches are all hot
- for (int i = 0; i < 5; i++) {
+ int warmupFrameCount = 5;
+ if (opts.renderOffscreen) {
+ // Do a few more warmups to try and boost the clocks up
+ warmupFrameCount = 10;
+ }
+ for (int i = 0; i < warmupFrameCount; i++) {
testContext.waitForVsync();
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
@@ -103,6 +158,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
+ nsecs_t start = systemTime(CLOCK_MONOTONIC);
for (int i = 0; i < opts.count; i++) {
testContext.waitForVsync();
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
@@ -121,6 +177,13 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
}
}
}
+ proxy->fence();
+ nsecs_t end = systemTime(CLOCK_MONOTONIC);
- proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
+ if (reporter) {
+ outputBenchmarkReport(info, opts, reporter, proxy.get(),
+ (end - start) / (double) s2ns(1));
+ } else {
+ proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
+ }
}
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index 02a39501e647..ffeef4599774 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+#include "tests/common/LeakChecker.h"
#include "tests/common/TestScene.h"
#include "protos/hwui.pb.h"
#include "Properties.h"
+#include <benchmark/benchmark.h>
+#include <../src/sysinfo.h>
#include <getopt.h>
#include <stdio.h>
#include <string>
@@ -39,8 +42,10 @@ using namespace android::uirenderer::test;
static int gRepeatCount = 1;
static std::vector<TestScene::Info> gRunTests;
static TestScene::Options gOpts;
+std::unique_ptr<benchmark::BenchmarkReporter> gBenchmarkReporter;
-void run(const TestScene::Info& info, const TestScene::Options& opts);
+void run(const TestScene::Info& info, const TestScene::Options& opts,
+ benchmark::BenchmarkReporter* reporter);
static void printHelp() {
printf(R"(
@@ -121,6 +126,20 @@ static void moveToCpuSet(const char* cpusetName) {
close(fd);
}
+static bool setBenchmarkFormat(const char* format) {
+ if (!strcmp(format, "tabular")) {
+ gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
+ } else if (!strcmp(format, "json")) {
+ gBenchmarkReporter.reset(new benchmark::JSONReporter());
+ } else if (!strcmp(format, "csv")) {
+ gBenchmarkReporter.reset(new benchmark::CSVReporter());
+ } else {
+ fprintf(stderr, "Unknown format '%s'", format);
+ return false;
+ }
+ return true;
+}
+
// For options that only exist in long-form. Anything in the
// 0-255 range is reserved for short options (which just use their ASCII value)
namespace LongOpts {
@@ -130,6 +149,8 @@ enum {
WaitForGpu,
ReportFrametime,
CpuSet,
+ BenchmarkFormat,
+ Offscreen,
};
}
@@ -141,6 +162,8 @@ static const struct option LONG_OPTIONS[] = {
{ "wait-for-gpu", no_argument, nullptr, LongOpts::WaitForGpu },
{ "report-frametime", optional_argument, nullptr, LongOpts::ReportFrametime },
{ "cpuset", required_argument, nullptr, LongOpts::CpuSet },
+ { "benchmark_format", required_argument, nullptr, LongOpts::BenchmarkFormat },
+ { "offscreen", no_argument, nullptr, LongOpts::Offscreen },
{ 0, 0, 0, 0 }
};
@@ -214,6 +237,20 @@ void parseOptions(int argc, char* argv[]) {
moveToCpuSet(optarg);
break;
+ case LongOpts::BenchmarkFormat:
+ if (!optarg) {
+ error = true;
+ break;
+ }
+ if (!setBenchmarkFormat(optarg)) {
+ error = true;
+ }
+ break;
+
+ case LongOpts::Offscreen:
+ gOpts.renderOffscreen = true;
+ break;
+
case 'h':
printHelp();
exit(EXIT_SUCCESS);
@@ -237,12 +274,18 @@ void parseOptions(int argc, char* argv[]) {
if (optind < argc) {
do {
const char* test = argv[optind++];
- auto pos = TestScene::testMap().find(test);
- if (pos == TestScene::testMap().end()) {
- fprintf(stderr, "Unknown test '%s'\n", test);
- exit(EXIT_FAILURE);
+ if (!strcmp(test, "all")) {
+ for (auto& iter : TestScene::testMap()) {
+ gRunTests.push_back(iter.second);
+ }
} else {
- gRunTests.push_back(pos->second);
+ auto pos = TestScene::testMap().find(test);
+ if (pos == TestScene::testMap().end()) {
+ fprintf(stderr, "Unknown test '%s'\n", test);
+ exit(EXIT_FAILURE);
+ } else {
+ gRunTests.push_back(pos->second);
+ }
}
} while (optind < argc);
} else {
@@ -255,12 +298,36 @@ int main(int argc, char* argv[]) {
gOpts.count = 150;
parseOptions(argc, argv);
+ if (!gBenchmarkReporter && gOpts.renderOffscreen) {
+ gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
+ }
+
+ if (gBenchmarkReporter) {
+ size_t name_field_width = 10;
+ for (auto&& test : gRunTests) {
+ name_field_width = std::max<size_t>(name_field_width, test.name.size());
+ }
+ // _50th, _90th, etc...
+ name_field_width += 5;
+
+ benchmark::BenchmarkReporter::Context context;
+ context.num_cpus = benchmark::NumCPUs();
+ context.mhz_per_cpu = benchmark::CyclesPerSecond() / 1000000.0f;
+ context.cpu_scaling_enabled = benchmark::CpuScalingEnabled();
+ context.name_field_width = name_field_width;
+ gBenchmarkReporter->ReportContext(context);
+ }
for (int i = 0; i < gRepeatCount; i++) {
for (auto&& test : gRunTests) {
- run(test, gOpts);
+ run(test, gOpts, gBenchmarkReporter.get());
}
}
- printf("Success!\n");
+
+ if (gBenchmarkReporter) {
+ gBenchmarkReporter->Finalize();
+ }
+
+ LeakChecker::checkForLeaks();
return 0;
}
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 06b68d1dea8f..ed3b84753eeb 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -17,21 +17,13 @@
#include <benchmark/benchmark.h>
#include "DisplayList.h"
-#if HWUI_NEW_OPS
#include "RecordingCanvas.h"
-#else
-#include "DisplayListCanvas.h"
-#endif
#include "tests/common/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
-#if HWUI_NEW_OPS
typedef RecordingCanvas TestCanvas;
-#else
-typedef DisplayListCanvas TestCanvas;
-#endif
void BM_DisplayList_alloc(benchmark::State& benchState) {
while (benchState.KeepRunning()) {
@@ -169,3 +161,37 @@ void BM_CanvasState_translate(benchmark::State& benchState) {
}
}
BENCHMARK(BM_CanvasState_translate);
+
+void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
+ sp<RenderNode> child = TestUtils::createNode(50, 50, 100, 100,
+ [](auto& props, auto& canvas) {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ });
+
+ TestCanvas canvas(100, 100);
+ delete canvas.finishRecording();
+
+ while (benchState.KeepRunning()) {
+ canvas.resetRecording(200, 200);
+ canvas.setHighContrastText(false);
+ canvas.translate(0, 0); // mScrollX, mScrollY
+
+ // Clip to padding
+ // Can expect ~25% of views to have clip to padding with a non-null padding
+ int clipRestoreCount = canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(1, 1, 199, 199, SkRegion::kIntersect_Op);
+
+ canvas.insertReorderBarrier(true);
+
+ // Draw child loop
+ for (int i = 0; i < benchState.range_x(); i++) {
+ canvas.drawRenderNode(child.get());
+ }
+
+ canvas.insertReorderBarrier(false);
+ canvas.restoreToCount(clipRestoreCount);
+
+ delete canvas.finishRecording();
+ }
+}
+BENCHMARK(BM_DisplayListCanvas_basicViewGroupDraw)->Arg(1)->Arg(5)->Arg(10);
diff --git a/libs/hwui/tests/microbench/TaskManagerBench.cpp b/libs/hwui/tests/microbench/TaskManagerBench.cpp
index c6b9f3bca55f..cf47f273c144 100644
--- a/libs/hwui/tests/microbench/TaskManagerBench.cpp
+++ b/libs/hwui/tests/microbench/TaskManagerBench.cpp
@@ -29,7 +29,7 @@ class TrivialTask : public Task<char> {};
class TrivialProcessor : public TaskProcessor<char> {
public:
- TrivialProcessor(TaskManager* manager)
+ explicit TrivialProcessor(TaskManager* manager)
: TaskProcessor(manager) {}
virtual ~TrivialProcessor() {}
virtual void onProcess(const sp<Task<char> >& task) override {
diff --git a/libs/hwui/tests/microbench/how_to_run.txt b/libs/hwui/tests/microbench/how_to_run.txt
index e6f80b278276..915fe5d959f9 100755
--- a/libs/hwui/tests/microbench/how_to_run.txt
+++ b/libs/hwui/tests/microbench/how_to_run.txt
@@ -1,4 +1,3 @@
mmm -j8 frameworks/base/libs/hwui &&
-adb push $ANDROID_PRODUCT_OUT/data/local/tmp/hwuimicro \
- /data/local/tmp/hwuimicro &&
- adb shell /data/local/tmp/hwuimicro
+adb push $OUT/data/benchmarktest/hwuimicro/hwuimicro /data/benchmarktest/hwuimicro/hwuimicro &&
+adb shell /data/benchmarktest/hwuimicro/hwuimicro
diff --git a/libs/hwui/tests/microbench/main.cpp b/libs/hwui/tests/microbench/main.cpp
index a0157bc4f9ef..9771c85382b4 100644
--- a/libs/hwui/tests/microbench/main.cpp
+++ b/libs/hwui/tests/microbench/main.cpp
@@ -14,6 +14,19 @@
* limitations under the License.
*/
+#include "debug/GlesDriver.h"
+#include "debug/NullGlesDriver.h"
+
#include <benchmark/benchmark.h>
-BENCHMARK_MAIN();
+#include <memory>
+
+using namespace android;
+using namespace android::uirenderer;
+
+int main(int argc, char** argv) {
+ debug::GlesDriver::replace(std::make_unique<debug::NullGlesDriver>());
+ benchmark::Initialize(&argc, argv);
+ benchmark::RunSpecifiedBenchmarks();
+ return 0;
+}
diff --git a/libs/hwui/tests/scripts/prep_buller.sh b/libs/hwui/tests/scripts/prep_buller.sh
new file mode 100755
index 000000000000..b2f68bd44e7d
--- /dev/null
+++ b/libs/hwui/tests/scripts/prep_buller.sh
@@ -0,0 +1,49 @@
+#buller is bullhead & angler (☞゚ヮ゚)☞
+
+nr=$(adb shell cat /proc/cpuinfo | grep processor | wc -l)
+cpubase=/sys/devices/system/cpu
+gov=cpufreq/scaling_governor
+
+adb root
+adb wait-for-device
+adb shell stop thermal-engine
+adb shell stop perfd
+
+# LITTLE cores
+# 384000 460800 600000 672000 787200 864000 960000 1248000 1440000
+# BIG cores
+# 384000 480000 633600 768000 864000 960000 1248000 1344000 1440000
+# 1536000 1632000 1689600 1824000
+
+cpu=0
+S=960000
+while [ $((cpu < 4)) -eq 1 ]; do
+ echo "Setting cpu $cpu to $S hz"
+ adb shell "echo 1 > $cpubase/cpu${cpu}/online"
+ adb shell "echo userspace > $cpubase/cpu${cpu}/$gov"
+ adb shell "echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_max_freq"
+ adb shell "echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_min_freq"
+ adb shell "echo $S > $cpubase/cpu${cpu}/cpufreq/scaling_setspeed"
+ cpu=$(($cpu + 1))
+done
+
+while [ $((cpu < $nr)) -eq 1 ]; do
+ echo "disable cpu $cpu"
+ adb shell "echo 0 > $cpubase/cpu${cpu}/online"
+ cpu=$(($cpu + 1))
+done
+
+echo "setting GPU bus and idle timer"
+adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split"
+adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on"
+adb shell "echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer"
+
+#0 762 1144 1525 2288 3509 4173 5271 5928 7904 9887 11863
+adb shell "echo 11863 > /sys/class/devfreq/qcom,gpubw.70/min_freq" &> /dev/null
+adb shell "echo 11863 > /sys/class/devfreq/qcom,gpubw.19/min_freq" &> /dev/null
+
+#600000000 510000000 450000000 390000000 305000000 180000000
+echo "performance mode, 305 MHz"
+adb shell "echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor"
+adb shell "echo 305000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq"
+adb shell "echo 305000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq"
diff --git a/libs/hwui/tests/scripts/prep_volantis.sh b/libs/hwui/tests/scripts/prep_volantis.sh
index 0572ee55c9b9..6407844afa90 100755
--- a/libs/hwui/tests/scripts/prep_volantis.sh
+++ b/libs/hwui/tests/scripts/prep_volantis.sh
@@ -16,16 +16,8 @@
adb root
adb wait-for-device
-adb shell stop mpdecision
adb shell stop perfd
-adb shell stop
-for pid in $( adb shell ps | awk '{ if ( $9 == "surfaceflinger" ) { print $2 } }' ); do
- adb shell kill $pid
-done
-adb shell setprop debug.egl.traceGpuCompletion 1
-adb shell daemonize surfaceflinger
-sleep 3
-adb shell setprop service.bootanim.exit 1
+adb shell stop thermal-engine
# cpu possible frequencies
# 204000 229500 255000 280500 306000 331500 357000 382500 408000 433500 459000
diff --git a/libs/hwui/tests/scripts/stopruntime.sh b/libs/hwui/tests/scripts/stopruntime.sh
new file mode 100644
index 000000000000..bb8fcb6f3ee2
--- /dev/null
+++ b/libs/hwui/tests/scripts/stopruntime.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Copyright (C) 2016 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.
+
+adb root
+adb wait-for-device
+adb shell stop
+
+for pid in $( adb shell ps | awk '{ if ( $9 == "surfaceflinger" ) { print $2 } }' ); do
+ adb shell kill $pid
+done
+adb shell setprop debug.egl.traceGpuCompletion 1
+adb shell daemonize surfaceflinger
+sleep 3
+adb shell setprop service.bootanim.exit 1
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index af54e079daab..e5fc55611be3 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1953,7 +1953,7 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac
std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
class PropertyTestRenderer : public TestRendererBase {
public:
- PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback)
+ explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback)
: mCallback(callback) {}
void onRectOp(const RectOp& op, const BakedOpState& state) override {
EXPECT_EQ(mIndex++, 0);
@@ -2075,7 +2075,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
std::function<void(RenderProperties&)> propSetupCallback) {
class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
public:
- SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
+ explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
: mOutData(outData) {}
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp
index 95543d33b1ef..67e58e2aba0d 100644
--- a/libs/hwui/tests/unit/GlopBuilderTests.cpp
+++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp
@@ -85,9 +85,6 @@ static void expectTransformEq(Glop::Transform& expectedTransform, Glop::Transfor
}
static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) {
-#if !HWUI_NEW_OPS
- EXPECT_EQ(expectedGlop.bounds, builtGlop.bounds);
-#endif
expectBlendEq(expectedGlop.blend, builtGlop.blend);
expectFillEq(expectedGlop.fill, builtGlop.fill);
expectMeshEq(expectedGlop.mesh, builtGlop.mesh);
@@ -138,9 +135,6 @@ RENDERTHREAD_TEST(GlopBuilder, rectSnapTest) {
// unit quad also should be translate by additional (0.3, 0.3) to snap to exact pixels.
goldenGlop->transform.modelView.loadTranslate(1.3, 1.3, 0);
goldenGlop->transform.modelView.scale(99, 99, 1);
-#if !HWUI_NEW_OPS
- goldenGlop->bounds = android::uirenderer::Rect(1.70, 1.70, 100.70, 100.70);
-#endif
goldenGlop->transform.canvas = simpleTranslate;
goldenGlop->fill.texture.filter = GL_NEAREST;
expectGlopEq(*goldenGlop, glop);
diff --git a/libs/hwui/tests/unit/MeshStateTests.cpp b/libs/hwui/tests/unit/MeshStateTests.cpp
new file mode 100644
index 000000000000..0881fa246afd
--- /dev/null
+++ b/libs/hwui/tests/unit/MeshStateTests.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <debug/MockGlesDriver.h>
+#include <debug/ScopedReplaceDriver.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <renderstate/MeshState.h>
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+using namespace testing;
+
+RENDERTHREAD_TEST(MeshState, genOrUpdate) {
+ debug::ScopedReplaceDriver<debug::MockGlesDriver> driverRef;
+ auto& mockGlDriver = driverRef.get();
+ EXPECT_CALL(mockGlDriver, glGenBuffers_(_, _)).WillOnce(SetArgPointee<1>(35));
+ EXPECT_CALL(mockGlDriver, glBindBuffer_(_, 35));
+ EXPECT_CALL(mockGlDriver, glBufferData_(_, _, _, _));
+
+ GLuint buffer = 0;
+ renderThread.renderState().meshState().genOrUpdateMeshBuffer(&buffer, 10, nullptr, GL_DYNAMIC_DRAW);
+} \ No newline at end of file
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 9cd504ec0af7..d75ceb200a88 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -746,7 +746,7 @@ TEST(RecordingCanvas, drawText) {
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
- canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
+ canvas.drawText(dst.get(), 0, 5, 5, 25, 25, minikin::kBidi_Force_LTR, paint, NULL);
});
int count = 0;
@@ -770,7 +770,7 @@ TEST(RecordingCanvas, drawTextInHighContrast) {
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO");
- canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
+ canvas.drawText(dst.get(), 0, 5, 5, 25, 25, minikin::kBidi_Force_LTR, paint, NULL);
});
int count = 0;
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index cf76a8691dcd..132601efb543 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -68,7 +68,7 @@ TEST(RenderNode, hasParents) {
TEST(RenderNode, releasedCallback) {
class DecRefOnReleased : public GlFunctorLifecycleListener {
public:
- DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
+ explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
void onGlFunctorReleased(Functor* functor) override {
*mRefCnt -= 1;
}
@@ -105,8 +105,9 @@ TEST(RenderNode, releasedCallback) {
RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
ContextFactory contextFactory;
- CanvasContext canvasContext(renderThread, false, nullptr, &contextFactory);
- TreeInfo info(TreeInfo::MODE_RT_ONLY, canvasContext);
+ std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+ renderThread, false, nullptr, &contextFactory));
+ TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
info.observer = nullptr;
@@ -128,5 +129,5 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
nullDLNode->prepareTree(info);
}
- canvasContext.destroy(nullptr);
+ canvasContext->destroy(nullptr);
}
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 409a12d37693..d05bdbf1709e 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -15,19 +15,15 @@
*/
#include "gtest/gtest.h"
+#include "gmock/gmock.h"
#include "Caches.h"
+#include "debug/GlesDriver.h"
+#include "debug/NullGlesDriver.h"
#include "thread/TaskManager.h"
-#include "tests/common/TestUtils.h"
+#include "tests/common/LeakChecker.h"
-#include <memunreachable/memunreachable.h>
-
-#include <cstdio>
-#include <iostream>
-#include <map>
-#include <unordered_set>
#include <signal.h>
-#include <unistd.h>
using namespace std;
using namespace android;
@@ -54,67 +50,6 @@ static void gtestSigHandler(int sig, siginfo_t* siginfo, void* context) {
raise(sig);
}
-static void logUnreachable(initializer_list<UnreachableMemoryInfo> infolist) {
- // merge them all
- UnreachableMemoryInfo merged;
- unordered_set<uintptr_t> addrs;
- merged.allocation_bytes = 0;
- merged.leak_bytes = 0;
- merged.num_allocations = 0;
- merged.num_leaks = 0;
- for (auto& info : infolist) {
- // We'll be a little hazzy about these ones and just hope the biggest
- // is the most accurate
- merged.allocation_bytes = max(merged.allocation_bytes, info.allocation_bytes);
- merged.num_allocations = max(merged.num_allocations, info.num_allocations);
- for (auto& leak : info.leaks) {
- if (addrs.find(leak.begin) == addrs.end()) {
- merged.leaks.push_back(leak);
- merged.num_leaks++;
- merged.leak_bytes += leak.size;
- addrs.insert(leak.begin);
- }
- }
- }
-
- // Now log the result
- if (merged.num_leaks) {
- cout << endl << "Leaked memory!" << endl;
- if (!merged.leaks[0].backtrace.num_frames) {
- cout << "Re-run with 'setprop libc.debug.malloc.program hwui_unit_test'"
- << endl << "and 'setprop libc.debug.malloc.options backtrace=8'"
- << " to get backtraces" << endl;
- }
- cout << merged.ToString(false);
- }
-}
-
-static void checkForLeaks() {
- // TODO: Until we can shutdown the RT thread we need to do this in
- // two passes as GetUnreachableMemory has limited insight into
- // thread-local caches so some leaks will not be properly tagged as leaks
- nsecs_t before = systemTime();
- UnreachableMemoryInfo rtMemInfo;
- TestUtils::runOnRenderThread([&rtMemInfo](renderthread::RenderThread& thread) {
- if (Caches::hasInstance()) {
- Caches::getInstance().tasks.stop();
- }
- // Check for leaks
- if (!GetUnreachableMemory(rtMemInfo)) {
- cerr << "Failed to get unreachable memory!" << endl;
- return;
- }
- });
- UnreachableMemoryInfo uiMemInfo;
- if (!GetUnreachableMemory(uiMemInfo)) {
- cerr << "Failed to get unreachable memory!" << endl;
- return;
- }
- logUnreachable({rtMemInfo, uiMemInfo});
- nsecs_t after = systemTime();
- cout << "Leak check took " << ns2ms(after - before) << "ms" << endl;
-}
-
int main(int argc, char* argv[]) {
// Register a crash handler
struct sigaction sa;
@@ -127,10 +62,15 @@ int main(int argc, char* argv[]) {
gSigChain.insert(pair<int, struct sigaction>(sig, old_sa));
}
+ // Replace the default GLES driver
+ debug::GlesDriver::replace(std::make_unique<debug::NullGlesDriver>());
+
// Run the tests
testing::InitGoogleTest(&argc, argv);
+ testing::InitGoogleMock(&argc, argv);
+
int ret = RUN_ALL_TESTS();
- checkForLeaks();
+ test::LeakChecker::checkForLeaks();
return ret;
}
diff --git a/libs/hwui/utils/NinePatchImpl.cpp b/libs/hwui/utils/NinePatchImpl.cpp
index 985f3fb66814..2b59ca9266d1 100644
--- a/libs/hwui/utils/NinePatchImpl.cpp
+++ b/libs/hwui/utils/NinePatchImpl.cpp
@@ -111,15 +111,6 @@ void NinePatch::Draw(SkCanvas* canvas, const SkRect& bounds,
const int32_t* xDivs = chunk.getXDivs();
const int32_t* yDivs = chunk.getYDivs();
- // if our SkCanvas were back by GL we should enable this and draw this as
- // a mesh, which will be faster in most cases.
- if ((false)) {
- SkNinePatch::DrawMesh(canvas, bounds, bitmap,
- xDivs, chunk.numXDivs,
- yDivs, chunk.numYDivs,
- paint);
- return;
- }
if (kUseTrace) {
gTrace = true;
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index b3195c4bbbfb..b879f781bce1 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -16,7 +16,6 @@
#include "TestWindowContext.h"
#include "AnimationContext.h"
-#include "DisplayListCanvas.h"
#include "IContextFactory.h"
#include "RecordingCanvas.h"
#include "RenderNode.h"
@@ -28,6 +27,7 @@
#include "gui/Surface.h"
#include "renderthread/RenderProxy.h"
+#include <cutils/memory.h>
namespace {
@@ -57,7 +57,7 @@ class TestWindowContext::TestWindowData {
public:
- TestWindowData(SkISize size) : mSize(size) {
+ explicit TestWindowData(SkISize size) : mSize(size) {
android::BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mCpuConsumer = new android::CpuConsumer(mConsumer, 1);
mCpuConsumer->setName(android::String8("TestWindowContext"));
@@ -86,14 +86,9 @@ public:
mProxy->initialize(mAndroidSurface.get());
float lightX = mSize.width() / 2.0f;
android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
- mProxy->setup(mSize.width(), mSize.height(), 800.0f,
- 255 * 0.075f, 255 * 0.15f);
+ mProxy->setup(800.0f, 255 * 0.075f, 255 * 0.15f);
mProxy->setLightCenter(lightVector);
-#if HWUI_NEW_OPS
mCanvas.reset(new android::uirenderer::RecordingCanvas(mSize.width(), mSize.height()));
-#else
- mCanvas.reset(new android::uirenderer::DisplayListCanvas(mSize.width(), mSize.height()));
-#endif
}
SkCanvas* prepareToDraw() {
@@ -119,8 +114,8 @@ public:
SkImageInfo::Make(mSize.width(), mSize.height(),
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
bmp->allocPixels(destinationConfig);
- sk_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
- mSize.width() * mSize.height());
+ android_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
+ mSize.width() * mSize.height() * 4);
android::CpuConsumer::LockedBuffer nativeBuffer;
android::status_t retval = mCpuConsumer->lockNextBuffer(&nativeBuffer);
@@ -171,11 +166,7 @@ private:
std::unique_ptr<android::uirenderer::RenderNode> mRootNode;
std::unique_ptr<android::uirenderer::renderthread::RenderProxy> mProxy;
-#if HWUI_NEW_OPS
std::unique_ptr<android::uirenderer::RecordingCanvas> mCanvas;
-#else
- std::unique_ptr<android::uirenderer::DisplayListCanvas> mCanvas;
-#endif
android::sp<android::IGraphicBufferProducer> mProducer;
android::sp<android::IGraphicBufferConsumer> mConsumer;
android::sp<android::CpuConsumer> mCpuConsumer;
diff --git a/libs/hwui/utils/VectorDrawableUtils.cpp b/libs/hwui/utils/VectorDrawableUtils.cpp
index ca75c5945b7f..6f0c96db4b1e 100644
--- a/libs/hwui/utils/VectorDrawableUtils.cpp
+++ b/libs/hwui/utils/VectorDrawableUtils.cpp
@@ -198,12 +198,12 @@ static void drawArc(SkPath* p,
/* Solve for intersecting unit circles */
double dsq = dx * dx + dy * dy;
if (dsq == 0.0) {
- ALOGW("Points are coincident");
+ VECTOR_DRAWABLE_LOGD("Points are coincident");
return; /* Points are coincident */
}
double disc = 1.0 / dsq - 1.0 / 4.0;
if (disc < 0.0) {
- ALOGW("Points are too far apart %f", dsq);
+ VECTOR_DRAWABLE_LOGD("Points are too far apart %f", dsq);
float adjust = (float) (sqrt(dsq) / 1.99999);
drawArc(p, x0, y0, x1, y1, a * adjust,
b * adjust, theta, isMoreThanHalf, isPositiveArc);