egl_cache.cpp revision 766010858ea7696d64f1b559413670bdd8627595
1/*
2 ** Copyright 2011, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#include "egl_cache.h"
18#include "egl_display.h"
19#include "egl_impl.h"
20#include "egldefs.h"
21
22// Cache size limits.
23static const size_t maxKeySize = 1024;
24static const size_t maxValueSize = 4096;
25static const size_t maxTotalSize = 64 * 1024;
26
27// ----------------------------------------------------------------------------
28namespace android {
29// ----------------------------------------------------------------------------
30
31#define BC_EXT_STR "EGL_ANDROID_blob_cache"
32
33//
34// Callback functions passed to EGL.
35//
36static void setBlob(const void* key, EGLsizei keySize, const void* value,
37        EGLsizei valueSize) {
38    egl_cache_t::get()->setBlob(key, keySize, value, valueSize);
39}
40
41static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
42        EGLsizei valueSize) {
43    return egl_cache_t::get()->getBlob(key, keySize, value, valueSize);
44}
45
46//
47// egl_cache_t definition
48//
49egl_cache_t::egl_cache_t() :
50        mInitialized(false),
51        mBlobCache(NULL) {
52}
53
54egl_cache_t::~egl_cache_t() {
55}
56
57egl_cache_t* egl_cache_t::get() {
58    static egl_cache_t theCache;
59    return &theCache;
60}
61
62void egl_cache_t::initialize(egl_display_t *display) {
63    Mutex::Autolock lock(mMutex);
64    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
65        egl_connection_t* const cnx = &gEGLImpl[i];
66        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
67            const char* exts = display->disp[i].queryString.extensions;
68            size_t bcExtLen = strlen(BC_EXT_STR);
69            size_t extsLen = strlen(exts);
70            bool equal = !strcmp(BC_EXT_STR, exts);
71            bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
72            bool atEnd = (bcExtLen+1) < extsLen &&
73                    !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
74            bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
75            if (equal || atStart || atEnd || inMiddle) {
76                PFNEGLSETBLOBCACHEFUNCSPROC eglSetBlobCacheFuncs;
77                eglSetBlobCacheFuncs =
78                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSPROC>(
79                            cnx->egl.eglGetProcAddress("eglSetBlobCacheFuncs"));
80                if (eglSetBlobCacheFuncs == NULL) {
81                    LOGE("EGL_ANDROID_blob_cache advertised by display %d, "
82                            "but unable to get eglSetBlobCacheFuncs", i);
83                    continue;
84                }
85
86                eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob,
87                        android::getBlob);
88                EGLint err = cnx->egl.eglGetError();
89                if (err != EGL_SUCCESS) {
90                    LOGE("eglSetBlobCacheFuncs resulted in an error: %#x",
91                            err);
92                }
93            }
94        }
95    }
96    mInitialized = true;
97}
98
99void egl_cache_t::terminate() {
100    Mutex::Autolock lock(mMutex);
101    if (mBlobCache != NULL) {
102        saveBlobCacheLocked();
103        mBlobCache = NULL;
104    }
105    mInitialized = false;
106}
107
108void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value,
109        EGLsizei valueSize) {
110    Mutex::Autolock lock(mMutex);
111
112    if (keySize < 0 || valueSize < 0) {
113        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
114        return;
115    }
116
117    if (mInitialized) {
118        sp<BlobCache> bc = getBlobCacheLocked();
119        bc->set(key, keySize, value, valueSize);
120    }
121}
122
123EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value,
124        EGLsizei valueSize) {
125    Mutex::Autolock lock(mMutex);
126
127    if (keySize < 0 || valueSize < 0) {
128        LOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
129        return 0;
130    }
131
132    if (mInitialized) {
133        sp<BlobCache> bc = getBlobCacheLocked();
134        return bc->get(key, keySize, value, valueSize);
135    }
136    return 0;
137}
138
139sp<BlobCache> egl_cache_t::getBlobCacheLocked() {
140    if (mBlobCache == NULL) {
141        mBlobCache = new BlobCache(maxKeySize, maxValueSize, maxTotalSize);
142        loadBlobCacheLocked();
143    }
144    return mBlobCache;
145}
146
147void egl_cache_t::saveBlobCacheLocked() {
148}
149
150void egl_cache_t::loadBlobCacheLocked() {
151}
152
153// ----------------------------------------------------------------------------
154}; // namespace android
155// ----------------------------------------------------------------------------
156