Export libui_headers as vndk header library am: 5f81367c6f am: 1744c252d6
am: 9fd37ff364  -s ours

Change-Id: I2ab825e03fc1573f72e7a865e6786bea72cfc42d
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.cpp b/shared/OpenglCodecCommon/GLSharedGroup.cpp
index 9da011a..19dfe0f 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -180,7 +180,7 @@
     for (GLuint i = 0; i < m_numIndexes; i++) {
         GLint elemIndex = appLoc - m_Indexes[i].appBase;
         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
-            if (m_Indexes[i].type == GL_TEXTURE_2D) {
+            if (m_Indexes[i].type == GL_SAMPLER_2D) {
                 m_Indexes[i].samplerValue = val;
                 if (target) {
                     if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
diff --git a/shared/OpenglCodecCommon/glUtils.cpp b/shared/OpenglCodecCommon/glUtils.cpp
index 7e5e4a2..baa7c23 100644
--- a/shared/OpenglCodecCommon/glUtils.cpp
+++ b/shared/OpenglCodecCommon/glUtils.cpp
@@ -125,6 +125,8 @@
     case GL_DEPTH_FUNC:
     case GL_DEPTH_BITS:
     case GL_MAX_CLIP_PLANES:
+    case GL_MAX_COLOR_ATTACHMENTS:
+    case GL_MAX_DRAW_BUFFERS:
     case GL_GREEN_BITS:
     case GL_MAX_MODELVIEW_STACK_DEPTH:
     case GL_MAX_PROJECTION_STACK_DEPTH:
@@ -243,14 +245,18 @@
     case GL_STENCIL_BACK_PASS_DEPTH_PASS:
     case GL_STENCIL_BACK_WRITEMASK:
     case GL_TEXTURE_2D:
+    case GL_TEXTURE_BASE_LEVEL:
     case GL_TEXTURE_BINDING_2D:
     case GL_TEXTURE_BINDING_CUBE_MAP:
     case GL_TEXTURE_BINDING_EXTERNAL_OES:
+    case GL_TEXTURE_COMPARE_FUNC:
+    case GL_TEXTURE_COMPARE_MODE:
     case GL_TEXTURE_COORD_ARRAY:
     case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
     case GL_TEXTURE_COORD_ARRAY_SIZE:
     case GL_TEXTURE_COORD_ARRAY_STRIDE:
     case GL_TEXTURE_COORD_ARRAY_TYPE:
+    case GL_TEXTURE_IMMUTABLE_FORMAT:
     case GL_UNPACK_ALIGNMENT:
     case GL_VERTEX_ARRAY:
     case GL_VERTEX_ARRAY_BUFFER_BINDING:
@@ -260,8 +266,15 @@
     case GL_SPOT_CUTOFF:
     case GL_TEXTURE_MIN_FILTER:
     case GL_TEXTURE_MAG_FILTER:
+    case GL_TEXTURE_MAX_LOD:
+    case GL_TEXTURE_MIN_LOD:
     case GL_TEXTURE_WRAP_S:
     case GL_TEXTURE_WRAP_T:
+    case GL_TEXTURE_WRAP_R:
+    case GL_TEXTURE_SWIZZLE_R:
+    case GL_TEXTURE_SWIZZLE_G:
+    case GL_TEXTURE_SWIZZLE_B:
+    case GL_TEXTURE_SWIZZLE_A:
     case GL_GENERATE_MIPMAP:
     case GL_GENERATE_MIPMAP_HINT:
     case GL_RENDERBUFFER_WIDTH_OES:
@@ -303,6 +316,8 @@
     case GL_SHADER_SOURCE_LENGTH:
     case GL_CURRENT_PROGRAM:
     case GL_SUBPIXEL_BITS:
+    case GL_MAX_3D_TEXTURE_SIZE:
+    case GL_MAX_ARRAY_TEXTURE_LAYERS:
     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
     case GL_NUM_SHADER_BINARY_FORMATS:
     case GL_SHADER_COMPILER:
@@ -327,10 +342,13 @@
     case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
     case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
     case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+    case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
     case GL_CURRENT_QUERY:
     case GL_QUERY_RESULT:
     case GL_QUERY_RESULT_AVAILABLE:
     case GL_READ_BUFFER:
+    case GL_NUM_PROGRAM_BINARY_FORMATS:
+    case GL_PROGRAM_BINARY_FORMATS:
 
     case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
     case GL_ACTIVE_ATTRIBUTES:
@@ -343,6 +361,7 @@
     case GL_DELETE_STATUS:
     case GL_INFO_LOG_LENGTH:
     case GL_LINK_STATUS:
+    case GL_PROGRAM_BINARY_LENGTH:
     case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
     case GL_PROGRAM_SEPARABLE:
     case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 39e4cda..0e72478 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -195,6 +195,8 @@
     OVERRIDEOES(glDeleteVertexArrays);
     OVERRIDEOES(glBindVertexArray);
 
+    OVERRIDE_CUSTOM(glMapBufferOES);
+    OVERRIDE_CUSTOM(glUnmapBufferOES);
     OVERRIDE_CUSTOM(glMapBufferRange);
     OVERRIDE_CUSTOM(glUnmapBuffer);
     OVERRIDE_CUSTOM(glFlushMappedBufferRange);
@@ -2579,6 +2581,27 @@
     state->setVertexArrayObject(array);
 }
 
+void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+
+    RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
+
+    GLuint boundBuffer = ctx->m_state->getBuffer(target);
+
+    RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
+
+    BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
+    RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
+
+    return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
+}
+
+GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+
+    return ctx->glUnmapBuffer(ctx, target);
+}
+
 void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
     GL2Encoder* ctx = (GL2Encoder*)self;
     GLClientState* state = ctx->m_state;
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 3084713..0cb6630 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -391,6 +391,8 @@
     static void s_glBindVertexArray(void *self , GLuint array);
 
     // Mapped buffers
+    static void* s_glMapBufferOES(void* self, GLenum target, GLenum access);
+    static GLboolean s_glUnmapBufferOES(void* self, GLenum target);
     static void* s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
     static GLboolean s_glUnmapBuffer(void* self, GLenum target);
     static void s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length);
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index ce89021..0b5304f 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -233,8 +233,10 @@
 #if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__))
     rcEnc->setSyncImpl(SYNC_IMPL_NONE);
 #else
