Support GL_EXT_robustness

We reuse glReadPixels, glGetUniformfv and glGetUniformiv for the
implementation.

BUG: 121414786

Test: manual

Change-Id: Ic956318f366cd59bbfc1a94267c0456204b7c701
diff --git a/system/GLESv1_enc/GLEncoder.cpp b/system/GLESv1_enc/GLEncoder.cpp
index 8db973f..968dfd6 100644
--- a/system/GLESv1_enc/GLEncoder.cpp
+++ b/system/GLESv1_enc/GLEncoder.cpp
@@ -98,6 +98,11 @@
         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
         break;
 
+    case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+        // BUG: 121414786
+        *ptr = GL_LOSE_CONTEXT_ON_RESET_EXT;
+        break;
+
     default:
         if (!state->getClientStateParameter<GLint>(param,ptr)) {
             ctx->m_glGetIntegerv_enc(self, param, ptr);
@@ -1078,6 +1083,8 @@
     OVERRIDE(glFramebufferTexture2DOES);
     OVERRIDE(glFramebufferTexture2DMultisampleIMG);
     OVERRIDE(glGetFramebufferAttachmentParameterivOES);
+
+    this->glReadnPixelsEXT = s_glReadnPixelsEXT;
 }
 
 GLEncoder::~GLEncoder()
@@ -1096,3 +1103,12 @@
     GLEncoder *ctx = (GLEncoder *)self;
     ctx->glFinishRoundTrip(self);
 }
+
+void GLEncoder::s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
+        GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
+        GLvoid* pixels) {
+    GLEncoder *ctx = (GLEncoder*)self;
+    SET_ERROR_IF(bufSize < ctx->pixelDataSize(width, height, format,
+        type, 1), GL_INVALID_OPERATION);
+    ctx->glReadPixels(self, x, y, width, height, format, type, pixels);
+}
diff --git a/system/GLESv1_enc/GLEncoder.h b/system/GLESv1_enc/GLEncoder.h
index 1518030..95537a2 100644
--- a/system/GLESv1_enc/GLEncoder.h
+++ b/system/GLESv1_enc/GLEncoder.h
@@ -164,6 +164,9 @@
     static void s_glFramebufferTexture2DOES(void* self, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
     static void s_glFramebufferTexture2DMultisampleIMG(void* self, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
     static void s_glGetFramebufferAttachmentParameterivOES(void* self, GLenum target, GLenum attachment, GLenum pname, GLint* params);
+    static void s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
+            GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
+            GLvoid* pixels);
 
 public:
     glEGLImageTargetTexture2DOES_client_proc_t m_glEGLImageTargetTexture2DOES_enc;
diff --git a/system/GLESv1_enc/gl_client_context.cpp b/system/GLESv1_enc/gl_client_context.cpp
index cb504c8..64fc5f5 100644
--- a/system/GLESv1_enc/gl_client_context.cpp
+++ b/system/GLESv1_enc/gl_client_context.cpp
@@ -301,6 +301,8 @@
 	glExtGetProgramBinarySourceQCOM = (glExtGetProgramBinarySourceQCOM_client_proc_t) getProc("glExtGetProgramBinarySourceQCOM", userData);
 	glStartTilingQCOM = (glStartTilingQCOM_client_proc_t) getProc("glStartTilingQCOM", userData);
 	glEndTilingQCOM = (glEndTilingQCOM_client_proc_t) getProc("glEndTilingQCOM", userData);
+	glGetGraphicsResetStatusEXT = (glGetGraphicsResetStatusEXT_client_proc_t) getProc("glGetGraphicsResetStatusEXT", userData);
+	glReadnPixelsEXT = (glReadnPixelsEXT_client_proc_t) getProc("glReadnPixelsEXT", userData);
 	return 0;
 }
 
diff --git a/system/GLESv1_enc/gl_client_context.h b/system/GLESv1_enc/gl_client_context.h
index 6d46a9b..8e341d3 100644
--- a/system/GLESv1_enc/gl_client_context.h
+++ b/system/GLESv1_enc/gl_client_context.h
@@ -301,6 +301,8 @@
 	glExtGetProgramBinarySourceQCOM_client_proc_t glExtGetProgramBinarySourceQCOM;
 	glStartTilingQCOM_client_proc_t glStartTilingQCOM;
 	glEndTilingQCOM_client_proc_t glEndTilingQCOM;
