Merge Android Pie into master
Bug: 112104996
Change-Id: Ia560f566f920ec33a00c74c751319acde0d7bc33
diff --git a/host/include/libOpenglRender/IOStream.h b/host/include/libOpenglRender/IOStream.h
index 445ec17..1d32ea1 100644
--- a/host/include/libOpenglRender/IOStream.h
+++ b/host/include/libOpenglRender/IOStream.h
@@ -83,6 +83,8 @@
return readFully(buf, len);
}
+ void readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels);
+
private:
unsigned char *m_buf;
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index 6e9c8f6..7d40389 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -664,6 +664,29 @@
return 1;
}
+void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
+{
+ if (width <= 0 || height <= 0) {
+ *startOffset = 0;
+ *pixelRowSize = 0;
+ *totalRowSize = 0;
+ return;
+ }
+
+ GLESTextureUtils::computePackingOffsets2D(
+ width, height,
+ format, type,
+ m_pixelStore.pack_alignment,
+ m_pixelStore.pack_row_length,
+ m_pixelStore.pack_skip_pixels,
+ m_pixelStore.pack_skip_rows,
+ startOffset,
+ pixelRowSize,
+ totalRowSize);
+
+ *skipRows = m_pixelStore.pack_skip_rows;
+}
+
void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
UniformBlockInfoKey key;
key.program = program;
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index e41cf44..675cea4 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -239,6 +239,7 @@
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 clearBufferNumElts(GLenum buffer) const;
+ void getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const;
void setCurrentProgram(GLint program) { m_currentProgram = program; }
void setCurrentShaderProgram(GLint program) { m_currentShaderProgram = program; }
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.cpp b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
index 1aef8cb..4572905 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.cpp
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.cpp
@@ -284,4 +284,29 @@
return end - start;
}
+void computePackingOffsets2D(
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ int packAlignment,
+ int packRowLength,
+ int packSkipPixels,
+ int packSkipRows,
+ int* startOffset,
+ int* packingPixelRowSize,
+ int* packingTotalRowSize) {
+
+ int widthTotal = (packRowLength == 0) ? width : packRowLength;
+ int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
+ int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
+
+ int packingOffsetStart =
+ computePackingOffset(
+ format, type, widthTotal, height, packAlignment, packSkipPixels, packSkipRows, 0 /* skip images = 0 */);
+
+ if (startOffset) *startOffset = packingOffsetStart;
+ if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
+ if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
+}
+
+
} // namespace GLESTextureUtils
diff --git a/shared/OpenglCodecCommon/GLESTextureUtils.h b/shared/OpenglCodecCommon/GLESTextureUtils.h
index 906e590..f623d23 100644
--- a/shared/OpenglCodecCommon/GLESTextureUtils.h
+++ b/shared/OpenglCodecCommon/GLESTextureUtils.h
@@ -37,6 +37,21 @@
int unpackSkipRows,
int unpackSkipImages);
+// Writes out |height| offsets for glReadPixels to read back
+// data in separate rows of pixels. Returns:
+// 1. |startOffset|: offset in bytes to apply at the beginning
+// 2. |packingPixelRowSize|: the buffer size in bytes that has the actual pixels per row.
+// 2. |packingTotalRowSize|: the length in bytes of each row including the padding from row length.
+void computePackingOffsets2D(
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ int packAlignment,
+ int packRowLength,
+ int packSkipPixels,
+ int packSkipRows,
+ int* startOffset,
+ int* packingPixelRowSize,
+ int* packingTotalRowSize);
} // namespace GLESTextureUtils
#endif
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.cpp b/shared/OpenglCodecCommon/GLSharedGroup.cpp
index 9da011a..19dfe0f 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -180,7 +180,7 @@
for (GLuint i = 0; i < m_numIndexes; i++) {
GLint elemIndex = appLoc - m_Indexes[i].appBase;
if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
- if (m_Indexes[i].type == GL_TEXTURE_2D) {
+ if (m_Indexes[i].type == GL_SAMPLER_2D) {
m_Indexes[i].samplerValue = val;
if (target) {
if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
diff --git a/shared/OpenglCodecCommon/glUtils.cpp b/shared/OpenglCodecCommon/glUtils.cpp
index 7e5e4a2..3136d13 100644
--- a/shared/OpenglCodecCommon/glUtils.cpp
+++ b/shared/OpenglCodecCommon/glUtils.cpp
@@ -125,6 +125,8 @@
case GL_DEPTH_FUNC:
case GL_DEPTH_BITS:
case GL_MAX_CLIP_PLANES:
+ case GL_MAX_COLOR_ATTACHMENTS:
+ case GL_MAX_DRAW_BUFFERS:
case GL_GREEN_BITS:
case GL_MAX_MODELVIEW_STACK_DEPTH:
case GL_MAX_PROJECTION_STACK_DEPTH:
@@ -243,14 +245,18 @@
case GL_STENCIL_BACK_PASS_DEPTH_PASS:
case GL_STENCIL_BACK_WRITEMASK:
case GL_TEXTURE_2D:
+ case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_BINDING_2D:
case GL_TEXTURE_BINDING_CUBE_MAP:
case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ case GL_TEXTURE_COMPARE_FUNC:
+ case GL_TEXTURE_COMPARE_MODE:
case GL_TEXTURE_COORD_ARRAY:
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
case GL_TEXTURE_COORD_ARRAY_SIZE:
case GL_TEXTURE_COORD_ARRAY_STRIDE:
case GL_TEXTURE_COORD_ARRAY_TYPE:
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
case GL_UNPACK_ALIGNMENT:
case GL_VERTEX_ARRAY:
case GL_VERTEX_ARRAY_BUFFER_BINDING:
@@ -260,8 +266,15 @@
case GL_SPOT_CUTOFF:
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
case GL_GENERATE_MIPMAP:
case GL_GENERATE_MIPMAP_HINT:
case GL_RENDERBUFFER_WIDTH_OES:
@@ -303,6 +316,8 @@
case GL_SHADER_SOURCE_LENGTH:
case GL_CURRENT_PROGRAM:
case GL_SUBPIXEL_BITS:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ case GL_MAX_ARRAY_TEXTURE_LAYERS:
case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
case GL_NUM_SHADER_BINARY_FORMATS:
case GL_SHADER_COMPILER:
@@ -327,10 +342,13 @@
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
case GL_CURRENT_QUERY:
case GL_QUERY_RESULT:
case GL_QUERY_RESULT_AVAILABLE:
case GL_READ_BUFFER:
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ case GL_PROGRAM_BINARY_FORMATS:
case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
case GL_ACTIVE_ATTRIBUTES:
@@ -343,6 +361,7 @@
case GL_DELETE_STATUS:
case GL_INFO_LOG_LENGTH:
case GL_LINK_STATUS:
+ case GL_PROGRAM_BINARY_LENGTH:
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
case GL_PROGRAM_SEPARABLE:
case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
@@ -444,6 +463,10 @@
}
}
+#ifndef GL_RGBA16F
+#define GL_RGBA16F 0x881A
+#endif // GL_RGBA16F
+
int glUtilsPixelBitSize(GLenum format, GLenum type)
{
int components = 0;
@@ -455,7 +478,16 @@
componentsize = 8;
break;
case GL_SHORT:
+ case GL_HALF_FLOAT:
case GL_UNSIGNED_SHORT:
+ componentsize = 16;
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ case GL_FIXED:
+ componentsize = 32;
+ break;
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_5_5_5_1:
@@ -464,15 +496,12 @@
case GL_RGBA4_OES:
pixelsize = 16;
break;
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_FLOAT:
- case GL_FIXED:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_24_8_OES:
pixelsize = 32;
break;
default:
- ERR("glUtilsPixelBitSize: unknown pixel type - assuming pixel data 0\n");
+ ERR("glUtilsPixelBitSize: unknown pixel type %d - assuming pixel data 0\n", type);
componentsize = 0;
}
@@ -502,11 +531,16 @@
case GL_BGRA_EXT:
components = 4;
break;
+ case GL_RGBA16F:
+ pixelsize = 64;
+ break;
default:
- ERR("glUtilsPixelBitSize: unknown pixel format...\n");
+ ERR("glUtilsPixelBitSize: unknown pixel format %d\n", format);
components = 0;
}
- pixelsize = components * componentsize;
+ if (pixelsize == 0) {
+ pixelsize = components * componentsize;
+ }
}
return pixelsize;
diff --git a/system/GLESv1/gl.cpp b/system/GLESv1/gl.cpp
index e20b45d..6e07004 100644
--- a/system/GLESv1/gl.cpp
+++ b/system/GLESv1/gl.cpp
@@ -86,28 +86,32 @@
}
}
-void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image)
+void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES img)
{
(void)self;
(void)target;
- DBG("glEGLImageTargetRenderbufferStorageOES v1 target=%#x image=%p",
- target, image);
+ DBG("glEGLImageTargetRenderbufferStorageOES v1 image=%p\n", img);
//TODO: check error - we don't have a way to set gl error
- android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+ EGLImage_t *image = (EGLImage_t*)img;
- if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
- return;
+ if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
+ android_native_buffer_t* native_buffer = ((EGLImage_t*)image)->native_buffer;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+ return;
+ }
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+ return;
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION();
+ rcEnc->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle);
+ } else {
+ //TODO
}
- if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
- return;
- }
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION();
- rcEnc->rcBindRenderbuffer(rcEnc,
- ((cb_handle_t *)(native_buffer->handle))->hostHandle);
-
return;
}
diff --git a/system/GLESv2/gl2.cpp b/system/GLESv2/gl2.cpp
index b75f899..331da78 100644
--- a/system/GLESv2/gl2.cpp
+++ b/system/GLESv2/gl2.cpp
@@ -88,26 +88,32 @@
}
}
-void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image)
+void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES img)
{
(void)self;
(void)target;
- DBG("glEGLImageTargetRenderbufferStorageOES v2 image=%p\n", image);
+ DBG("glEGLImageTargetRenderbufferStorageOES v2 image=%p\n", img);
//TODO: check error - we don't have a way to set gl error
- android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+ EGLImage_t *image = (EGLImage_t*)img;
- if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
- return;
+ if (image->target == EGL_NATIVE_BUFFER_ANDROID) {
+ android_native_buffer_t* native_buffer = ((EGLImage_t*)image)->native_buffer;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+ return;
+ }
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+ return;
+ }
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION();
+ rcEnc->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle);
+ } else {
+ //TODO
}
- if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
- return;
- }
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION();
- rcEnc->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle);
-
return;
}
diff --git a/system/GLESv2_enc/Android.mk b/system/GLESv2_enc/Android.mk
index c5081d3..f61c9f7 100644
--- a/system/GLESv2_enc/Android.mk
+++ b/system/GLESv2_enc/Android.mk
@@ -10,6 +10,7 @@
gl2_client_context.cpp \
gl2_enc.cpp \
gl2_entry.cpp \
+ ../enc_common/IOStream_common.cpp \
LOCAL_CFLAGS += -DLOG_TAG=\"emuglGLESv2_enc\"
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 39e4cda..cbc0c32 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -73,6 +73,7 @@
m_currMajorVersion = 2;
m_currMinorVersion = 0;
m_initialized = false;
+ m_noHostError = false;
m_state = NULL;
m_error = GL_NO_ERROR;
m_num_compressedTextureFormats = 0;
@@ -195,6 +196,8 @@
OVERRIDEOES(glDeleteVertexArrays);
OVERRIDEOES(glBindVertexArray);
+ OVERRIDE_CUSTOM(glMapBufferOES);
+ OVERRIDE_CUSTOM(glUnmapBufferOES);
OVERRIDE_CUSTOM(glMapBufferRange);
OVERRIDE_CUSTOM(glUnmapBuffer);
OVERRIDE_CUSTOM(glFlushMappedBufferRange);
@@ -363,7 +366,11 @@
return err;
}
- return ctx->m_glGetError_enc(self);
+ if (ctx->m_noHostError) {
+ return GL_NO_ERROR;
+ } else {
+ return ctx->m_glGetError_enc(self);
+ }
}
class GL2Encoder::ErrorUpdater {
@@ -629,6 +636,9 @@
GLClientState* state = ctx->m_state;
switch (param) {
+ case GL_NUM_EXTENSIONS:
+ *ptr = (int)ctx->m_currExtensionsArray.size();
+ break;
case GL_MAJOR_VERSION:
*ptr = ctx->m_deviceMajorVersion;
break;
@@ -1321,42 +1331,73 @@
// #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME
// SAMPLER(ExternalOES, mySampler);
//
-static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
-{
- static const char STR_HASH_EXTENSION[] = "#extension";
- static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
- static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
- static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
- // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
+static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES";
+static const char STR_SAMPLER2D_SPACE[] = "sampler2D ";
+static const char STR_DEFINE[] = "#define";
+
+static std::vector<std::string> getSamplerExternalAliases(char* str) {
+ std::vector<std::string> res;
+
+ res.push_back(STR_SAMPLER_EXTERNAL_OES);
+
+ // -- capture #define x samplerExternalOES
char* c = str;
- while ((c = strstr(c, STR_HASH_EXTENSION))) {
- char* start = c;
- c += sizeof(STR_HASH_EXTENSION)-1;
- while (isspace(*c) && *c != '\0') {
- c++;
- }
- if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
- sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0)
- {
- // #extension statements are terminated by end of line
- c = start;
- while (*c != '\0' && *c != '\r' && *c != '\n') {
- *c++ = ' ';
+ while ((c = strstr(c, STR_DEFINE))) {
+ // Don't push it if samplerExternalOES is not even there.
+ char* samplerExternalOES_next = strstr(c, STR_SAMPLER_EXTERNAL_OES);
+ if (!samplerExternalOES_next) break;
+
+ bool prevIdent = false;
+
+ std::vector<std::string> idents;
+ std::string curr;
+
+ while (*c != '\0') {
+
+ if (isspace(*c)) {
+ if (prevIdent) {
+ idents.push_back(curr);
+ curr = "";
+ }
}
+
+ if (*c == '\n' || idents.size() == 3) break;
+
+ if (isalpha(*c) || *c == '_') {
+ curr.push_back(*c);
+ prevIdent = true;
+ }
+
+ ++c;
}
+
+ if (idents.size() != 3) continue;
+
+ const std::string& defineLhs = idents[1];
+ const std::string& defineRhs = idents[2];
+
+ if (defineRhs == STR_SAMPLER_EXTERNAL_OES) {
+ res.push_back(defineLhs);
+ }
+
+ if (*c == '\0') break;
}
+ return res;
+}
+
+static bool replaceExternalSamplerUniformDefinition(char* str, const std::string& samplerExternalType, ShaderData* data) {
// -- replace "samplerExternalOES" with "sampler2D" and record name
- c = str;
- while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) {
+ char* c = str;
+ while ((c = strstr(c, samplerExternalType.c_str()))) {
// Make sure "samplerExternalOES" isn't a substring of a larger token
if (c == str || !isspace(*(c-1))) {
c++;
continue;
}
char* sampler_start = c;
- c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1;
+ c += samplerExternalType.size();
if (!isspace(*c) && *c != '\0') {
continue;
}
@@ -1376,8 +1417,58 @@
data->samplerExternalNames.push_back(
android::String8(name_start, c - name_start));
- // memcpy instead of strcpy since we don't want the NUL terminator
- memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
+ // We only need to perform a string replacement for the original
+ // occurrence of samplerExternalOES if a #define was used.
+ //
+ // The important part was to record the name in
+ // |data->samplerExternalNames|.
+ if (samplerExternalType == STR_SAMPLER_EXTERNAL_OES) {
+ memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1);
+ }
+ }
+
+ return true;
+}
+
+static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data)
+{
+ static const char STR_HASH_EXTENSION[] = "#extension";
+ static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external";
+ static const char STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3[] = "GL_OES_EGL_image_external_essl3";
+
+ // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements
+ char* c = str;
+ while ((c = strstr(c, STR_HASH_EXTENSION))) {
+ char* start = c;
+ c += sizeof(STR_HASH_EXTENSION)-1;
+ while (isspace(*c) && *c != '\0') {
+ c++;
+ }
+
+ bool hasBaseImageExternal =
+ !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL,
+ sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL) - 1);
+ bool hasEssl3ImageExternal =
+ !strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3,
+ sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL_ESSL3) - 1);
+
+ if (hasBaseImageExternal || hasEssl3ImageExternal)
+ {
+ // #extension statements are terminated by end of line
+ c = start;
+ while (*c != '\0' && *c != '\r' && *c != '\n') {
+ *c++ = ' ';
+ }
+ }
+ }
+
+ std::vector<std::string> samplerExternalAliases =
+ getSamplerExternalAliases(str);
+
+ for (size_t i = 0; i < samplerExternalAliases.size(); i++) {
+ if (!replaceExternalSamplerUniformDefinition(
+ str, samplerExternalAliases[i], data))
+ return false;
}
return true;
@@ -2579,6 +2670,27 @@
state->setVertexArrayObject(array);
}
+void* GL2Encoder::s_glMapBufferOES(void* self, GLenum target, GLenum access) {
+ GL2Encoder* ctx = (GL2Encoder*)self;
+
+ RET_AND_SET_ERROR_IF(!GLESv2Validation::bufferTarget(ctx, target), GL_INVALID_ENUM, NULL);
+
+ GLuint boundBuffer = ctx->m_state->getBuffer(target);
+
+ RET_AND_SET_ERROR_IF(boundBuffer == 0, GL_INVALID_OPERATION, NULL);
+
+ BufferData* buf = ctx->m_shared->getBufferData(boundBuffer);
+ RET_AND_SET_ERROR_IF(!buf, GL_INVALID_VALUE, NULL);
+
+ return ctx->glMapBufferRange(ctx, target, 0, buf->m_size, access);
+}
+
+GLboolean GL2Encoder::s_glUnmapBufferOES(void* self, GLenum target) {
+ GL2Encoder* ctx = (GL2Encoder*)self;
+
+ return ctx->glUnmapBuffer(ctx, target);
+}
+
void* GL2Encoder::s_glMapBufferRange(void* self, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
GL2Encoder* ctx = (GL2Encoder*)self;
GLClientState* state = ctx->m_state;
@@ -2739,6 +2851,10 @@
state->setBoundTextureInternalFormat(stateTarget, (GLint)internalformat);
state->setBoundTextureDims(stateTarget, level, width, height, 1);
+ if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
+ ctx->override2DTextureTarget(target);
+ }
+
if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
ctx->glCompressedTexImage2DOffsetAEMU(
ctx, target, level, internalformat,
@@ -2750,6 +2866,10 @@
width, height, border,
imageSize, data);
}
+
+ if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
+ ctx->restore2DTextureTarget(target);
+ }
}
void GL2Encoder::s_glCompressedTexSubImage2D(void* self, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
@@ -2774,6 +2894,10 @@
GL_INVALID_OPERATION);
SET_ERROR_IF(xoffset < 0 || yoffset < 0, GL_INVALID_VALUE);
+ if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
+ ctx->override2DTextureTarget(target);
+ }
+
if (ctx->boundBuffer(GL_PIXEL_UNPACK_BUFFER)) {
ctx->glCompressedTexSubImage2DOffsetAEMU(
ctx, target, level,
@@ -2787,6 +2911,10 @@
width, height, format,
imageSize, data);
}
+
+ if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) {
+ ctx->restore2DTextureTarget(target);
+ }
}
void GL2Encoder::s_glBindBufferRange(void* self, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
@@ -3383,7 +3511,16 @@
state->setBoundTextureInternalFormat(target, internalformat);
state->setBoundTextureDims(target, -1, width, height, 1);
state->setBoundTextureImmutableFormat(target);
+
+ if (target == GL_TEXTURE_2D) {
+ ctx->override2DTextureTarget(target);
+ }
+
ctx->m_glTexStorage2D_enc(ctx, target, levels, internalformat, width, height);
+
+ if (target == GL_TEXTURE_2D) {
+ ctx->restore2DTextureTarget(target);
+ }
}
void GL2Encoder::s_glTransformFeedbackVaryings(void* self, GLuint program, GLsizei count, const char** varyings, GLenum bufferMode) {
@@ -3873,7 +4010,7 @@
const GLubyte* GL2Encoder::s_glGetStringi(void* self, GLenum name, GLuint index) {
GL2Encoder *ctx = (GL2Encoder *)self;
- GLubyte *retval = (GLubyte *) "";
+ const GLubyte *retval = (GLubyte *) "";
RET_AND_SET_ERROR_IF(
name != GL_VENDOR &&
@@ -3887,11 +4024,16 @@
name == GL_VENDOR ||
name == GL_RENDERER ||
name == GL_VERSION ||
- name == GL_EXTENSIONS &&
index != 0,
GL_INVALID_VALUE,
retval);
+ RET_AND_SET_ERROR_IF(
+ name == GL_EXTENSIONS &&
+ index >= ctx->m_currExtensionsArray.size(),
+ GL_INVALID_VALUE,
+ retval);
+
switch (name) {
case GL_VENDOR:
retval = gVendorString;
@@ -3903,7 +4045,7 @@
retval = gVersionString;
break;
case GL_EXTENSIONS:
- retval = gExtensionsString;
+ retval = (const GLubyte*)(ctx->m_currExtensionsArray[index].c_str());
break;
}
@@ -4148,7 +4290,8 @@
SET_ERROR_IF(target != GL_TEXTURE_2D &&
target != GL_TEXTURE_3D &&
- target != GL_TEXTURE_CUBE_MAP,
+ target != GL_TEXTURE_CUBE_MAP &&
+ target != GL_TEXTURE_2D_ARRAY,
GL_INVALID_ENUM);
GLuint tex = state->getBoundTexture(target);
@@ -4163,7 +4306,15 @@
GLESv2Validation::filterableTexFormat(ctx, internalformat)),
GL_INVALID_OPERATION);
+ if (target == GL_TEXTURE_2D) {
+ ctx->override2DTextureTarget(target);
+ }
+
ctx->m_glGenerateMipmap_enc(ctx, target);
+
+ if (target == GL_TEXTURE_2D) {
+ ctx->restore2DTextureTarget(target);
+ }
}
void GL2Encoder::s_glBindSampler(void* self, GLuint unit, GLuint sampler) {
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 3084713..3018622 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -22,11 +22,15 @@
#include "FixedBuffer.h"
#include <string>
+#include <vector>
class GL2Encoder : public gl2_encoder_context_t {
public:
GL2Encoder(IOStream *stream, ChecksumCalculator* protocol);
virtual ~GL2Encoder();
+ void setNoHostError(bool noHostError) {
+ m_noHostError = noHostError;
+ }
void setClientState(GLClientState *state) {
m_state = state;
}
@@ -56,8 +60,10 @@
}
int majorVersion() const { return m_currMajorVersion; }
int minorVersion() const { return m_currMinorVersion; }
- void setExtensions(const char* exts) {
+ void setExtensions(const char* exts,
+ const std::vector<std::string>& extArray) {
m_currExtensions = std::string(exts);
+ m_currExtensionsArray = extArray;
}
bool hasExtension(const char* ext) const {
return m_currExtensions.find(ext) != std::string::npos;
@@ -90,8 +96,10 @@
int m_deviceMajorVersion;
int m_deviceMinorVersion;
std::string m_currExtensions;
+ std::vector<std::string> m_currExtensionsArray;
bool m_initialized;
+ bool m_noHostError;
GLClientState *m_state;
GLSharedGroupPtr m_shared;
GLenum m_error;
@@ -391,6 +399,8 @@
static void s_glBindVertexArray(void *self , GLuint array);
// Mapped buffers
+ 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 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_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index 8357c68..f42e7ba 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -3028,7 +3028,10 @@
if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
- stream->readback(pixels, __size_pixels);
+ // TODO: make this part of autogenerated pipe code.
+ // b/79208762
+ stream->readbackPixels(self, width, height, format, type, pixels);
+
if (useChecksum) checksumCalculator->addBuffer(pixels, __size_pixels);
if (useChecksum) {
unsigned char *checksumBufPtr = NULL;
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index ce89021..34ddef4 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -37,7 +37,8 @@
m_rcEnc(NULL),
m_checksumHelper(),
m_glExtensions(),
- m_grallocOnly(true)
+ m_grallocOnly(true),
+ m_noHostError(false)
{
}
@@ -146,6 +147,7 @@
m_gl2Enc = new GL2Encoder(m_stream, checksumHelper());
DBG("HostConnection::gl2Encoder new encoder %p, tid %d", m_gl2Enc, gettid());
m_gl2Enc->setContextAccessor(s_getGL2Context);
+ m_gl2Enc->setNoHostError(m_noHostError);
}
return m_gl2Enc;
}
@@ -158,6 +160,7 @@
queryAndSetSyncImpl(m_rcEnc);
queryAndSetDmaImpl(m_rcEnc);
queryAndSetGLESMaxVersion(m_rcEnc);
+ queryAndSetNoErrorState(m_rcEnc);
processPipeInit(m_rcEnc);
}
return m_rcEnc;
@@ -233,8 +236,10 @@
#if PLATFORM_SDK_VERSION <= 16 || (!defined(__i386__) && !defined(__x86_64__))
rcEnc->setSyncImpl(SYNC_IMPL_NONE);
#else
- if (glExtensions.find(kRCNativeSync) != std::string::npos) {
- rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC);
+ if (glExtensions.find(kRCNativeSyncV3) != std::string::npos) {
+ rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3);
+ } else if (glExtensions.find(kRCNativeSyncV2) != std::string::npos) {
+ rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2);
} else {
rcEnc->setSyncImpl(SYNC_IMPL_NONE);
}
@@ -270,3 +275,10 @@
rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2);
}
}
+
+void HostConnection::queryAndSetNoErrorState(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kGLESNoHostError) != std::string::npos) {
+ m_noHostError = true;
+ }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 25d42d6..2b49857 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -40,16 +40,15 @@
// capability, and we will use a fence fd to synchronize buffer swaps.
enum SyncImpl {
SYNC_IMPL_NONE = 0,
- SYNC_IMPL_NATIVE_SYNC = 1
+ SYNC_IMPL_NATIVE_SYNC_V2 = 1,
+ SYNC_IMPL_NATIVE_SYNC_V3 = 2,
};
// Interface:
-// If this GL extension string shows up, we use
-// SYNC_IMPL_NATIVE_SYNC, otherwise we use SYNC_IMPL_NONE.
-// This string is always updated to require the _latest_
-// version of Android emulator native sync in this system image;
-// otherwise, we do not use the feature.
-static const char kRCNativeSync[] = "ANDROID_EMU_native_sync_v2";
+// Use the highest of v2 or v3 that show up, making us
+// SYNC_IMPL_NATIVE_SYNC_V2 or SYNC_IMPL_NATIVE_SYNC_V3.
+static const char kRCNativeSyncV2[] = "ANDROID_EMU_native_sync_v2";
+static const char kRCNativeSyncV3[] = "ANDROID_EMU_native_sync_v3";
// DMA for OpenGL
enum DmaImpl {
@@ -72,6 +71,9 @@
static const char kGLESMaxVersion_3_1[] = "ANDROID_EMU_gles_max_version_3_1";
static const char kGLESMaxVersion_3_2[] = "ANDROID_EMU_gles_max_version_3_2";
+// No querying errors from host extension
+static const char kGLESNoHostError[] = "ANDROID_EMU_gles_no_host_error";
+
// ExtendedRCEncoderContext is an extended version of renderControl_encoder_context_t
// that will be used to track SyncImpl.
class ExtendedRCEncoderContext : public renderControl_encoder_context_t {
@@ -82,7 +84,8 @@
}
void setSyncImpl(SyncImpl syncImpl) { m_syncImpl = syncImpl; }
void setDmaImpl(DmaImpl dmaImpl) { m_dmaImpl = dmaImpl; }
- bool hasNativeSync() const { return m_syncImpl == SYNC_IMPL_NATIVE_SYNC; }
+ bool hasNativeSync() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V2; }
+ bool hasNativeSyncV3() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V3; }
DmaImpl getDmaVersion() const { return m_dmaImpl; }
void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
@@ -148,6 +151,7 @@
void queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc);
void queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc);
void queryAndSetGLESMaxVersion(ExtendedRCEncoderContext *rcEnc);
+ void queryAndSetNoErrorState(ExtendedRCEncoderContext *rcEnc);
private:
IOStream *m_stream;
@@ -158,6 +162,7 @@
std::string m_glExtensions;
bool m_grallocOnly;
int m_pipeFd;
+ bool m_noHostError;
};
#endif
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 185fbc9..16285f9 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -160,12 +160,14 @@
}
#define VALIDATE_CONTEXT_RETURN(context,ret) \
- if (!(context)) { \
+ if (!(context) || !s_display.isContext((context))) { \
RETURN_ERROR(ret,EGL_BAD_CONTEXT); \
}
#define VALIDATE_SURFACE_RETURN(surface, ret) \
if ((surface) != EGL_NO_SURFACE) { \
+ if (!s_display.isSurface((surface))) \
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE); \
egl_surface_t* s( static_cast<egl_surface_t*>(surface) ); \
if (s->dpy != (EGLDisplay)&s_display) \
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
@@ -282,7 +284,9 @@
virtual void setCollectingTimestamps(EGLint collect) { }
virtual EGLint isCollectingTimestamps() const { return EGL_FALSE; }
-
+ EGLint deletePending;
+ void setIsCurrent(bool isCurrent) { mIsCurrent = isCurrent; }
+ bool isCurrent() const { return mIsCurrent;}
private:
//
//Surface attributes
@@ -296,7 +300,7 @@
// Give it some default values.
int nativeWidth;
int nativeHeight;
-
+ bool mIsCurrent;
protected:
void setWidth(EGLint w) { width = w; }
void setHeight(EGLint h) { height = h; }
@@ -308,7 +312,8 @@
};
egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
- : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
+ : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0),
+ deletePending(0), mIsCurrent(false)
{
width = 0;
height = 0;
@@ -603,6 +608,34 @@
}
}
+// Destroy a pending surface and set it to NULL.
+
+static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
+ if (!s_display.isSurface(surface)) {
+ *surface = NULL;
+ return;
+ }
+
+ egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
+ if (surf && surf->deletePending) {
+ delete surf;
+ *surface = NULL;
+ }
+}
+
+static void s_destroyPendingSurfacesInContext(EGLContext_t* context) {
+ if (context->read == context->draw) {
+ // If they are the same, delete it only once
+ s_destroyPendingSurfaceAndSetNull(&context->draw);
+ if (context->draw == NULL) {
+ context->read = NULL;
+ }
+ } else {
+ s_destroyPendingSurfaceAndSetNull(&context->draw);
+ s_destroyPendingSurfaceAndSetNull(&context->read);
+ }
+}
+
EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
@@ -638,6 +671,68 @@
return pb;
}
+// Required for Skia.
+static const char kOESEGLImageExternalEssl3[] = "GL_OES_EGL_image_external_essl3";
+
+static bool sWantES30OrAbove(const char* exts) {
+ if (strstr(exts, kGLESMaxVersion_3_0) ||
+ strstr(exts, kGLESMaxVersion_3_1) ||
+ strstr(exts, kGLESMaxVersion_3_2)) {
+ return true;
+ }
+ return false;
+}
+
+static std::vector<std::string> getExtStringArray() {
+ std::vector<std::string> res;
+
+ EGLThreadInfo *tInfo = getEGLThreadInfo();
+ if (!tInfo || !tInfo->currentContext) {
+ return res;
+ }
+
+#define GL_EXTENSIONS 0x1F03
+
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(res);
+
+ char *hostStr = NULL;
+ int n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, NULL, 0);
+ if (n < 0) {
+ hostStr = new char[-n+1];
+ n = rcEnc->rcGetGLString(rcEnc, GL_EXTENSIONS, hostStr, -n);
+ if (n <= 0) {
+ delete [] hostStr;
+ hostStr = NULL;
+ }
+ }
+
+ if (!hostStr || !strlen(hostStr)) { return res; }
+
+ // find the number of extensions
+ int extStart = 0;
+ int extEnd = 0;
+ int currentExtIndex = 0;
+ int numExts = 0;
+
+ if (sWantES30OrAbove(hostStr) &&
+ !strstr(hostStr, kOESEGLImageExternalEssl3)) {
+ res.push_back(kOESEGLImageExternalEssl3);
+ }
+
+ while (extEnd < strlen(hostStr)) {
+ if (hostStr[extEnd] == ' ') {
+ int extSz = extEnd - extStart;
+ res.push_back(std::string(hostStr + extStart, extSz));
+ currentExtIndex++;
+ extStart = extEnd + 1;
+ }
+ extEnd++;
+ }
+
+ delete [] hostStr;
+ return res;
+}
+
static const char *getGLString(int glEnum)
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
@@ -675,18 +770,42 @@
return NULL;
}
- //
- // first query of that string - need to query host
- //
- DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
- char *hostStr = NULL;
- int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
- if (n < 0) {
- hostStr = new char[-n+1];
- n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
- if (n <= 0) {
- delete [] hostStr;
- hostStr = NULL;
+ char* hostStr = NULL;
+
+ if (glEnum == GL_EXTENSIONS) {
+
+ std::vector<std::string> exts = getExtStringArray();
+
+ int totalSz = 1; // null terminator
+ for (int i = 0; i < exts.size(); i++) {
+ totalSz += exts[i].size() + 1; // for space
+ }
+
+ if (totalSz == 1) return NULL;
+
+ hostStr = new char[totalSz];
+ memset(hostStr, 0, totalSz);
+
+ char* current = hostStr;
+ for (int i = 0; i < exts.size(); i++) {
+ memcpy(current, exts[i].c_str(), exts[i].size());
+ current += exts[i].size();
+ *current = ' ';
+ ++current;
+ }
+ } else {
+ //
+ // first query of that string - need to query host
+ //
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(NULL);
+ int n = rcEnc->rcGetGLString(rcEnc, glEnum, NULL, 0);
+ if (n < 0) {
+ hostStr = new char[-n+1];
+ n = rcEnc->rcGetGLString(rcEnc, glEnum, hostStr, -n);
+ if (n <= 0) {
+ delete [] hostStr;
+ hostStr = NULL;
+ }
}
}
@@ -701,7 +820,7 @@
static EGLClient_eglInterface s_eglIface = {
getThreadInfo: getEGLThreadInfo,
- getGLString: getGLString
+ getGLString: getGLString,
};
#define DBG_FUNC DBG("%s\n", __FUNCTION__)
@@ -984,8 +1103,13 @@
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+ EGLThreadInfo* tInfo = getEGLThreadInfo();
egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
- delete surface;
+ if (surface->isCurrent()) {
+ surface->deletePending = 1;
+ } else {
+ delete surface;
+ }
return EGL_TRUE;
}
@@ -1150,7 +1274,7 @@
tInfo->eglError = EGL_SUCCESS;
EGLContext_t* context = tInfo->currentContext;
- if (!context) return EGL_TRUE;
+ if (!context || !s_display.isContext(context)) return EGL_TRUE;
// The following code is doing pretty much the same thing as
// eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
@@ -1160,6 +1284,9 @@
// anyway once we are on the host, so skip rcMakeCurrent here.
// rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
context->flags &= ~EGLContext_t::IS_CURRENT;
+
+ s_destroyPendingSurfacesInContext(context);
+
if (context->deletePending) {
if (context->rcContext) {
rcEnc->rcDestroyContext(rcEnc, context->rcContext);
@@ -1342,17 +1469,12 @@
RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
}
break;
- case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
- switch (attrib_val) {
- case EGL_NO_RESET_NOTIFICATION_KHR:
- case EGL_LOSE_CONTEXT_ON_RESET_KHR:
- break;
- default:
- RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
- }
- reset_notification_strategy = attrib_val;
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ // According to the spec, we are allowed not to honor this hint.
+ // https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt
break;
default:
+ ALOGV("eglCreateContext unsupported attrib 0x%x", attrib_list[0]);
setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
}
attrib_list+=2;
@@ -1472,10 +1594,8 @@
EGLContext_t * context = static_cast<EGLContext_t*>(ctx);
- if (!context) return EGL_TRUE;
-
- if (getEGLThreadInfo()->currentContext == context) {
- getEGLThreadInfo()->currentContext->deletePending = 1;
+ if (context->flags & EGLContext_t::IS_CURRENT) {
+ context->deletePending = 1;
return EGL_TRUE;
}
@@ -1518,15 +1638,24 @@
if (tInfo->currentContext == context &&
(context == NULL ||
- (context && context->draw == draw && context->read == read))) {
+ (context && (context->draw == draw) && (context->read == read)))) {
return EGL_TRUE;
}
- if (tInfo->currentContext && tInfo->currentContext->deletePending) {
- if (tInfo->currentContext != context) {
- EGLContext_t * contextToDelete = tInfo->currentContext;
+ if (tInfo->currentContext) {
+ EGLContext_t* prevCtx = tInfo->currentContext;
+
+ if (prevCtx->draw) {
+ static_cast<egl_surface_t *>(prevCtx->draw)->setIsCurrent(false);
+ }
+ if (prevCtx->read) {
+ static_cast<egl_surface_t *>(prevCtx->read)->setIsCurrent(false);
+ }
+ s_destroyPendingSurfacesInContext(tInfo->currentContext);
+
+ if (prevCtx->deletePending && prevCtx != context) {
tInfo->currentContext = 0;
- eglDestroyContext(dpy, contextToDelete);
+ eglDestroyContext(dpy, prevCtx);
}
}
@@ -1551,6 +1680,12 @@
hostCon->setGrallocOnly(false);
context->draw = draw;
context->read = read;
+ if (drawSurf) {
+ drawSurf->setIsCurrent(true);
+ }
+ if (readSurf) {
+ readSurf->setIsCurrent(true);
+ }
context->flags |= EGLContext_t::IS_CURRENT;
GLClientState* contextState =
context->getClientState();
@@ -1633,8 +1768,9 @@
}
- if (tInfo->currentContext)
+ if (tInfo->currentContext && (tInfo->currentContext != context)) {
tInfo->currentContext->flags &= ~EGLContext_t::IS_CURRENT;
+ }
//Now make current
tInfo->currentContext = context;
@@ -1649,7 +1785,7 @@
}
const char* exts = getGLString(GL_EXTENSIONS);
if (exts) {
- hostCon->gl2Encoder()->setExtensions(exts);
+ hostCon->gl2Encoder()->setExtensions(exts, getExtStringArray());
}
}
else {
@@ -1823,6 +1959,8 @@
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_YV12:
case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
break;
default:
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
@@ -2097,10 +2235,24 @@
}
}
-// TODO: Implement EGL_KHR_wait_sync
EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR eglsync, EGLint flags) {
(void)dpy;
- (void)eglsync;
- (void)flags;
+
+ if (!eglsync) {
+ ALOGE("%s: null sync object!", __FUNCTION__);
+ return EGL_FALSE;
+ }
+
+ if (flags) {
+ ALOGE("%s: flags must be 0, got 0x%x", __FUNCTION__, flags);
+ return EGL_FALSE;
+ }
+
+ DEFINE_HOST_CONNECTION;
+ if (rcEnc->hasNativeSyncV3()) {
+ EGLSync_t* sync = (EGLSync_t*)eglsync;
+ rcEnc->rcWaitSyncKHR(rcEnc, sync->handle, flags);
+ }
+
return EGL_TRUE;
}
diff --git a/system/egl/eglDisplay.cpp b/system/egl/eglDisplay.cpp
index c7ff179..f593598 100644
--- a/system/egl/eglDisplay.cpp
+++ b/system/egl/eglDisplay.cpp
@@ -33,6 +33,7 @@
// extensions to add dynamically depending on host-side support
static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync ";
+static const char kDynamicEGLExtWaitSync[] = "EGL_KHR_wait_sync ";
static void *s_gles_lib = NULL;
static void *s_gles2_lib = NULL;
@@ -347,6 +348,10 @@
if (hcon->rcEncoder()->hasNativeSync() &&
!strstr(initialEGLExts, kDynamicEGLExtNativeSync)) {
dynamicEGLExtensions += kDynamicEGLExtNativeSync;
+
+ if (hcon->rcEncoder()->hasNativeSyncV3()) {
+ dynamicEGLExtensions += kDynamicEGLExtWaitSync;
+ }
}
asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str());
@@ -572,3 +577,16 @@
pthread_mutex_unlock(&m_surfaceLock);
}
+bool eglDisplay::isContext(EGLContext ctx) {
+ pthread_mutex_lock(&m_ctxLock);
+ bool res = m_contexts.find(ctx) != m_contexts.end();
+ pthread_mutex_unlock(&m_ctxLock);
+ return res;
+}
+
+bool eglDisplay::isSurface(EGLSurface surface) {
+ pthread_mutex_lock(&m_surfaceLock);
+ bool res = m_surfaces.find(surface) != m_surfaces.end();
+ pthread_mutex_unlock(&m_surfaceLock);
+ return res;
+}
diff --git a/system/egl/eglDisplay.h b/system/egl/eglDisplay.h
index ba39201..9fb6f07 100644
--- a/system/egl/eglDisplay.h
+++ b/system/egl/eglDisplay.h
@@ -67,6 +67,9 @@
void onDestroyContext(EGLContext ctx);
void onDestroySurface(EGLSurface surface);
+
+ bool isContext(EGLContext ctx);
+ bool isSurface(EGLSurface ctx);
private:
EGLClient_glesInterface *loadGLESClientAPI(const char *libName,
EGLClient_eglInterface *eglIface,
diff --git a/system/enc_common/IOStream_common.cpp b/system/enc_common/IOStream_common.cpp
new file mode 100644
index 0000000..43f03af
--- /dev/null
+++ b/system/enc_common/IOStream_common.cpp
@@ -0,0 +1,59 @@
+#include "IOStream.h"
+
+#include "GL2Encoder.h"
+
+#include <GLES3/gl31.h>
+
+#include <vector>
+
+void IOStream::readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels) {
+ GL2Encoder *ctx = (GL2Encoder *)context;
+ assert (ctx->state() != NULL);
+
+ int startOffset = 0;
+ int pixelRowSize = 0;
+ int totalRowSize = 0;
+ int skipRows = 0;
+
+ ctx->state()->getPackingOffsets2D(width, height, format, type,
+ &startOffset,
+ &pixelRowSize,
+ &totalRowSize,
+ &skipRows);
+
+ size_t pixelDataSize =
+ ctx->state()->pixelDataSize(
+ width, height, 1, format, type, 1 /* is pack */);
+
+ if (startOffset == 0 &&
+ pixelRowSize == totalRowSize) {
+ // fast path
+ readback(pixels, pixelDataSize);
+ } else if (pixelRowSize == totalRowSize) {
+ // fast path but with skip in the beginning
+ std::vector<char> paddingToDiscard(startOffset, 0);
+ readback(&paddingToDiscard[0], startOffset);
+ readback((char*)pixels + startOffset, pixelDataSize - startOffset);
+ } else {
+ int totalReadback = 0;
+
+ if (startOffset > 0) {
+ std::vector<char> paddingToDiscard(startOffset, 0);
+ readback(&paddingToDiscard[0], startOffset);
+ totalReadback += startOffset;
+ }
+ // need to read back row by row
+ size_t paddingSize = totalRowSize - pixelRowSize;
+ std::vector<char> paddingToDiscard(paddingSize, 0);
+
+ char* start = (char*)pixels + startOffset;
+
+ for (int i = 0; i < height; i++) {
+ readback(start, pixelRowSize);
+ totalReadback += pixelRowSize;
+ readback(&paddingToDiscard[0], paddingSize);
+ totalReadback += paddingSize;
+ start += totalRowSize;
+ }
+ }
+}
diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp
index 223f87a..cabc27b 100644
--- a/system/gralloc/gralloc.cpp
+++ b/system/gralloc/gralloc.cpp
@@ -118,6 +118,7 @@
struct gralloc_memregions_t {
MemRegionSet ashmemRegions;
+ pthread_mutex_t lock;
};
#define INITIAL_DMA_REGION_SIZE 4096
@@ -126,15 +127,17 @@
uint32_t sz;
uint32_t refcount;
pthread_mutex_t lock;
+ uint32_t bigbufCount;
};
// global device instance
-static gralloc_memregions_t* s_grdev = NULL;
+static gralloc_memregions_t* s_memregions = NULL;
static gralloc_dmaregion_t* s_grdma = NULL;
void init_gralloc_memregions() {
- if (s_grdev) return;
- s_grdev = new gralloc_memregions_t;
+ if (s_memregions) return;
+ s_memregions = new gralloc_memregions_t;
+ pthread_mutex_init(&s_memregions->lock, NULL);
}
void init_gralloc_dmaregion() {
@@ -144,6 +147,7 @@
s_grdma = new gralloc_dmaregion_t;
s_grdma->sz = INITIAL_DMA_REGION_SIZE;
s_grdma->refcount = 0;
+ s_grdma->bigbufCount = 0;
pthread_mutex_init(&s_grdma->lock, NULL);
pthread_mutex_lock(&s_grdma->lock);
@@ -169,11 +173,18 @@
s_grdma->sz = new_sz;
}
-bool put_gralloc_dmaregion() {
+// max dma size: 2x 4K rgba8888
+#define MAX_DMA_SIZE 66355200
+
+bool put_gralloc_dmaregion(uint32_t sz) {
if (!s_grdma) return false;
pthread_mutex_lock(&s_grdma->lock);
D("%s: call. refcount before: %u\n", __FUNCTION__, s_grdma->refcount);
s_grdma->refcount--;
+ if (sz > MAX_DMA_SIZE &&
+ s_grdma->bigbufCount) {
+ s_grdma->bigbufCount--;
+ }
bool shouldDelete = !s_grdma->refcount;
if (shouldDelete) {
D("%s: should delete!\n", __FUNCTION__);
@@ -191,8 +202,14 @@
D("%s: for sz %u, refcount %u", __FUNCTION__, sz, s_grdma->refcount);
uint32_t new_sz = std::max(s_grdma->sz, sz);
if (new_sz != s_grdma->sz) {
- D("%s: change sz from %u to %u", __FUNCTION__, s_grdma->sz, sz);
- resize_gralloc_dmaregion_locked(new_sz);
+ if (new_sz > MAX_DMA_SIZE) {
+ D("%s: requested sz %u too large (limit %u), set to fallback.",
+ __FUNCTION__, sz, MAX_DMA_SIZE);
+ s_grdma->bigbufCount++;
+ } else {
+ D("%s: change sz from %u to %u", __FUNCTION__, s_grdma->sz, sz);
+ resize_gralloc_dmaregion_locked(new_sz);
+ }
}
if (!s_grdma->goldfish_dma.mapped) {
goldfish_dma_map(&s_grdma->goldfish_dma);
@@ -205,15 +222,17 @@
D("%s: call for %p", __FUNCTION__, ashmemBase);
MemRegionInfo lookup;
lookup.ashmemBase = ashmemBase;
- mem_region_handle_t handle = s_grdev->ashmemRegions.find(lookup);
- if (handle == s_grdev->ashmemRegions.end()) {
+ pthread_mutex_lock(&s_memregions->lock);
+ mem_region_handle_t handle = s_memregions->ashmemRegions.find(lookup);
+ if (handle == s_memregions->ashmemRegions.end()) {
MemRegionInfo newRegion;
newRegion.ashmemBase = ashmemBase;
newRegion.refCount = 1;
- s_grdev->ashmemRegions.insert(newRegion);
+ s_memregions->ashmemRegions.insert(newRegion);
} else {
handle->refCount++;
}
+ pthread_mutex_unlock(&s_memregions->lock);
}
bool put_mem_region(void* ashmemBase) {
@@ -221,25 +240,28 @@
D("%s: call for %p", __FUNCTION__, ashmemBase);
MemRegionInfo lookup;
lookup.ashmemBase = ashmemBase;
- mem_region_handle_t handle = s_grdev->ashmemRegions.find(lookup);
- if (handle == s_grdev->ashmemRegions.end()) {
+ pthread_mutex_lock(&s_memregions->lock);
+ mem_region_handle_t handle = s_memregions->ashmemRegions.find(lookup);
+ if (handle == s_memregions->ashmemRegions.end()) {
ALOGE("%s: error: tried to put nonexistent mem region!", __FUNCTION__);
+ pthread_mutex_unlock(&s_memregions->lock);
return true;
} else {
handle->refCount--;
bool shouldRemove = !handle->refCount;
if (shouldRemove) {
- s_grdev->ashmemRegions.erase(lookup);
+ s_memregions->ashmemRegions.erase(lookup);
}
+ pthread_mutex_unlock(&s_memregions->lock);
return shouldRemove;
}
}
void dump_regions() {
init_gralloc_memregions();
- mem_region_handle_t curr = s_grdev->ashmemRegions.begin();
+ mem_region_handle_t curr = s_memregions->ashmemRegions.begin();
std::stringstream res;
- for (; curr != s_grdev->ashmemRegions.end(); curr++) {
+ for (; curr != s_memregions->ashmemRegions.end(); curr++) {
res << "\tashmem base " << curr->ashmemBase << " refcount " << curr->refCount << "\n";
}
ALOGD("ashmem region dump [\n%s]", res.str().c_str());
@@ -354,7 +376,12 @@
width, height, top, left, bpp);
}
- if (s_grdma) {
+ if (s_grdma->bigbufCount) {
+ D("%s: there are big buffers alive, use fallback (count %u)", __FUNCTION__,
+ s_grdma->bigbufCount);
+ }
+
+ if (s_grdma && !s_grdma->bigbufCount) {
if (cb->frameworkFormat == HAL_PIXEL_FORMAT_YV12) {
get_yv12_offsets(width, height, NULL, NULL,
&send_buffer_size);
@@ -394,12 +421,15 @@
#ifndef GL_RGBA16F
#define GL_RGBA16F 0x881A
#endif // GL_RGBA16F
-#ifndef GL_UNSIGNED_INT_10_10_10_2
-#define GL_UNSIGNED_INT_10_10_10_2 0x8DF6
-#endif // GL_UNSIGNED_INT_10_10_10_2
#ifndef GL_HALF_FLOAT
#define GL_HALF_FLOAT 0x140B
#endif // GL_HALF_FLOAT
+#ifndef GL_RGB10_A2
+#define GL_RGB10_A2 0x8059
+#endif // GL_RGB10_A2
+#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#endif // GL_UNSIGNED_INT_2_10_10_10_REV
//
// gralloc device functions (alloc interface)
//
@@ -496,7 +526,10 @@
break;
case HAL_PIXEL_FORMAT_RGB_565:
bpp = 2;
- glFormat = GL_RGB;
+ // Workaround: distinguish vs the RGB8/RGBA8
+ // by changing |glFormat| to GL_RGB565
+ // (previously, it was still GL_RGB)
+ glFormat = GL_RGB565;
glType = GL_UNSIGNED_SHORT_5_6_5;
break;
#if PLATFORM_SDK_VERSION >= 26
@@ -507,8 +540,8 @@
break;
case HAL_PIXEL_FORMAT_RGBA_1010102:
bpp = 4;
- glFormat = GL_RGBA;
- glType = GL_UNSIGNED_INT_10_10_10_2;
+ glFormat = GL_RGB10_A2;
+ glType = GL_UNSIGNED_INT_2_10_10_10_REV;
break;
#endif // PLATFORM_SDK_VERSION >= 26
#if PLATFORM_SDK_VERSION >= 21
@@ -577,7 +610,11 @@
// rendering will still happen on the host but we also need to be able to
// read back from the color buffer, which requires that there is a buffer
//
+#if PLATFORM_SDK_VERSION >= 17
+ bool needHostCb = ((!yuv_format && frameworkFormat != HAL_PIXEL_FORMAT_BLOB) ||
+#else
bool needHostCb = (!yuv_format ||
+#endif
frameworkFormat == HAL_PIXEL_FORMAT_YV12 ||
frameworkFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) &&
#if PLATFORM_SDK_VERSION >= 15
@@ -678,10 +715,19 @@
if (needHostCb) {
if (hostCon && rcEnc) {
+ GLenum allocFormat = glFormat;
+ // The handling of RGBX_8888 is very subtle. Most of the time
+ // we want it to be treated as RGBA_8888, with the exception
+ // that alpha is always ignored and treated as 1. The solution
+ // is to create 3 channel RGB texture instead and host GL will
+ // handle the Alpha channel.
+ if (HAL_PIXEL_FORMAT_RGBX_8888 == format) {
+ allocFormat = GL_RGB;
+ }
if (s_grdma) {
- cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, glFormat, cb->emuFrameworkFormat);
+ cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, allocFormat, cb->emuFrameworkFormat);
} else {
- cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
+ cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, allocFormat);
}
D("Created host ColorBuffer 0x%x\n", cb->hostHandle);
}
@@ -760,7 +806,7 @@
if (cb->ashmemSize > 0 && cb->ashmemBase) {
D("%s: unmapped %p", __FUNCTION__, cb->ashmemBase);
munmap((void *)cb->ashmemBase, cb->ashmemSize);
- put_gralloc_dmaregion();
+ put_gralloc_dmaregion(cb->ashmemSize);
}
close(cb->fd);
}
@@ -914,8 +960,6 @@
return sFallback->registerBuffer(sFallback, handle);
}
- D("gralloc_register_buffer(%p) called", handle);
-
private_module_t *gr = (private_module_t *)module;
cb_handle_t *cb = (cb_handle_t *)handle;
@@ -924,6 +968,9 @@
return -EINVAL;
}
+ D("gralloc_register_buffer(%p) w %d h %d format 0x%x framworkFormat 0x%x",
+ handle, cb->width, cb->height, cb->format, cb->frameworkFormat);
+
if (cb->hostHandle != 0) {
DEFINE_AND_VALIDATE_HOST_CONNECTION;
D("Opening host ColorBuffer 0x%x\n", cb->hostHandle);
@@ -1006,7 +1053,7 @@
if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
PUT_ASHMEM_REGION(cb);
- put_gralloc_dmaregion();
+ put_gralloc_dmaregion(cb->ashmemSize);
if (!SHOULD_UNMAP) goto done;
@@ -1169,8 +1216,8 @@
cb->lockedHeight = h;
}
- DD("gralloc_lock success. vaddr: %p, *vaddr: %p, usage: %x, cpu_addr: %p",
- vaddr, vaddr ? *vaddr : 0, usage, cpu_addr);
+ DD("gralloc_lock success. vaddr: %p, *vaddr: %p, usage: %x, cpu_addr: %p, base: %p",
+ vaddr, vaddr ? *vaddr : 0, usage, cpu_addr, cb->ashmemBase);
return 0;
}
@@ -1288,14 +1335,12 @@
cStep = 1;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
- align = 1;
yStride = cb->width;
- cStride = yStride / 2;
+ cStride = cb->width;
yOffset = 0;
- cSize = cStride * cb->height/2;
- uOffset = yStride * cb->height;
- vOffset = uOffset + cSize;
- cStep = 1;
+ vOffset = yStride * cb->height;
+ uOffset = vOffset + 1;
+ cStep = 2;
break;
default:
ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
@@ -1322,9 +1367,9 @@
cb->lockedHeight = h;
DD("gralloc_lock_ycbcr success. usage: %x, ycbcr.y: %p, .cb: %p, .cr: %p, "
- ".ystride: %d , .cstride: %d, .chroma_step: %d", usage,
+ ".ystride: %d , .cstride: %d, .chroma_step: %d, base: %p", usage,
ycbcr->y, ycbcr->cb, ycbcr->cr, ycbcr->ystride, ycbcr->cstride,
- ycbcr->chroma_step);
+ ycbcr->chroma_step, cb->ashmemBase);
return 0;
}
diff --git a/system/renderControl_enc/renderControl_client_context.cpp b/system/renderControl_enc/renderControl_client_context.cpp
index 617e8f9..4a86244 100644
--- a/system/renderControl_enc/renderControl_client_context.cpp
+++ b/system/renderControl_enc/renderControl_client_context.cpp
@@ -46,6 +46,7 @@
rcSetPuid = (rcSetPuid_client_proc_t) getProc("rcSetPuid", userData);
rcUpdateColorBufferDMA = (rcUpdateColorBufferDMA_client_proc_t) getProc("rcUpdateColorBufferDMA", userData);
rcCreateColorBufferDMA = (rcCreateColorBufferDMA_client_proc_t) getProc("rcCreateColorBufferDMA", userData);
+ rcWaitSyncKHR = (rcWaitSyncKHR_client_proc_t) getProc("rcWaitSyncKHR", userData);
return 0;
}
diff --git a/system/renderControl_enc/renderControl_client_context.h b/system/renderControl_enc/renderControl_client_context.h
index 7a3e3f6..1e5594b 100644
--- a/system/renderControl_enc/renderControl_client_context.h
+++ b/system/renderControl_enc/renderControl_client_context.h
@@ -46,6 +46,7 @@
rcSetPuid_client_proc_t rcSetPuid;
rcUpdateColorBufferDMA_client_proc_t rcUpdateColorBufferDMA;
rcCreateColorBufferDMA_client_proc_t rcCreateColorBufferDMA;
+ rcWaitSyncKHR_client_proc_t rcWaitSyncKHR;
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 e517d07..3f1e5bb 100644
--- a/system/renderControl_enc/renderControl_client_proc.h
+++ b/system/renderControl_enc/renderControl_client_proc.h
@@ -45,6 +45,7 @@
typedef void (renderControl_APIENTRY *rcSetPuid_client_proc_t) (void * ctx, uint64_t);
typedef int (renderControl_APIENTRY *rcUpdateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*, uint32_t);
typedef uint32_t (renderControl_APIENTRY *rcCreateColorBufferDMA_client_proc_t) (void * ctx, uint32_t, uint32_t, GLenum, int);
+typedef void (renderControl_APIENTRY *rcWaitSyncKHR_client_proc_t) (void * ctx, uint64_t, EGLint);
#endif
diff --git a/system/renderControl_enc/renderControl_enc.cpp b/system/renderControl_enc/renderControl_enc.cpp
index 3c4a3f3..e22d7c0 100644
--- a/system/renderControl_enc/renderControl_enc.cpp
+++ b/system/renderControl_enc/renderControl_enc.cpp
@@ -1365,6 +1365,32 @@
return retval;
}
+void rcWaitSyncKHR_enc(void *self , uint64_t sync, EGLint flags)
+{
+
+ 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;
+
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + 8 + 4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(totalSize);
+ ptr = buf;
+ int tmp = OP_rcWaitSyncKHR;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ memcpy(ptr, &sync, 8); ptr += 8;
+ memcpy(ptr, &flags, 4); ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ if (useChecksum) checksumCalculator->writeChecksum(ptr, checksumSize); ptr += checksumSize;
+
+}
+
} // namespace
renderControl_encoder_context_t::renderControl_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -1408,5 +1434,6 @@
this->rcSetPuid = &rcSetPuid_enc;
this->rcUpdateColorBufferDMA = &rcUpdateColorBufferDMA_enc;
this->rcCreateColorBufferDMA = &rcCreateColorBufferDMA_enc;
+ this->rcWaitSyncKHR = &rcWaitSyncKHR_enc;
}
diff --git a/system/renderControl_enc/renderControl_entry.cpp b/system/renderControl_enc/renderControl_entry.cpp
index 101806e..9a47dd3 100644
--- a/system/renderControl_enc/renderControl_entry.cpp
+++ b/system/renderControl_enc/renderControl_entry.cpp
@@ -41,6 +41,7 @@
void rcSetPuid(uint64_t puid);
int rcUpdateColorBufferDMA(uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels, uint32_t pixels_size);
uint32_t rcCreateColorBufferDMA(uint32_t width, uint32_t height, GLenum internalFormat, int frameworkFormat);
+ void rcWaitSyncKHR(uint64_t sync, EGLint flags);
};
#ifndef GET_CONTEXT
@@ -265,3 +266,9 @@
return ctx->rcCreateColorBufferDMA(ctx, width, height, internalFormat, frameworkFormat);
}
+void rcWaitSyncKHR(uint64_t sync, EGLint flags)
+{
+ GET_CONTEXT;
+ ctx->rcWaitSyncKHR(ctx, sync, flags);
+}
+
diff --git a/system/renderControl_enc/renderControl_ftable.h b/system/renderControl_enc/renderControl_ftable.h
index 4f2a09e..7bfc7c5 100644
--- a/system/renderControl_enc/renderControl_ftable.h
+++ b/system/renderControl_enc/renderControl_ftable.h
@@ -44,6 +44,7 @@
{"rcSetPuid", (void*)rcSetPuid},
{"rcUpdateColorBufferDMA", (void*)rcUpdateColorBufferDMA},
{"rcCreateColorBufferDMA", (void*)rcCreateColorBufferDMA},
+ {"rcWaitSyncKHR", (void*)rcWaitSyncKHR},
};
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 43d8f30..146164f 100644
--- a/system/renderControl_enc/renderControl_opcodes.h
+++ b/system/renderControl_enc/renderControl_opcodes.h
@@ -39,7 +39,8 @@
#define OP_rcSetPuid 10033
#define OP_rcUpdateColorBufferDMA 10034
#define OP_rcCreateColorBufferDMA 10035
-#define OP_last 10036
+#define OP_rcWaitSyncKHR 10036
+#define OP_last 10037
#endif