Merge changes I361741f8,I036b2cd1
* changes:
Revert "SurfaceFlinger: protect state members in Layer"
SF: Latching buffers requires holding mStateLock
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index fade8cf..a2b4da2 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -146,7 +146,21 @@
int binder_become_context_manager(struct binder_state *bs)
{
- return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+ struct flat_binder_object obj;
+ memset(&obj, 0, sizeof(obj));
+ obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+
+ int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+ // fallback to original method
+ if (result != 0) {
+#ifndef VENDORSERVICEMANAGER
+ android_errorWriteLog(0x534e4554, "121035042");
+#endif
+
+ result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+ }
+ return result;
}
int binder_write(struct binder_state *bs, void *data, size_t len)
@@ -240,13 +254,28 @@
#endif
ptr += sizeof(struct binder_ptr_cookie);
break;
+ case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION: {
- struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
- if ((end - ptr) < sizeof(*txn)) {
- ALOGE("parse: txn too small!\n");
- return -1;
+ struct binder_transaction_data_secctx txn;
+ if (cmd == BR_TRANSACTION_SEC_CTX) {
+ if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
+ ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
+ return -1;
+ }
+ memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
+ ptr += sizeof(struct binder_transaction_data_secctx);
+ } else /* BR_TRANSACTION */ {
+ if ((end - ptr) < sizeof(struct binder_transaction_data)) {
+ ALOGE("parse: txn too small (binder_transaction_data)!\n");
+ return -1;
+ }
+ memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
+ ptr += sizeof(struct binder_transaction_data);
+
+ txn.secctx = 0;
}
- binder_dump_txn(txn);
+
+ binder_dump_txn(&txn.transaction_data);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
@@ -254,15 +283,14 @@
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
- bio_init_from_txn(&msg, txn);
- res = func(bs, txn, &msg, &reply);
- if (txn->flags & TF_ONE_WAY) {
- binder_free_buffer(bs, txn->data.ptr.buffer);
+ bio_init_from_txn(&msg, &txn.transaction_data);
+ res = func(bs, &txn, &msg, &reply);
+ if (txn.transaction_data.flags & TF_ONE_WAY) {
+ binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
} else {
- binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+ binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
}
}
- ptr += sizeof(*txn);
break;
}
case BR_REPLY: {
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index c95b33f..70be3b4 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,8 @@
#define _BINDER_H_
#include <sys/ioctl.h>
-#include <linux/android/binder.h>
+
+#include "binder_kernel.h"
struct binder_state;
@@ -42,7 +43,7 @@
};
typedef int (*binder_handler)(struct binder_state *bs,
- struct binder_transaction_data *txn,
+ struct binder_transaction_data_secctx *txn,
struct binder_io *msg,
struct binder_io *reply);
diff --git a/cmds/servicemanager/binder_kernel.h b/cmds/servicemanager/binder_kernel.h
new file mode 100644
index 0000000..19fd773
--- /dev/null
+++ b/cmds/servicemanager/binder_kernel.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BINDER_KERNEL_H
+#define ANDROID_BINDER_KERNEL_H
+
+#include <linux/android/binder.h>
+
+/**
+ * This file exists because the uapi kernel headers in bionic are built
+ * from upstream kernel headers only, and not all of the hwbinder kernel changes
+ * have made it upstream yet. Therefore, the modifications to the
+ * binder header are added locally in this file.
+ */
+
+enum {
+ FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
+};
+
+#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object)
+
+struct binder_transaction_data_secctx {
+ struct binder_transaction_data transaction_data;
+ binder_uintptr_t secctx;
+};
+
+enum {
+ BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+ struct binder_transaction_data_secctx),
+};
+
+
+#endif // ANDROID_BINDER_KERNEL_H
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 79cd6b5..ca004e9 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -61,14 +61,14 @@
static char *service_manager_context;
static struct selabel_handle* sehandle;
-static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
+static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
{
- char *sctx = NULL;
+ char *lookup_sid = NULL;
const char *class = "service_manager";
bool allowed;
struct audit_data ad;
- if (getpidcon(spid, &sctx) < 0) {
+ if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
return false;
}
@@ -77,19 +77,25 @@
ad.uid = uid;
ad.name = name;
- int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
+#ifndef VENDORSERVICEMANAGER
+ if (sid == NULL) {
+ android_errorWriteLog(0x534e4554, "121035042");
+ }
+#endif
+
+ int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
allowed = (result == 0);
- freecon(sctx);
+ freecon(lookup_sid);
return allowed;
}
-static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
+static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
{
- return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
+ return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
}
-static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
+static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
{
bool allowed;
char *tctx = NULL;
@@ -104,12 +110,12 @@
return false;
}
- allowed = check_mac_perms(spid, uid, tctx, perm, name);
+ allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
freecon(tctx);
return allowed;
}
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "add";
@@ -117,19 +123,19 @@
return 0; /* Don't allow apps to register services */
}
- return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}
-static int svc_can_list(pid_t spid, uid_t uid)
+static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "list";
- return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
+ return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
}
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
const char *perm = "find";
- return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+ return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}
struct svcinfo
@@ -175,7 +181,7 @@
};
-uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
{
struct svcinfo *si = find_svc(s, len);
@@ -192,7 +198,7 @@
}
}
- if (!svc_can_find(s, len, spid, uid)) {
+ if (!svc_can_find(s, len, spid, sid, uid)) {
return 0;
}
@@ -200,7 +206,7 @@
}
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
- uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
+ uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
struct svcinfo *si;
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -209,7 +215,7 @@
if (!handle || (len == 0) || (len > 127))
return -1;
- if (!svc_can_register(s, len, spid, uid)) {
+ if (!svc_can_register(s, len, spid, sid, uid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
@@ -248,7 +254,7 @@
}
int svcmgr_handler(struct binder_state *bs,
- struct binder_transaction_data *txn,
+ struct binder_transaction_data_secctx *txn_secctx,
struct binder_io *msg,
struct binder_io *reply)
{
@@ -260,6 +266,8 @@
int allow_isolated;
uint32_t dumpsys_priority;
+ struct binder_transaction_data *txn = &txn_secctx->transaction_data;
+
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
@@ -305,7 +313,8 @@
if (s == NULL) {
return -1;
}
- handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
+ handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
+ (const char*) txn_secctx->secctx);
if (!handle)
break;
bio_put_ref(reply, handle);
@@ -320,7 +329,7 @@
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
- txn->sender_pid))
+ txn->sender_pid, (const char*) txn_secctx->secctx))
return -1;
break;
@@ -328,7 +337,7 @@
uint32_t n = bio_get_uint32(msg);
uint32_t req_dumpsys_priority = bio_get_uint32(msg);
- if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
+ if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 9dc7431..660e3c3 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -284,16 +284,7 @@
} else {
// The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily
// load ANGLE and call the updatable opt-in/out logic:
-
- // Check if ANGLE is enabled. Workaround for several bugs:
- // b/119305693 b/119322355 b/119305887
- // Something is not working correctly in the feature library
- char prop[PROPERTY_VALUE_MAX];
- property_get("debug.angle.enable", prop, "0");
- void* featureSo = nullptr;
- if (atoi(prop)) {
- featureSo = loadLibrary("feature_support");
- }
+ void* featureSo = loadLibrary("feature_support");
if (featureSo) {
ALOGV("loaded ANGLE's opt-in/out logic from namespace");
mUseAngle = checkAngleRules(featureSo);
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index d0a0ac8..94a6650 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -626,6 +626,25 @@
return NO_ERROR;
}
+FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
+ // Translate win by the rounded corners rect coordinates, to have all values in
+ // layer coordinate space.
+ FloatRect cropWin = layer.geometry.boundaries;
+ const FloatRect& roundedCornersCrop = layer.geometry.roundedCornersCrop;
+ cropWin.left -= roundedCornersCrop.left;
+ cropWin.right -= roundedCornersCrop.left;
+ cropWin.top -= roundedCornersCrop.top;
+ cropWin.bottom -= roundedCornersCrop.top;
+ Mesh::VertexArray<vec2> cropCoords(mesh.getCropCoordArray<vec2>());
+ cropCoords[0] = vec2(cropWin.left, cropWin.top);
+ cropCoords[1] = vec2(cropWin.left, cropWin.top + cropWin.getHeight());
+ cropCoords[2] = vec2(cropWin.right, cropWin.top + cropWin.getHeight());
+ cropCoords[3] = vec2(cropWin.right, cropWin.top);
+
+ setupCornerRadiusCropSize(roundedCornersCrop.getWidth(), roundedCornersCrop.getHeight());
+ return cropWin;
+}
+
status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
@@ -714,6 +733,10 @@
setDisplayMaxLuminance(display.maxLuminance);
mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+ mState.projectionMatrix = projectionMatrix;
+ if (!display.clearRegion.isEmpty()) {
+ fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
+ }
Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
for (auto layer : layers) {
@@ -726,6 +749,7 @@
position[2] = vec2(bounds.right, bounds.bottom);
position[3] = vec2(bounds.right, bounds.top);
+ setupLayerCropping(layer, mesh);
setColorTransform(display.colorTransform * layer.colorTransform);
bool usePremultipliedAlpha = true;
@@ -760,7 +784,7 @@
// Buffer sources will have a black solid color ignored in the shader,
// so in that scenario the solid color passed here is arbitrary.
setupLayerBlending(usePremultipliedAlpha, layer.source.buffer.isOpaque, disableTexture,
- color, /*cornerRadius=*/0.0);
+ color, layer.geometry.roundedCornersRadius);
setSourceDataSpace(layer.sourceDataspace);
drawMesh(mesh);
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 2af2aed..511a784 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -128,6 +128,9 @@
// defined by the clip.
void setViewportAndProjection(Rect viewport, Rect clip);
status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence);
+ // Computes the cropping window for the layer and sets up cropping
+ // coordinates for the mesh.
+ FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh);
EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 0c92353..af8de23 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -51,9 +51,10 @@
// to the output dataspace.
mat4 colorTransform = mat4();
- // Region that will be cleared to (0, 0, 0, 0) prior to rendering.
- // clearRegion will first be transformed by globalTransform so that it will
- // be in the same coordinate space as the rendered layers.
+ // Region that will be cleared to (0, 0, 0, 1) prior to rendering.
+ // RenderEngine will transform the clearRegion passed in here, by
+ // globalTransform, so that it will be in the same coordinate space as the
+ // rendered layers.
Region clearRegion = Region::INVALID_REGION;
};
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index a37a163..4d53205 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -69,6 +69,20 @@
// Transform matrix to apply to mesh coordinates.
mat4 positionTransform = mat4();
+
+ // Radius of rounded corners, if greater than 0. Otherwise, this layer's
+ // corners are not rounded.
+ // Having corner radius will force GPU composition on the layer and its children, drawing it
+ // with a special shader. The shader will receive the radius and the crop rectangle as input,
+ // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
+ // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
+ // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
+ // in local layer coordinate space, so we have to take the layer transform into account when
+ // walking up the tree.
+ float roundedCornersRadius = 0.0;
+
+ // Rectangle within which corners will be rounded.
+ FloatRect roundedCornersCrop = FloatRect();
};
// Descriptor of the source pixels for this layer.
@@ -94,11 +108,11 @@
half alpha = half(0.0);
// Color space describing how the source pixels should be interpreted.
- ui::Dataspace sourceDataspace;
+ ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
// Additional layer-specific color transform to be applied before the global
// transform.
- mat4 colorTransform;
+ mat4 colorTransform = mat4();
};
} // namespace renderengine
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index e43ee37..bef25a8 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -172,6 +172,12 @@
template <typename SourceVariant>
void fillBufferColorTransform();
+ template <typename SourceVariant>
+ void fillRedBufferWithRoundedCorners();
+
+ template <typename SourceVariant>
+ void fillBufferWithRoundedCorners();
+
void fillRedBufferTextureTransform();
void fillBufferTextureTransform();
@@ -184,6 +190,12 @@
void fillBufferWithoutPremultiplyAlpha();
+ void fillGreenColorBufferThenClearRegion();
+
+ void clearLeftRegion();
+
+ void fillBufferThenClearRegion();
+
// Dumb hack to get aroud the fact that tear-down for renderengine isn't
// well defined right now, so we can't create multiple instances
static std::unique_ptr<renderengine::RenderEngine> sRE;
@@ -495,6 +507,42 @@
expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
}
+template <typename SourceVariant>
+void RenderEngineTest::fillRedBufferWithRoundedCorners() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings layer;
+ layer.geometry.boundaries = fullscreenRect().toFloatRect();
+ layer.geometry.roundedCornersRadius = 5.0f;
+ layer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
+ SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+ layer.alpha = 1.0f;
+
+ layers.push_back(layer);
+
+ invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferWithRoundedCorners() {
+ fillRedBufferWithRoundedCorners<SourceVariant>();
+ // Corners should be ignored...
+ expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
+ expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
+ DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ 0, 0, 0, 0);
+ // ...And the non-rounded portion should be red.
+ // Other pixels may be anti-aliased, so let's not check those.
+ expectBufferColor(Rect(5, 5, DEFAULT_DISPLAY_WIDTH - 5, DEFAULT_DISPLAY_HEIGHT - 5), 255, 0, 0,
+ 255);
+}
+
void RenderEngineTest::fillRedBufferTextureTransform() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
@@ -623,6 +671,30 @@
expectBufferColor(fullscreenRect(), 128, 0, 0, 64, 1);
}
+void RenderEngineTest::clearLeftRegion() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ // Here logical space is 4x4
+ settings.clip = Rect(4, 4);
+ settings.globalTransform = mat4::scale(vec4(2, 4, 0, 1));
+ settings.clearRegion = Region(Rect(1, 1));
+ std::vector<renderengine::LayerSettings> layers;
+ // dummy layer, without bounds should not render anything
+ renderengine::LayerSettings layer;
+ layers.push_back(layer);
+ invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferThenClearRegion() {
+ fillGreenBuffer<ColorSourceVariant>();
+ // Reuse mBuffer
+ clearLeftRegion();
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 255);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+ DEFAULT_DISPLAY_HEIGHT),
+ 0, 255, 0, 255);
+}
+
TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
drawEmptyLayers();
}
@@ -671,6 +743,10 @@
fillBufferLayerTransform<ColorSourceVariant>();
}
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
+ fillBufferWithRoundedCorners<ColorSourceVariant>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
@@ -715,6 +791,10 @@
fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
+ fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
@@ -759,6 +839,10 @@
fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
+ fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
fillBufferTextureTransform();
}
@@ -771,4 +855,8 @@
fillBufferWithoutPremultiplyAlpha();
}
+TEST_F(RenderEngineTest, drawLayers_fillBufferThenClearRegion) {
+ fillBufferThenClearRegion();
+}
+
} // namespace android
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 0582e1a..1184960 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -64,7 +64,6 @@
using BufferHubDefs::AnyClientAcquired;
using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
using BufferHubDefs::IsClientAcquired;
using BufferHubDefs::IsClientGained;
using BufferHubDefs::IsClientPosted;
@@ -226,8 +225,7 @@
int BufferHubBuffer::Post() {
uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- uint32_t current_active_clients_bit_mask = 0U;
- uint32_t updated_buffer_state = 0U;
+ uint32_t updated_buffer_state = (~mClientStateMask) & kHighBitsMask;
do {
if (!IsClientGained(current_buffer_state, mClientStateMask)) {
ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
@@ -236,9 +234,7 @@
return -EBUSY;
}
// Set the producer client buffer state to released, other clients' buffer state to posted.
- current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire);
- updated_buffer_state =
- current_active_clients_bit_mask & (~mClientStateMask) & kHighBitsMask;
+ // Post to all existing and non-existing clients.
} while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
std::memory_order_acq_rel,
std::memory_order_acquire));
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 1b339a0..69b9590 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -67,9 +67,9 @@
}
std::unique_ptr<BufferHubBuffer> b1;
- uint64_t b1ClientMask = 0U;
+ uint32_t b1ClientMask = 0U;
std::unique_ptr<BufferHubBuffer> b2;
- uint64_t b2ClientMask = 0U;
+ uint32_t b2ClientMask = 0U;
private:
// Creates b1 and b2 as the clients of the same buffer for testing.
@@ -125,7 +125,7 @@
auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
int id1 = b1->id();
- uint64_t bufferStateMask1 = b1->client_state_mask();
+ uint32_t bufferStateMask1 = b1->client_state_mask();
EXPECT_NE(bufferStateMask1, 0U);
EXPECT_TRUE(b1->IsValid());
EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
@@ -148,7 +148,7 @@
EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
int id2 = b2->id();
- uint64_t bufferStateMask2 = b2->client_state_mask();
+ uint32_t bufferStateMask2 = b2->client_state_mask();
EXPECT_NE(bufferStateMask2, 0U);
// These two buffer instances are based on the same physical buffer under the
@@ -340,5 +340,53 @@
EXPECT_EQ(b2->Release(), 0);
}
+TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) {
+ // 1 producer buffer and 1 consumer buffer initialised in testcase setup.
+ // Test if this set of basic operation succeed:
+ // Producer post three times to the consumer, and released by consumer.
+ for (int i = 0; i < 3; ++i) {
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b2->Acquire(), 0);
+ ASSERT_EQ(b2->Release(), 0);
+ }
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) {
+ // Create a poducer buffer and gain.
+ std::unique_ptr<BufferHubBuffer> b1 =
+ BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ kUserMetadataSize);
+ ASSERT_EQ(b1->Gain(), 0);
+
+ // Create a consumer of the buffer and test if the consumer can acquire the
+ // buffer if producer posts.
+ auto statusOrHandle = b1->Duplicate();
+ ASSERT_TRUE(statusOrHandle);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(statusOrHandle.take()));
+ ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+ ASSERT_EQ(b1->Post(), 0);
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) {
+ // Create a poducer buffer and post.
+ std::unique_ptr<BufferHubBuffer> b1 =
+ BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ kUserMetadataSize);
+ ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->Post(), 0);
+
+ // Create a consumer of the buffer and test if the consumer can acquire the
+ // buffer if producer posts.
+ auto statusOrHandle = b1->Duplicate();
+ ASSERT_TRUE(statusOrHandle);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(statusOrHandle.take()));
+ ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+ EXPECT_EQ(b2->Acquire(), 0);
+}
+
} // namespace
} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 1359f4c..487a604 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -361,9 +361,11 @@
ASSERT_TRUE(p.get() != nullptr);
ASSERT_EQ(0, p->GainAsync());
ASSERT_EQ(0, p->Post(LocalHandle()));
- // Producer state bit is in released state after post. The overall state of
- // the buffer is also released because there is no consumer of this buffer.
- ASSERT_TRUE(IsBufferReleased(p->buffer_state()));
+ // Producer state bit is in released state after post, other clients shall be
+ // in posted state although there is no consumer of this buffer yet.
+ ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+ ASSERT_FALSE(IsBufferReleased(p->buffer_state()));
+ ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
// Gain in released state should succeed.
LocalHandle invalid_fence;
@@ -450,27 +452,17 @@
LocalHandle invalid_fence;
// Post the gained buffer before any consumer gets created.
- // The buffer should be in released state because it is not expected to be
- // read by any clients.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+ EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
- // Newly created consumer will not be signalled for the posted buffer before
- // its creation. It cannot acquire the buffer immediately.
+ // Newly created consumer will be signalled for the posted buffer although it
+ // is created after producer posting.
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
- EXPECT_FALSE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
- EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
-
- // Producer should be able to gain back and post the buffer
- EXPECT_EQ(0, p->GainAsync());
- EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-
- // Consumer should be able to pick up the buffer this time.
+ EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
- EXPECT_TRUE(IsClientAcquired(c->buffer_state(), c->client_state_mask()));
}
TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 440a59d..889763a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -94,6 +94,12 @@
return buffer_state_->load(std::memory_order_acquire);
};
+ // Returns whether the buffer is already released by all current clients.
+ bool is_released() {
+ return (buffer_state() &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
+ }
+
// A state mask which is unique to a buffer hub client among all its siblings
// sharing the same concrete graphic buffer.
uint32_t client_state_mask() const { return client_state_mask_; }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 5274bf2..edfdddf 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -89,13 +89,10 @@
return -EBUSY;
}
- // Set the producer client buffer state to released, other clients' buffer
- // state to posted.
- uint32_t current_active_clients_bit_mask =
- active_clients_bit_mask_->load(std::memory_order_acquire);
- uint32_t updated_buffer_state = current_active_clients_bit_mask &
- (~client_state_mask()) &
- BufferHubDefs::kHighBitsMask;
+ // Set the producer client buffer state to released, that of all other clients
+ // (both existing and non-existing clients) to posted.
+ uint32_t updated_buffer_state =
+ (~client_state_mask()) & BufferHubDefs::kHighBitsMask;
while (!buffer_state_->compare_exchange_weak(
current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
std::memory_order_acquire)) {
@@ -176,7 +173,9 @@
}
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
current_buffer_state);
@@ -198,7 +197,9 @@
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+ (BufferHubDefs::AnyClientPosted(
+ current_buffer_state &
+ active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
ALOGE(
"%s: Failed to gain the buffer. The buffer is no longer released. "
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c80b79a..25958e2 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -208,6 +208,7 @@
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv2\""],
+ version_script: "libGLESv2.map.txt",
}
//##############################################################################
@@ -218,4 +219,5 @@
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv3\""],
+ version_script: "libGLESv3.map.txt",
}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 297e0c4..00caff2 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -106,7 +106,7 @@
.flags = ANDROID_DLEXT_USE_NAMESPACE,
.library_namespace = ns,
};
- void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ void* so = android_dlopen_ext("libGLESv2_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
angleGetDisplayPlatform =
reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
diff --git a/opengl/libs/libGLESv1_CM.map.txt b/opengl/libs/libGLESv1_CM.map.txt
index 8ba91e6..41bf4ca 100644
--- a/opengl/libs/libGLESv1_CM.map.txt
+++ b/opengl/libs/libGLESv1_CM.map.txt
@@ -179,6 +179,7 @@
glLoadPaletteFromModelViewMatrixOES;
glLogicOp;
glMapBufferOES;
+ glMapBufferRangeEXT;
glMaterialf;
glMaterialfv;
glMaterialx;
diff --git a/opengl/libs/libGLESv2.map.txt b/opengl/libs/libGLESv2.map.txt
index 787c835..844d1e2 100644
--- a/opengl/libs/libGLESv2.map.txt
+++ b/opengl/libs/libGLESv2.map.txt
@@ -1,19 +1,28 @@
LIBGLESV2 {
global:
+ glActiveShaderProgramEXT;
glActiveTexture;
glAttachShader;
+ glBeginQueryEXT;
glBeginPerfMonitorAMD;
glBindAttribLocation;
glBindBuffer;
+ glBindFragDataLocationEXT; # introduced=24
+ glBindFragDataLocationIndexedEXT; # introduced=24
glBindFramebuffer;
+ glBindProgramPipelineEXT;
glBindRenderbuffer;
glBindTexture;
glBindVertexArrayOES; # introduced-mips=9 introduced-x86=9
glBlendColor;
glBlendEquation;
+ glBlendEquationiOES; # introduced=24
glBlendEquationSeparate;
+ glBlendEquationSeparateiOES; # introduced=24
glBlendFunc;
+ glBlendFunciOES; # introduced=24
glBlendFuncSeparate;
+ glBlendFuncSeparateiOES; # introduced=24
glBufferData;
glBufferSubData;
glCheckFramebufferStatus;
@@ -22,6 +31,7 @@
glClearDepthf;
glClearStencil;
glColorMask;
+ glColorMaskiOES; # introduced=24
glCompileShader;
glCompressedTexImage2D;
glCompressedTexImage3DOES;
@@ -34,12 +44,16 @@
glCoverageOperationNV; # introduced-mips=9 introduced-x86=9
glCreateProgram;
glCreateShader;
+ glCreateShaderProgramvEXT;
glCullFace;
+ glDebugMessageCallbackKHR; # introduced=21
glDeleteBuffers;
glDeleteFencesNV;
glDeleteFramebuffers;
glDeletePerfMonitorsAMD;
glDeleteProgram;
+ glDeleteProgramPipelinesEXT;
+ glDeleteQueriesEXT;
glDeleteRenderbuffers;
glDeleteShader;
glDeleteTextures;
@@ -49,17 +63,32 @@
glDepthRangef;
glDetachShader;
glDisable;
+ glDisableiOES; # introduced=24
glDisableDriverControlQCOM;
glDisableVertexAttribArray;
glDiscardFramebufferEXT; # introduced-mips=9 introduced-x86=9
glDrawArrays;
+ glDrawArraysInstancedBaseInstanceEXT; # introduced=24
+ glDrawArraysInstancedEXT; # introduced=21
+ glDrawBuffersEXT; # introduced=21
+ glDrawBuffersIndexedEXT; # introduced=21
glDrawElements;
+ glDrawElementsBaseVertexEXT; # introduced=24
+ glDrawElementsBaseVertexOES; # introduced=24
+ glDrawElementsInstancedBaseInstanceEXT; # introduced=24
+ glDrawElementsInstancedBaseVertexEXT; # introduced=24
+ glDrawElementsInstancedBaseVertexOES; # introduced=24
+ glDrawElementsInstancedBaseVertexBaseInstanceEXT; # introduced=24
+ glDrawRangeElementsBaseVertexEXT; # introduced=24
+ glDrawRangeElementsBaseVertexOES; # introduced=24
glEGLImageTargetRenderbufferStorageOES;
glEGLImageTargetTexture2DOES;
glEnable;
+ glEnableiOES; # introduced=24
glEnableDriverControlQCOM;
glEnableVertexAttribArray;
glEndPerfMonitorAMD;
+ glEndQueryEXT;
glEndTilingQCOM; # introduced-mips=9 introduced-x86=9
glExtGetBufferPointervQCOM; # introduced-mips=9 introduced-x86=9
glExtGetBuffersQCOM; # introduced-mips=9 introduced-x86=9
@@ -76,17 +105,20 @@
glFinish;
glFinishFenceNV;
glFlush;
+ glFlushMappedBufferRangeEXT; # introduced=21
glFramebufferRenderbuffer;
glFramebufferTexture2D;
glFramebufferTexture2DMultisampleIMG; # introduced-mips=9 introduced-x86=9
glFramebufferTexture2DMultisampleEXT; # introduced=28
glFramebufferTexture3DOES;
+ glFramebufferTextureOES; # introduced=24
glFrontFace;
glGenBuffers;
glGenFencesNV;
glGenFramebuffers;
glGenPerfMonitorsAMD;
glGenRenderbuffers;
+ glGenQueriesEXT;
glGenTextures;
glGenVertexArraysOES; # introduced-mips=9 introduced-x86=9
glGenerateMipmap;
@@ -102,24 +134,49 @@
glGetError;
glGetFenceivNV;
glGetFloatv;
+ glGetFragDataIndexEXT; # introduced=24
glGetFramebufferAttachmentParameteriv;
+ glGetGraphicsResetStatusEXT;
+ glGetGraphicsResetStatusKHR; # introduced=24
+ glGetIntegeri_vEXT; # introduced=21
glGetIntegerv;
+ glGetnUniformfvEXT;
+ glGetnUniformfvKHR; # introduced=24
+ glGetnUniformivEXT;
+ glGetnUniformivKHR; # introduced=24
+ glGetnUniformuivKHR; # introduced=24
+ glGetObjectLabelEXT;
+ glCopyImageSubDataOES; # introduced=24
glGetPerfMonitorCounterDataAMD;
glGetPerfMonitorCounterInfoAMD;
glGetPerfMonitorCounterStringAMD;
glGetPerfMonitorCountersAMD;
glGetPerfMonitorGroupStringAMD;
glGetPerfMonitorGroupsAMD;
+ glGetPointervKHR; # introduced=21
glGetProgramBinaryOES;
glGetProgramInfoLog;
glGetProgramiv;
+ glGenProgramPipelinesEXT;
+ glGetProgramPipelineInfoLogEXT;
+ glGetProgramPipelineivEXT;
+ glGetProgramResourceLocationIndexEXT; # introduced=24
+ glGetQueryivEXT;
+ glGetQueryObjectivEXT; # introduced=21
+ glGetQueryObjectuivEXT;
+ glGetQueryObjecti64vEXT; # introduced=21
+ glGetQueryObjectui64vEXT; # introduced=21
glGetRenderbufferParameteriv;
+ glGetSamplerParameterIivOES; # introduced=24
+ glGetSamplerParameterIuivOES; # introduced=24
glGetShaderInfoLog;
glGetShaderPrecisionFormat;
glGetShaderSource;
glGetShaderiv;
glGetString;
glGetTexParameterfv;
+ glGetTexParameterIivOES; # introduced=24
+ glGetTexParameterIuivOES; # introduced=24
glGetTexParameteriv;
glGetUniformLocation;
glGetUniformfv;
@@ -128,29 +185,83 @@
glGetVertexAttribfv;
glGetVertexAttribiv;
glHint;
+ glInsertEventMarkerEXT;
glIsBuffer;
glIsEnabled;
+ glIsEnablediOES; # introduced=24
glIsFenceNV;
glIsFramebuffer;
glIsProgram;
+ glIsProgramPipelineEXT;
+ glIsQueryEXT;
glIsRenderbuffer;
glIsShader;
glIsTexture;
glIsVertexArrayOES; # introduced-mips=9 introduced-x86=9
+ glLabelObjectEXT;
glLineWidth;
glLinkProgram;
glMapBufferOES;
glMultiDrawArraysEXT; # introduced-mips=9 introduced-x86=9
+ glMultiDrawArraysIndirectEXT; # introduced=24
+ glMultiDrawElementsIndirectEXT; # introduced=24
+ glMultiDrawElementsBaseVertexEXT; # introduced=24
+ glDrawElementsInstancedEXT; # introduced=21
glMultiDrawElementsEXT; # introduced-mips=9 introduced-x86=9
+ glPatchParameteriOES; # introduced=24
glPixelStorei;
glPolygonOffset;
+ glPopGroupMarkerEXT; # introduced=21
+ glPrimitiveBoundingBoxOES; # introduced=24
glProgramBinaryOES;
+ glProgramParameteriEXT;
+ glProgramUniform1fEXT;
+ glProgramUniform1fvEXT;
+ glProgramUniform1iEXT;
+ glProgramUniform1ivEXT;
+ glProgramUniform1uiEXT; # introduced=21
+ glProgramUniform1uivEXT; # introduced=21
+ glProgramUniform2fEXT;
+ glProgramUniform2fvEXT;
+ glProgramUniform2iEXT;
+ glProgramUniform2ivEXT;
+ glProgramUniform2uiEXT; # introduced=21
+ glProgramUniform2uivEXT; # introduced=21
+ glProgramUniform3fEXT;
+ glProgramUniform3fvEXT;
+ glProgramUniform3iEXT;
+ glProgramUniform3ivEXT;
+ glProgramUniform3uiEXT; # introduced=21
+ glProgramUniform3uivEXT; # introduced=21
+ glProgramUniform4fEXT;
+ glProgramUniform4fvEXT;
+ glProgramUniform4iEXT;
+ glProgramUniform4ivEXT;
+ glProgramUniform4uiEXT; # introduced=21
+ glProgramUniform4uivEXT; # introduced=21
+ glProgramUniformMatrix2fvEXT;
+ glProgramUniformMatrix2x3fvEXT; # introduced=21
+ glProgramUniformMatrix2x4fvEXT; # introduced=21
+ glProgramUniformMatrix3fvEXT;
+ glProgramUniformMatrix3x2fvEXT; # introduced=21
+ glProgramUniformMatrix3x4fvEXT; # introduced=21
+ glProgramUniformMatrix4fvEXT;
+ glProgramUniformMatrix4x2fvEXT; # introduced=21
+ glProgramUniformMatrix4x3fvEXT; # introduced=21
+ glPushGroupMarkerEXT;
+ glQueryCounterEXT; # introduced=21
+ glRasterSamplesEXT; # introduced=24
+ glReadBufferIndexedEXT; # introduced=21
+ glReadnPixelsEXT;
+ glReadnPixelsKHR; # introduced=24
glReadPixels;
glReleaseShaderCompiler;
glRenderbufferStorage;
glRenderbufferStorageMultisampleEXT; # introduced=28
glRenderbufferStorageMultisampleIMG; # introduced-mips=9 introduced-x86=9
glSampleCoverage;
+ glSamplerParameterIivOES; # introduced=24
+ glSamplerParameterIuivOES; # introduced=24
glScissor;
glSelectPerfMonitorCountersAMD;
glSetFenceNV;
@@ -164,14 +275,27 @@
glStencilOp;
glStencilOpSeparate;
glTestFenceNV;
+ glTexBufferOES; # introduced=24
+ glTexBufferRangeOES; # introduced=24
glTexImage2D;
glTexImage3DOES;
+ glTexPageCommitmentEXT; # introduced=24
glTexParameterf;
glTexParameterfv;
glTexParameteri;
+ glTexParameterIivOES; # introduced=24
+ glTexParameterIuivOES; # introduced=24
glTexParameteriv;
+ glTexStorage1DEXT;
+ glTexStorage2DEXT;
+ glTexStorage3DEXT;
glTexSubImage2D;
glTexSubImage3DOES;
+ glTextureStorage1DEXT;
+ glTextureStorage2DEXT;
+ glTextureStorage3DEXT;
+ glTextureViewEXT; # introduced=21
+ glTextureViewOES; # introduced=24
glUniform1f;
glUniform1fv;
glUniform1i;
@@ -193,7 +317,11 @@
glUniformMatrix4fv;
glUnmapBufferOES;
glUseProgram;
+ glUseProgramStagesEXT;
glValidateProgram;
+ glValidateProgramPipelineEXT;
+ glVertexAttribDivisorANGLE; # introduced=21
+ glVertexAttribDivisorEXT; # introduced=21
glVertexAttrib1f;
glVertexAttrib1fv;
glVertexAttrib2f;
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 2a6e9da..409bce9 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -369,7 +369,9 @@
(consumer_state_mask & BufferHubDefs::kHighBitsMask);
}
}
- if (update_buffer_state) {
+ if (update_buffer_state || BufferHubDefs::IsClientPosted(
+ buffer_state_->load(std::memory_order_acquire),
+ consumer_state_mask)) {
consumer->OnProducerPosted();
}
@@ -537,8 +539,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
if (orphaned_consumer_bit_mask_) {
ALOGW(
@@ -564,8 +571,13 @@
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
+ uint32_t current_active_clients_bit_mask =
+ active_clients_bit_mask_->load(std::memory_order_acquire);
+ // Signal producer if all current active consumers have released the buffer.
if (BufferHubDefs::IsBufferReleased(current_buffer_state &
- ~orphaned_consumer_bit_mask_)) {
+ ~orphaned_consumer_bit_mask_ &
+ current_active_clients_bit_mask)) {
+ buffer_state_->store(0U);
SignalAvailable();
}