Snap for 7620055 from 4494e762319a6156cf427a20c8b38f66d5be886a to sc-release

Change-Id: Ibecdb28940ae4494e9a60d8edff6b6e66f2096ea
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index f6d8ce5..a21b257 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -133,6 +133,9 @@
 // Batched descriptor set update
 static const char kVulkanBatchedDescriptorSetUpdate[] = "ANDROID_EMU_vulkan_batched_descriptor_set_update";
 
+// DMA for readback
+static const char kReadColorBufferDma[] = "ANDROID_EMU_read_color_buffer_dma";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -159,7 +162,8 @@
         hasAsyncFrameCommands(false),
         hasVulkanQueueSubmitWithCommands(false),
         hasVulkanBatchedDescriptorSetUpdate(false),
-        hasSyncBufferData(false)
+        hasSyncBufferData(false),
+        hasReadColorBufferDma(false)
     { }
 
     SyncImpl syncImpl;
@@ -185,6 +189,7 @@
     bool hasVulkanQueueSubmitWithCommands;
     bool hasVulkanBatchedDescriptorSetUpdate;
     bool hasSyncBufferData;
+    bool hasReadColorBufferDma;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 4afa20e..8d15d08 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -672,6 +672,7 @@
         queryAndSetVulkanQueueSubmitWithCommandsSupport(rcEnc);
         queryAndSetVulkanBatchedDescriptorSetUpdateSupport(rcEnc);
         queryAndSetSyncBufferData(rcEnc);
+        queryAndSetReadColorBufferDma(rcEnc);
         queryVersion(rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, rcEnc);
@@ -971,6 +972,13 @@
     }
 }
 
+void HostConnection::queryAndSetReadColorBufferDma(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kReadColorBufferDma) != std::string::npos) {
+        rcEnc->featureInfo()->hasReadColorBufferDma = true;
+    }
+}
+
 GLint HostConnection::queryVersion(ExtendedRCEncoderContext* rcEnc) {
     GLint version = m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
     return version;
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 7c55629..31ca84c 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -85,7 +85,9 @@
     }
     virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
         if (m_dmaPtr && m_dmaPhysAddr) {
-            memcpy(m_dmaPtr, data, size);
+            if (data != m_dmaPtr) {
+                memcpy(m_dmaPtr, data, size);
+            }
             return m_dmaPhysAddr;
         } else if (m_dmaCxt) {
             return writeGoldfishDma(data, size, m_dmaCxt);
@@ -242,6 +244,7 @@
     void queryAndSetVulkanQueueSubmitWithCommandsSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanBatchedDescriptorSetUpdateSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetSyncBufferData(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetReadColorBufferDma(ExtendedRCEncoderContext *rcEnc);
     GLint queryVersion(ExtendedRCEncoderContext* rcEnc);
 
 private:
diff --git a/system/hals/Android.mk b/system/hals/Android.mk
index 72ac6ce..06fdc21 100644
--- a/system/hals/Android.mk
+++ b/system/hals/Android.mk
@@ -35,7 +35,7 @@
     libcutils \
     libhidlbase \
     liblog \
-    libutils
+    libutils \
 
 LOCAL_STATIC_LIBRARIES += libqemupipe.ranchu libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX)
 LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
@@ -75,7 +75,8 @@
     libhidlbase \
     liblog \
     libutils \
-    libsync
+    libsync \
+	libandroidemu \
 
 LOCAL_STATIC_LIBRARIES += libqemupipe.ranchu libGoldfishAddressSpace$(GOLDFISH_OPENGL_LIB_SUFFIX)
 LOCAL_HEADER_LIBRARIES += libgralloc_cb.ranchu
diff --git a/system/hals/cb_handle_30.h b/system/hals/cb_handle_30.h
index 374008e..7e5e73d 100644
--- a/system/hals/cb_handle_30.h
+++ b/system/hals/cb_handle_30.h
@@ -53,7 +53,9 @@
                           p_mmapedOffset),
               mmapedSize(p_mmapedSize),
               bytesPerPixel(p_bytesPerPixel),
