Snap for 8746144 from 427da2c7807073b810eb61a0677ddf0b26d2f864 to mainline-scheduling-release

Change-Id: Ib2cccc239bea3d02b40da858f179fce4d888c980
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index 2dfc80e..a6dbbd6 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -1051,17 +1051,17 @@
 }
 
 bool GLClientState::isTexture(GLuint tex_name) const {
-    return getTextureRec(tex_name);
+    return getTextureRec(tex_name) != nullptr;
 }
 
 bool GLClientState::isTextureWithStorage(GLuint tex_name) const {
-    TextureRec* rec = getTextureRec(tex_name);
+    TextureRec* rec = getTextureRecPtr(tex_name);
     if (!rec) return false;
     return rec->hasStorage;
 }
 
 bool GLClientState::isTextureCubeMap(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return false;
     switch (texrec->target) {
         case GL_TEXTURE_CUBE_MAP:
@@ -1203,7 +1203,7 @@
             pack ? 0 : m_pixelStore.unpack_skip_images);
 }
 
-size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
+size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack, int ignoreTrailing) const
 {
     if (width <= 0 || height <= 0 || depth <= 0) return 0;
 
@@ -1231,7 +1231,8 @@
             pack ? 0 : m_pixelStore.unpack_image_height,
             pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
             pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
-            pack ? 0 : m_pixelStore.unpack_skip_images);
+            pack ? 0 : m_pixelStore.unpack_skip_images,
+            ignoreTrailing);
 }
 
 
@@ -1445,7 +1446,7 @@
 {
     GLboolean first = GL_FALSE;
 
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) {
         texrec = addTextureRec(texture, target);
         first = GL_TRUE;
@@ -1496,7 +1497,7 @@
         setBoundRenderbufferDimensions(width, height);
     } else {
         GLuint texture = getBoundTexture(target);
-        TextureRec* texrec = getTextureRec(texture);
+        TextureRec* texrec = getTextureRecPtr(texture);
         if (!texrec) return;
         texrec->boundEGLImage = true;
         setBoundTextureInternalFormat(target, GL_RGBA);
@@ -1526,11 +1527,12 @@
     tex->hasCubePosZ = false;
 
     AutoWriteLock guard(m_tex.textureRecs->lock);
-    m_tex.textureRecs->map[id] = tex;
+    m_tex.textureRecs->map[id] = std::shared_ptr<TextureRec>(tex);
     return tex;
 }
 
-TextureRec* GLClientState::getTextureRecLocked(GLuint id) const {
+std::shared_ptr<TextureRec> GLClientState::getTextureRec(GLuint id) const {
+    AutoReadLock guard(m_tex.textureRecs->lock);
     SharedTextureDataMap::const_iterator it =
         m_tex.textureRecs->map.find(id);
     if (it == m_tex.textureRecs->map.end()) {
@@ -1539,28 +1541,37 @@
     return it->second;
 }
 
-TextureRec* GLClientState::getTextureRec(GLuint id) const {
+TextureRec* GLClientState::getTextureRecPtrLocked(GLuint id) const {
+    SharedTextureDataMap::const_iterator it =
+        m_tex.textureRecs->map.find(id);
+    if (it == m_tex.textureRecs->map.end()) {
+        return NULL;
+    }
+    return it->second.get();
+}
+
+TextureRec* GLClientState::getTextureRecPtr(GLuint id) const {
     AutoReadLock guard(m_tex.textureRecs->lock);
-    return getTextureRecLocked(id);
+    return getTextureRecPtrLocked(id);
 }
 
 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
     texrec->internalformat = internalformat;
 }
 
 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
     texrec->format = format;
 }
 
 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
     texrec->type = type;
 }
@@ -1585,7 +1596,7 @@
 
 void GLClientState::setBoundTextureDims(GLenum target, GLenum cubetarget, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) {
         return;
     }
@@ -1643,7 +1654,7 @@
 
 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
     texrec->multisamples = samples;
 }
