#include "Loader.h"
+#include <string>
+
#include <dirent.h>
#include <dlfcn.h>
#include <cutils/properties.h>
#include <log/log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
#include <ui/GraphicsEnv.h>
+#include "egl_trace.h"
#include "egldefs.h"
// ----------------------------------------------------------------------------
*
*/
-ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
+Loader& Loader::getInstance() {
+ static Loader loader;
+ return loader;
+}
/* This function is called to check whether we run inside the emulator,
* and if this is the case whether GLES GPU emulation is supported.
}
}
-status_t Loader::driver_t::set(void* hnd, int32_t api)
+int Loader::driver_t::set(void* hnd, int32_t api)
{
switch (api) {
case EGL:
dso[2] = hnd;
break;
default:
- return BAD_INDEX;
+ return -EOVERFLOW;
}
- return NO_ERROR;
+ return 0;
}
// ----------------------------------------------------------------------------
return (void*)hnd;
}
-status_t Loader::close(void* driver)
+void Loader::close(void* driver)
{
driver_t* hnd = (driver_t*)driver;
delete hnd;
- return NO_ERROR;
}
void Loader::init_api(void* dso,
ATRACE_CALL();
class MatchFile {
public:
- static String8 find(const char* kind) {
- String8 result;
+ static std::string find(const char* kind) {
+ std::string result;
int emulationStatus = checkGlesEmulationStatus();
switch (emulationStatus) {
case 0:
#if defined(__LP64__)
- result.setTo("/system/lib64/egl/libGLES_android.so");
+ result = "/system/lib64/egl/libGLES_android.so";
#else
- result.setTo("/system/lib/egl/libGLES_android.so");
+ result = "/system/lib/egl/libGLES_android.so";
#endif
return result;
case 1:
// Use host-side OpenGL through the "emulation" library
#if defined(__LP64__)
- result.appendFormat("/system/lib64/egl/lib%s_emulation.so", kind);
+ result = std::string("/system/lib64/egl/lib") + kind + "_emulation.so";
#else
- result.appendFormat("/system/lib/egl/lib%s_emulation.so", kind);
+ result = std::string("/system/lib/egl/lib") + kind + "_emulation.so";
#endif
return result;
default:
break;
}
- String8 pattern;
- pattern.appendFormat("lib%s", kind);
+ std::string pattern = std::string("lib") + kind;
const char* const searchPaths[] = {
#if defined(__LP64__)
"/vendor/lib64/egl",
}
private:
- static bool find(String8& result,
- const String8& pattern, const char* const search, bool exact) {
+ static bool find(std::string& result,
+ const std::string& pattern, const char* const search, bool exact) {
if (exact) {
- String8 absolutePath;
- absolutePath.appendFormat("%s/%s.so", search, pattern.string());
- if (!access(absolutePath.string(), R_OK)) {
+ std::string absolutePath = std::string(search) + "/" + pattern;
+ if (!access(absolutePath.c_str(), R_OK)) {
result = absolutePath;
return true;
}
// always skip the software renderer
continue;
}
- if (strstr(e->d_name, pattern.string()) == e->d_name) {
+ if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
- result.clear();
- result.appendFormat("%s/%s", search, e->d_name);
+ result = std::string(search) + "/" + e->d_name;
closedir(d);
return true;
}
};
- String8 absolutePath = MatchFile::find(kind);
- if (absolutePath.isEmpty()) {
+ std::string absolutePath = MatchFile::find(kind);
+ if (absolutePath.empty()) {
// this happens often, we don't want to log an error
return 0;
}
- const char* const driver_absolute_path = absolutePath.string();
+ const char* const driver_absolute_path = absolutePath.c_str();
void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
const char* err = dlerror();
- ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
+ ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
return 0;
}
char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
if (property_get(key, prop, nullptr) > 0) {
- String8 name;
- name.appendFormat("lib%s_%s.so", kind, prop);
- so = do_android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ std::string name = std::string("lib") + kind + "_" + prop + ".so";
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
if (so) {
return so;
}
#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
#include <EGL/egl.h>
// ----------------------------------------------------------------------------
struct egl_connection_t;
-class Loader : public Singleton<Loader> {
- friend class Singleton<Loader>;
-
+class Loader {
typedef __eglMustCastToProperFunctionPointerType (* getProcAddressType)(const char*);
enum {
struct driver_t {
explicit driver_t(void* gles);
~driver_t();
- status_t set(void* hnd, int32_t api);
+ // returns -errno
+ int set(void* hnd, int32_t api);
void* dso[3];
};
getProcAddressType getProcAddress;
public:
+ static Loader& getInstance();
~Loader();
void* open(egl_connection_t* cnx);
- status_t close(void* driver);
+ void close(void* driver);
private:
Loader();
#include <EGL/egl.h>
-#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <log/log.h>
if (name != GL_EXTENSIONS)
return NULL;
- return (const GLubyte *)c->gl_extensions.string();
+ return (const GLubyte *)c->gl_extensions.c_str();
}
const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) {
if (index >= c->tokenized_gl_extensions.size())
return NULL;
- return (const GLubyte *)c->tokenized_gl_extensions.itemAt(index).string();
+ return (const GLubyte *)c->tokenized_gl_extensions[index].c_str();
}
GLint egl_get_num_extensions_for_current_context() {
}
static pthread_mutex_t sLogPrintMutex = PTHREAD_MUTEX_INITIALIZER;
-static nsecs_t sLogPrintTime = 0;
-#define NSECS_DURATION 1000000000
+static std::chrono::steady_clock::time_point sLogPrintTime;
+static constexpr std::chrono::seconds DURATION(1);
void gl_unimplemented() {
bool printLog = false;
- nsecs_t now = systemTime();
+ auto now = std::chrono::steady_clock::now();
pthread_mutex_lock(&sLogPrintMutex);
- if ((now - sLogPrintTime) > NSECS_DURATION) {
+ if ((now - sLogPrintTime) > DURATION) {
sLogPrintTime = now;
printLog = true;
}
#include <cutils/properties.h>
#include <log/log.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-#include <utils/Thread.h>
+#include <condition_variable>
+#include <deque>
+#include <mutex>
+#include <unordered_map>
+#include <string>
+#include <thread>
#include "../egl_impl.h"
#include "egl_display.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include "egl_trace.h"
using namespace android;
namespace android {
+using nsecs_t = int64_t;
+
struct extention_map_t {
const char* name;
__eglMustCastToProperFunctionPointerType address;
// accesses protected by sExtensionMapMutex
-static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+
static int sGLExtentionSlot = 0;
static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
}
int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result != OK) {
+ if (result < 0) {
ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
"failed (%#x) (already connected to another API?)",
window, result);
*
*/
- const String8 name(procname);
- addr = sGLExtentionMap.valueFor(name);
+ const std::string name(procname);
+
+ auto& extentionMap = sGLExtentionMap;
+ auto pos = extentionMap.find(name);
+ addr = (pos != extentionMap.end()) ? pos->second : nullptr;
const int slot = sGLExtentionSlot;
ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
if (found) {
addr = gExtensionForwarders[slot];
- sGLExtentionMap.add(name, addr);
+ extentionMap[name] = addr;
sGLExtentionSlot++;
}
}
return addr;
}
-class FrameCompletionThread : public Thread {
+class FrameCompletionThread {
public:
static void queueSync(EGLSyncKHR sync) {
- static sp<FrameCompletionThread> thread(new FrameCompletionThread);
- static bool running = false;
- if (!running) {
- thread->run("GPUFrameCompletion");
- running = true;
- }
- {
- Mutex::Autolock lock(thread->mMutex);
- ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
- thread->mFramesQueued).string());
- thread->mQueue.push_back(sync);
- thread->mCondition.signal();
- thread->mFramesQueued++;
- ATRACE_INT("GPU Frames Outstanding", int32_t(thread->mQueue.size()));
- }
+ static FrameCompletionThread thread;
+
+ char name[64];
+
+ std::lock_guard<std::mutex> lock(thread.mMutex);
+ snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
+ ATRACE_NAME(name);
+
+ thread.mQueue.push_back(sync);
+ thread.mCondition.notify_one();
+ thread.mFramesQueued++;
+ ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
}
private:
- FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
- virtual bool threadLoop() {
+ FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
+ std::thread thread(&FrameCompletionThread::loop, this);
+ thread.detach();
+ }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+ void loop() {
+ while (true) {
+ threadLoop();
+ }
+ }
+#pragma clang diagnostic pop
+
+ void threadLoop() {
EGLSyncKHR sync;
uint32_t frameNum;
{
- Mutex::Autolock lock(mMutex);
- while (mQueue.isEmpty()) {
- mCondition.wait(mMutex);
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mQueue.empty()) {
+ mCondition.wait(lock);
}
sync = mQueue[0];
frameNum = mFramesCompleted;
}
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
{
- ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
- frameNum).string());
+ char name[64];
+ snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
+ ATRACE_NAME(name);
+
EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
if (result == EGL_FALSE) {
ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
eglDestroySyncKHR(dpy, sync);
}
{
- Mutex::Autolock lock(mMutex);
- mQueue.removeAt(0);
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.pop_front();
mFramesCompleted++;
ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
}
- return true;
}
uint32_t mFramesQueued;
uint32_t mFramesCompleted;
- Vector<EGLSyncKHR> mQueue;
- Condition mCondition;
- Mutex mMutex;
+ std::deque<EGLSyncKHR> mQueue;
+ std::condition_variable mCondition;
+ std::mutex mMutex;
};
EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
}
- Vector<android_native_rect_t> androidRects;
+ std::vector<android_native_rect_t> androidRects((size_t)n_rects);
for (int r = 0; r < n_rects; ++r) {
int offset = r * 4;
int x = rects[offset];
androidRect.bottom = y;
androidRects.push_back(androidRect);
}
- native_window_set_surface_damage(s->win.get(), androidRects.array(),
- androidRects.size());
+ native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
egl_surface_t * const s = get_surface(surface);
if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
setError(EGL_BAD_SURFACE, EGL_FALSE);
}
- int err = native_window_set_auto_refresh(s->win.get(), value ? true : false);
- return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
+ return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
if (attribute == EGL_TIMESTAMPS_ANDROID) {
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
- int err = native_window_enable_frame_timestamps(s->win.get(), value ? true : false);
- return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
+ return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
if (s->cnx->egl.eglSurfaceAttrib) {
}
egl_surface_t const * const s = get_surface(surface);
- native_window_set_buffers_timestamp(s->win.get(), time);
+ native_window_set_buffers_timestamp(s->getNativeWindow(), time);
return EGL_TRUE;
}
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
uint64_t nextFrameId = 0;
- status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
+ int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
- if (ret != NO_ERROR) {
+ if (ret != 0) {
// This should not happen. Return an error that is not in the spec
// so it's obvious something is very wrong.
ALOGE("eglGetNextFrameId: Unexpected error.");
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
}
}
- status_t ret = native_window_get_compositor_timing(s->win.get(),
+ int ret = native_window_get_compositor_timing(s->getNativeWindow(),
compositeDeadline, compositeInterval, compositeToPresentLatency);
switch (ret) {
- case NO_ERROR:
+ case 0:
return EGL_TRUE;
- case INVALID_OPERATION:
+ case -ENOSYS:
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
default:
// This should not happen. Return an error that is not in the spec
egl_surface_t const * const s = get_surface(surface);
- ANativeWindow* window = s->win.get();
+ ANativeWindow* window = s->getNativeWindow();
if (!window) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
}
}
- status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
+ int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
displayRetireTime, dequeueReadyTime, releaseTime);
switch (ret) {
- case NO_ERROR:
+ case 0:
return EGL_TRUE;
- case NAME_NOT_FOUND:
+ case -ENOENT:
return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
- case INVALID_OPERATION:
+ case -ENOSYS:
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
- case BAD_VALUE:
+ case -EINVAL:
return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
default:
// This should not happen. Return an error that is not in the spec
egl_surface_t const * const s = get_surface(surface);
- ANativeWindow* window = s->win.get();
+ ANativeWindow* window = s->getNativeWindow();
if (!window) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
#include <sys/mman.h>
#include <sys/stat.h>
-#include <utils/Thread.h>
+#include <thread>
+
+#include <log/log.h>
// Cache size limits.
static const size_t maxKeySize = 12 * 1024;
}
void egl_cache_t::initialize(egl_display_t *display) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
}
void egl_cache_t::terminate() {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
saveBlobCacheLocked();
mBlobCache = NULL;
}
void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize,
const void* value, EGLsizeiANDROID valueSize) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
if (keySize < 0 || valueSize < 0) {
ALOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
bc->set(key, keySize, value, valueSize);
if (!mSavePending) {
- class DeferredSaveThread : public Thread {
- public:
- DeferredSaveThread() : Thread(false) {}
-
- virtual bool threadLoop() {
- sleep(deferredSaveDelay);
- egl_cache_t* c = egl_cache_t::get();
- Mutex::Autolock lock(c->mMutex);
- if (c->mInitialized) {
- c->saveBlobCacheLocked();
- }
- c->mSavePending = false;
- return false;
- }
- };
-
- // The thread will hold a strong ref to itself until it has finished
- // running, so there's no need to keep a ref around.
- sp<Thread> deferredSaveThread(new DeferredSaveThread());
mSavePending = true;
- deferredSaveThread->run("DeferredSaveThread");
+ std::thread deferredSaveThread([this]() {
+ sleep(deferredSaveDelay);
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mInitialized) {
+ saveBlobCacheLocked();
+ }
+ mSavePending = false;
+ });
+ deferredSaveThread.detach();
}
}
}
EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize,
void* value, EGLsizeiANDROID valueSize) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
if (keySize < 0 || valueSize < 0) {
ALOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
}
void egl_cache_t::setCacheFilename(const char* filename) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
mFilename = filename;
}
if (mFilename.length() > 0 && mBlobCache != NULL) {
size_t cacheSize = mBlobCache->getFlattenedSize();
size_t headerSize = cacheFileHeaderSize;
- const char* fname = mFilename.string();
+ const char* fname = mFilename.c_str();
// Try to create the file with no permissions so we can write it
// without anyone trying to read it.
return;
}
- status_t err = mBlobCache->flatten(buf + headerSize, cacheSize);
- if (err != OK) {
+ int err = mBlobCache->flatten(buf + headerSize, cacheSize);
+ if (err < 0) {
ALOGE("error writing cache contents: %s (%d)", strerror(-err),
-err);
delete [] buf;
if (mFilename.length() > 0) {
size_t headerSize = cacheFileHeaderSize;
- int fd = open(mFilename.string(), O_RDONLY, 0);
+ int fd = open(mFilename.c_str(), O_RDONLY, 0);
if (fd == -1) {
if (errno != ENOENT) {
- ALOGE("error opening cache file %s: %s (%d)", mFilename.string(),
+ ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
strerror(errno), errno);
}
return;
return;
}
- status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize);
- if (err != OK) {
+ int err = mBlobCache->unflatten(buf + headerSize, cacheSize);
+ if (err < 0) {
ALOGE("error reading cache contents: %s (%d)", strerror(-err),
-err);
munmap(buf, fileSize);
#include <EGL/eglext.h>
#include <utils/BlobCache.h>
-#include <utils/Mutex.h>
-#include <utils/String8.h>
#include <utils/StrongPointer.h>
+#include <mutex>
+#include <string>
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
// construction time, and can be set with the setCacheFilename method. An
// empty string indicates that the cache should not be saved to or restored
// from disk.
- String8 mFilename;
+ std::string mFilename;
// mSavePending indicates whether or not a deferred save operation is
// pending. Each time a key/value pair is inserted into the cache via
// mMutex is the mutex used to prevent concurrent access to the member
// variables. It must be locked whenever the member variables are accessed.
- mutable Mutex mMutex;
+ mutable std::mutex mMutex;
// sCache is the singleton egl_cache_t object.
static egl_cache_t sCache;
#include "egl_cache.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include "egl_trace.h"
#include "Loader.h"
#include <cutils/properties.h>
-#include <utils/Trace.h>
-
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
}
void egl_display_t::addObject(egl_object_t* object) {
- Mutex::Autolock _l(lock);
- objects.add(object);
+ std::lock_guard<std::mutex> _l(lock);
+ objects.insert(object);
}
void egl_display_t::removeObject(egl_object_t* object) {
- Mutex::Autolock _l(lock);
- objects.remove(object);
+ std::lock_guard<std::mutex> _l(lock);
+ objects.erase(object);
}
bool egl_display_t::getObject(egl_object_t* object) const {
- Mutex::Autolock _l(lock);
- if (objects.indexOf(object) >= 0) {
+ std::lock_guard<std::mutex> _l(lock);
+ if (objects.find(object) != objects.end()) {
if (object->getDisplay() == this) {
object->incRef();
return true;
EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
ATRACE_CALL();
// get our driver loader
EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
- {
- Mutex::Autolock _rf(refLock);
-
+ { // scope for refLock
+ std::unique_lock<std::mutex> _l(refLock);
refs++;
if (refs > 1) {
if (major != NULL)
*major = VERSION_MAJOR;
if (minor != NULL)
*minor = VERSION_MINOR;
- while(!eglIsInitialized) refCond.wait(refLock);
+ while(!eglIsInitialized) {
+ refCond.wait(_l);
+ }
return EGL_TRUE;
}
-
- while(eglIsInitialized) refCond.wait(refLock);
+ while(eglIsInitialized) {
+ refCond.wait(_l);
+ }
}
- {
- Mutex::Autolock _l(lock);
+ { // scope for lock
+ std::lock_guard<std::mutex> _l(lock);
setGLHooksThreadSpecific(&gHooksNoContext);
}
// the query strings are per-display
- mVendorString.setTo(sVendorString);
- mVersionString.setTo(sVersionString);
- mClientApiString.setTo(sClientApiString);
+ mVendorString = sVendorString;
+ mVersionString = sVersionString;
+ mClientApiString = sClientApiString;
- mExtensionString.setTo(gBuiltinExtensionString);
+ mExtensionString = gBuiltinExtensionString;
char const* start = gExtensionString;
do {
// length of the extension name
size_t len = strcspn(start, " ");
if (len) {
// NOTE: we could avoid the copy if we had strnstr.
- const String8 ext(start, len);
- if (findExtension(disp.queryString.extensions, ext.string(),
- len)) {
+ const std::string ext(start, len);
+ if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
mExtensionString.append(ext + " ");
}
// advance to the next extension name, skipping the space.
*minor = VERSION_MINOR;
}
- {
- Mutex::Autolock _rf(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _l(refLock);
eglIsInitialized = true;
- refCond.broadcast();
+ refCond.notify_all();
}
return EGL_TRUE;
EGLBoolean egl_display_t::terminate() {
- {
- Mutex::Autolock _rl(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _rl(refLock);
if (refs == 0) {
/*
* From the EGL spec (3.2):
EGLBoolean res = EGL_FALSE;
- {
- Mutex::Autolock _l(lock);
+ { // scope for lock
+ std::lock_guard<std::mutex> _l(lock);
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
// Reset the extension string since it will be regenerated if we get
// reinitialized.
- mExtensionString.setTo("");
+ mExtensionString.clear();
// Mark all objects remaining in the list as terminated, unless
// there are no reference to them, it which case, we're free to
// delete them.
size_t count = objects.size();
ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
- for (size_t i=0 ; i<count ; i++) {
- egl_object_t* o = objects.itemAt(i);
+ for (auto o : objects) {
o->destroy();
}
objects.clear();
}
- {
- Mutex::Autolock _rl(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _rl(refLock);
eglIsInitialized = false;
- refCond.broadcast();
+ refCond.notify_all();
}
return res;
SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
cur_c->onLooseCurrent();
}
SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
if (c) {
result = c->cnx->egl.eglMakeCurrent(
disp.dpy, impl_draw, impl_read, impl_ctx);
if (!nameLen) {
nameLen = strlen(name);
}
- return findExtension(mExtensionString.string(), name, nameLen);
+ return findExtension(mExtensionString.c_str(), name, nameLen);
}
// ----------------------------------------------------------------------------
#include <stdint.h>
#include <stddef.h>
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <unordered_set>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <cutils/compiler.h>
-#include <utils/SortedVector.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <utils/String8.h>
#include "egldefs.h"
#include "../hooks.h"
inline bool isValid() const { return magic == '_dpy'; }
inline bool isAlive() const { return isValid(); }
- char const * getVendorString() const { return mVendorString.string(); }
- char const * getVersionString() const { return mVersionString.string(); }
- char const * getClientApiString() const { return mClientApiString.string(); }
- char const * getExtensionString() const { return mExtensionString.string(); }
+ char const * getVendorString() const { return mVendorString.c_str(); }
+ char const * getVersionString() const { return mVersionString.c_str(); }
+ char const * getClientApiString() const { return mClientApiString.c_str(); }
+ char const * getExtensionString() const { return mExtensionString.c_str(); }
bool haveExtension(const char* name, size_t nameLen = 0) const;
uint32_t refs;
bool eglIsInitialized;
- mutable Mutex lock, refLock;
- mutable Condition refCond;
- SortedVector<egl_object_t*> objects;
- String8 mVendorString;
- String8 mVersionString;
- String8 mClientApiString;
- String8 mExtensionString;
+ mutable std::mutex lock;
+ mutable std::mutex refLock;
+ mutable std::condition_variable refCond;
+ std::unordered_set<egl_object_t*> objects;
+ std::string mVendorString;
+ std::string mVersionString;
+ std::string mClientApiString;
+ std::string mExtensionString;
};
// ----------------------------------------------------------------------------
egl_connection_t const* cnx) :
egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
connected(true)
-{}
+{
+ if (win) {
+ win->incStrong(this);
+ }
+}
egl_surface_t::~egl_surface_t() {
- ANativeWindow* const window = win.get();
- if (window != NULL) {
+ if (win != NULL) {
disconnect();
+ win->decStrong(this);
}
}
void egl_surface_t::disconnect() {
- ANativeWindow* const window = win.get();
- if (window != NULL && connected) {
- native_window_set_buffers_format(window, 0);
- if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
- ALOGW("EGLNativeWindowType %p disconnect failed", window);
+ if (win != NULL && connected) {
+ native_window_set_buffers_format(win, 0);
+ if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) {
+ ALOGW("EGLNativeWindowType %p disconnect failed", win);
}
connected = false;
}
* add the extensions always handled by the wrapper
*/
- if (gl_extensions.isEmpty()) {
+ if (gl_extensions.empty()) {
// call the implementation's glGetString(GL_EXTENSIONS)
const char* exts = (const char *)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS);
- gl_extensions.setTo(exts);
- if (gl_extensions.find("GL_EXT_debug_marker") < 0) {
- String8 temp("GL_EXT_debug_marker ");
- temp.append(gl_extensions);
- gl_extensions.setTo(temp);
+ gl_extensions = exts;
+ if (gl_extensions.find("GL_EXT_debug_marker") != std::string::npos) {
+ gl_extensions.insert(0, "GL_EXT_debug_marker ");
}
// tokenize the supported extensions for the glGetStringi() wrapper
std::stringstream ss;
std::string str;
- ss << gl_extensions.string();
+ ss << gl_extensions;
while (ss >> str) {
- tokenized_gl_extensions.push(String8(str.c_str()));
+ tokenized_gl_extensions.push_back(str);
}
}
}
#include <stdint.h>
#include <stddef.h>
+#include <string>
+#include <vector>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <utils/StrongPointer.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-
#include <system/window.h>
+#include <log/log.h>
+
#include "egl_display.h"
// ----------------------------------------------------------------------------
EGLNativeWindowType win, EGLSurface surface,
egl_connection_t const* cnx);
+ ANativeWindow* getNativeWindow() { return win; }
+ ANativeWindow* getNativeWindow() const { return win; }
+
+ // Try to keep the order of these fields and size unchanged. It's not public API, but
+ // it's not hard to imagine native games accessing them.
EGLSurface surface;
EGLConfig config;
- sp<ANativeWindow> win;
+private:
+ ANativeWindow* win;
+public:
egl_connection_t const* cnx;
private:
bool connected;
EGLSurface draw;
egl_connection_t const* cnx;
int version;
- String8 gl_extensions;
- Vector<String8> tokenized_gl_extensions;
+ std::string gl_extensions;
+ std::vector<std::string> tokenized_gl_extensions;
};
// ----------------------------------------------------------------------------
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(__ANDROID__)
+
+#include <stdint.h>
+
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more ATRACE_* macros.
+
+// ATRACE_NAME traces from its location until the end of its enclosing scope.
+#define _PASTE(x, y) x ## y
+#define PASTE(x, y) _PASTE(x,y)
+#define ATRACE_NAME(name) android::EglScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+
+// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
+
+namespace android {
+
+class EglScopedTrace {
+public:
+ inline EglScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
+ atrace_begin(mTag, name);
+ }
+
+ inline ~EglScopedTrace() {
+ atrace_end(mTag);
+ }
+
+private:
+ uint64_t mTag;
+};
+
+}; // namespace android
+
+#else // !__ANDROID__
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#endif // __ANDROID__