-    if (glExtensions.find(kRCNativeSync) != std::string::npos) {
-        rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC);
+    if (glExtensions.find(kRCNativeSyncV3) != std::string::npos) {
+        rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3);
+    } else if (glExtensions.find(kRCNativeSyncV2) != std::string::npos) {
+        rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2);
     } else {
         rcEnc->setSyncImpl(SYNC_IMPL_NONE);
     }
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 25d42d6..0924cf9 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -40,16 +40,15 @@
 // capability, and we will use a fence fd to synchronize buffer swaps.
 enum SyncImpl {
     SYNC_IMPL_NONE = 0,
-    SYNC_IMPL_NATIVE_SYNC = 1
+    SYNC_IMPL_NATIVE_SYNC_V2 = 1,
+    SYNC_IMPL_NATIVE_SYNC_V3 = 2,
 };
 
 // Interface:
-// If this GL extension string shows up, we use
-// SYNC_IMPL_NATIVE_SYNC, otherwise we use SYNC_IMPL_NONE.
-// This string is always updated to require the _latest_
-// version of Android emulator native sync in this system image;
-// otherwise, we do not use the feature.
-static const char kRCNativeSync[] = "ANDROID_EMU_native_sync_v2";
+// Use the highest of v2 or v3 that show up, making us
+// SYNC_IMPL_NATIVE_SYNC_V2 or SYNC_IMPL_NATIVE_SYNC_V3.
+static const char kRCNativeSyncV2[] = "ANDROID_EMU_native_sync_v2";
+static const char kRCNativeSyncV3[] = "ANDROID_EMU_native_sync_v3";
 
 // DMA for OpenGL
 enum DmaImpl {
@@ -82,7 +81,8 @@
         }
     void setSyncImpl(SyncImpl syncImpl) { m_syncImpl = syncImpl; }
     void setDmaImpl(DmaImpl dmaImpl) { m_dmaImpl = dmaImpl; }
