Add DMA support for glMapBufferRange

Bug: 116046430
Test: run antutu and 3dmark
Change-Id: I3f204bac889d75cdeba21fd88f0920c04c5d589a
Signed-off-by: Roman Kiryanov <rkir@google.com>
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 3512a3b..220f198 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -2818,6 +2818,20 @@
     return ctx->glUnmapBuffer(ctx, target);
 }
 
+void* GL2Encoder::s_glMapBufferRangeAEMUImpl(GL2Encoder* ctx, GLenum target,
+                                             GLintptr offset, GLsizeiptr length,
+                                             GLbitfield access, BufferData* buf) {
+    char* bits = (char*)buf->m_fixedBuffer.ptr() + offset;
+
+    ctx->glMapBufferRangeAEMU(
+            ctx, target,
+            offset, length,
+            access,
+            bits);
+
+    return bits;
+}
+
 void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
     GL2Encoder* ctx = (GL2Encoder*)self;
     GLClientState* state = ctx->m_state;
@@ -2856,14 +2870,37 @@
     buf->m_mappedOffset = offset;
     buf->m_mappedLength = length;
 
-    char* todo = (char*)buf->m_fixedBuffer.ptr() + offset;
-    ctx->glMapBufferRangeAEMU(
-            ctx, target,
-            offset, length,
-            access,
-            todo);
+    if (ctx->hasExtension("ANDROID_EMU_dma_v2")) {
+        if (buf->dma_buffer.get().size < length) {
+            goldfish_dma_context region;
 
-    return todo;
+            const int PAGE_BITS = 12;
+            GLsizeiptr aligned_length = (length + (1 << PAGE_BITS) - 1) & ~((1 << PAGE_BITS) - 1);
+
+            if (goldfish_dma_create_region(aligned_length, &region)) {
+                buf->dma_buffer.reset(NULL);
+                return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
+            }
+
+            if (!goldfish_dma_map(&region)) {
+                buf->dma_buffer.reset(NULL);
+                return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
+            }
+
+            buf->m_guest_paddr = goldfish_dma_guest_paddr(&region);
+            buf->dma_buffer.reset(&region);
+        }
+
+        ctx->glMapBufferRangeDMA(
+                ctx, target,
+                offset, length,
+                access,
+                buf->m_guest_paddr);
+
+        return reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr);
+    } else {
+        return s_glMapBufferRangeAEMUImpl(ctx, target, offset, length, access, buf);
+    }
 }
 
 GLboolean GL2Encoder::s_glUnmapBuffer(void* self, GLenum target) {
@@ -2891,13 +2928,27 @@
 
     GLboolean host_res = GL_TRUE;
 
-    ctx->glUnmapBufferAEMU(
-            ctx, target,
-            buf->m_mappedOffset,
-            buf->m_mappedLength,
-            buf->m_mappedAccess,
-            (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
-            &host_res);
+    if (buf->dma_buffer.get().mapped_addr) {
+        memcpy(static_cast<char*>(buf->m_fixedBuffer.ptr()) + buf->m_mappedOffset,
+               reinterpret_cast<void*>(buf->dma_buffer.get().mapped_addr),
+               buf->m_mappedLength);
+
+        ctx->glUnmapBufferDMA(
+                ctx, target,
+                buf->m_mappedOffset,
+                buf->m_mappedLength,
+                buf->m_mappedAccess,
+                goldfish_dma_guest_paddr(&buf->dma_buffer.get()),
+                &host_res);
+    } else {
+        ctx->glUnmapBufferAEMU(
+                ctx, target,
+                buf->m_mappedOffset,
+                buf->m_mappedLength,
+                buf->m_mappedAccess,
+                (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
+                &host_res);
+    }
 
     buf->m_mapped = false;
     buf->m_mappedAccess = 0;
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 5a5d038..5b51f7b 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -414,6 +414,9 @@
     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 void* s_glMapBufferRangeAEMUImpl(GL2Encoder* ctx, GLenum target,
+                                            GLintptr offset, GLsizeiptr length,
+                                            GLbitfield access, BufferData* buf);
     static GLboolean s_glUnmapBuffer(void* self, GLenum target);
     static void s_glFlushMappedBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length);
 
diff --git a/system/GLESv2_enc/gl2_client_context.cpp b/system/GLESv2_enc/gl2_client_context.cpp
index 9eb4ac4..7da3e33 100644
--- a/system/GLESv2_enc/gl2_client_context.cpp
+++ b/system/GLESv2_enc/gl2_client_context.cpp
@@ -421,6 +421,8 @@
 	glGetFramebufferParameteriv = (glGetFramebufferParameteriv_client_proc_t) getProc("glGetFramebufferParameteriv", userData);
 	glGetTexLevelParameterfv = (glGetTexLevelParameterfv_client_proc_t) getProc("glGetTexLevelParameterfv", userData);
 	glGetTexLevelParameteriv = (glGetTexLevelParameteriv_client_proc_t) getProc("glGetTexLevelParameteriv", userData);
+	glMapBufferRangeDMA = (glMapBufferRangeDMA_client_proc_t) getProc("glMapBufferRangeDMA", userData);
+	glUnmapBufferDMA = (glUnmapBufferDMA_client_proc_t) getProc("glUnmapBufferDMA", userData);
 	return 0;
 }
 
diff --git a/system/GLESv2_enc/gl2_client_context.h b/system/GLESv2_enc/gl2_client_context.h
index 6616e53..e2400a9 100644
--- a/system/GLESv2_enc/gl2_client_context.h
+++ b/system/GLESv2_enc/gl2_client_context.h
@@ -421,6 +421,8 @@
 	glGetFramebufferParameteriv_client_proc_t glGetFramebufferParameteriv;
 	glGetTexLevelParameterfv_client_proc_t glGetTexLevelParameterfv;
 	glGetTexLevelParameteriv_client_proc_t glGetTexLevelParameteriv;
+	glMapBufferRangeDMA_client_proc_t glMapBufferRangeDMA;
+	glUnmapBufferDMA_client_proc_t glUnmapBufferDMA;
 	virtual ~gl2_client_context_t() {}
 
 	typedef gl2_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/GLESv2_enc/gl2_client_proc.h b/system/GLESv2_enc/gl2_client_proc.h
index 8c88678..8829c58 100644
--- a/system/GLESv2_enc/gl2_client_proc.h
+++ b/system/GLESv2_enc/gl2_client_proc.h
@@ -420,6 +420,8 @@
 typedef void (gl2_APIENTRY *glGetFramebufferParameteriv_client_proc_t) (void * ctx, GLenum, GLenum, GLint*);
 typedef void (gl2_APIENTRY *glGetTexLevelParameterfv_client_proc_t) (void * ctx, GLenum, GLint, GLenum, GLfloat*);
 typedef void (gl2_APIENTRY *glGetTexLevelParameteriv_client_proc_t) (void * ctx, GLenum, GLint, GLenum, GLint*);
+typedef void (gl2_APIENTRY *glMapBufferRangeDMA_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, uint64_t);
+typedef void (gl2_APIENTRY *glUnmapBufferDMA_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, uint64_t, GLboolean*);
 
 
 #endif
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index ffffa49..d5ae4b5 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -11044,6 +11044,78 @@
 	}
 }
 