@@ -1652,7 +1663,7 @@
     if (stateTarget != GL_TEXTURE_CUBE_MAP) return;
 
     GLuint texture = getBoundTexture(stateTarget);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
 
     switch (cubeTarget) {
@@ -1679,7 +1690,7 @@
 
 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return;
     texrec->immutable = true;
     if (target == GL_TEXTURE_CUBE_MAP) {
@@ -1694,14 +1705,14 @@
 
 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return false;
     return texrec->immutable;
 }
 
 bool GLClientState::isBoundTextureComplete(GLenum target) const {
     GLuint texture = getBoundTexture(target);
-    TextureRec* texrec = getTextureRec(texture);
+    TextureRec* texrec = getTextureRecPtr(texture);
     if (!texrec) return false;
 
     if (texrec->immutable) return true;
@@ -1914,7 +1925,7 @@
     if (!renderable) return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
     // Check dimensions
-    GLuint id;
+    std::shared_ptr<TextureRec> texrec;
     std::shared_ptr<RboProps> rbo;
     switch (fbo_format_info.type) {
     case FBO_ATTACHMENT_RENDERBUFFER:
@@ -1927,13 +1938,14 @@
         }
         break;
     case FBO_ATTACHMENT_TEXTURE:
-        id = getFboAttachmentTextureId(target, attachment);
+        texrec = getFboAttachmentTexture(target, attachment);
         if (!fbo_format_info.tex_external) {
-            if (0 == queryTexWidth(fbo_format_info.tex_level, id) || 0 == queryTexHeight(fbo_format_info.tex_level, id)) {
+            if (0 == texrec->dims->widths[fbo_format_info.tex_level] ||
+                    0 == texrec->dims->heights[fbo_format_info.tex_level]) {
                 ALOGD("%s: texture has zero dimension\n", __func__);
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
-            GLsizei depth = queryTexDepth(fbo_format_info.tex_level, id);
+            GLsizei depth = texrec->dims->depths[fbo_format_info.tex_level];
             if (fbo_format_info.tex_layer >= depth) {
                 ALOGD("%s: texture layer/zoffset too high, wanted %d but only have %d layers\n", __func__,
                       fbo_format_info.tex_layer, depth);
@@ -2054,13 +2066,12 @@
     TextureRec* texrec;
     for (const GLuint* texture = textures; texture != textures + n; texture++) {
         AutoWriteLock guard(m_tex.textureRecs->lock);
-        texrec = getTextureRecLocked(*texture);
+        texrec = getTextureRecPtrLocked(*texture);
         if (texrec && texrec->dims) {
             delete [] texrec->dims;
         }
         if (texrec) {
             m_tex.textureRecs->map.erase(*texture);
-            delete texrec;
             for (TextureUnit* unit = m_tex.unit;
                  unit != m_tex.unit + MAX_TEXTURE_UNITS;
                  unit++)
@@ -2091,7 +2102,6 @@
 }
 
 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
-    std::vector<std::shared_ptr<RboProps>> to_remove;
     bool unbindCurrent = false;
     {
         RenderbufferInfo::ScopedView view(mRboState.rboData);
@@ -2101,18 +2111,12 @@
                 if (!rboPtr) {
                     continue;
                 }
-                to_remove.push_back(rboPtr);
+                unbindCurrent |=
+                        (mRboState.boundRenderbuffer == rboPtr);
                 setFboCompletenessDirtyForRbo(rboPtr);
+                view.remove(renderbuffers[i]);
             }
         }
-
-        for (size_t i = 0; i < to_remove.size(); i++) {
-            if (mRboState.boundRenderbuffer == to_remove[i]) {
-                unbindCurrent = true;
-                break;
-            }
-            view.remove(to_remove[i]->id);
-        }
     }
 
     if (unbindCurrent) {
@@ -2158,13 +2162,13 @@
 // FBO//////////////////////////////////////////////////////////////////////////
 
 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return -1;
     return texrec->internalformat;
 }
 
 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) {
         return 0;
     }
@@ -2172,43 +2176,43 @@
 }
 
 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return 0;
     return texrec->dims->heights[level];
 }
 
 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return 0;
     return texrec->dims->depths[level];
 }
 
 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return false;
     return texrec->boundEGLImage;
 }
 
 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return -1;
     return texrec->format;
 }
 
 GLenum GLClientState::queryTexType(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return -1;
     return texrec->type;
 }
 
 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return 0;
     return texrec->multisamples;
 }
 
 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
-    TextureRec* texrec = getTextureRec(tex_name);
+    TextureRec* texrec = getTextureRecPtr(tex_name);
     if (!texrec) return GL_NONE;
     return texrec->target;
 }
@@ -2241,18 +2245,16 @@
                     props.colorAttachmenti_rbos[colorAttachmentIndex]->boundEGLImage;
         } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
             res_info->type = FBO_ATTACHMENT_TEXTURE;