-    bool hasNativeSync() const { return m_syncImpl == SYNC_IMPL_NATIVE_SYNC; }
+    bool hasNativeSync() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V2; }
+    bool hasNativeSyncV3() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V3; }
     DmaImpl getDmaVersion() const { return m_dmaImpl; }
     void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
     virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 185fbc9..9500fef 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -282,7 +282,9 @@
 
     virtual     void setCollectingTimestamps(EGLint collect) { }
     virtual     EGLint isCollectingTimestamps() const { return EGL_FALSE; }
-
+    EGLint      deletePending;
+    void        setIsCurrent(bool isCurrent) { mIsCurrent = isCurrent; }
+    bool        isCurrent() const { return mIsCurrent;}
 private:
     //
     //Surface attributes
@@ -296,7 +298,7 @@
     // Give it some default values.
     int nativeWidth;
     int nativeHeight;
-
+    bool mIsCurrent;
 protected:
     void        setWidth(EGLint w)  { width = w;  }
     void        setHeight(EGLint h) { height = h; }
@@ -308,7 +310,8 @@
 };
 
 egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
-    : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
+    : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0),
+      deletePending(0), mIsCurrent(false)
 {
     width = 0;
     height = 0;
@@ -603,6 +606,29 @@
     }
 }
 
+// Destroy a pending surface and set it to NULL.
+
+static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
+    egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
+    if (surf && surf->deletePending) {
+        delete surf;
+        *surface = NULL;
+    }
+}
+
+static void s_destroyPendingSurfacesInContext(EGLContext_t* context) {
+    if (context->read == context->draw) {
+        // If they are the same, delete it only once
+        s_destroyPendingSurfaceAndSetNull(&context->draw);
+        if (context->draw == NULL) {
+            context->read = NULL;
+        }
+    } else {
+        s_destroyPendingSurfaceAndSetNull(&context->draw);
+        s_destroyPendingSurfaceAndSetNull(&context->read);
+    }
+}
+
 EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
 {
     DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
@@ -984,8 +1010,13 @@
     VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
     VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
 
+    EGLThreadInfo* tInfo = getEGLThreadInfo();
     egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
-    delete surface;
+    if (surface->isCurrent()) {
+        surface->deletePending = 1;
+    } else {
+        delete surface;
+    }
 
     return EGL_TRUE;
 }
@@ -1160,6 +1191,9 @@
     // anyway once we are on the host, so skip rcMakeCurrent here.
     // rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
     context->flags &= ~EGLContext_t::IS_CURRENT;
+
+    s_destroyPendingSurfacesInContext(context);
+
     if (context->deletePending) {
         if (context->rcContext) {
             rcEnc->rcDestroyContext(rcEnc, context->rcContext);
@@ -1352,7 +1386,12 @@
             }
             reset_notification_strategy = attrib_val;
             break;
+        case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+            // According to the spec, we are allowed not to honor this hint.
+            // https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
+            break;
         default:
+            ALOGV("eglCreateContext unsupported attrib 0x%x", attrib_list[0]);
             setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
         }
         attrib_list+=2;
@@ -1474,8 +1513,8 @@
 
     if (!context) return EGL_TRUE;
 
-    if (getEGLThreadInfo()->currentContext == context) {
-        getEGLThreadInfo()->currentContext->deletePending = 1;
+    if (context->flags & EGLContext_t::IS_CURRENT) {
+        context->deletePending = 1;
         return EGL_TRUE;
     }
 
@@ -1522,11 +1561,20 @@
         return EGL_TRUE;
     }
 
-    if (tInfo->currentContext && tInfo->currentContext->deletePending) {
-        if (tInfo->currentContext != context) {
-            EGLContext_t * contextToDelete = tInfo->currentContext;
+    if (tInfo->currentContext) {
+        EGLContext_t* prevCtx = tInfo->currentContext;
+
+        if (prevCtx->draw) {
+            static_cast<egl_surface_t *>(prevCtx->draw)->setIsCurrent(false);
+        }
+        if (prevCtx->read) {
+            static_cast<egl_surface_t *>(prevCtx->read)->setIsCurrent(false);
+        }
+        s_destroyPendingSurfacesInContext(tInfo->currentContext);
+
+        if (prevCtx->deletePending && prevCtx != context) {
             tInfo->currentContext = 0;
-            eglDestroyContext(dpy, contextToDelete);
+            eglDestroyContext(dpy, prevCtx);
         }
     }
 
@@ -1551,6 +1599,12 @@
         hostCon->setGrallocOnly(false);
         context->draw = draw;
         context->read = read;
+        if (drawSurf) {
+            drawSurf->setIsCurrent(true);
+        }
+        if (readSurf) {
+            readSurf->setIsCurrent(true);
+        }
         context->flags |= EGLContext_t::IS_CURRENT;
         GLClientState* contextState =
             context->getClientState();
@@ -2097,10 +2151,24 @@
     }
 }
 