+	glGetGraphicsResetStatusEXT_client_proc_t glGetGraphicsResetStatusEXT;
+	glReadnPixelsEXT_client_proc_t glReadnPixelsEXT;
 	virtual ~gl_client_context_t() {}
 
 	typedef gl_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/GLESv1_enc/gl_client_proc.h b/system/GLESv1_enc/gl_client_proc.h
index 7d0f857..92eba98 100644
--- a/system/GLESv1_enc/gl_client_proc.h
+++ b/system/GLESv1_enc/gl_client_proc.h
@@ -303,6 +303,8 @@
 typedef void (gl_APIENTRY *glExtGetProgramBinarySourceQCOM_client_proc_t) (void * ctx, GLuint, GLenum, GLchar*, GLint*);
 typedef void (gl_APIENTRY *glStartTilingQCOM_client_proc_t) (void * ctx, GLuint, GLuint, GLuint, GLuint, GLbitfield);
 typedef void (gl_APIENTRY *glEndTilingQCOM_client_proc_t) (void * ctx, GLbitfield);
+typedef GLenum (gl_APIENTRY *glGetGraphicsResetStatusEXT_client_proc_t) (void * ctx);
+typedef void (gl_APIENTRY *glReadnPixelsEXT_client_proc_t) (void * ctx, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, GLvoid*);
 
 
 #endif
diff --git a/system/GLESv1_enc/gl_enc.cpp b/system/GLESv1_enc/gl_enc.cpp
index 31c1269..4e672c6 100644
--- a/system/GLESv1_enc/gl_enc.cpp
+++ b/system/GLESv1_enc/gl_enc.cpp
@@ -8278,6 +8278,90 @@
 
 }
 
+GLenum glGetGraphicsResetStatusEXT_enc(void *self )
+{
+
+	gl_encoder_context_t *ctx = (gl_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;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glGetGraphicsResetStatusEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	GLenum 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("glGetGraphicsResetStatusEXT: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
+void glReadnPixelsEXT_enc(void *self , GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data)
+{
+
+	gl_encoder_context_t *ctx = (gl_encoder_context_t *)self;
+	IOStream *stream = ctx->m_stream;
+	ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+	bool useChecksum = checksumCalculator->getVersion() > 0;
+
+	const unsigned int __size_data =  bufSize;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 0 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glReadnPixelsEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 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;
+		memcpy(ptr, &bufSize, 4); ptr += 4;
+	*(unsigned int *)(ptr) = __size_data; ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	stream->readback(data, __size_data);
+	if (useChecksum) checksumCalculator->addBuffer(data, __size_data);
+	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("glReadnPixelsEXT: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+}
+
 }  // namespace
 
 gl_encoder_context_t::gl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -8576,5 +8660,7 @@
 	this->glExtGetProgramBinarySourceQCOM = (glExtGetProgramBinarySourceQCOM_client_proc_t) &enc_unsupported;
 	this->glStartTilingQCOM = &glStartTilingQCOM_enc;
 	this->glEndTilingQCOM = &glEndTilingQCOM_enc;
+	this->glGetGraphicsResetStatusEXT = &glGetGraphicsResetStatusEXT_enc;
+	this->glReadnPixelsEXT = &glReadnPixelsEXT_enc;
 }
 
diff --git a/system/GLESv1_enc/gl_entry.cpp b/system/GLESv1_enc/gl_entry.cpp
index 0101e9d..27a8faf 100644
--- a/system/GLESv1_enc/gl_entry.cpp
+++ b/system/GLESv1_enc/gl_entry.cpp
@@ -296,6 +296,8 @@
 	void glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar* source, GLint* length);
 	void glStartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
 	void glEndTilingQCOM(GLbitfield preserveMask);
+	GLenum glGetGraphicsResetStatusEXT();
+	void glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data);
 };
 
 #ifndef GET_CONTEXT