-            res_info->tex_external = queryTexEGLImageBacked(
-                    props.colorAttachmenti_textures[colorAttachmentIndex]);
+            res_info->tex_external =
+                    props.colorAttachmenti_textures[colorAttachmentIndex]->boundEGLImage;
             res_info->tex_internalformat =
-                queryTexInternalFormat(
-                        props.colorAttachmenti_textures[colorAttachmentIndex]);
+                    props.colorAttachmenti_textures[colorAttachmentIndex]->internalformat;
             res_info->tex_format =
-                queryTexFormat(
-                        props.colorAttachmenti_textures[colorAttachmentIndex]);
+                    props.colorAttachmenti_textures[colorAttachmentIndex]->format;
             res_info->tex_type =
-                queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
+                    props.colorAttachmenti_textures[colorAttachmentIndex]->type;
             res_info->tex_multisamples =
-                queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
+                    props.colorAttachmenti_textures[colorAttachmentIndex]->multisamples;
             res_info->tex_level = props.colorAttachmenti_texture_levels[colorAttachmentIndex];
             res_info->tex_layer = props.colorAttachmenti_texture_layers[colorAttachmentIndex];
         } else {
@@ -2269,12 +2271,11 @@
             res_info->rb_external = props.depthAttachment_rbo->boundEGLImage;
         } else if (props.depthAttachment_hasTexObj) {
             res_info->type = FBO_ATTACHMENT_TEXTURE;
-            res_info->tex_external = queryTexEGLImageBacked(props.depthAttachment_texture);
-            res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
-            res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
-            res_info->tex_type = queryTexType(props.depthAttachment_texture);
-            res_info->tex_multisamples =
-                queryTexSamples(props.depthAttachment_texture);
+            res_info->tex_external = props.depthAttachment_texture->boundEGLImage;
+            res_info->tex_internalformat = props.depthAttachment_texture->internalformat;
+            res_info->tex_format = props.depthAttachment_texture->format;
+            res_info->tex_type = props.depthAttachment_texture->type;
+            res_info->tex_multisamples = props.depthAttachment_texture->multisamples;
             res_info->tex_level = props.depthAttachment_texture_level;
             res_info->tex_layer = props.depthAttachment_texture_layer;
         } else {
@@ -2289,12 +2290,11 @@
             res_info->rb_external = props.stencilAttachment_rbo->boundEGLImage;
         } else if (props.stencilAttachment_hasTexObj) {
             res_info->type = FBO_ATTACHMENT_TEXTURE;
-            res_info->tex_external = queryTexEGLImageBacked(props.stencilAttachment_texture);
-            res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
-            res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
-            res_info->tex_type = queryTexType(props.stencilAttachment_texture);
-            res_info->tex_multisamples =
-                queryTexSamples(props.stencilAttachment_texture);
+            res_info->tex_external = props.stencilAttachment_texture->boundEGLImage;
+            res_info->tex_internalformat = props.stencilAttachment_texture->internalformat;
+            res_info->tex_format = props.stencilAttachment_texture->format;
+            res_info->tex_type = props.stencilAttachment_texture->type;
+            res_info->tex_multisamples = props.stencilAttachment_texture->multisamples;
             res_info->tex_level = props.depthAttachment_texture_level;
             res_info->tex_layer = props.depthAttachment_texture_layer;
         } else {
@@ -2309,12 +2309,11 @@
             res_info->rb_external = props.depthstencilAttachment_rbo->boundEGLImage;
         } else if (props.depthstencilAttachment_hasTexObj) {
             res_info->type = FBO_ATTACHMENT_TEXTURE;
-            res_info->tex_external = queryTexEGLImageBacked(props.depthstencilAttachment_texture);
-            res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
-            res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
-            res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
-            res_info->tex_multisamples =
-                queryTexSamples(props.depthstencilAttachment_texture);
+            res_info->tex_external = props.depthstencilAttachment_texture->boundEGLImage;
+            res_info->tex_internalformat = props.depthstencilAttachment_texture->internalformat;
+            res_info->tex_format = props.depthstencilAttachment_texture->format;
+            res_info->tex_type = props.depthstencilAttachment_texture->type;
+            res_info->tex_multisamples = props.depthstencilAttachment_texture->multisamples;
             res_info->tex_level = props.depthAttachment_texture_level;
             res_info->tex_layer = props.depthAttachment_texture_layer;
         } else {
@@ -2538,6 +2537,7 @@
         GLenum attachment, GLuint texture, GLint level, GLint layer) {
 
     bool attach = texture != 0;
+    std::shared_ptr<TextureRec> texrec = getTextureRec(texture);
 
     int colorAttachmentIndex =
         glUtilsColorAttachmentIndex(attachment);
@@ -2545,7 +2545,7 @@
     boundFboProps(target).completenessDirty = true;
 
     if (colorAttachmentIndex != -1) {
-        boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
+        boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texrec;
         boundFboProps(target).colorAttachmenti_texture_levels[colorAttachmentIndex] = level;
         boundFboProps(target).colorAttachmenti_texture_layers[colorAttachmentIndex] = layer;
         boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = attach;
@@ -2553,23 +2553,23 @@
 
     switch (attachment) {
     case GL_DEPTH_ATTACHMENT:
-        boundFboProps(target).depthAttachment_texture = texture;
+        boundFboProps(target).depthAttachment_texture = texrec;
         boundFboProps(target).depthAttachment_texture_level = level;
         boundFboProps(target).depthAttachment_texture_layer = layer;
         boundFboProps(target).depthAttachment_hasTexObj = attach;
         break;
     case GL_STENCIL_ATTACHMENT:
-        boundFboProps(target).stencilAttachment_texture = texture;
+        boundFboProps(target).stencilAttachment_texture = texrec;
         boundFboProps(target).stencilAttachment_texture_level = level;
         boundFboProps(target).stencilAttachment_texture_layer = layer;
         boundFboProps(target).stencilAttachment_hasTexObj = attach;
         break;
     case GL_DEPTH_STENCIL_ATTACHMENT:
-        boundFboProps(target).depthstencilAttachment_texture = texture;
+        boundFboProps(target).depthstencilAttachment_texture = texrec;
         boundFboProps(target).depthstencilAttachment_hasTexObj = attach;
-        boundFboProps(target).stencilAttachment_texture = texture;
+        boundFboProps(target).stencilAttachment_texture = texrec;
         boundFboProps(target).stencilAttachment_hasTexObj = attach;
-        boundFboProps(target).depthAttachment_texture = texture;
+        boundFboProps(target).depthAttachment_texture = texrec;
         boundFboProps(target).depthAttachment_hasTexObj = attach;
         boundFboProps(target).depthAttachment_texture_level = level;
         boundFboProps(target).depthAttachment_texture_layer = layer;
@@ -2579,8 +2579,8 @@
     }
 }
 
-GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
-    GLuint res = 0; // conservative
+std::shared_ptr<TextureRec> GLClientState::getFboAttachmentTexture(GLenum target, GLenum attachment) const {
+    std::shared_ptr<TextureRec> res = {}; // conservative
 
     int colorAttachmentIndex =
         glUtilsColorAttachmentIndex(attachment);
@@ -2731,12 +2731,13 @@
 }
 
 void GLClientState::setFboCompletenessDirtyForTexture(GLuint texture) {
+    std::shared_ptr<TextureRec> texrec = getTextureRec(texture);
     std::map<GLuint, FboProps>::iterator it = mFboState.fboData.begin();
     while (it != mFboState.fboData.end()) {
         FboProps& props = it->second;
         for (int i = 0; i < m_hostDriverCaps.max_color_attachments; ++i) {
             if (props.colorAttachmenti_hasTex[i]) {
-                if (texture == props.colorAttachmenti_textures[i]) {
+                if (texrec == props.colorAttachmenti_textures[i]) {
                     props.completenessDirty = true;
                     return;
                 }
@@ -2744,21 +2745,21 @@
         }
 
         if (props.depthAttachment_hasTexObj) {
-            if (texture == props.depthAttachment_texture) {
+            if (texrec == props.depthAttachment_texture) {
                     props.completenessDirty = true;
                     return;
             }
         }
 
         if (props.stencilAttachment_hasTexObj) {
-            if (texture == props.stencilAttachment_texture) {
+            if (texrec == props.stencilAttachment_texture) {
                 props.completenessDirty = true;
                 return;
             }
         }
 
         if (props.depthstencilAttachment_hasTexObj) {
-            if (texture == props.depthstencilAttachment_texture) {
+            if (texrec == props.depthstencilAttachment_texture) {
                 props.completenessDirty = true;
                 return;
             }
@@ -2832,51 +2833,21 @@
     return res;
 }
 
-GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
+bool GLClientState::depthStencilHasSameObject(GLenum target) const {
     const FboProps& props = boundFboProps_const(target);
 
-    int colorAttachmentIndex =
-        glUtilsColorAttachmentIndex(attachment);
-
-    if (colorAttachmentIndex != -1) {
-        if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
-            return props.colorAttachmenti_textures[colorAttachmentIndex];
-        } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
-            return props.colorAttachmenti_rbos[colorAttachmentIndex]->id;
-        } else {
-            return 0;
-        }
+    if (props.depthAttachment_hasTexObj != props.stencilAttachment_hasTexObj
+            || props.depthAttachment_hasRbo != props.stencilAttachment_hasRbo) {
+        return false;
     }
-
-    switch (attachment) {
-    case GL_DEPTH_ATTACHMENT:
-        if (props.depthAttachment_hasTexObj) {
-            return props.depthAttachment_texture;
-        } else if (props.depthAttachment_hasRbo) {
-            return props.depthAttachment_rbo->id;
-        } else {
-            return 0;
-        }
-        break;
-    case GL_STENCIL_ATTACHMENT:
-        if (props.stencilAttachment_hasTexObj) {
-            return props.stencilAttachment_texture;
-        } else if (props.stencilAttachment_hasRbo) {
-            return props.stencilAttachment_rbo->id;
-        } else {
-            return 0;
-        }
-    case GL_DEPTH_STENCIL_ATTACHMENT:
-        if (props.depthstencilAttachment_hasTexObj) {
-            return props.depthstencilAttachment_texture;
-        } else if (props.depthstencilAttachment_hasRbo) {
-            return props.depthstencilAttachment_rbo->id;
-        } else {
-            return 0;
-        }
-        break;
+    if (props.depthAttachment_hasTexObj) {
+        return props.depthAttachment_texture == props.stencilAttachment_texture;
     }
-    return 0;
+    if (props.depthAttachment_hasRbo) {
+        return props.depthAttachment_rbo == props.stencilAttachment_rbo;
+    }
+    // No attachment in either
+    return true;
 }
 
 void GLClientState::setTransformFeedbackActive(bool active) {
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index b71054f..308b737 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -40,6 +40,7 @@
 
 #include <vector>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 
@@ -81,7 +82,7 @@
     bool previouslyBound;
     bool completenessDirty;
     GLenum cachedCompleteness;
-    std::vector<GLuint> colorAttachmenti_textures;
+    std::vector<std::shared_ptr<TextureRec>> colorAttachmenti_textures;
     std::vector<GLint> colorAttachmenti_texture_levels;
     std::vector<GLint> colorAttachmenti_texture_layers;
 
@@ -90,9 +91,9 @@
     GLint stencilAttachment_texture_level;
     GLint stencilAttachment_texture_layer;
 
-    GLuint depthAttachment_texture;
-    GLuint stencilAttachment_texture;
-    GLuint depthstencilAttachment_texture;
+    std::shared_ptr<TextureRec> depthAttachment_texture;
+    std::shared_ptr<TextureRec> stencilAttachment_texture;
+    std::shared_ptr<TextureRec> depthstencilAttachment_texture;
 
     std::vector<bool> colorAttachmenti_hasTex;
     bool depthAttachment_hasTexObj;
@@ -331,7 +332,7 @@
     void setLastEncodedBufferBind(GLenum target, GLuint id);
 
     size_t pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
-    size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const;
+    size_t pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack, int ignoreTrailing = 0) const;
     size_t clearBufferNumElts(GLenum buffer) const;
     void getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
     void getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
@@ -489,7 +490,7 @@
 
     // Texture object -> FBO
     void attachTextureObject(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-    GLuint getFboAttachmentTextureId(GLenum target, GLenum attachment) const;
+    std::shared_ptr<TextureRec> getFboAttachmentTexture(GLenum target, GLenum attachment) const;
 
     // RBO -> FBO
     void detachRbo(GLuint renderbuffer);
@@ -499,7 +500,7 @@
 
     // FBO attachments in general
     bool attachmentHasObject(GLenum target, GLenum attachment) const;
-    GLuint objectOfAttachment(GLenum target, GLenum attachment) const;
+    bool depthStencilHasSameObject(GLenum target) const;
 
     // Dirty FBO completeness
     void setFboCompletenessDirtyForTexture(GLuint texture);
@@ -739,8 +740,9 @@
 
     static int compareTexId(const void* pid, const void* prec);
     TextureRec* addTextureRec(GLuint id, GLenum target);
-    TextureRec* getTextureRec(GLuint id) const;
-    TextureRec* getTextureRecLocked(GLuint id) const;
+    std::shared_ptr<TextureRec> getTextureRec(GLuint id) const;
+    TextureRec* getTextureRecPtr(GLuint id) const;
+    TextureRec* getTextureRecPtrLocked(GLuint id) const;
 
 public:
     bool isTexture(GLuint name) const;
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.cpp b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
index 87d6312..0fa0e23 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.cpp
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
@@ -1,5 +1,7 @@
 #include "GLESTextureUtils.h"
 
+#include <algorithm>
+
 #include "glUtils.h"
 #include "etc.h"
 #include "astc-codec.h"
@@ -254,7 +256,8 @@
         int unpackSkipRows,
         int unpackSkipImages,
         int* start,
-        int* end) {
+        int* end,
+        int ignoreTrailing) {
 
     GLsizei inputWidth = (unpackRowLength == 0) ? width : unpackRowLength;
     GLsizei inputPitch = computePitch(inputWidth, format, type, unpackAlignment);
@@ -263,7 +266,17 @@
     ALOGV("%s: input idim %d %d %d w p h %d %d %d:", __FUNCTION__, width, height, depth, inputWidth, inputPitch, inputHeight);
 
     int startVal = computePackingOffset(format, type, inputWidth, inputHeight, unpackAlignment, unpackSkipPixels, unpackSkipRows, unpackSkipImages);
-    int endVal = startVal + inputPitch * inputHeight * depth;
+    int endVal;
+    if (ignoreTrailing) {
+        // The last row needs to have just enough data per spec, and could
+        // ignore alignment.
+        // b/223402256
+        endVal = startVal + inputPitch * inputHeight * (depth - 1);
+        endVal += inputPitch * (std::min(height, inputHeight) - 1);
+        endVal += computePitch(std::min(width, inputWidth), format, type, 1);
+    } else {
+        endVal = startVal + inputPitch * inputHeight * depth;
+    }
 
     if (start) *start = startVal;
     if (end) *end = endVal;
@@ -293,7 +306,8 @@
             unpackSkipRows,
             unpackSkipImages,
             &start,
-            &end);
+            &end,
+            0);
     return end;
 }
 
@@ -305,7 +319,8 @@
         int unpackImageHeight,
         int unpackSkipPixels,
         int unpackSkipRows,
-        int unpackSkipImages) {
+        int unpackSkipImages,
+        int ignoreTrailing) {
 
     int start, end;
     computeTextureStartEnd(
@@ -318,7 +333,8 @@
             unpackSkipRows,
             unpackSkipImages,
             &start,
-            &end);
+            &end,
+            ignoreTrailing);
     return end - start;
 }
 
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.h b/shared/OpenglCodecCommon/GLESTextureUtils.h
index 0b636ac..45af27e 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.h
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.h
@@ -5,6 +5,11 @@
 
 namespace GLESTextureUtils {
 
+// By spec, the buffer is only required to provide just enough data. The
+// last row does not have to fill unpackRowLength. But our decoder is
+// written to always read full row. So we add "ignoreTrailing" here. When
+// ignoreTrailing == 1 we compute the real size as defined by spec. When
+// ignoreTrailing == 0 we compute the size used by decoder/encoder.
 void computeTextureStartEnd(
         GLsizei width, GLsizei height, GLsizei depth,
         GLenum format, GLenum type,
@@ -15,7 +20,8 @@
         int unpackSkipRows,
         int unpackSkipImages,
         int* start,
-        int* end);
+        int* end,
+        int ignoreTrailing);
 
 int computeTotalImageSize(
         GLsizei width, GLsizei height, GLsizei depth,
@@ -35,7 +41,8 @@
         int unpackImageHeight,
         int unpackSkipPixels,
         int unpackSkipRows,
-        int unpackSkipImages);
+        int unpackSkipImages,
+        int ignoreTrailing);
 
 // Writes out |height| offsets for glReadPixels to read back
 // data in separate rows of pixels. Returns:
diff --git a/shared/OpenglCodecCommon/TextureSharedData.h b/shared/OpenglCodecCommon/TextureSharedData.h
index aee1996..fafb435 100644
--- a/shared/OpenglCodecCommon/TextureSharedData.h
+++ b/shared/OpenglCodecCommon/TextureSharedData.h
@@ -18,6 +18,7 @@
 
 #include <GLES/gl.h>
 #include <map>
+#include <memory>
 
 #include "android/base/synchronization/AndroidLock.h"
 
@@ -49,7 +50,7 @@
 };
 
 struct SharedTextureDataMap {
-  using MapType = std::map<GLuint, TextureRec*>;
+  using MapType = std::map<GLuint, std::shared_ptr<TextureRec>>;
 
   using iterator = MapType::iterator;
   using const_iterator = MapType::const_iterator;
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 382274c..65048cf 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -2721,10 +2721,9 @@
     }
 
     // If unpack buffer is nonzero, verify buffer data fits and is evenly divisible by the type.
-
     SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
                  ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER) &&
-                 (state->pboNeededDataSize(width, height, 1, format, type, 0) + (uintptr_t)pixels >
+                 (state->pboNeededDataSize(width, height, 1, format, type, 0, 1) + (uintptr_t)pixels >
                   ctx->getBufferData(GL_PIXEL_UNPACK_BUFFER)->m_size),
                  GL_INVALID_OPERATION);
     SET_ERROR_IF(ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER) &&
@@ -3091,8 +3090,7 @@
         GL_INVALID_ENUM);
     SET_ERROR_IF(attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
                  pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME &&
-                 (state->objectOfAttachment(target, GL_DEPTH_ATTACHMENT) !=
-                  state->objectOfAttachment(target, GL_STENCIL_ATTACHMENT)),
+                 !state->depthStencilHasSameObject(target),
                  GL_INVALID_OPERATION);
     SET_ERROR_IF(state->boundFramebuffer(target) &&
                  (attachment == GL_BACK ||
diff --git a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
index 8e87145..90b5653 100644
--- a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
+++ b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
@@ -670,10 +670,11 @@
 void C2GoldfishAvcDec::checkMode(const std::shared_ptr<C2BlockPool> &pool) {
     mWidth = mIntf->width();
     mHeight = mIntf->height();
-    const bool isGraphic = (pool->getAllocatorId() == C2Allocator::GRAPHIC);
+    const bool isGraphic = (pool->getAllocatorId() & C2Allocator::GRAPHIC);
+    DDD("buffer id %d", (int)(pool->getAllocatorId()));
     if (isGraphic) {
         DDD("decoding to host color buffer");
-        mEnableAndroidNativeBuffers = false;
+        mEnableAndroidNativeBuffers = true;
     } else {
         DDD("decoding to guest byte buffer");
         mEnableAndroidNativeBuffers = false;
diff --git a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
index 7aac56f..7008bd5 100644
--- a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
+++ b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
@@ -661,10 +661,11 @@
 void C2GoldfishHevcDec::checkMode(const std::shared_ptr<C2BlockPool> &pool) {
     mWidth = mIntf->width();
     mHeight = mIntf->height();
-    const bool isGraphic = (pool->getAllocatorId() == C2Allocator::GRAPHIC);
+    const bool isGraphic = (pool->getAllocatorId() & C2Allocator::GRAPHIC);
+    DDD("buffer id %d", (int)(pool->getAllocatorId()));
     if (isGraphic) {
         DDD("decoding to host color buffer");
-        mEnableAndroidNativeBuffers = false;
+        mEnableAndroidNativeBuffers = true;
     } else {
         DDD("decoding to guest byte buffer");
         mEnableAndroidNativeBuffers = false;
diff --git a/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp b/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
index bb61cf9..99f0469 100644
--- a/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
+++ b/system/codecs/c2/decoders/vpxdec/C2GoldfishVpxDec.cpp
@@ -465,10 +465,11 @@
     mCtx = new vpx_codec_ctx_t;
     mCtx->vpversion = mMode == MODE_VP8 ? 8 : 9;
 
-    const bool isGraphic = (pool->getAllocatorId() == C2Allocator::GRAPHIC);
+    const bool isGraphic = (pool->getAllocatorId() & C2Allocator::GRAPHIC);
+    DDD("buffer id %d", (int)(pool->getAllocatorId()));
     if (isGraphic) {
         DDD("decoding to host color buffer");
-        mEnableAndroidNativeBuffers = false;
+        mEnableAndroidNativeBuffers = true;
     } else {
         DDD("decoding to guest byte buffer");
         mEnableAndroidNativeBuffers = false;
diff --git a/system/vulkan_enc/AndroidHardwareBuffer.cpp b/system/vulkan_enc/AndroidHardwareBuffer.cpp
index 40360a2..c49693d 100644
--- a/system/vulkan_enc/AndroidHardwareBuffer.cpp
+++ b/system/vulkan_enc/AndroidHardwareBuffer.cpp
@@ -75,8 +75,46 @@
         if (!(desc.usage & (gpu_usage))) {
             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
         }
-
-        ahbFormatProps->format = vk_format_from_android(desc.format);
+        switch(desc.format) {
+            case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_R8G8B8_UNORM;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_R5G6B5_UNORM_PACK16;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+                  ahbFormatProps->format = VK_FORMAT_R16G16B16A16_SFLOAT;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_D16_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_D16_UNORM;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_D24_UNORM:
+                  ahbFormatProps->format = VK_FORMAT_X8_D24_UNORM_PACK32;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
+                  ahbFormatProps->format = VK_FORMAT_D24_UNORM_S8_UINT;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
+                  ahbFormatProps->format = VK_FORMAT_D32_SFLOAT;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
+                  ahbFormatProps->format = VK_FORMAT_D32_SFLOAT_S8_UINT;
+                  break;
+            case AHARDWAREBUFFER_FORMAT_S8_UINT:
+                  ahbFormatProps->format = VK_FORMAT_S8_UINT;
+                  break;
+            default:
+                  ahbFormatProps->format = VK_FORMAT_UNDEFINED;
+        }
         ahbFormatProps->externalFormat = desc.format;
 
         // The formatFeatures member must include
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index a4bf2e7..76e8677 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -362,6 +362,10 @@
         VkDeviceSize currentBackingSize = 0;
         bool baseRequirementsKnown = false;
         VkMemoryRequirements baseRequirements;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        bool hasExternalFormat = false;
+        unsigned androidFormat = 0;
+#endif
 #ifdef VK_USE_PLATFORM_FUCHSIA
         bool isSysmemBackedMemory = false;
 #endif
@@ -5055,6 +5059,11 @@
         info.createInfo = *pCreateInfo;
         info.createInfo.pNext = nullptr;
 
+        if (extFormatAndroidPtr && extFormatAndroidPtr->externalFormat) {
+            info.hasExternalFormat = true;
+            info.androidFormat = extFormatAndroidPtr->externalFormat;
+        }
+
         if (supportsCreateResourcesWithRequirements()) {
             info.baseRequirementsKnown = true;
         }
@@ -5192,7 +5201,8 @@
             vk_find_struct<VkSamplerYcbcrConversionInfo>(pCreateInfo);
         if (samplerYcbcrConversionInfo) {
             if (samplerYcbcrConversionInfo->conversion != VK_YCBCR_CONVERSION_DO_NOTHING) {
-                localVkSamplerYcbcrConversionInfo = vk_make_orphan_copy(*samplerYcbcrConversionInfo);
+                localVkSamplerYcbcrConversionInfo =
+                    vk_make_orphan_copy(*samplerYcbcrConversionInfo);
                 vk_append_struct(&structChainIter, &localVkSamplerYcbcrConversionInfo);
             }
         }
@@ -7575,14 +7585,24 @@
         (void)input_result;
 
         VkImageViewCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo);
+        vk_struct_chain_iterator structChainIter = vk_make_chain_iterator(&localCreateInfo);
 
 #if defined(VK_USE_PLATFORM_ANDROID_KHR) || defined(__linux__)
-        const VkExternalFormatANDROID* extFormatAndroidPtr =
-            vk_find_struct<VkExternalFormatANDROID>(pCreateInfo);
-        if (extFormatAndroidPtr) {
-            if (extFormatAndroidPtr->externalFormat) {
-                localCreateInfo.format =
-                    vk_format_from_android(extFormatAndroidPtr->externalFormat);
+        if (pCreateInfo->format == VK_FORMAT_UNDEFINED) {
+            AutoLock<RecursiveLock> lock(mLock);
+
+            auto it = info_VkImage.find(pCreateInfo->image);
+            if (it != info_VkImage.end() && it->second.hasExternalFormat) {
+                localCreateInfo.format = vk_format_from_android(it->second.androidFormat);
+            }
+        }
+        VkSamplerYcbcrConversionInfo localVkSamplerYcbcrConversionInfo;
+        const VkSamplerYcbcrConversionInfo* samplerYcbcrConversionInfo =
+            vk_find_struct<VkSamplerYcbcrConversionInfo>(pCreateInfo);
+        if (samplerYcbcrConversionInfo) {
+            if (samplerYcbcrConversionInfo->conversion != VK_YCBCR_CONVERSION_DO_NOTHING) {
+                localVkSamplerYcbcrConversionInfo = vk_make_orphan_copy(*samplerYcbcrConversionInfo);
+                vk_append_struct(&structChainIter, &localVkSamplerYcbcrConversionInfo);
             }
         }
 #endif