-// TODO: Implement EGL_KHR_wait_sync
 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
     (void)dpy;
-    (void)eglsync;
-    (void)flags;
+
+    if (!eglsync) {
+        ALOGE("%s: null sync object!", __FUNCTION__);
+        return EGL_FALSE;
+    }
+
+    if (flags) {
+        ALOGE("%s: flags must be 0, got 0x%x", __FUNCTION__, flags);
+        return EGL_FALSE;
+    }
+
+    DEFINE_HOST_CONNECTION;
+    if (rcEnc->hasNativeSyncV3()) {
+        EGLSync_t* sync = (EGLSync_t*)eglsync;
+        rcEnc->rcWaitSyncKHR(rcEnc, sync->handle, flags);
+    }
+
     return EGL_TRUE;
 }
diff --git a/system/egl/eglDisplay.cpp b/system/egl/eglDisplay.cpp
index c7ff179..e2fb279 100644
--- a/system/egl/eglDisplay.cpp
+++ b/system/egl/eglDisplay.cpp
@@ -33,6 +33,7 @@
 
 // extensions to add dynamically depending on host-side support
 static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync ";
+static const char kDynamicEGLExtWaitSync[] = "EGL_KHR_wait_sync ";
 
 static void *s_gles_lib = NULL;
 static void *s_gles2_lib = NULL;
@@ -347,6 +348,10 @@
         if (hcon->rcEncoder()->hasNativeSync() &&
             !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) {
             dynamicEGLExtensions += kDynamicEGLExtNativeSync;
+
+            if (hcon->rcEncoder()->hasNativeSyncV3()) {
+                dynamicEGLExtensions += kDynamicEGLExtWaitSync;
+            }
         }
 
         asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str());
diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp
index 3a1d2dd..e45bf63 100644
--- a/system/gralloc/gralloc.cpp
+++ b/system/gralloc/gralloc.cpp
@@ -118,6 +118,7 @@
 
 struct gralloc_memregions_t {
     MemRegionSet ashmemRegions;
+    pthread_mutex_t lock;
 };
 
 #define INITIAL_DMA_REGION_SIZE 4096
@@ -126,15 +127,17 @@
     uint32_t sz;
     uint32_t refcount;
     pthread_mutex_t lock;
+    uint32_t bigbufCount;
 };
 
 // global device instance
-static gralloc_memregions_t* s_grdev = NULL;
+static gralloc_memregions_t* s_memregions = NULL;
 static gralloc_dmaregion_t* s_grdma = NULL;
 
 void init_gralloc_memregions() {
-    if (s_grdev) return;
-    s_grdev = new gralloc_memregions_t;
+    if (s_memregions) return;
+    s_memregions = new gralloc_memregions_t;
+    pthread_mutex_init(&s_memregions->lock, NULL);
 }
 
 void init_gralloc_dmaregion() {
@@ -144,6 +147,7 @@
     s_grdma = new gralloc_dmaregion_t;
     s_grdma->sz = INITIAL_DMA_REGION_SIZE;
     s_grdma->refcount = 0;
+    s_grdma->bigbufCount = 0;
 
     pthread_mutex_init(&s_grdma->lock, NULL);
     pthread_mutex_lock(&s_grdma->lock);
@@ -169,11 +173,18 @@
     s_grdma->sz = new_sz;
 }
 