@@ -2062,3 +2064,15 @@
 	ctx->glEndTilingQCOM(ctx, preserveMask);
 }
 
+GLenum glGetGraphicsResetStatusEXT()
+{
+	GET_CONTEXT;
+	return ctx->glGetGraphicsResetStatusEXT(ctx);
+}
+
+void glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data)
+{
+	GET_CONTEXT;
+	ctx->glReadnPixelsEXT(ctx, x, y, width, height, format, type, bufSize, data);
+}
+
diff --git a/system/GLESv1_enc/gl_ftable.h b/system/GLESv1_enc/gl_ftable.h
index 67ba6f4..2570a82 100644
--- a/system/GLESv1_enc/gl_ftable.h
+++ b/system/GLESv1_enc/gl_ftable.h
@@ -281,6 +281,8 @@
 	{"glExtGetProgramBinarySourceQCOM", (void*)glExtGetProgramBinarySourceQCOM},
 	{"glStartTilingQCOM", (void*)glStartTilingQCOM},
 	{"glEndTilingQCOM", (void*)glEndTilingQCOM},
+	{"glGetGraphicsResetStatusEXT", (void*)glGetGraphicsResetStatusEXT},
+	{"glReadnPixelsEXT", (void*)glReadnPixelsEXT},
 };
 static const int gl_num_funcs = sizeof(gl_funcs_by_name) / sizeof(struct _gl_funcs_by_name);
 
diff --git a/system/GLESv1_enc/gl_opcodes.h b/system/GLESv1_enc/gl_opcodes.h
index 319d0a1..fc65260 100644
--- a/system/GLESv1_enc/gl_opcodes.h
+++ b/system/GLESv1_enc/gl_opcodes.h
@@ -294,7 +294,9 @@
 #define OP_glExtGetProgramBinarySourceQCOM 					1312
 #define OP_glStartTilingQCOM 					1313
 #define OP_glEndTilingQCOM 					1314
-#define OP_last 					1315
+#define OP_glGetGraphicsResetStatusEXT 					1315
+#define OP_glReadnPixelsEXT 					1316
+#define OP_last 					1317
 
 
 #endif
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 2be0699..50cca08 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -363,6 +363,11 @@
     OVERRIDE_CUSTOM(glDrawElementsIndirect);
 
     OVERRIDE(glTexStorage2DMultisample);
+
+    OVERRIDE_CUSTOM(glGetGraphicsResetStatusEXT);
+    OVERRIDE_CUSTOM(glReadnPixelsEXT);
+    OVERRIDE_CUSTOM(glGetnUniformfvEXT);
+    OVERRIDE_CUSTOM(glGetnUniformivEXT);
 }
 
 GL2Encoder::~GL2Encoder()
@@ -853,6 +858,10 @@
             ctx->m_max_vertexAttribBindings = *ptr;
         }
         break;
+    case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+        // BUG: 121414786
+        *ptr = GL_LOSE_CONTEXT_ON_RESET_EXT;
+        break;
     default:
         SET_ERROR_IF(!state, GL_INVALID_OPERATION);
         if (!state->getClientStateParameter<GLint>(param, ptr)) {
@@ -5320,3 +5329,32 @@
     ctx->m_glTexStorage2DMultisample_enc(ctx, target, samples, internalformat, width, height, fixedsamplelocations);
 }
 
