Merge change 22399 into eclair
* changes:
Refactor VCard handling code, phase 2, 3, 4, 5
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 523aed0..67c2dd8 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -287,6 +287,7 @@
vec4_t normalizedObjPosition;
vec4_t spotDir;
vec4_t normalizedSpotDir;
+ vec4_t objViewer;
GLfixed spotExp;
GLfixed spotCutoff;
GLfixed spotCutoffCosine;
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 8ae32cc..f211bca 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -216,6 +216,8 @@
static inline void validate_light_mvi(ogles_context_t* c)
{
uint32_t en = c->lighting.enabledLights;
+ // Vector from object to viewer, in eye coordinates
+ const vec4_t eyeViewer = { 0, 0, 0x1000, 0 };
while (en) {
const int i = 31 - gglClz(en);
en &= ~(1<<i);
@@ -223,6 +225,9 @@
c->transforms.mvui.point4(&c->transforms.mvui,
&l.objPosition, &l.position);
vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
+ c->transforms.mvui.point4(&c->transforms.mvui,
+ &l.objViewer, &eyeViewer);
+ vnorm3(l.objViewer.v, l.objViewer.v);
}
}
@@ -379,9 +384,9 @@
// specular
if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
vec4_t h;
- h.x = d.x;
- h.y = d.y;
- h.z = d.z + 0x10000;
+ h.x = d.x + l.objViewer.x;
+ h.y = d.y + l.objViewer.y;
+ h.z = d.z + l.objViewer.z;
vnorm3(h.v, h.v);
s = dot3(n.v, h.v);
s = (s<0) ? (twoSide?(-s):0) : s;
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 0b68dc0..21ef50e 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -696,6 +696,8 @@
f[2] = 0; f[6] = 0; f[10] = A; f[14] = B;
f[3] = 0; f[7] = 0; f[11] = 0; f[15] = 1;
c->transforms.dirty |= transform_state_t::VIEWPORT;
+ if (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)
+ c->transforms.dirty |= transform_state_t::MVP;
}
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index e1fd48b..9578452 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -28,6 +28,10 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
+ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+LOCAL_CFLAGS += -DADRENO130=1
+endif
+
include $(BUILD_SHARED_LIBRARY)
installed_libEGL := $(LOCAL_INSTALLED_MODULE)
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 03e764c..d1ddcd3 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -36,6 +36,8 @@
#include <cutils/properties.h>
#include <cutils/memory.h>
+#include <utils/SortedVector.h>
+
#include "hooks.h"
#include "egl_impl.h"
#include "Loader.h"
@@ -63,40 +65,122 @@
// ----------------------------------------------------------------------------
-template <int MAGIC>
-struct egl_object_t
-{
- egl_object_t() : magic(MAGIC) { }
- ~egl_object_t() { magic = 0; }
- bool isValid() const { return magic == MAGIC; }
+class egl_object_t {
+ static SortedVector<egl_object_t*> sObjects;
+ static Mutex sLock;
+
+ volatile int32_t terminated;
+ mutable volatile int32_t count;
+
+public:
+ egl_object_t() : terminated(0), count(1) {
+ Mutex::Autolock _l(sLock);
+ sObjects.add(this);
+ }
+
+ inline bool isAlive() const { return !terminated; }
+
private:
- uint32_t magic;
+ bool get() {
+ Mutex::Autolock _l(sLock);
+ if (egl_object_t::sObjects.indexOf(this) >= 0) {
+ android_atomic_inc(&count);
+ return true;
+ }
+ return false;
+ }
+
+ bool put() {
+ Mutex::Autolock _l(sLock);
+ if (android_atomic_dec(&count) == 1) {
+ sObjects.remove(this);
+ return true;
+ }
+ return false;
+ }
+
+public:
+ template <typename N, typename T>
+ struct LocalRef {
+ N* ref;
+ LocalRef(T o) : ref(0) {
+ N* native = reinterpret_cast<N*>(o);
+ if (o && native->get()) {
+ ref = native;
+ }
+ }
+ ~LocalRef() {
+ if (ref && ref->put()) {
+ delete ref;
+ }
+ }
+ inline N* get() {
+ return ref;
+ }
+ void acquire() const {
+ if (ref) {
+ android_atomic_inc(&ref->count);
+ }
+ }
+ void release() const {
+ if (ref) {
+ int32_t c = android_atomic_dec(&ref->count);
+ // ref->count cannot be 1 prior atomic_dec because we have
+ // a reference, and if we have one, it means there was
+ // already one before us.
+ LOGE_IF(c==1, "refcount is now 0 in release()");
+ }
+ }
+ void terminate() {
+ if (ref) {
+ ref->terminated = 1;
+ release();
+ }
+ }
+ };
};
-struct egl_display_t : public egl_object_t<'_dpy'>
-{
- EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
- EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
- EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
- EGLint numTotalConfigs;
- char const* extensionsString;
- volatile int32_t refs;
+SortedVector<egl_object_t*> egl_object_t::sObjects;
+Mutex egl_object_t::sLock;
+
+struct egl_display_t {
+ enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
+
struct strings_t {
char const * vendor;
char const * version;
char const * clientApi;
char const * extensions;
};
- strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+
+ struct DisplayImpl {
+ DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
+ state(NOT_INITIALIZED), numConfigs(0) { }
+ EGLDisplay dpy;
+ EGLConfig* config;
+ EGLint state;
+ EGLint numConfigs;
+ strings_t queryString;
+ };
+
+ uint32_t magic;
+ DisplayImpl disp[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+ EGLint numTotalConfigs;
+ volatile int32_t refs;
+
+ egl_display_t() : magic('_dpy'), numTotalConfigs(0) { }
+ ~egl_display_t() { magic = 0; }
+ inline bool isValid() const { return magic == '_dpy'; }
+ inline bool isAlive() const { return isValid(); }
};
-struct egl_surface_t : public egl_object_t<'_srf'>
+struct egl_surface_t : public egl_object_t
{
+ typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
+
egl_surface_t(EGLDisplay dpy, EGLSurface surface,
int impl, egl_connection_t const* cnx)
- : dpy(dpy), surface(surface), impl(impl), cnx(cnx)
- {
- // NOTE: window must be incRef'ed and connected already
+ : dpy(dpy), surface(surface), impl(impl), cnx(cnx) {
}
~egl_surface_t() {
}
@@ -106,8 +190,10 @@
egl_connection_t const* cnx;
};
-struct egl_context_t : public egl_object_t<'_ctx'>
+struct egl_context_t : public egl_object_t
{
+ typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
+
egl_context_t(EGLDisplay dpy, EGLContext context,
int impl, egl_connection_t const* cnx)
: dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx)
@@ -121,8 +207,10 @@
egl_connection_t const* cnx;
};
-struct egl_image_t : public egl_object_t<'_img'>
+struct egl_image_t : public egl_object_t
{
+ typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
+
egl_image_t(EGLDisplay dpy, EGLContext context)
: dpy(dpy), context(context)
{
@@ -133,6 +221,10 @@
EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
};
+typedef egl_surface_t::Ref SurfaceRef;
+typedef egl_context_t::Ref ContextRef;
+typedef egl_image_t::Ref ImageRef;
+
struct tls_t
{
tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
@@ -272,14 +364,14 @@
static EGLint configToUniqueId(egl_display_t const* dp, int i, int index)
{
// NOTE: this mapping works only if we have no more than two EGLimpl
- return (i>0 ? dp->numConfigs[0] : 0) + index;
+ return (i>0 ? dp->disp[0].numConfigs : 0) + index;
}
static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId,
int& i, int& index)
{
// NOTE: this mapping works only if we have no more than two EGLimpl
- size_t numConfigs = dp->numConfigs[0];
+ size_t numConfigs = dp->disp[0].numConfigs;
i = configId / numConfigs;
index = configId % numConfigs;
}
@@ -391,7 +483,7 @@
return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
}
index = uintptr_t(config) & 0xFFFFFF;
- if (index >= dp->numConfigs[impl]) {
+ if (index >= dp->disp[impl].numConfigs) {
return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
}
egl_connection_t* const cnx = &gEGLImpl[impl];
@@ -405,11 +497,9 @@
{
if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (!get_display(dpy)->isValid())
+ if (!get_display(dpy)->isAlive())
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (!ctx) // TODO: make sure context is a valid object
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- if (!get_context(ctx)->isValid())
+ if (!get_context(ctx)->isAlive())
return setError(EGL_BAD_CONTEXT, EGL_FALSE);
return EGL_TRUE;
}
@@ -418,37 +508,34 @@
{
if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (!get_display(dpy)->isValid())
+ if (!get_display(dpy)->isAlive())
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (!surface) // TODO: make sure surface is a valid object
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (!get_surface(surface)->isValid())
+ if (!get_surface(surface)->isAlive())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
return EGL_TRUE;
}
-
EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
{
+ ImageRef _i(image);
+ if (!_i.get()) return EGL_NO_IMAGE_KHR;
+
EGLContext context = getContext();
if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
return EGL_NO_IMAGE_KHR;
egl_context_t const * const c = get_context(context);
- if (!c->isValid())
+ if (!c->isAlive())
return EGL_NO_IMAGE_KHR;
egl_image_t const * const i = get_image(image);
- if (!i->isValid())
- return EGL_NO_IMAGE_KHR;
-
return i->images[c->impl];
}
// ----------------------------------------------------------------------------
// this mutex protects:
-// d->dpys[]
+// d->disp[]
// egl_init_drivers_locked()
//
static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -477,7 +564,7 @@
if (cnx->dso) {
EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
- d->dpys[IMPL_SOFTWARE] = dpy;
+ d->disp[IMPL_SOFTWARE].dpy = dpy;
if (dpy == EGL_NO_DISPLAY) {
loader.close(cnx->dso);
cnx->dso = NULL;
@@ -495,7 +582,7 @@
if (cnx->dso) {
EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
- d->dpys[IMPL_HARDWARE] = dpy;
+ d->disp[IMPL_HARDWARE].dpy = dpy;
if (dpy == EGL_NO_DISPLAY) {
loader.close(cnx->dso);
cnx->dso = NULL;
@@ -505,7 +592,7 @@
LOGD("3D hardware acceleration is disabled");
}
}
-
+
if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
return EGL_FALSE;
}
@@ -563,7 +650,6 @@
// initialize each EGL and
// build our own extension string first, based on the extension we know
// and the extension supported by our client implementation
- dp->extensionsString = strdup(gExtensionString);
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
cnx->major = -1;
@@ -571,25 +657,43 @@
if (!cnx->dso)
continue;
- if (cnx->hooks->egl.eglInitialize(
- dp->dpys[i], &cnx->major, &cnx->minor)) {
+#if defined(ADRENO130)
+#warning "Adreno-130 eglInitialize() workaround"
+ /*
+ * The ADRENO 130 driver returns a different EGLDisplay each time
+ * eglGetDisplay() is called, but also makes the EGLDisplay invalid
+ * after eglTerminate() has been called, so that eglInitialize()
+ * cannot be called again. Therefore, we need to make sure to call
+ * eglGetDisplay() before calling eglInitialize();
+ */
+ if (i == IMPL_HARDWARE) {
+ dp->disp[i].dpy =
+ cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ }
+#endif
+
+ EGLDisplay idpy = dp->disp[i].dpy;
+ if (cnx->hooks->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
//LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
- // i, dp->dpys[i], cnx->major, cnx->minor, cnx);
+ // i, idpy, cnx->major, cnx->minor, cnx);
+
+ // display is now initialized
+ dp->disp[i].state = egl_display_t::INITIALIZED;
// get the query-strings for this display for each implementation
- dp->queryString[i].vendor =
- cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR);
- dp->queryString[i].version =
- cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION);
- dp->queryString[i].extensions = strdup(
- cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS));
- dp->queryString[i].clientApi =
- cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS);
+ dp->disp[i].queryString.vendor =
+ cnx->hooks->egl.eglQueryString(idpy, EGL_VENDOR);
+ dp->disp[i].queryString.version =
+ cnx->hooks->egl.eglQueryString(idpy, EGL_VERSION);
+ dp->disp[i].queryString.extensions =
+ cnx->hooks->egl.eglQueryString(idpy, EGL_EXTENSIONS);
+ dp->disp[i].queryString.clientApi =
+ cnx->hooks->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
} else {
- LOGD("%d: eglInitialize() failed (%s)",
- i, egl_strerror(cnx->hooks->egl.eglGetError()));
+ LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+ egl_strerror(cnx->hooks->egl.eglGetError()));
}
}
@@ -598,15 +702,16 @@
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
EGLint n;
- if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) {
- dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
- if (dp->configs[i]) {
+ if (cnx->hooks->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
+ dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
+ if (dp->disp[i].config) {
if (cnx->hooks->egl.eglGetConfigs(
- dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i]))
+ dp->disp[i].dpy, dp->disp[i].config, n,
+ &dp->disp[i].numConfigs))
{
// sort the configurations so we can do binary searches
- qsort( dp->configs[i],
- dp->numConfigs[i],
+ qsort( dp->disp[i].config,
+ dp->disp[i].numConfigs,
sizeof(EGLConfig), cmp_configs);
dp->numTotalConfigs += n;
@@ -639,18 +744,24 @@
EGLBoolean res = EGL_FALSE;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- cnx->hooks->egl.eglTerminate(dp->dpys[i]);
+ if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
+ if (cnx->hooks->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
+ LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
+ egl_strerror(cnx->hooks->egl.eglGetError()));
+ }
// REVISIT: it's unclear what to do if eglTerminate() fails
- free(dp->configs[i]);
- free((void*)dp->queryString[i].extensions);
- dp->numConfigs[i] = 0;
- dp->dpys[i] = EGL_NO_DISPLAY;
+ free(dp->disp[i].config);
+
+ dp->disp[i].numConfigs = 0;
+ dp->disp[i].config = 0;
+ dp->disp[i].state = egl_display_t::TERMINATED;
+
res = EGL_TRUE;
}
}
- free((void*)dp->extensionsString);
- dp->extensionsString = 0;
+
+ // TODO: all egl_object_t should be marked for termination
+
dp->numTotalConfigs = 0;
clearTLS();
return res;
@@ -674,7 +785,7 @@
}
GLint n = 0;
for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
- for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
+ for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
*configs++ = MAKE_CONFIG(j, i);
config_size--;
n++;
@@ -731,7 +842,7 @@
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
cnx->hooks->egl.eglGetConfigAttrib(
- dp->dpys[i], dp->configs[i][index],
+ dp->disp[i].dpy, dp->disp[i].config[index],
EGL_CONFIG_ID, &configId);
// and switch to the new list
@@ -746,7 +857,7 @@
// which one.
res = cnx->hooks->egl.eglChooseConfig(
- dp->dpys[i], attrib_list, configs, config_size, &n);
+ dp->disp[i].dpy, attrib_list, configs, config_size, &n);
if (res && n>0) {
// n has to be 0 or 1, by construction, and we already know
// which config it will return (since there can be only one).
@@ -765,13 +876,14 @@
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
if (cnx->hooks->egl.eglChooseConfig(
- dp->dpys[i], attrib_list, configs, config_size, &n)) {
+ dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
if (configs) {
// now we need to convert these client EGLConfig to our
// internal EGLConfig format. This is done in O(n log n).
for (int j=0 ; j<n ; j++) {
int index = binarySearch<EGLConfig>(
- dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]);
+ dp->disp[i].config, 0,
+ dp->disp[i].numConfigs-1, configs[j]);
if (index >= 0) {
if (configs) {
configs[j] = MAKE_CONFIG(i, index);
@@ -806,7 +918,7 @@
return EGL_TRUE;
}
return cnx->hooks->egl.eglGetConfigAttrib(
- dp->dpys[i], dp->configs[i][index], attribute, value);
+ dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
}
// ----------------------------------------------------------------------------
@@ -822,7 +934,7 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
if (cnx) {
EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
- dp->dpys[i], dp->configs[i][index], window, attrib_list);
+ dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list);
if (surface != EGL_NO_SURFACE) {
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
return s;
@@ -840,7 +952,7 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
if (cnx) {
EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
- dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
+ dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list);
if (surface != EGL_NO_SURFACE) {
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
return s;
@@ -857,7 +969,7 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
if (cnx) {
EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
- dp->dpys[i], dp->configs[i][index], attrib_list);
+ dp->disp[i].dpy, dp->disp[i].config[index], attrib_list);
if (surface != EGL_NO_SURFACE) {
egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
return s;
@@ -868,28 +980,35 @@
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
- egl_surface_t const * const s = get_surface(surface);
+ egl_surface_t * const s = get_surface(surface);
EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
- dp->dpys[s->impl], s->surface);
-
- delete s;
+ dp->disp[s->impl].dpy, s->surface);
+ if (result == EGL_TRUE) {
+ _s.terminate();
+ }
return result;
}
EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
EGLint attribute, EGLint *value)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(surface);
return s->cnx->hooks->egl.eglQuerySurface(
- dp->dpys[s->impl], s->surface, attribute, value);
+ dp->disp[s->impl].dpy, s->surface, attribute, value);
}
// ----------------------------------------------------------------------------
@@ -904,7 +1023,8 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
if (cnx) {
EGLContext context = cnx->hooks->egl.eglCreateContext(
- dp->dpys[i], dp->configs[i][index], share_list, attrib_list);
+ dp->disp[i].dpy, dp->disp[i].config[index],
+ share_list, attrib_list);
if (context != EGL_NO_CONTEXT) {
egl_context_t* c = new egl_context_t(dpy, context, i, cnx);
return c;
@@ -915,66 +1035,125 @@
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
+ ContextRef _c(ctx);
+ if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
if (!validate_display_context(dpy, ctx))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_context_t * const c = get_context(ctx);
EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext(
- dp->dpys[c->impl], c->context);
- delete c;
+ dp->disp[c->impl].dpy, c->context);
+ if (result == EGL_TRUE) {
+ _c.terminate();
+ }
return result;
}
EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx)
{
+ // get a reference to the object passed in
+ ContextRef _c(ctx);
+ SurfaceRef _d(draw);
+ SurfaceRef _r(read);
+
+ // validate the display and the context (if not EGL_NO_CONTEXT)
egl_display_t const * const dp = get_display(dpy);
if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- if (read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE &&
- ctx == EGL_NO_CONTEXT)
- {
- EGLBoolean result = EGL_TRUE;
- ctx = getContext();
- if (ctx) {
- egl_context_t * const c = get_context(ctx);
- result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0);
- if (result == EGL_TRUE) {
- setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
- setContext(EGL_NO_CONTEXT);
- }
- }
- return result;
+ if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
+ // EGL_NO_CONTEXT is valid
+ return EGL_FALSE;
}
- if (!validate_display_context(dpy, ctx))
- return EGL_FALSE;
-
+ // these are the underlying implementation's object
+ EGLContext impl_ctx = EGL_NO_CONTEXT;
EGLSurface impl_draw = EGL_NO_SURFACE;
EGLSurface impl_read = EGL_NO_SURFACE;
- egl_context_t * const c = get_context(ctx);
+
+ // these are our objects structs passed in
+ egl_context_t * c = NULL;
+ egl_surface_t const * d = NULL;
+ egl_surface_t const * r = NULL;
+
+ // these are the current objects structs
+ egl_context_t * cur_c = get_context(getContext());
+ egl_surface_t * cur_r = NULL;
+ egl_surface_t * cur_d = NULL;
+
+ if (ctx != EGL_NO_CONTEXT) {
+ c = get_context(ctx);
+ cur_r = get_surface(c->read);
+ cur_d = get_surface(c->draw);
+ impl_ctx = c->context;
+ } else {
+ // no context given, use the implementation of the current context
+ if (cur_c == NULL) {
+ // no current context
+ if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
+ // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+ // not an error, there is just not current context.
+ return EGL_TRUE;
+ }
+ }
+
+ // retrieve the underlying implementation's draw EGLSurface
if (draw != EGL_NO_SURFACE) {
- egl_surface_t const * d = get_surface(draw);
- if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (d->impl != c->impl)
+ d = get_surface(draw);
+ // make sure the EGLContext and EGLSurface passed in are for
+ // the same driver
+ if (c && d->impl != c->impl)
return setError(EGL_BAD_MATCH, EGL_FALSE);
impl_draw = d->surface;
}
+
+ // retrieve the underlying implementation's read EGLSurface
if (read != EGL_NO_SURFACE) {
- egl_surface_t const * r = get_surface(read);
- if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (r->impl != c->impl)
+ r = get_surface(read);
+ // make sure the EGLContext and EGLSurface passed in are for
+ // the same driver
+ if (c && r->impl != c->impl)
return setError(EGL_BAD_MATCH, EGL_FALSE);
impl_read = r->surface;
}
- EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent(
- dp->dpys[c->impl], impl_draw, impl_read, c->context);
+
+ EGLBoolean result;
+
+ if (c) {
+ result = c->cnx->hooks->egl.eglMakeCurrent(
+ dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ } else {
+ result = cur_c->cnx->hooks->egl.eglMakeCurrent(
+ dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ }
if (result == EGL_TRUE) {
- setGlThreadSpecific(c->cnx->hooks);
- setContext(ctx);
- c->read = read;
- c->draw = draw;
+ // by construction, these are either 0 or valid (possibly terminated)
+ // it should be impossible for these to be invalid
+ ContextRef _cur_c(cur_c);
+ SurfaceRef _cur_r(cur_r);
+ SurfaceRef _cur_d(cur_d);
+
+ // cur_c has to be valid here (but could be terminated)
+ if (ctx != EGL_NO_CONTEXT) {
+ setGlThreadSpecific(c->cnx->hooks);
+ setContext(ctx);
+ _c.acquire();
+ } else {
+ setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+ setContext(EGL_NO_CONTEXT);
+ }
+ _cur_c.release();
+
+ _r.acquire();
+ _cur_r.release();
+ if (c) c->read = read;
+
+ _d.acquire();
+ _cur_d.release();
+ if (c) c->draw = draw;
}
return result;
}
@@ -983,6 +1162,9 @@
EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
EGLint attribute, EGLint *value)
{
+ ContextRef _c(ctx);
+ if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
if (!validate_display_context(dpy, ctx))
return EGL_FALSE;
@@ -990,7 +1172,7 @@
egl_context_t * const c = get_context(ctx);
return c->cnx->hooks->egl.eglQueryContext(
- dp->dpys[c->impl], c->context, attribute, value);
+ dp->disp[c->impl].dpy, c->context, attribute, value);
}
EGLContext eglGetCurrentContext(void)
@@ -1158,22 +1340,28 @@
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
+ SurfaceRef _s(draw);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, draw))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(draw);
- return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface);
+ return s->cnx->hooks->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
}
EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
NativePixmapType target)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(surface);
return s->cnx->hooks->egl.eglCopyBuffers(
- dp->dpys[s->impl], s->surface, target);
+ dp->disp[s->impl].dpy, s->surface, target);
}
const char* eglQueryString(EGLDisplay dpy, EGLint name)
@@ -1200,13 +1388,16 @@
EGLBoolean eglSurfaceAttrib(
EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->hooks->egl.eglSurfaceAttrib) {
return s->cnx->hooks->egl.eglSurfaceAttrib(
- dp->dpys[s->impl], s->surface, attribute, value);
+ dp->disp[s->impl].dpy, s->surface, attribute, value);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1214,13 +1405,16 @@
EGLBoolean eglBindTexImage(
EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->hooks->egl.eglBindTexImage) {
return s->cnx->hooks->egl.eglBindTexImage(
- dp->dpys[s->impl], s->surface, buffer);
+ dp->disp[s->impl].dpy, s->surface, buffer);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1228,13 +1422,16 @@
EGLBoolean eglReleaseTexImage(
EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->hooks->egl.eglReleaseTexImage) {
return s->cnx->hooks->egl.eglReleaseTexImage(
- dp->dpys[s->impl], s->surface, buffer);
+ dp->disp[s->impl].dpy, s->surface, buffer);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1249,7 +1446,8 @@
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
if (cnx->hooks->egl.eglSwapInterval) {
- if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) {
+ if (cnx->hooks->egl.eglSwapInterval(
+ dp->disp[i].dpy, interval) == EGL_FALSE) {
res = EGL_FALSE;
}
}
@@ -1351,7 +1549,8 @@
if (!cnx) return EGL_FALSE;
if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
- dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list);
+ dp->disp[i].dpy, buftype, buffer,
+ dp->disp[i].config[index], attrib_list);
}
return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
}
@@ -1363,6 +1562,9 @@
EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
const EGLint *attrib_list)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
@@ -1371,13 +1573,16 @@
if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
return s->cnx->hooks->egl.eglLockSurfaceKHR(
- dp->dpys[s->impl], s->surface, attrib_list);
+ dp->disp[s->impl].dpy, s->surface, attrib_list);
}
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
}
EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
{
+ SurfaceRef _s(surface);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, surface))
return EGL_FALSE;
@@ -1386,7 +1591,7 @@
if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
- dp->dpys[s->impl], s->surface);
+ dp->disp[s->impl].dpy, s->surface);
}
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
}
@@ -1395,13 +1600,15 @@
EGLClientBuffer buffer, const EGLint *attrib_list)
{
if (ctx != EGL_NO_CONTEXT) {
+ ContextRef _c(ctx);
+ if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
if (!validate_display_context(dpy, ctx))
return EGL_NO_IMAGE_KHR;
egl_display_t const * const dp = get_display(dpy);
egl_context_t * const c = get_context(ctx);
// since we have an EGLContext, we know which implementation to use
EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR(
- dp->dpys[c->impl], c->context, target, buffer, attrib_list);
+ dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
if (image == EGL_NO_IMAGE_KHR)
return image;
@@ -1425,7 +1632,7 @@
if (cnx->dso) {
if (cnx->hooks->egl.eglCreateImageKHR) {
implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
- dp->dpys[i], ctx, target, buffer, attrib_list);
+ dp->disp[i].dpy, ctx, target, buffer, attrib_list);
if (implImages[i] != EGL_NO_IMAGE_KHR) {
success = true;
}
@@ -1443,16 +1650,15 @@
EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
{
- egl_display_t const * const dp = get_display(dpy);
+ egl_display_t const * const dp = get_display(dpy);
if (dp == 0) {
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
}
- egl_image_t* image = get_image(img);
- if (!image->isValid()) {
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- }
+ ImageRef _i(img);
+ if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ egl_image_t* image = get_image(img);
bool success = false;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
@@ -1460,7 +1666,7 @@
if (cnx->dso) {
if (cnx->hooks->egl.eglCreateImageKHR) {
if (cnx->hooks->egl.eglDestroyImageKHR(
- dp->dpys[i], image->images[i])) {
+ dp->disp[i].dpy, image->images[i])) {
success = true;
}
}
@@ -1470,7 +1676,7 @@
if (!success)
return EGL_FALSE;
- delete image;
+ _i.terminate();
return EGL_TRUE;
}
@@ -1483,26 +1689,32 @@
EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
EGLint left, EGLint top, EGLint width, EGLint height)
{
+ SurfaceRef _s(draw);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
if (!validate_display_surface(dpy, draw))
return EGL_FALSE;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(draw);
if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) {
- return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl],
- s->surface, left, top, width, height);
+ return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(
+ dp->disp[s->impl].dpy, s->surface, left, top, width, height);
}
return setError(EGL_BAD_DISPLAY, NULL);
}
EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
{
+ SurfaceRef _s(draw);
+ if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0);
+
if (!validate_display_surface(dpy, draw))
return 0;
egl_display_t const * const dp = get_display(dpy);
egl_surface_t const * const s = get_surface(draw);
if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) {
- return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl],
- s->surface);
+ return s->cnx->hooks->egl.eglGetRenderBufferANDROID(
+ dp->disp[s->impl].dpy, s->surface);
}
return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
}