-bool put_gralloc_dmaregion() {
+// max dma size: 2x 4K rgba8888
+#define MAX_DMA_SIZE 66355200
+
+bool put_gralloc_dmaregion(uint32_t sz) {
     if (!s_grdma) return false;
     pthread_mutex_lock(&s_grdma->lock);
     D("%s: call. refcount before: %u\n", __FUNCTION__, s_grdma->refcount);
     s_grdma->refcount--;
+    if (sz > MAX_DMA_SIZE &&
+        s_grdma->bigbufCount) {
+        s_grdma->bigbufCount--;
+    }
     bool shouldDelete = !s_grdma->refcount;
     if (shouldDelete) {
         D("%s: should delete!\n", __FUNCTION__);
@@ -191,8 +202,14 @@
     D("%s: for sz %u, refcount %u", __FUNCTION__, sz, s_grdma->refcount);
     uint32_t new_sz = std::max(s_grdma->sz, sz);
     if (new_sz != s_grdma->sz) {
-        D("%s: change sz from %u to %u", __FUNCTION__, s_grdma->sz, sz);
-        resize_gralloc_dmaregion_locked(new_sz);
+        if (new_sz > MAX_DMA_SIZE)  {
+            D("%s: requested sz %u too large (limit %u), set to fallback.",
+              __FUNCTION__, sz, MAX_DMA_SIZE);
+            s_grdma->bigbufCount++;
+        } else {
+            D("%s: change sz from %u to %u", __FUNCTION__, s_grdma->sz, sz);
+            resize_gralloc_dmaregion_locked(new_sz);
+        }
     }
     if (!s_grdma->goldfish_dma.mapped) {
         goldfish_dma_map(&s_grdma->goldfish_dma);
@@ -205,15 +222,17 @@
     D("%s: call for %p", __FUNCTION__, ashmemBase);
     MemRegionInfo lookup;
     lookup.ashmemBase = ashmemBase;
-    mem_region_handle_t handle = s_grdev->ashmemRegions.find(lookup);
-    if (handle == s_grdev->ashmemRegions.end()) {
+    pthread_mutex_lock(&s_memregions->lock);
+    mem_region_handle_t handle = s_memregions->ashmemRegions.find(lookup);
+    if (handle == s_memregions->ashmemRegions.end()) {
         MemRegionInfo newRegion;
         newRegion.ashmemBase = ashmemBase;
         newRegion.refCount = 1;
-        s_grdev->ashmemRegions.insert(newRegion);
+        s_memregions->ashmemRegions.insert(newRegion);
     } else {
         handle->refCount++;
     }
+    pthread_mutex_unlock(&s_memregions->lock);
 }
 
 bool put_mem_region(void* ashmemBase) {
@@ -221,25 +240,28 @@
     D("%s: call for %p", __FUNCTION__, ashmemBase);
     MemRegionInfo lookup;
     lookup.ashmemBase = ashmemBase;
-    mem_region_handle_t handle = s_grdev->ashmemRegions.find(lookup);
-    if (handle == s_grdev->ashmemRegions.end()) {
+    pthread_mutex_lock(&s_memregions->lock);
+    mem_region_handle_t handle = s_memregions->ashmemRegions.find(lookup);
+    if (handle == s_memregions->ashmemRegions.end()) {
         ALOGE("%s: error: tried to put nonexistent mem region!", __FUNCTION__);
+        pthread_mutex_unlock(&s_memregions->lock);
         return true;
     } else {
         handle->refCount--;
         bool shouldRemove = !handle->refCount;
         if (shouldRemove) {
-            s_grdev->ashmemRegions.erase(lookup);
+            s_memregions->ashmemRegions.erase(lookup);
         }
+        pthread_mutex_unlock(&s_memregions->lock);
         return shouldRemove;
     }
 }
 
 void dump_regions() {
     init_gralloc_memregions();
-    mem_region_handle_t curr = s_grdev->ashmemRegions.begin();
+    mem_region_handle_t curr = s_memregions->ashmemRegions.begin();
     std::stringstream res;
-    for (; curr != s_grdev->ashmemRegions.end(); curr++) {
+    for (; curr != s_memregions->ashmemRegions.end(); curr++) {
         res << "\tashmem base " << curr->ashmemBase << " refcount " << curr->refCount << "\n";
     }
     ALOGD("ashmem region dump [\n%s]", res.str().c_str());
@@ -354,7 +376,12 @@
                 width, height, top, left, bpp);
     }
 
-    if (s_grdma) {
+    if (s_grdma->bigbufCount) {
+        D("%s: there are big buffers alive, use fallback (count %u)", __FUNCTION__,
+          s_grdma->bigbufCount);
+    }
+
+    if (s_grdma && !s_grdma->bigbufCount) {
         if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
             get_yv12_offsets(width, height, NULL, NULL,
                              &send_buffer_size);
@@ -496,7 +523,10 @@
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
             bpp = 2;
-            glFormat = GL_RGB;
+            // Workaround: distinguish vs the RGB8/RGBA8
+            // by changing |glFormat| to GL_RGB565
+            // (previously, it was still GL_RGB)
+            glFormat = GL_RGB565;
             glType = GL_UNSIGNED_SHORT_5_6_5;
             break;
 #if PLATFORM_SDK_VERSION >= 26
@@ -577,7 +607,11 @@
     // rendering will still happen on the host but we also need to be able to
     // read back from the color buffer, which requires that there is a buffer
     //
+#if PLATFORM_SDK_VERSION >= 17
+    bool needHostCb = ((!yuv_format && frameworkFormat != HAL_PIXEL_FORMAT_BLOB) ||
+#else
     bool needHostCb = (!yuv_format ||
+#endif
                        frameworkFormat == HAL_PIXEL_FORMAT_YV12 ||
                        frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) &&
 #if PLATFORM_SDK_VERSION >= 15
@@ -760,7 +794,7 @@
         if (cb->ashmemSize > 0 && cb->ashmemBase) {
             D("%s: unmapped %p", __FUNCTION__, cb->ashmemBase);
             munmap((void *)cb->ashmemBase, cb->ashmemSize);
-            put_gralloc_dmaregion();
+            put_gralloc_dmaregion(cb->ashmemSize);
         }
         close(cb->fd);
     }
@@ -914,8 +948,6 @@
         return sFallback->registerBuffer(sFallback, handle);
     }
 
-    D("gralloc_register_buffer(%p) called", handle);
-
     private_module_t *gr = (private_module_t *)module;
     cb_handle_t *cb = (cb_handle_t *)handle;
 
@@ -924,6 +956,9 @@
         return -EINVAL;
     }
 
+    D("gralloc_register_buffer(%p) w %d h %d format 0x%x framworkFormat 0x%x",
+        handle, cb->width, cb->height, cb->format, cb->frameworkFormat);
+
     if (cb->hostHandle != 0) {
         DEFINE_AND_VALIDATE_HOST_CONNECTION;
         D("Opening host ColorBuffer 0x%x\n", cb->hostHandle);
@@ -1006,7 +1041,7 @@
     if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
 
         PUT_ASHMEM_REGION(cb);
-        put_gralloc_dmaregion();
+        put_gralloc_dmaregion(cb->ashmemSize);
 
         if (!SHOULD_UNMAP) goto done;
 
@@ -1169,8 +1204,8 @@
         cb->lockedHeight = h;
     }
 
-    DD("gralloc_lock success. vaddr: %p, *vaddr: %p, usage: %x, cpu_addr: %p",
-            vaddr, vaddr ? *vaddr : 0, usage, cpu_addr);
+    DD("gralloc_lock success. vaddr: %p, *vaddr: %p, usage: %x, cpu_addr: %p, base: %p",
+            vaddr, vaddr ? *vaddr : 0, usage, cpu_addr, cb->ashmemBase);
 
     return 0;
 }
@@ -1288,14 +1323,12 @@
             cStep = 1;
             break;
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
-            align = 1;
             yStride = cb->width;
-            cStride = yStride / 2;
+            cStride = cb->width;
             yOffset = 0;
-            cSize = cStride * cb->height/2;
-            uOffset = yStride * cb->height;
-            vOffset = uOffset + cSize;
-            cStep = 1;
+            vOffset = yStride * cb->height;
+            uOffset = vOffset + 1;
+            cStep = 2;
             break;
         default:
             ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
@@ -1322,9 +1355,9 @@
     cb->lockedHeight = h;
 
     DD("gralloc_lock_ycbcr success. usage: %x, ycbcr.y: %p, .cb: %p, .cr: %p, "
-            ".ystride: %d , .cstride: %d, .chroma_step: %d", usage,
+            ".ystride: %d , .cstride: %d, .chroma_step: %d, base: %p", usage,
             ycbcr->y, ycbcr->cb, ycbcr->cr, ycbcr->ystride, ycbcr->cstride,
-            ycbcr->chroma_step);
+            ycbcr->chroma_step, cb->ashmemBase);
 
     return 0;
 }
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 617e8f9..4a86244 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -46,6 +46,7 @@
 	rcSetPuid = (rcSetPuid_client_proc_t) getProc("rcSetPuid", userData);
 	rcUpdateColorBufferDMA = (rcUpdateColorBufferDMA_client_proc_t) getProc("rcUpdateColorBufferDMA", userData);
 	rcCreateColorBufferDMA = (rcCreateColorBufferDMA_client_proc_t) getProc("rcCreateColorBufferDMA", userData);
+	rcWaitSyncKHR = (rcWaitSyncKHR_client_proc_t) getProc("rcWaitSyncKHR", userData);
 	return 0;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 7a3e3f6..1e5594b 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -46,6 +46,7 @@
 	rcSetPuid_client_proc_t rcSetPuid;
 	rcUpdateColorBufferDMA_client_proc_t rcUpdateColorBufferDMA;
 	rcCreateColorBufferDMA_client_proc_t rcCreateColorBufferDMA;
+	rcWaitSyncKHR_client_proc_t rcWaitSyncKHR;
 	virtual ~renderControl_client_context_t() {}
 
 	typedef renderControl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/renderControl_enc/renderControl_client_proc.h b/system/renderControl_enc/renderControl_client_proc.h
index e517d07..3f1e5bb 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -45,6 +45,7 @@
 typedef void (renderControl_APIENTRY *rcSetPuid_client_proc_t) (void * ctx, uint64_t);
 typedef int (renderControl_APIENTRY *rcUpdateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
 typedef uint32_t (renderControl_APIENTRY *rcCreateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, uint32_t, GLenum, int);
+typedef void (renderControl_APIENTRY *rcWaitSyncKHR_client_proc_t) (void * ctx, uint64_t, EGLint);
 
 
 #endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 3c4a3f3..e22d7c0 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -1365,6 +1365,32 @@
 	return retval;
 }
 
+void rcWaitSyncKHR_enc(void *self , uint64_t sync, EGLint flags)
+{
+
+	renderControl_encoder_context_t *ctx = (renderControl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 8 + 4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcWaitSyncKHR;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &sync, 8); ptr += 8;
+		memcpy(ptr, &flags, 4); ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
 }  // namespace
 
 renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -1408,5 +1434,6 @@
 	this->rcSetPuid = &rcSetPuid_enc;
 	this->rcUpdateColorBufferDMA = &rcUpdateColorBufferDMA_enc;
 	this->rcCreateColorBufferDMA = &rcCreateColorBufferDMA_enc;
+	this->rcWaitSyncKHR = &rcWaitSyncKHR_enc;
 }
 
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 101806e..9a47dd3 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -41,6 +41,7 @@
 	void rcSetPuid(uint64_t puid);
 	int rcUpdateColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
 	uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat);