+GLenum GL2Encoder::s_glGetGraphicsResetStatusEXT(void* self) {
+    (void)self;
+    return GL_NO_ERROR;
+}
+
+void GL2Encoder::s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
+        GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
+        GLvoid* pixels) {
+    GL2Encoder *ctx = (GL2Encoder*)self;
+    SET_ERROR_IF(bufSize < glesv2_enc::pixelDataSize(self, width, height, format,
+        type, 1), GL_INVALID_OPERATION);
+    s_glReadPixels(self, x, y, width, height, format, type, pixels);
+}
+
+void GL2Encoder::s_glGetnUniformfvEXT(void *self, GLuint program, GLint location,
+        GLsizei bufSize, GLfloat* params) {
+    GL2Encoder *ctx = (GL2Encoder*)self;
+    SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
+        location)), GL_INVALID_OPERATION);
+    s_glGetUniformfv(self, program, location, params);
+}
+
+void GL2Encoder::s_glGetnUniformivEXT(void *self, GLuint program, GLint location,
+        GLsizei bufSize, GLint* params) {
+    GL2Encoder *ctx = (GL2Encoder*)self;
+    SET_ERROR_IF(bufSize < glSizeof(glesv2_enc::uniformType(self, program,
+        location)), GL_INVALID_OPERATION);
+    s_glGetUniformiv(self, program, location, params);
+}
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 39f7feb..35d4737 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -719,6 +719,14 @@
     glTexStorage2DMultisample_client_proc_t m_glTexStorage2DMultisample_enc;
     static void s_glTexStorage2DMultisample(void* self, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
 
+    static GLenum s_glGetGraphicsResetStatusEXT(void* self);
+    static void s_glReadnPixelsEXT(void* self, GLint x, GLint y, GLsizei width,
+            GLsizei height, GLenum format, GLenum type, GLsizei bufSize,
+            GLvoid* pixels);
+    static void s_glGetnUniformfvEXT(void *self, GLuint program, GLint location,
+            GLsizei bufSize, GLfloat* params);
+    static void s_glGetnUniformivEXT(void *self, GLuint program, GLint location,
+            GLsizei bufSize, GLint* params);
 public:
     glEGLImageTargetTexture2DOES_client_proc_t m_glEGLImageTargetTexture2DOES_enc;
 
diff --git a/system/GLESv2_enc/gl2_client_context.cpp b/system/GLESv2_enc/gl2_client_context.cpp
index 482b604..783ecd0 100644
--- a/system/GLESv2_enc/gl2_client_context.cpp
+++ b/system/GLESv2_enc/gl2_client_context.cpp
@@ -426,6 +426,10 @@
 	glMapBufferRangeDirect = (glMapBufferRangeDirect_client_proc_t) getProc("glMapBufferRangeDirect", userData);
 	glUnmapBufferDirect = (glUnmapBufferDirect_client_proc_t) getProc("glUnmapBufferDirect", userData);
 	glFlushMappedBufferRangeDirect = (glFlushMappedBufferRangeDirect_client_proc_t) getProc("glFlushMappedBufferRangeDirect", userData);
+	glGetGraphicsResetStatusEXT = (glGetGraphicsResetStatusEXT_client_proc_t) getProc("glGetGraphicsResetStatusEXT", userData);
+	glReadnPixelsEXT = (glReadnPixelsEXT_client_proc_t) getProc("glReadnPixelsEXT", userData);
+	glGetnUniformfvEXT = (glGetnUniformfvEXT_client_proc_t) getProc("glGetnUniformfvEXT", userData);
+	glGetnUniformivEXT = (glGetnUniformivEXT_client_proc_t) getProc("glGetnUniformivEXT", userData);
 	return 0;
 }
 
diff --git a/system/GLESv2_enc/gl2_client_context.h b/system/GLESv2_enc/gl2_client_context.h
index 4a11c2a..fe5c893 100644
--- a/system/GLESv2_enc/gl2_client_context.h
+++ b/system/GLESv2_enc/gl2_client_context.h
@@ -426,6 +426,10 @@
 	glMapBufferRangeDirect_client_proc_t glMapBufferRangeDirect;
 	glUnmapBufferDirect_client_proc_t glUnmapBufferDirect;
 	glFlushMappedBufferRangeDirect_client_proc_t glFlushMappedBufferRangeDirect;
+	glGetGraphicsResetStatusEXT_client_proc_t glGetGraphicsResetStatusEXT;
+	glReadnPixelsEXT_client_proc_t glReadnPixelsEXT;
+	glGetnUniformfvEXT_client_proc_t glGetnUniformfvEXT;
+	glGetnUniformivEXT_client_proc_t glGetnUniformivEXT;
 	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 05d006a..1237dad 100644
