#include "GL2Encoder.h"
#endif
+#include <GLES3/gl31.h>
+
#if PLATFORM_SDK_VERSION >= 16
#include <system/window.h>
#else // PLATFORM_SDK_VERSION >= 16
// The one and only supported display object.
static eglDisplay s_display;
-EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
+EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx, int maj, int min) :
dpy(dpy),
config(config),
read(EGL_NO_SURFACE),
shareCtx(shareCtx),
rcContext(0),
versionString(NULL),
+ majorVersion(maj),
+ minorVersion(min),
vendorString(NULL),
rendererString(NULL),
shaderVersionString(NULL),
goldfishSyncFd(-1)
{
flags = 0;
- version = 1;
- clientState = new GLClientState();
- if (shareCtx)
+ clientState = new GLClientState(majorVersion, minorVersion);
+ if (shareCtx)
sharedGroup = shareCtx->getSharedGroup();
else
sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
int presentFenceFd = -1;
+ if (buffer == NULL) {
+ ALOGE("egl_window_surface_t::swapBuffers called with NULL buffer");
+ setErrorReturn(EGL_BAD_SURFACE, EGL_FALSE);
+ }
+
#if PLATFORM_SDK_VERSION <= 16
rcEnc->rcFlushWindowColorBuffer(rcEnc, rcSurface);
// equivalent to glFinish if no native sync
return EGL_FALSE;
}
- rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(),
- pixelFormat);
+ rcColorBuffer = rcEnc->rcCreateColorBuffer(rcEnc, getWidth(), getHeight(), pixelFormat);
if (!rcColorBuffer) {
ALOGE("rcCreateColorBuffer returned 0");
return EGL_FALSE;
return NULL;
}
- if (*strPtr != NULL) {
- //
- // string is already cached
- //
- return *strPtr;
- }
-
//
// first query of that string - need to query host
//
attribs_size++; //for the terminating EGL_NONE
}
- // API 16 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
+ // API 19 passes EGL_SWAP_BEHAVIOR_PRESERVED_BIT to surface type,
// while the host never supports it.
// We remove the bit here.
EGLint* local_attrib_list = NULL;
- if (PLATFORM_SDK_VERSION <= 16) {
+ if (PLATFORM_SDK_VERSION <= 19) {
local_attrib_list = new EGLint[attribs_size];
memcpy(local_attrib_list, attrib_list, attribs_size * sizeof(EGLint));
EGLint* local_attrib_p = local_attrib_list;
}
else
{
+ ALOGD("%s: bad attrib 0x%x", __FUNCTION__, attribute);
RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
}
}
// with the only issue that we do not require a valid display here.
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
- if (context->version == 2) {
+ if (context->majorVersion > 1) {
hostCon->gl2Encoder()->setClientState(NULL);
hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
}
VALIDATE_DISPLAY_INIT(dpy, EGL_NO_CONTEXT);
VALIDATE_CONFIG(config, EGL_NO_CONTEXT);
- EGLint version = 1; //default
+ EGLint majorVersion = 1; //default
+ EGLint minorVersion = 0;
+ EGLint context_flags = 0;
+ EGLint profile_mask = 0;
+ EGLint reset_notification_strategy = 0;
+
+ bool wantedMajorVersion = false;
+ bool wantedMinorVersion = false;
+
while (attrib_list && attrib_list[0] != EGL_NONE) {
- if (attrib_list[0] == EGL_CONTEXT_CLIENT_VERSION) {
- version = attrib_list[1];
- } else { // Only the attribute EGL_CONTEXT_CLIENT_VERSION may be specified.
+ EGLint attrib_val = attrib_list[1];
+ switch(attrib_list[0]) {
+ case EGL_CONTEXT_MAJOR_VERSION_KHR:
+ majorVersion = attrib_val;
+ wantedMajorVersion = true;
+ break;
+ case EGL_CONTEXT_MINOR_VERSION_KHR:
+ minorVersion = attrib_val;
+ wantedMinorVersion = true;
+ break;
+ case EGL_CONTEXT_FLAGS_KHR:
+ if ((attrib_val | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) ||
+ (attrib_val | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) ||
+ (attrib_val | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
+ context_flags = attrib_val;
+ } else {
+ RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
+ }
+ break;
+ case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+ if ((attrib_val | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ||
+ (attrib_val | EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)) {
+ profile_mask = attrib_val;
+ } else {
+ 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;
+ break;
+ default:
setErrorReturn(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
}
attrib_list+=2;
}
- // Currently only support GLES1 and 2
- if (version != 1 && version != 2) {
+ if (!wantedMajorVersion) {
+ majorVersion = 1;
+ }
+
+ // Support up to GLES 3.2 depending on advertised version from the host system.
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
+ switch (majorVersion) {
+ case 1:
+ case 2:
+ break;
+ case 3:
+ if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_0) {
+ ALOGE("%s: EGL_BAD_CONFIG: no ES 3 support", __FUNCTION__);
+ setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+ switch (minorVersion) {
+ case 0:
+ break;
+ case 1:
+ if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_1) {
+ ALOGE("%s: EGL_BAD_CONFIG: no ES 3.1 support", __FUNCTION__);
+ setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+ break;
+ case 2:
+ if (rcEnc->getGLESMaxVersion() < GLES_MAX_VERSION_3_2) {
+ ALOGE("%s: EGL_BAD_CONFIG: no ES 3.2 support", __FUNCTION__);
+ setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+ break;
+ default:
+ ALOGE("%s: EGL_BAD_CONFIG: Unknown ES version %d.%d",
+ __FUNCTION__, majorVersion, minorVersion);
+ setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+ }
+ break;
+ default:
setErrorReturn(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
}
setErrorReturn(EGL_BAD_MATCH, EGL_NO_CONTEXT);
}
- DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_NO_CONTEXT);
// We've created EGL context. Disconnecting
// would be dangerous at this point.
hostCon->setGrallocOnly(false);
- uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, version);
+ int rcMajorVersion = majorVersion;
+ if (majorVersion == 3 && minorVersion == 1) {
+ rcMajorVersion = 4;
+ }
+ if (majorVersion == 3 && minorVersion == 2) {
+ rcMajorVersion = 4;
+ }
+ uint32_t rcContext = rcEnc->rcCreateContext(rcEnc, (uintptr_t)config, rcShareCtx, rcMajorVersion);
if (!rcContext) {
ALOGE("rcCreateContext returned 0");
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
}
- EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx);
- if (!context)
+ EGLContext_t * context = new EGLContext_t(dpy, config, shareCtx, majorVersion, minorVersion);
+ ALOGD("%s: %p: maj %d min %d rcv %d", __FUNCTION__, context, majorVersion, minorVersion, rcMajorVersion);
+ if (!context) {
+ ALOGE("could not alloc egl context!");
setErrorReturn(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ }
- context->version = version;
context->rcContext = rcContext;
-
-
return context;
}
//Now make the local bind
if (context) {
+
+ ALOGD("%s: %p: ver %d %d", __FUNCTION__, context, context->majorVersion, context->minorVersion);
// This is a nontrivial context.
// The thread cannot be gralloc-only anymore.
hostCon->setGrallocOnly(false);
context->draw = draw;
context->read = read;
context->flags |= EGLContext_t::IS_CURRENT;
+ GLClientState* contextState =
+ context->getClientState();
+
+ if (!hostCon->gl2Encoder()->isInitialized()) {
+ s_display.gles2_iface()->init();
+ hostCon->gl2Encoder()->setInitialized();
+ ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
+ }
+ if (contextState->needsInitFromCaps()) {
+ // Get caps for indexed buffers from host.
+ // Some need a current context.
+ int max_transform_feedback_separate_attribs = 0;
+ int max_uniform_buffer_bindings = 0;
+ int max_atomic_counter_buffer_bindings = 0;
+ int max_shader_storage_buffer_bindings = 0;
+ int max_vertex_attrib_bindings = 0;
+ int max_color_attachments = 1;
+ int max_draw_buffers = 1;
+ if (context->majorVersion > 2) {
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uniform_buffer_bindings);
+ if (context->minorVersion > 0) {
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &max_atomic_counter_buffer_bindings);
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &max_shader_storage_buffer_bindings);
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
+ }
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
+ s_display.gles2_iface()->getIntegerv(
+ GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
+ }
+ contextState->initFromCaps(
+ max_transform_feedback_separate_attribs,
+ max_uniform_buffer_bindings,
+ max_atomic_counter_buffer_bindings,
+ max_shader_storage_buffer_bindings,
+ max_vertex_attrib_bindings,
+ max_color_attachments,
+ max_draw_buffers);
+ }
+
//set the client state
- if (context->version == 2) {
- hostCon->gl2Encoder()->setClientStateMakeCurrent(context->getClientState());
+ if (context->majorVersion > 1) {
+ hostCon->gl2Encoder()->setClientStateMakeCurrent(
+ contextState,
+ context->majorVersion,
+ context->minorVersion);
hostCon->gl2Encoder()->setSharedGroup(context->getSharedGroup());
}
else {
}
else if (tInfo->currentContext) {
//release ClientState & SharedGroup
- if (tInfo->currentContext->version == 2) {
+ if (tInfo->currentContext->majorVersion > 1) {
hostCon->gl2Encoder()->setClientState(NULL);
hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr(NULL));
}
//Check maybe we need to init the encoder, if it's first eglMakeCurrent
if (tInfo->currentContext) {
- if (tInfo->currentContext->version == 2) {
+ if (tInfo->currentContext->majorVersion > 1) {
if (!hostCon->gl2Encoder()->isInitialized()) {
s_display.gles2_iface()->init();
hostCon->gl2Encoder()->setInitialized();
*value = EGL_OPENGL_ES_API;
break;
case EGL_CONTEXT_CLIENT_VERSION:
- *value = context->version;
+ *value = context->majorVersion;
break;
case EGL_RENDER_BUFFER:
if (!context->draw)
return EGL_FALSE;
}
- if (tInfo->currentContext->version == 2) {
+ if (tInfo->currentContext->majorVersion > 1) {
s_display.gles2_iface()->finish();
}
else {
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE);
// post the surface
- d->swapBuffers();
+ EGLBoolean ret = d->swapBuffers();
hostCon->flush();
- return EGL_TRUE;
+ return ret;
}
EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
return (EGLImageKHR)image;
}
-
+
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}