Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76601085 authored by Jamie Gennis's avatar Jamie Gennis
Browse files

EGL: use an in-memory the blob cache

This change makes the makes the stub EGL_ANDROID_blob_cache callbacks
actually use a BlobCache object.

Bug: 5474671
Change-Id: I5cbaae2dea3aad2fe306c9f57029c3f215a0863a
parent 33e55a95
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -256,6 +256,21 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
#endif


/* EGL_ANDROID_blob_cache
 */
#ifndef EGL_ANDROID_blob_cache
#define EGL_ANDROID_blob_cache 1
typedef khronos_ssize_t EGLsizei;
typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize);
typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get);
#endif /* EGL_EGLEXT_PROTOTYPES */
typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
        EGLSetBlobFunc set, EGLGetBlobFunc get);
#endif

#ifdef __cplusplus
}
#endif
+76 −16
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@
#include "egl_impl.h"
#include "egldefs.h"

// Cache size limits.
static const size_t maxKeySize = 1024;
static const size_t maxValueSize = 4096;
static const size_t maxTotalSize = 64 * 1024;

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -26,29 +31,27 @@ namespace android {
#define BC_EXT_STR "EGL_ANDROID_blob_cache"

//
// EGL_ANDROID_blob_cache types and functions
// Callback functions passed to EGL.
//
typedef khronos_ssize_t EGLsizei;

typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
        const void* value, EGLsizei valueSize);

typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
        void* value, EGLsizei valueSize);
static void setBlob(const void* key, EGLsizei keySize, const void* value,
        EGLsizei valueSize) {
    egl_cache_t::get()->setBlob(key, keySize, value, valueSize);
}

typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
        EGLSetBlobFunc set, EGLGetBlobFunc get);
static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
        EGLsizei valueSize) {
    return egl_cache_t::get()->getBlob(key, keySize, value, valueSize);
}

//
// egl_cache_t definition
//
static void setBlob(const void* key, EGLsizei keySize, const void* value,
        EGLsizei valueSize) {
egl_cache_t::egl_cache_t() :
        mInitialized(false),
        mBlobCache(NULL) {
}

static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
        EGLsizei valueSize) {
    return 0;
egl_cache_t::~egl_cache_t() {
}

egl_cache_t* egl_cache_t::get() {
@@ -57,6 +60,7 @@ egl_cache_t* egl_cache_t::get() {
}

void egl_cache_t::initialize(egl_display_t *display) {
    Mutex::Autolock lock(mMutex);
    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
        egl_connection_t* const cnx = &gEGLImpl[i];
        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
@@ -79,7 +83,8 @@ void egl_cache_t::initialize(egl_display_t *display) {
                    continue;
                }

                eglSetBlobCacheFuncs(display->disp[i].dpy, setBlob, getBlob);
                eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob,
                        android::getBlob);
                EGLint err = cnx->egl.eglGetError();
                if (err != EGL_SUCCESS) {
                    LOGE("eglSetBlobCacheFuncs resulted in an error: %#x",
@@ -88,6 +93,61 @@ void egl_cache_t::initialize(egl_display_t *display) {
            }
        }
    }
    mInitialized = true;
}

void egl_cache_t::terminate() {
    Mutex::Autolock lock(mMutex);
    if (mBlobCache != NULL) {
        saveBlobCacheLocked();
        mBlobCache = NULL;
    }
    mInitialized = false;
}

void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value,
        EGLsizei valueSize) {
    Mutex::Autolock lock(mMutex);

    if (keySize < 0 || valueSize < 0) {
        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
        return;
    }

    if (mInitialized) {
        sp<BlobCache> bc = getBlobCacheLocked();
        bc->set(key, keySize, value, valueSize);
    }
}

EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value,
        EGLsizei valueSize) {
    Mutex::Autolock lock(mMutex);

    if (keySize < 0 || valueSize < 0) {
        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
        return 0;
    }

    if (mInitialized) {
        sp<BlobCache> bc = getBlobCacheLocked();
        return bc->get(key, keySize, value, valueSize);
    }
    return 0;
}

sp<BlobCache> egl_cache_t::getBlobCacheLocked() {
    if (mBlobCache == NULL) {
        mBlobCache = new BlobCache(maxKeySize, maxValueSize, maxTotalSize);
        loadBlobCacheLocked();
    }
    return mBlobCache;
}

void egl_cache_t::saveBlobCacheLocked() {
}

void egl_cache_t::loadBlobCacheLocked() {
}

// ----------------------------------------------------------------------------
+75 −0
Original line number Diff line number Diff line
@@ -14,6 +14,15 @@
 ** limitations under the License.
 */

#ifndef ANDROID_EGL_CACHE_H
#define ANDROID_EGL_CACHE_H

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <utils/BlobCache.h>
#include <utils/StrongPointer.h>

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -23,11 +32,77 @@ class egl_display_t;
class egl_cache_t {
public:

    // get returns a pointer to the singleton egl_cache_t object.  This
    // singleton object will never be destroyed.
    static egl_cache_t* get();

    // initialize puts the egl_cache_t into an initialized state, such that it
    // is able to insert and retrieve entries from the cache.  This should be
    // called when EGL is initialized.  When not in the initialized state the
    // getBlob and setBlob methods will return without performing any cache
    // operations.
    void initialize(egl_display_t* display);

    // terminate puts the egl_cache_t back into the uninitialized state.  When
    // in this state the getBlob and setBlob methods will return without
    // performing any cache operations.
    void terminate();

    // setBlob attempts to insert a new key/value blob pair into the cache.
    // This will be called by the hardware vendor's EGL implementation via the
    // EGL_ANDROID_blob_cache extension.
    void setBlob(const void* key, EGLsizei keySize, const void* value,
        EGLsizei valueSize);

    // getBlob attempts to retrieve the value blob associated with a given key
    // blob from cache.  This will be called by the hardware vendor's EGL
    // implementation via the EGL_ANDROID_blob_cache extension.
    EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
        EGLsizei valueSize);

private:
    // Creation and (the lack of) destruction is handled internally.
    egl_cache_t();
    ~egl_cache_t();

    // Copying is disallowed.
    egl_cache_t(const egl_cache_t&); // not implemented
    void operator=(const egl_cache_t&); // not implemented

    // getBlobCacheLocked returns the BlobCache object being used to store the
    // key/value blob pairs.  If the BlobCache object has not yet been created,
    // this will do so, loading the serialized cache contents from disk if
    // possible.
    sp<BlobCache> getBlobCacheLocked();

    // saveBlobCache attempts to save the current contents of mBlobCache to
    // disk.
    void saveBlobCacheLocked();

    // loadBlobCache attempts to load the saved cache contents from disk into
    // mBlobCache.
    void loadBlobCacheLocked();

    // mInitialized indicates whether the egl_cache_t is in the initialized
    // state.  It is initialized to false at construction time, and gets set to
    // true when initialize is called.  It is set back to false when terminate
    // is called.  When in this state, the cache behaves as normal.  When not,
    // the getBlob and setBlob methods will return without performing any cache
    // operations.
    bool mInitialized;

    // mBlobCache is the cache in which the key/value blob pairs are stored.  It
    // is initially NULL, and will be initialized by getBlobCacheLocked the
    // first time it's needed.
    sp<BlobCache> mBlobCache;

    // 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;
};

// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------

#endif // ANDROID_EGL_CACHE_H
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ egl_display_t::egl_display_t() :

egl_display_t::~egl_display_t() {
    magic = 0;
    egl_cache_t::get()->terminate();
}

egl_display_t* egl_display_t::get(EGLDisplay dpy) {