--- a/system/GLESv2_enc/gl2_client_proc.h
+++ b/system/GLESv2_enc/gl2_client_proc.h
@@ -428,6 +428,10 @@
 typedef uint64_t (gl2_APIENTRY *glMapBufferRangeDirect_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, uint64_t);
 typedef void (gl2_APIENTRY *glUnmapBufferDirect_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, uint64_t, uint64_t, GLboolean*);
 typedef void (gl2_APIENTRY *glFlushMappedBufferRangeDirect_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield);
+typedef GLenum (gl2_APIENTRY *glGetGraphicsResetStatusEXT_client_proc_t) (void * ctx);
+typedef void (gl2_APIENTRY *glReadnPixelsEXT_client_proc_t) (void * ctx, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLsizei, GLvoid*);
+typedef void (gl2_APIENTRY *glGetnUniformfvEXT_client_proc_t) (void * ctx, GLuint, GLint, GLsizei, GLfloat*);
+typedef void (gl2_APIENTRY *glGetnUniformivEXT_client_proc_t) (void * ctx, GLuint, GLint, GLsizei, GLint*);
 
 
 #endif
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index 300994e..cae2416 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -3030,9 +3030,7 @@
 	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
 	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
 
-	// TODO: emugen produces bad code here, see b/79208762
-	stream->readbackPixels(self, width, height, format, type, pixels);
-
+	stream->readback(pixels, __size_pixels);
 	if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
 	if (useChecksum) {
 		unsigned char *checksumBufPtr = NULL;
@@ -11232,6 +11230,172 @@
 
 }
 
+GLenum glGetGraphicsResetStatusEXT_enc(void *self )
+{
+
+	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;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glGetGraphicsResetStatusEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+
+	GLenum 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("glGetGraphicsResetStatusEXT: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+	return retval;
+}
+
+void glReadnPixelsEXT_enc(void *self , GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data)
+{
+
+	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_data =  bufSize;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 0 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glReadnPixelsEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 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;
+		memcpy(ptr, &bufSize, 4); ptr += 4;
+	*(unsigned int *)(ptr) = __size_data; ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	stream->readback(data, __size_data);
+	if (useChecksum) checksumCalculator->addBuffer(data, __size_data);
+	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("glReadnPixelsEXT: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+}
+
+void glGetnUniformfvEXT_enc(void *self , GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+
+	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_params =  bufSize;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 0 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glGetnUniformfvEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &program, 4); ptr += 4;
+		memcpy(ptr, &location, 4); ptr += 4;
+		memcpy(ptr, &bufSize, 4); ptr += 4;
+	*(unsigned int *)(ptr) = __size_params; ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	stream->readback(params, __size_params);
+	if (useChecksum) checksumCalculator->addBuffer(params, __size_params);
+	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("glGetnUniformfvEXT: GL communication error, please report this issue to b.android.com.\n");
+			abort();
+		}
+	}
+}
+
+void glGetnUniformivEXT_enc(void *self , GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+
+	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_params =  bufSize;
+	 unsigned char *ptr;
+	 unsigned char *buf;
+	 const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 0 + 1*4;
+	 const size_t checksumSize = checksumCalculator->checksumByteSize();
+	 const size_t totalSize = sizeWithoutChecksum + checksumSize;
+	buf = stream->alloc(totalSize);
+	ptr = buf;
+	int tmp = OP_glGetnUniformivEXT;memcpy(ptr, &tmp, 4); ptr += 4;
+	memcpy(ptr, &totalSize, 4);  ptr += 4;
+
+		memcpy(ptr, &program, 4); ptr += 4;
+		memcpy(ptr, &location, 4); ptr += 4;
+		memcpy(ptr, &bufSize, 4); ptr += 4;
+	*(unsigned int *)(ptr) = __size_params; ptr += 4;
+
+	if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+	if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+	stream->readback(params, __size_params);
+	if (useChecksum) checksumCalculator->addBuffer(params, __size_params);
+	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("glGetnUniformivEXT: 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)
@@ -11655,5 +11819,9 @@
 	this->glMapBufferRangeDirect = &glMapBufferRangeDirect_enc;
 	this->glUnmapBufferDirect = &glUnmapBufferDirect_enc;
 	this->glFlushMappedBufferRangeDirect = &glFlushMappedBufferRangeDirect_enc;
+	this->glGetGraphicsResetStatusEXT = &glGetGraphicsResetStatusEXT_enc;
+	this->glReadnPixelsEXT = &glReadnPixelsEXT_enc;
+	this->glGetnUniformfvEXT = &glGetnUniformfvEXT_enc;
+	this->glGetnUniformivEXT = &glGetnUniformivEXT_enc;
 }
 
diff --git a/system/GLESv2_enc/gl2_entry.cpp b/system/GLESv2_enc/gl2_entry.cpp
index 118b2ee..70b22bc 100644
--- a/system/GLESv2_enc/gl2_entry.cpp
+++ b/system/GLESv2_enc/gl2_entry.cpp
@@ -421,6 +421,10 @@
 	uint64_t glMapBufferRangeDirect(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr);
 	void glUnmapBufferDirect(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, uint64_t paddr, uint64_t guest_ptr, GLboolean* out_res);
 	void glFlushMappedBufferRangeDirect(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+	GLenum glGetGraphicsResetStatusEXT();
+	void glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data);
+	void glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
+	void glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params);
 };
 
 #ifndef GET_CONTEXT
