rcReadColorBufferDMA + host side ColorBuffer create opts

Bug: 189960317

Change-Id: I2c45bd89c46a6b0f2ab5488b190f8a70c119118d
diff --git a/protocols/generic-apigen/ApiGen.cpp b/protocols/generic-apigen/ApiGen.cpp
index 1238512..5f140c6 100644
--- a/protocols/generic-apigen/ApiGen.cpp
+++ b/protocols/generic-apigen/ApiGen.cpp
@@ -792,11 +792,19 @@
                     if (evars[j].guestUnpackExpression() != "") {
                         fprintf(fp, "%s%s;\n", indent, evars[j].guestUnpackExpression().c_str());
                     } else {
-                        fprintf(fp, "%sstream->readback(%s, __size_%s);\n",
+                        if (evars[j].isDMA()) {
+                            fprintf(fp, "%s// Skip readback for var %s as it's DMA\n", indent, varname);
+                        } else {
+                            fprintf(fp, "%sstream->readback(%s, __size_%s);\n",
+                                    indent, varname, varname);
+                        }
+                    }
+                    if (evars[j].isDMA()) {
+                        fprintf(fp, "%s// Skip checksum for var %s as it's DMA\n", indent, varname);
+                    } else {
+                        fprintf(fp, "%sif (useChecksum) checksumCalculator->addBuffer(%s, __size_%s);\n",
                                 indent, varname, varname);
                     }
-                    fprintf(fp, "%sif (useChecksum) checksumCalculator->addBuffer(%s, __size_%s);\n",
-                            indent, varname, varname);
                     if (evars[j].nullAllowed()) {
                         fprintf(fp, "\t}\n");
                     }
diff --git a/protocols/renderControl/renderControl.attrib b/protocols/renderControl/renderControl.attrib
index d8c3ac1..5cd75f0 100644
--- a/protocols/renderControl/renderControl.attrib
+++ b/protocols/renderControl/renderControl.attrib
@@ -111,3 +111,9 @@
     dir buffer in
     len buffer bufferSize
     flag flushOnEncode
+
+rcReadColorBufferDMA
+    dir pixels out
+    len pixels pixels_size
+    var_flag pixels DMA
+
diff --git a/protocols/renderControl/renderControl.in b/protocols/renderControl/renderControl.in
index 5be924e..acd2ca8 100644
--- a/protocols/renderControl/renderControl.in
+++ b/protocols/renderControl/renderControl.in
@@ -62,3 +62,4 @@
 GL_ENTRY(void, rcComposeAsyncWithoutPost, uint32_t bufferSize, void *buffer);
 GL_ENTRY(int, rcCreateDisplayById, uint32_t displayId);
 GL_ENTRY(int, rcSetDisplayPoseDpi, uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h, uint32_t dpi);
+GL_ENTRY(int, rcReadColorBufferDMA, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
diff --git a/stream-servers/RenderControl.cpp b/stream-servers/RenderControl.cpp
index b03ac7e..3333f7f 100644
--- a/stream-servers/RenderControl.cpp
+++ b/stream-servers/RenderControl.cpp
@@ -238,6 +238,9 @@
 // Async vkQSRI
 static const char* kVulkanAsyncQsri = "ANDROID_EMU_vulkan_async_qsri";
 
+// Read color buffer DMA
+static const char* kReadColorBufferDma = "ANDROID_EMU_read_color_buffer_dma";
+
 static void rcTriggerWait(uint64_t glsync_ptr,
                           uint64_t thread_ptr,
                           uint64_t timeline);
@@ -492,6 +495,7 @@
     bool vulkanBatchedDescriptorSetUpdate = shouldEnableBatchedDescriptorSetUpdate();
     bool syncBufferDataEnabled = true;
     bool vulkanAsyncQsri = shouldEnableVulkanAsyncQsri();
+    bool readColorBufferDma = directMemEnabled && hasSharedSlotsHostMemoryAllocatorEnabled;
 
     if (isChecksumEnabled && name == GL_EXTENSIONS) {
         glStr += ChecksumCalculatorThreadInfo::getMaxVersionString();
@@ -625,6 +629,11 @@
         glStr += " ";
     }
 
+    if (readColorBufferDma) {
+        glStr += kReadColorBufferDma;
+        glStr += " ";
+    }
+
     if (name == GL_EXTENSIONS) {
 
         GLESDispatchMaxVersion guestExtVer = GLES_DISPATCH_MAX_VERSION_2;
@@ -1532,6 +1541,23 @@
     fenceSync->decRef();
 }
 
+static int rcReadColorBufferDMA(uint32_t colorBuffer,
+                                GLint x, GLint y,
+                                GLint width, GLint height,
+                                GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
+{
+    FrameBuffer *fb = FrameBuffer::getFB();
+    if (!fb) {
+        return -1;
+    }
+
+    // Update from Vulkan if necessary
+    goldfish_vk::updateColorBufferFromVkImage(colorBuffer);
+
+    fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
+    return 0;
+}
+
 void initRenderControlContext(renderControl_decoder_context_t *dec)
 {
     dec->rcGetRendererVersion = rcGetRendererVersion;
@@ -1598,4 +1624,5 @@
     dec->rcComposeAsyncWithoutPost = rcComposeAsyncWithoutPost;
     dec->rcCreateDisplayById = rcCreateDisplayById;
     dec->rcSetDisplayPoseDpi = rcSetDisplayPoseDpi;
+    dec->rcReadColorBufferDMA = rcReadColorBufferDMA;
 }
diff --git a/stream-servers/renderControl_dec/renderControl_dec.cpp b/stream-servers/renderControl_dec/renderControl_dec.cpp
index 8b27562..61c8f14 100644
--- a/stream-servers/renderControl_dec/renderControl_dec.cpp
+++ b/stream-servers/renderControl_dec/renderControl_dec.cpp
@@ -1265,6 +1265,36 @@
 			android::base::endTrace();
 			break;
 		}
+		case OP_rcReadColorBufferDMA: {
+			android::base::beginTrace("rcReadColorBufferDMA decode");
+			uint32_t var_colorbuffer = Unpack<uint32_t,uint32_t>(ptr + 8);
+			GLint var_x = Unpack<GLint,uint32_t>(ptr + 8 + 4);
+			GLint var_y = Unpack<GLint,uint32_t>(ptr + 8 + 4 + 4);
+			GLint var_width = Unpack<GLint,uint32_t>(ptr + 8 + 4 + 4 + 4);
+			GLint var_height = Unpack<GLint,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4);
+			GLenum var_format = Unpack<GLenum,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4);
+			GLenum var_type = Unpack<GLenum,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4);
+			uint64_t var_pixels_guest_paddr = Unpack<uint64_t,uint64_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
+			void* var_pixels = stream->getDmaForReading(var_pixels_guest_paddr);
+			uint32_t size_pixels __attribute__((unused)) = Unpack<uint32_t,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8);
+			uint32_t var_pixels_size = Unpack<uint32_t,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8);
+			if (useChecksum) {
+				ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 4, ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 4, checksumSize, 
+					"renderControl_decoder_context_t::decode, OP_rcReadColorBufferDMA: GL checksumCalculator failure\n");
+			}
+			size_t totalTmpSize = sizeof(int);
+			totalTmpSize += checksumSize;
+			unsigned char *tmpBuf = stream->alloc(totalTmpSize);
+			*(int *)(&tmpBuf[0]) = 			this->rcReadColorBufferDMA(var_colorbuffer, var_x, var_y, var_width, var_height, var_format, var_type, var_pixels, var_pixels_size);
+			stream->unlockDma(var_pixels_guest_paddr);
+			if (useChecksum) {
+				ChecksumCalculatorThreadInfo::writeChecksum(checksumCalc, &tmpBuf[0], totalTmpSize - checksumSize, &tmpBuf[totalTmpSize - checksumSize], checksumSize);
+			}
+			stream->flush();
+			SET_LASTCALL("rcReadColorBufferDMA");
+			android::base::endTrace();
+			break;
+		}
 		default:
 			return ptr - (unsigned char*)buf;
 		} //switch
