diff options
Diffstat (limited to 'libs/surfaceflinger')
-rw-r--r-- | libs/surfaceflinger/Barrier.h | 4 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 137 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.h | 20 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBlur.cpp | 4 | ||||
-rw-r--r-- | libs/surfaceflinger/MessageQueue.cpp | 13 | ||||
-rw-r--r-- | libs/surfaceflinger/MessageQueue.h | 35 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.cpp | 34 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.h | 11 | ||||
-rw-r--r-- | libs/surfaceflinger/TextureManager.cpp | 3 | ||||
-rw-r--r-- | libs/surfaceflinger/TextureManager.h | 19 |
10 files changed, 165 insertions, 115 deletions
diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h index e2bcf6a..6f8507e 100644 --- a/libs/surfaceflinger/Barrier.h +++ b/libs/surfaceflinger/Barrier.h @@ -29,10 +29,6 @@ public: inline Barrier() : state(CLOSED) { } inline ~Barrier() { } void open() { - // gcc memory barrier, this makes sure all memory writes - // have been issued by gcc. On an SMP system we'd need a real - // h/w barrier. - asm volatile ("":::"memory"); Mutex::Autolock _l(lock); state = OPENED; cv.broadcast(); diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 1fe997d..621b7e3 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -60,7 +60,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. lcblk = new SharedBufferServer( - client->ctrlblk, i, mBufferManager.getBufferCount(), + client->ctrlblk, i, mBufferManager.getDefaultBufferCount(), getIdentity()); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); @@ -68,7 +68,10 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Layer::~Layer() { - destroy(); + // FIXME: must be called from the main UI thread + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + mBufferManager.destroy(dpy); + // the actual buffers will be destroyed here delete lcblk; } @@ -81,17 +84,6 @@ void Layer::onRemoved() lcblk->setStatus(NO_INIT); } -void Layer::destroy() -{ - EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); - mBufferManager.destroy(dpy); - - mSurface.clear(); - - Mutex::Autolock _l(mLock); - mWidth = mHeight = 0; -} - sp<LayerBaseClient::Surface> Layer::createSurface() const { return mSurface; @@ -99,9 +91,17 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const status_t Layer::ditch() { + // NOTE: Called from the main UI thread + // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); - destroy(); + + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + mBufferManager.destroy(dpy); + mSurface.clear(); + + Mutex::Autolock _l(mLock); + mWidth = mHeight = 0; return NO_ERROR; } @@ -211,7 +211,7 @@ void Layer::onDraw(const Region& clip) const status_t Layer::setBufferCount(int bufferCount) { - // this ensures our client doesn't go away while we're accessing + // Ensures our client doesn't go away while we're accessing // the shared area. sp<Client> ourClient(client.promote()); if (ourClient == 0) { @@ -219,15 +219,10 @@ status_t Layer::setBufferCount(int bufferCount) return DEAD_OBJECT; } - status_t err; - - // FIXME: resize() below is NOT thread-safe, we need to synchronize - // the users of lcblk in our process (ie: retire), and we assume the - // client is not mucking with the SharedStack, which is only enforced - // by construction, therefore we need to protect ourselves against - // buggy and malicious client (as always) - - err = lcblk->resize(bufferCount); + // NOTE: lcblk->resize() is protected by an internal lock + status_t err = lcblk->resize(bufferCount); + if (err == NO_ERROR) + mBufferManager.resize(bufferCount); return err; } @@ -248,7 +243,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage) * This is called from the client's Surface::dequeue(). This can happen * at any time, especially while we're in the middle of using the * buffer 'index' as our front buffer. - * + * * Make sure the buffer we're resizing is not the front buffer and has been * dequeued. Once this condition is asserted, we are guaranteed that this * buffer cannot become the front buffer under our feet, since we're called @@ -544,12 +539,20 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const // --------------------------------------------------------------------------- Layer::BufferManager::BufferManager(TextureManager& tm) - : mTextureManager(tm), mActiveBuffer(0), mFailover(false) + : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), + mActiveBuffer(0), mFailover(false) +{ +} + +Layer::BufferManager::~BufferManager() { } -size_t Layer::BufferManager::getBufferCount() const { - return NUM_BUFFERS; +status_t Layer::BufferManager::resize(size_t size) +{ + Mutex::Autolock _l(mLock); + mNumBuffers = size; + return NO_ERROR; } // only for debugging @@ -568,51 +571,55 @@ size_t Layer::BufferManager::getActiveBufferIndex() const { } Texture Layer::BufferManager::getActiveTexture() const { - return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture; + Texture res; + if (mFailover) { + res = mFailoverTexture; + } else { + static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture; + } + return res; } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { + const size_t activeBuffer = mActiveBuffer; + BufferData const * const buffers = mBufferData; Mutex::Autolock _l(mLock); - return mBufferData[mActiveBuffer].buffer; + return buffers[activeBuffer].buffer; } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { + BufferData* const buffers = mBufferData; sp<GraphicBuffer> buffer; Mutex::Autolock _l(mLock); - buffer = mBufferData[index].buffer; - mBufferData[index].buffer = 0; + buffer = buffers[index].buffer; + buffers[index].buffer = 0; return buffer; } status_t Layer::BufferManager::attachBuffer(size_t index, const sp<GraphicBuffer>& buffer) { + BufferData* const buffers = mBufferData; Mutex::Autolock _l(mLock); - mBufferData[index].buffer = buffer; - mBufferData[index].texture.dirty = true; - return NO_ERROR; -} - -status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy) -{ - if (tex->name != -1U) { - glDeleteTextures(1, &tex->name); - tex->name = -1U; - } - if (tex->image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(dpy, tex->image); - tex->image = EGL_NO_IMAGE_KHR; - } + buffers[index].buffer = buffer; + buffers[index].texture.dirty = true; return NO_ERROR; } status_t Layer::BufferManager::destroy(EGLDisplay dpy) { - Mutex::Autolock _l(mLock); - for (size_t i=0 ; i<NUM_BUFFERS ; i++) { - destroyTexture(&mBufferData[i].texture, dpy); - mBufferData[i].buffer = 0; + BufferData* const buffers = mBufferData; + size_t num; + { // scope for the lock + Mutex::Autolock _l(mLock); + num = mNumBuffers; + for (size_t i=0 ; i<num ; i++) { + buffers[i].buffer = 0; + } + } + for (size_t i=0 ; i<num ; i++) { + destroyTexture(&buffers[i].texture, dpy); } destroyTexture(&mFailoverTexture, dpy); return NO_ERROR; @@ -622,7 +629,7 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) { size_t index = mActiveBuffer; - Texture& texture(mBufferData[index].texture); + Image& texture(mBufferData[index].texture); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); // if EGLImage fails, we switch to regular texture mode, and we // free all resources associated with using EGLImages. @@ -631,7 +638,8 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, destroyTexture(&mFailoverTexture, dpy); } else { mFailover = true; - for (size_t i=0 ; i<NUM_BUFFERS ; i++) { + const size_t num = mNumBuffers; + for (size_t i=0 ; i<num ; i++) { destroyTexture(&mBufferData[i].texture, dpy); } } @@ -644,6 +652,19 @@ status_t Layer::BufferManager::loadTexture( return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); } +status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy) +{ + if (tex->name != -1U) { + glDeleteTextures(1, &tex->name); + tex->name = -1U; + } + if (tex->image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, tex->image); + tex->image = EGL_NO_IMAGE_KHR; + } + return NO_ERROR; +} + // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, @@ -661,6 +682,11 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); if (owner != 0) { + /* + * requestBuffer() cannot be called from the main thread + * as it could cause a dead-lock, since it may have to wait + * on conditions updated my the main thread. + */ buffer = owner->requestBuffer(index, usage); } return buffer; @@ -671,6 +697,11 @@ status_t Layer::SurfaceLayer::setBufferCount(int bufferCount) status_t err = DEAD_OBJECT; sp<Layer> owner(getOwner()); if (owner != 0) { + /* + * setBufferCount() cannot be called from the main thread + * as it could cause a dead-lock, since it may have to wait + * on conditions updated my the main thread. + */ err = owner->setBufferCount(bufferCount); } return err; diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 80fbd6a..247748b 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -90,7 +90,6 @@ private: sp<GraphicBuffer> requestBuffer(int index, int usage); status_t setBufferCount(int bufferCount); - void destroy(); class SurfaceLayer : public LayerBaseClient::Surface { public: @@ -120,25 +119,32 @@ private: static const size_t NUM_BUFFERS = 2; struct BufferData { sp<GraphicBuffer> buffer; - Texture texture; + Image texture; }; + // this lock protect mBufferData[].buffer but since there + // is very little contention, we have only one like for + // the whole array, we also use it to protect mNumBuffers. mutable Mutex mLock; - BufferData mBufferData[NUM_BUFFERS]; + BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX]; + size_t mNumBuffers; Texture mFailoverTexture; TextureManager& mTextureManager; ssize_t mActiveBuffer; bool mFailover; - static status_t destroyTexture(Texture* tex, EGLDisplay dpy); + static status_t destroyTexture(Image* tex, EGLDisplay dpy); public: + static size_t getDefaultBufferCount() { return NUM_BUFFERS; } BufferManager(TextureManager& tm); - - size_t getBufferCount() const; + ~BufferManager(); // detach/attach buffer from/to given index sp<GraphicBuffer> detachBuffer(size_t index); status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); + // resize the number of active buffers + status_t resize(size_t size); + // ---------------------------------------------- // must be called from GL thread @@ -170,6 +176,8 @@ private: TextureManager mTextureManager; BufferManager mBufferManager; + // this lock protects mWidth and mHeight which are accessed from + // the main thread and requestBuffer's binder transaction thread. mutable Mutex mLock; uint32_t mWidth; uint32_t mHeight; diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index 2d77876..09c90e8 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -95,7 +95,9 @@ void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirty mCacheDirty = false; } else { if (!mAutoRefreshPending) { - mFlinger->signalDelayedEvent(ms2ns(500)); + mFlinger->postMessageAsync( + new MessageBase(MessageQueue::INVALIDATE), + ms2ns(500)); mAutoRefreshPending = true; } } diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp index b43d801..d668e88 100644 --- a/libs/surfaceflinger/MessageQueue.cpp +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -60,9 +60,9 @@ MessageQueue::~MessageQueue() { } -MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) +sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout) { - MessageList::value_type result; + sp<MessageBase> result; bool again; do { @@ -132,6 +132,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) if (again) { // the message has been processed. release our reference to it // without holding the lock. + result->notify(); result = 0; } @@ -141,7 +142,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) } status_t MessageQueue::postMessage( - const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) + const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags) { return queueMessage(message, relTime, flags); } @@ -154,7 +155,7 @@ status_t MessageQueue::invalidate() { } status_t MessageQueue::queueMessage( - const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) + const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags) { Mutex::Autolock _l(mLock); message->when = systemTime() + relTime; @@ -167,13 +168,13 @@ status_t MessageQueue::queueMessage( return NO_ERROR; } -void MessageQueue::dump(const MessageList::value_type& message) +void MessageQueue::dump(const sp<MessageBase>& message) { Mutex::Autolock _l(mLock); dumpLocked(message); } -void MessageQueue::dumpLocked(const MessageList::value_type& message) +void MessageQueue::dumpLocked(const sp<MessageBase>& message) { LIST::const_iterator cur(mMessages.begin()); LIST::const_iterator end(mMessages.end()); diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h index dc8138d..890f809 100644 --- a/libs/surfaceflinger/MessageQueue.h +++ b/libs/surfaceflinger/MessageQueue.h @@ -25,6 +25,7 @@ #include <utils/Timers.h> #include <utils/List.h> +#include "Barrier.h" namespace android { @@ -37,7 +38,6 @@ class MessageList List< sp<MessageBase> > mList; typedef List< sp<MessageBase> > LIST; public: - typedef sp<MessageBase> value_type; inline LIST::iterator begin() { return mList.begin(); } inline LIST::const_iterator begin() const { return mList.begin(); } inline LIST::iterator end() { return mList.end(); } @@ -63,11 +63,19 @@ public: // return true if message has a handler virtual bool handler() { return false; } + + // waits for the handler to be processed + void wait() const { barrier.wait(); } + // releases all waiters. this is done automatically if + // handler returns true + void notify() const { barrier.open(); } + protected: virtual ~MessageBase() { } private: + mutable Barrier barrier; friend class LightRefBase<MessageBase>; }; @@ -82,42 +90,33 @@ class MessageQueue typedef List< sp<MessageBase> > LIST; public: - // this is a work-around the multichar constant warning. A macro would - // work too, but would pollute the namespace. - template <int a, int b, int c, int d> - struct WHAT { - static const uint32_t Value = - (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)| - (uint32_t(c&0xff)<<8)|uint32_t(d&0xff); - }; - MessageQueue(); ~MessageQueue(); // pre-defined messages enum { - INVALIDATE = WHAT<'_','p','d','t'>::Value + INVALIDATE = '_upd' }; - MessageList::value_type waitMessage(nsecs_t timeout = -1); + sp<MessageBase> waitMessage(nsecs_t timeout = -1); - status_t postMessage(const MessageList::value_type& message, + status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0, uint32_t flags = 0); - + status_t invalidate(); - void dump(const MessageList::value_type& message); + void dump(const sp<MessageBase>& message); private: - status_t queueMessage(const MessageList::value_type& message, + status_t queueMessage(const sp<MessageBase>& message, nsecs_t reltime, uint32_t flags); - void dumpLocked(const MessageList::value_type& message); + void dumpLocked(const sp<MessageBase>& message); Mutex mLock; Condition mCondition; MessageList mMessages; bool mInvalidate; - MessageList::value_type mInvalidateMessage; + sp<MessageBase> mInvalidateMessage; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 62d829b..5a6893f 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -426,7 +426,7 @@ void SurfaceFlinger::waitForEvent() timeout = waitTime>0 ? waitTime : 0; } - MessageList::value_type msg = mEventQueue.waitMessage(timeout); + sp<MessageBase> msg = mEventQueue.waitMessage(timeout); // see if we timed out if (isFrozen()) { @@ -461,9 +461,20 @@ void SurfaceFlinger::signal() const { const_cast<SurfaceFlinger*>(this)->signalEvent(); } -void SurfaceFlinger::signalDelayedEvent(nsecs_t delay) +status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { - mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay); + return mEventQueue.postMessage(msg, reltime, flags); +} + +status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) +{ + status_t res = mEventQueue.postMessage(msg, reltime, flags); + if (res == NO_ERROR) { + msg->wait(); + } + return res; } // ---------------------------------------------------------------------------- @@ -1135,15 +1146,11 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) return android_atomic_and(~flags, &mTransactionFlags) & flags; } -uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay) +uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); if ((old & flags)==0) { // wake the server up - if (delay > 0) { - signalDelayedEvent(delay); - } else { - signalEvent(); - } + signalEvent(); } return old; } @@ -1245,7 +1252,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, //LOGD("createSurface for pid %d (%d x %d)", pid, w, h); int32_t id = client->generateId(pid); - if (uint32_t(id) >= NUM_LAYERS_MAX) { + if (uint32_t(id) >= SharedBufferStack::NUM_LAYERS_MAX) { LOGE("createSurface() failed, generateId = %d", id); return surfaceHandle; } @@ -1399,7 +1406,7 @@ status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) } }; - mEventQueue.postMessage( new MessageDestroySurface(this, layer) ); + postMessageAsync( new MessageDestroySurface(this, layer) ); return NO_ERROR; } @@ -1672,7 +1679,7 @@ Client::~Client() { int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); - if (i >= NUM_LAYERS_MAX) { + if (i >= SharedBufferStack::NUM_LAYERS_MAX) { return NO_MEMORY; } mPid = pid; @@ -1699,7 +1706,8 @@ void Client::free(int32_t id) } bool Client::isValid(int32_t i) const { - return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i))); + return (uint32_t(i)<SharedBufferStack::NUM_LAYERS_MAX) && + (mBitmap & (1<<(31-i))); } sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 9c8de51..2558324 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -255,8 +255,6 @@ private: public: // hack to work around gcc 4.0.3 bug void signalEvent(); private: - void signalDelayedEvent(nsecs_t delay); - void handleConsoleEvents(); void handleTransaction(uint32_t transactionFlags); void handleTransactionLocked( @@ -286,7 +284,7 @@ private: void free_resources_l(); uint32_t getTransactionFlags(uint32_t flags); - uint32_t setTransactionFlags(uint32_t flags, nsecs_t delay = 0); + uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); @@ -310,7 +308,12 @@ private: mutable MessageQueue mEventQueue; - + + status_t postMessageAsync(const sp<MessageBase>& msg, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t postMessageSync(const sp<MessageBase>& msg, + nsecs_t reltime=0, uint32_t flags = 0); // access must be protected by mStateLock diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp index e5d5302..ee2159b 100644 --- a/libs/surfaceflinger/TextureManager.cpp +++ b/libs/surfaceflinger/TextureManager.cpp @@ -68,7 +68,7 @@ bool TextureManager::isSupportedYuvFormat(int format) return false; } -status_t TextureManager::initEglImage(Texture* texture, +status_t TextureManager::initEglImage(Image* texture, EGLDisplay dpy, const sp<GraphicBuffer>& buffer) { status_t err = NO_ERROR; @@ -108,7 +108,6 @@ status_t TextureManager::initEglImage(Texture* texture, err = INVALID_OPERATION; } else { // Everything went okay! - texture->NPOTAdjust = false; texture->dirty = false; texture->width = clientBuf->width; texture->height = clientBuf->height; diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h index 90cb62b..d0acfe9 100644 --- a/libs/surfaceflinger/TextureManager.h +++ b/libs/surfaceflinger/TextureManager.h @@ -36,21 +36,24 @@ class GraphicBuffer; // --------------------------------------------------------------------------- -struct Texture { - Texture() : name(-1U), width(0), height(0), - image(EGL_NO_IMAGE_KHR), transform(0), - NPOTAdjust(false), dirty(true) { } +struct Image { + Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0), + transform(0), dirty(true) { } GLuint name; + EGLImageKHR image; GLuint width; GLuint height; + uint32_t transform; + bool dirty; +}; + +struct Texture : public Image { + Texture() : Image(), NPOTAdjust(false) { } GLuint potWidth; GLuint potHeight; GLfloat wScale; GLfloat hScale; - EGLImageKHR image; - uint32_t transform; bool NPOTAdjust; - bool dirty; }; // --------------------------------------------------------------------------- @@ -68,7 +71,7 @@ public: const Region& dirty, const GGLSurface& t); // make active buffer an EGLImage if needed - status_t initEglImage(Texture* texture, + status_t initEglImage(Image* texture, EGLDisplay dpy, const sp<GraphicBuffer>& buffer); }; |