-              stride(p_stride) {
+              stride(p_stride),
+              locked(0),
+              lockedUsage(0) {
         numInts = CB_HANDLE_NUM_INTS(numFds);
     }
 
@@ -76,6 +78,8 @@
     uint32_t mmapedSize;            // real allocation side
     uint32_t bytesPerPixel;
     uint32_t stride;
+    uint32_t locked;
+    uint32_t lockedUsage;
 };
 
 #endif // SYSTEM_HALS_CB_HANDLE_30_H
diff --git a/system/hals/mapper3.cpp b/system/hals/mapper3.cpp
index e74e76c..570ae5e 100644
--- a/system/hals/mapper3.cpp
+++ b/system/hals/mapper3.cpp
@@ -23,6 +23,10 @@
 #include "FormatConversions.h"
 #include "debug.h"
 
+#include "android/base/Tracing.h"
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 const int kOMX_COLOR_FormatYUV420Planar = 19;
 
 using ::android::hardware::hidl_handle;
@@ -445,11 +449,24 @@
                     }
                 }
             } else {
-                rcEnc->rcReadColorBuffer(rcEnc,
-                                         cb.hostHandle,
-                                         0, 0, cb.width, cb.height,
-                                         cb.glFormat, cb.glType,
-                                         bufferBits);
+                if (rcEnc->featureInfo()->hasReadColorBufferDma) {
+                    {
+                        AEMU_SCOPED_TRACE("bindDmaDirectly");
+                        rcEnc->bindDmaDirectly(bufferBits,
+                                getMmapedPhysAddr(cb.getMmapedOffset()));
+                    }
+                    rcEnc->rcReadColorBufferDMA(rcEnc,
+                        cb.hostHandle,
+                        0, 0, cb.width, cb.height,
+                        cb.glFormat, cb.glType,
+                        bufferBits, cb.width * cb.height * cb.bytesPerPixel);
+                } else {
+                    rcEnc->rcReadColorBuffer(rcEnc,
+                        cb.hostHandle,
+                        0, 0, cb.width, cb.height,
+                        cb.glFormat, cb.glType,
+                        bufferBits);
+                }
             }
         }
 
@@ -465,10 +482,14 @@
             cb.lockedHeight = cb.height;
         }
 