diff --git a/stream-servers/renderControl_dec/renderControl_opcodes.h b/stream-servers/renderControl_dec/renderControl_opcodes.h
index 732d3e0..00249d6 100644
--- a/stream-servers/renderControl_dec/renderControl_opcodes.h
+++ b/stream-servers/renderControl_dec/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
diff --git a/stream-servers/renderControl_dec/renderControl_server_context.cpp b/stream-servers/renderControl_dec/renderControl_server_context.cpp
index c6cbf23..e840603 100644
--- a/stream-servers/renderControl_dec/renderControl_server_context.cpp
+++ b/stream-servers/renderControl_dec/renderControl_server_context.cpp
@@ -74,6 +74,7 @@
 	rcComposeAsyncWithoutPost = (rcComposeAsyncWithoutPost_server_proc_t) getProc("rcComposeAsyncWithoutPost", userData);
 	rcCreateDisplayById = (rcCreateDisplayById_server_proc_t) getProc("rcCreateDisplayById", userData);
 	rcSetDisplayPoseDpi = (rcSetDisplayPoseDpi_server_proc_t) getProc("rcSetDisplayPoseDpi", userData);
+	rcReadColorBufferDMA = (rcReadColorBufferDMA_server_proc_t) getProc("rcReadColorBufferDMA", userData);
 	return 0;
 }
 
diff --git a/stream-servers/renderControl_dec/renderControl_server_context.h b/stream-servers/renderControl_dec/renderControl_server_context.h
index f151288..7a9640c 100644
--- a/stream-servers/renderControl_dec/renderControl_server_context.h
+++ b/stream-servers/renderControl_dec/renderControl_server_context.h
@@ -74,6 +74,7 @@
 	rcComposeAsyncWithoutPost_server_proc_t rcComposeAsyncWithoutPost;
 	rcCreateDisplayById_server_proc_t rcCreateDisplayById;
 	rcSetDisplayPoseDpi_server_proc_t rcSetDisplayPoseDpi;
+	rcReadColorBufferDMA_server_proc_t rcReadColorBufferDMA;
 	virtual ~renderControl_server_context_t() {}
 	int initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);
 };
diff --git a/stream-servers/renderControl_dec/renderControl_server_proc.h b/stream-servers/renderControl_dec/renderControl_server_proc.h
index 84d192a..c3769eb 100644
--- a/stream-servers/renderControl_dec/renderControl_server_proc.h
+++ b/stream-servers/renderControl_dec/renderControl_server_proc.h
@@ -76,6 +76,7 @@
 typedef void (renderControl_APIENTRY *rcComposeAsyncWithoutPost_server_proc_t) (uint32_t, void*);
 typedef int (renderControl_APIENTRY *rcCreateDisplayById_server_proc_t) (uint32_t);
 typedef int (renderControl_APIENTRY *rcSetDisplayPoseDpi_server_proc_t) (uint32_t, GLint, GLint, uint32_t, uint32_t, uint32_t);
+typedef int (renderControl_APIENTRY *rcReadColorBufferDMA_server_proc_t) (uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
 
 
 #endif