@@ -2962,3 +2966,27 @@
 	ctx->glFlushMappedBufferRangeDirect(ctx, target, offset, length, access);
 }
 
+GLenum glGetGraphicsResetStatusEXT()
+{
+	GET_CONTEXT;
+	return ctx->glGetGraphicsResetStatusEXT(ctx);
+}
+
+void glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid* data)
+{
+	GET_CONTEXT;
+	ctx->glReadnPixelsEXT(ctx, x, y, width, height, format, type, bufSize, data);
+}
+
+void glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+	GET_CONTEXT;
+	ctx->glGetnUniformfvEXT(ctx, program, location, bufSize, params);
+}
+
+void glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+	GET_CONTEXT;
+	ctx->glGetnUniformivEXT(ctx, program, location, bufSize, params);
+}
+
diff --git a/system/GLESv2_enc/gl2_ftable.h b/system/GLESv2_enc/gl2_ftable.h
index 99fe978..0e93cf1 100644
--- a/system/GLESv2_enc/gl2_ftable.h
+++ b/system/GLESv2_enc/gl2_ftable.h
@@ -381,6 +381,10 @@
 	{"glGetFramebufferParameteriv", (void*)glGetFramebufferParameteriv},
 	{"glGetTexLevelParameterfv", (void*)glGetTexLevelParameterfv},
 	{"glGetTexLevelParameteriv", (void*)glGetTexLevelParameteriv},
+	{"glGetGraphicsResetStatusEXT", (void*)glGetGraphicsResetStatusEXT},
+	{"glReadnPixelsEXT", (void*)glReadnPixelsEXT},
+	{"glGetnUniformfvEXT", (void*)glGetnUniformfvEXT},
+	{"glGetnUniformivEXT", (void*)glGetnUniformivEXT},
 };
 static const int gl2_num_funcs = sizeof(gl2_funcs_by_name) / sizeof(struct _gl2_funcs_by_name);
 
diff --git a/system/GLESv2_enc/gl2_opcodes.h b/system/GLESv2_enc/gl2_opcodes.h
index b359570..96688db 100644
--- a/system/GLESv2_enc/gl2_opcodes.h
+++ b/system/GLESv2_enc/gl2_opcodes.h
@@ -419,7 +419,11 @@
 #define OP_glMapBufferRangeDirect 					2461
 #define OP_glUnmapBufferDirect 					2462
 #define OP_glFlushMappedBufferRangeDirect 					2463
-#define OP_last 					2464
+#define OP_glGetGraphicsResetStatusEXT 					2464
+#define OP_glReadnPixelsEXT 					2465
+#define OP_glGetnUniformfvEXT 					2466
+#define OP_glGetnUniformivEXT 					2467
+#define OP_last 					2468
 
 
 #endif
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 23fb8cc..c5e27ed 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -735,6 +735,8 @@
             hostStr = NULL;
         }
     }
+    // push guest strings
+    res.push_back("GL_EXT_robustness");
 
     if (!hostStr || !strlen(hostStr)) { return res; }