+	void rcWaitSyncKHR(uint64_t sync, EGLint flags);
 };
 
 #ifndef GET_CONTEXT
@@ -265,3 +266,9 @@
 	return ctx->rcCreateColorBufferDMA(ctx, width, height, internalFormat, frameworkFormat);
 }
 
+void rcWaitSyncKHR(uint64_t sync, EGLint flags)
+{
+	GET_CONTEXT;
+	ctx->rcWaitSyncKHR(ctx, sync, flags);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 4f2a09e..7bfc7c5 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -44,6 +44,7 @@
 	{"rcSetPuid", (void*)rcSetPuid},
 	{"rcUpdateColorBufferDMA", (void*)rcUpdateColorBufferDMA},
 	{"rcCreateColorBufferDMA", (void*)rcCreateColorBufferDMA},
+	{"rcWaitSyncKHR", (void*)rcWaitSyncKHR},
 };
 static const int renderControl_num_funcs = sizeof(renderControl_funcs_by_name) / sizeof(struct _renderControl_funcs_by_name);
 
diff --git a/system/renderControl_enc/renderControl_opcodes.h b/system/renderControl_enc/renderControl_opcodes.h
index 43d8f30..146164f 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -39,7 +39,8 @@
 #define OP_rcSetPuid 					10033
 #define OP_rcUpdateColorBufferDMA 					10034
 #define OP_rcCreateColorBufferDMA 					10035
-#define OP_last 					10036
+#define OP_rcWaitSyncKHR 					10036
+#define OP_last 					10037
 
 
 #endif