+        cb.locked = 1;
+        cb.lockedUsage = usage;
+
         RETURN(Error3::NONE);
     }
 
     Error3 unlockImpl(void* raw) {
+        AEMU_SCOPED_TRACE("unlockImpl body");
         if (!raw) {
             RETURN_ERROR(Error3::BAD_BUFFER);
         }
@@ -492,54 +513,60 @@
     }
 
     void unlockHostImpl(cb_handle_30_t& cb, char* const bufferBits) {
+        AEMU_SCOPED_TRACE("unlockHostImpl body");
         const int bpp = glUtilsPixelBitSize(cb.glFormat, cb.glType) >> 3;
-        const int left = cb.lockedLeft;
-        const int top = cb.lockedTop;
-        const int width = cb.lockedWidth;
-        const int height = cb.lockedHeight;
-        const uint32_t rgbSize = width * height * bpp;
-        std::vector<char> convertedBuf;
+        const uint32_t lockedUsage = cb.lockedUsage;
+        const uint32_t rgbSize = cb.width * cb.height * bpp;
         const char* bitsToSend;
         uint32_t sizeToSend;
 
-        if (gralloc_is_yuv_format(cb.format)) {
-            bitsToSend = bufferBits;
-            switch (static_cast<PixelFormat>(cb.format)) {
-            case PixelFormat::YV12:
-                get_yv12_offsets(width, height, nullptr, nullptr, &sizeToSend);
-                break;
-            case PixelFormat::YCBCR_420_888:
-                get_yuv420p_offsets(width, height, nullptr, nullptr, &sizeToSend);
-                break;
-            default:
-                CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
-                break;
-            }
-        } else {
-            convertedBuf.resize(rgbSize);
-            copy_rgb_buffer_from_unlocked(
-                convertedBuf.data(), bufferBits,
-                cb.width,
-                width, height, top, left, bpp);
-            bitsToSend = convertedBuf.data();
-            sizeToSend = rgbSize;
-        }
+        const uint32_t usageSwWrite = (uint32_t)BufferUsage::CPU_WRITE_MASK;
+        uint32_t readOnly = (!(lockedUsage & usageSwWrite));
 
-        {
-            const HostConnectionSession conn = getHostConnectionSession();
-            ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
-            rcEnc->bindDmaDirectly(bufferBits,
-                                   getMmapedPhysAddr(cb.getMmapedOffset()));
-            rcEnc->rcUpdateColorBufferDMA(rcEnc, cb.hostHandle,
-                    left, top, width, height,
-                    cb.glFormat, cb.glType,
-                    const_cast<char*>(bitsToSend), sizeToSend);
+        if (!readOnly) {
+            if (gralloc_is_yuv_format(cb.format)) {
+                bitsToSend = bufferBits;
+                switch (static_cast<PixelFormat>(cb.format)) {
+                    case PixelFormat::YV12:
+                        get_yv12_offsets(cb.width, cb.height, nullptr, nullptr, &sizeToSend);
+                        break;
+                    case PixelFormat::YCBCR_420_888:
+                        get_yuv420p_offsets(cb.width, cb.height, nullptr, nullptr, &sizeToSend);
+                        break;
+                    default:
+                        CRASH("Unexpected format, switch is out of sync with gralloc_is_yuv_format");
+                        break;
+                }
+            } else {
+                bitsToSend = bufferBits;
+                sizeToSend = rgbSize;
+            }
+
+            {
+                const HostConnectionSession conn = getHostConnectionSession();
+                ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
+                {
+                    AEMU_SCOPED_TRACE("bindDmaDirectly");
+                    rcEnc->bindDmaDirectly(bufferBits,
+                            getMmapedPhysAddr(cb.getMmapedOffset()));
+                }
+                {
+                    AEMU_SCOPED_TRACE("updateColorBuffer");
+                    rcEnc->rcUpdateColorBufferDMA(rcEnc, cb.hostHandle,
+                            0, 0, cb.width, cb.height,
+                            cb.glFormat, cb.glType,
+                            const_cast<char*>(bitsToSend),
+                            sizeToSend);
+                }
+            }
         }
 
         cb.lockedLeft = 0;
         cb.lockedTop = 0;
         cb.lockedWidth = 0;
         cb.lockedHeight = 0;
+        cb.locked = 0;
+        cb.lockedUsage = 0;
     }
 
     bool isSupportedImpl(const IMapper::BufferDescriptorInfo& descriptor) const {
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 2b3f0ae..eb5c921 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -74,6 +74,7 @@
 	rcComposeAsyncWithoutPost = (rcComposeAsyncWithoutPost_client_proc_t) getProc("rcComposeAsyncWithoutPost", userData);
 	rcCreateDisplayById = (rcCreateDisplayById_client_proc_t) getProc("rcCreateDisplayById", userData);
 	rcSetDisplayPoseDpi = (rcSetDisplayPoseDpi_client_proc_t) getProc("rcSetDisplayPoseDpi", userData);
+	rcReadColorBufferDMA = (rcReadColorBufferDMA_client_proc_t) getProc("rcReadColorBufferDMA", userData);
 	return 0;
 }
 
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index cf2f8f0..395e4bb 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -74,6 +74,7 @@
 	rcComposeAsyncWithoutPost_client_proc_t rcComposeAsyncWithoutPost;
 	rcCreateDisplayById_client_proc_t rcCreateDisplayById;
 	rcSetDisplayPoseDpi_client_proc_t rcSetDisplayPoseDpi;
+	rcReadColorBufferDMA_client_proc_t rcReadColorBufferDMA;
 	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 2bd5d1f..2e52898 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -76,6 +76,7 @@
 typedef void (renderControl_APIENTRY *rcComposeAsyncWithoutPost_client_proc_t) (void * ctx, uint32_t, void*);
 typedef int (renderControl_APIENTRY *rcCreateDisplayById_client_proc_t) (void * ctx, uint32_t);
 typedef int (renderControl_APIENTRY *rcSetDisplayPoseDpi_client_proc_t) (void * ctx, uint32_t, GLint, GLint, uint32_t, uint32_t, uint32_t);
+typedef int (renderControl_APIENTRY *rcReadColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
 
 
 #endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 1c544a8..5efed5f 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -2490,6 +2490,58 @@
 	return retval;
 }
 
+int rcReadColorBufferDMA_enc(void *self , uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
+{
+	AEMU_SCOPED_TRACE("rcReadColorBufferDMA encode");
+
+	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;
+
+	const unsigned int __size_pixels =  pixels_size;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 4 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_rcReadColorBufferDMA;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &colorbuffer, 4); ptr += 4;
+		memcpy(ptr, &x, 4); ptr += 4;
+		memcpy(ptr, &y, 4); ptr += 4;
+		memcpy(ptr, &width, 4); ptr += 4;
+		memcpy(ptr, &height, 4); ptr += 4;
+		memcpy(ptr, &format, 4); ptr += 4;
+		memcpy(ptr, &type, 4); ptr += 4;
+	*(uint64_t *)(ptr) = ctx->lockAndWriteDma(pixels, __size_pixels); ptr += 8;
+		memcpy(ptr, &pixels_size, 4); ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	// stream->readback(pixels, __size_pixels);
+	// if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
+
+	int retval;
+	stream->readback(&retval, 4);
+	if (useChecksum) checksumCalculator->addBuffer(&retval, 4);
+	if (useChecksum) {
+		unsigned char *checksumBufPtr = NULL;
+		unsigned char checksumBuf[ChecksumCalculator::kMaxChecksumSize];
+		if (checksumSize > 0) checksumBufPtr = &checksumBuf[0];
+		stream->readback(checksumBufPtr, checksumSize);
+		if (!checksumCalculator->validate(checksumBufPtr, checksumSize)) {
+			ALOGE("rcReadColorBufferDMA: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
 }  // namespace
 
 renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -2561,5 +2613,6 @@
 	this->rcComposeAsyncWithoutPost = &rcComposeAsyncWithoutPost_enc;
 	this->rcCreateDisplayById = &rcCreateDisplayById_enc;
 	this->rcSetDisplayPoseDpi = &rcSetDisplayPoseDpi_enc;
+	this->rcReadColorBufferDMA = &rcReadColorBufferDMA_enc;
 }
 
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index c58ddf5..5b2bedd 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -69,6 +69,7 @@
 	void rcComposeAsyncWithoutPost(uint32_t bufferSize, void* buffer);
 	int rcCreateDisplayById(uint32_t displayId);
 	int rcSetDisplayPoseDpi(uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h, uint32_t dpi);
+	int rcReadColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
 };
 
 #ifndef GET_CONTEXT
@@ -461,3 +462,9 @@
 	return ctx->rcSetDisplayPoseDpi(ctx, displayId, x, y, w, h, dpi);
 }
 
+int rcReadColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
+{
+	GET_CONTEXT;
+	return ctx->rcReadColorBufferDMA(ctx, colorbuffer, x, y, width, height, format, type, pixels, pixels_size);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 2adf3bf..577cbae 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -72,6 +72,7 @@
 	{"rcComposeAsyncWithoutPost", (void*)rcComposeAsyncWithoutPost},
 	{"rcCreateDisplayById", (void*)rcCreateDisplayById},
 	{"rcSetDisplayPoseDpi", (void*)rcSetDisplayPoseDpi},
+	{"rcReadColorBufferDMA", (void*)rcReadColorBufferDMA},
 };
 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 732d3e0..00249d6 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -67,7 +67,8 @@
 #define OP_rcComposeAsyncWithoutPost 					10061
 #define OP_rcCreateDisplayById 					10062
 #define OP_rcSetDisplayPoseDpi 					10063
-#define OP_last 					10064
+#define OP_rcReadColorBufferDMA 					10064
+#define OP_last 					10065
 
 
 #endif