+void glMapBufferRangeDMA_enc(void *self , GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr)
+{
+
+	gl2_encoder_context_t *ctx = (gl2_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 + 4 + 4 + 4 + 4 + 8;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glMapBufferRangeDMA;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &target, 4); ptr += 4;
+		memcpy(ptr, &offset, 4); ptr += 4;
+		memcpy(ptr, &length, 4); ptr += 4;
+		memcpy(ptr, &access, 4); ptr += 4;
+		memcpy(ptr, &paddr, 8); ptr += 8;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
+void glUnmapBufferDMA_enc(void *self , GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr, GLboolean* out_res)
+{
+
+	gl2_encoder_context_t *ctx = (gl2_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	const unsigned int __size_out_res =  (sizeof(GLboolean));
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + 8 + 0 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glUnmapBufferDMA;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &target, 4); ptr += 4;
+		memcpy(ptr, &offset, 4); ptr += 4;
+		memcpy(ptr, &length, 4); ptr += 4;
+		memcpy(ptr, &access, 4); ptr += 4;
+		memcpy(ptr, &paddr, 8); ptr += 8;
+	*(unsigned int *)(ptr) = __size_out_res; ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	stream->readback(out_res, __size_out_res);
+	if (useChecksum) checksumCalculator->addBuffer(out_res, __size_out_res);
+	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("glUnmapBufferDMA: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+}
+
 }  // namespace
 
 gl2_encoder_context_t::gl2_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -11462,5 +11534,7 @@
 	this->glGetFramebufferParameteriv = &glGetFramebufferParameteriv_enc;
 	this->glGetTexLevelParameterfv = &glGetTexLevelParameterfv_enc;
 	this->glGetTexLevelParameteriv = &glGetTexLevelParameteriv_enc;
+	this->glMapBufferRangeDMA = &glMapBufferRangeDMA_enc;
+	this->glUnmapBufferDMA = &glUnmapBufferDMA_enc;
 }
 
diff --git a/system/GLESv2_enc/gl2_entry.cpp b/system/GLESv2_enc/gl2_entry.cpp
index 5713921..f60eb44 100644
--- a/system/GLESv2_enc/gl2_entry.cpp
+++ b/system/GLESv2_enc/gl2_entry.cpp
@@ -416,6 +416,8 @@
 	void glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params);
 	void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params);
 	void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params);
+	void glMapBufferRangeDMA(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr);
+	void glUnmapBufferDMA(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr, GLboolean* out_res);
 };
 
 #ifndef GET_CONTEXT
@@ -2927,3 +2929,15 @@
 	ctx->glGetTexLevelParameteriv(ctx, target, level, pname, params);
 }
 
+void glMapBufferRangeDMA(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr)
+{
+	GET_CONTEXT;
+	ctx->glMapBufferRangeDMA(ctx, target, offset, length, access, paddr);
+}
+
+void glUnmapBufferDMA(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr, GLboolean* out_res)
+{
+	GET_CONTEXT;
+	ctx->glUnmapBufferDMA(ctx, target, offset, length, access, paddr, out_res);
+}
+
diff --git a/system/GLESv2_enc/gl2_opcodes.h b/system/GLESv2_enc/gl2_opcodes.h
index 497ebfb..2affe0e 100644
--- a/system/GLESv2_enc/gl2_opcodes.h
+++ b/system/GLESv2_enc/gl2_opcodes.h
@@ -414,7 +414,9 @@
 #define OP_glGetFramebufferParameteriv 					2456
 #define OP_glGetTexLevelParameterfv 					2457
 #define OP_glGetTexLevelParameteriv 					2458
-#define OP_last 					2459
+#define OP_glMapBufferRangeDMA 					2459
+#define OP_glUnmapBufferDMA 					2460
+#define OP_last 					2461
 
 
 #endif