summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gui/ISurfaceTexture.h12
-rw-r--r--include/gui/SurfaceTexture.h23
-rw-r--r--include/gui/SurfaceTextureClient.h4
-rw-r--r--include/surfaceflinger/ISurfaceComposerClient.h3
-rw-r--r--include/surfaceflinger/Surface.h33
-rw-r--r--include/ui/PixelFormat.h10
-rw-r--r--include/utils/Pool.h71
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp6
-rw-r--r--libs/gui/ISurfaceTexture.cpp28
-rw-r--r--libs/gui/Surface.cpp74
-rw-r--r--libs/gui/SurfaceComposerClient.cpp2
-rw-r--r--libs/gui/SurfaceTexture.cpp88
-rw-r--r--libs/gui/SurfaceTextureClient.cpp15
-rw-r--r--libs/gui/tests/SurfaceTextureClient_test.cpp5
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp151
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp28
-rw-r--r--libs/utils/Android.mk1
-rw-r--r--libs/utils/Pool.cpp37
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp3
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp6
20 files changed, 290 insertions, 310 deletions
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index e764425498..1eda646695 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -51,7 +51,7 @@ protected:
// the given slot index, and the client is expected to mirror the
// slot->buffer mapping so that it's not necessary to transfer a
// GraphicBuffer for every dequeue operation.
- virtual sp<GraphicBuffer> requestBuffer(int slot) = 0;
+ virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
// setBufferCount sets the number of buffer slots available. Calling this
// will also cause all buffer slots to be emptied. The caller should empty
@@ -79,8 +79,8 @@ protected:
// must be monotonically increasing. Its other properties (zero point, etc)
// are client-dependent, and should be documented by the client.
//
- // outWidth, outHeight and outTransform are filed with the default width
- // default height of the window and current transform applied to buffers,
+ // outWidth, outHeight and outTransform are filled with the default width
+ // and height of the window and current transform applied to buffers,
// respectively.
virtual status_t queueBuffer(int slot, int64_t timestamp,
uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) = 0;
@@ -94,12 +94,6 @@ protected:
virtual status_t setTransform(uint32_t transform) = 0;
virtual status_t setScalingMode(int mode) = 0;
- // getAllocator retrieves the binder object that must be referenced as long
- // as the GraphicBuffers dequeued from this ISurfaceTexture are referenced.
- // Holding this binder reference prevents SurfaceFlinger from freeing the
- // buffers before the client is done with them.
- virtual sp<IBinder> getAllocator() = 0;
-
// query retrieves some information for this surface
// 'what' tokens allowed are that of android_natives.h
virtual int query(int what, int* value) = 0;
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 945f4bcd68..134c208f4d 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -69,7 +69,7 @@ public:
// SurfaceTexture object (i.e. they are not owned by the client).
virtual status_t setBufferCount(int bufferCount);
- virtual sp<GraphicBuffer> requestBuffer(int buf);
+ virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
// dequeueBuffer gets the next buffer slot index for the client to use. If a
// buffer slot is available then that slot index is written to the location
@@ -190,6 +190,17 @@ public:
// getCurrentScalingMode returns the scaling mode of the current buffer
uint32_t getCurrentScalingMode() const;
+ // abandon frees all the buffers and puts the SurfaceTexture into the
+ // 'abandoned' state. Once put in this state the SurfaceTexture can never
+ // leave it. When in the 'abandoned' state, all methods of the
+ // ISurfaceTexture interface will fail with the NO_INIT error.
+ //
+ // Note that while calling this method causes all the buffers to be freed
+ // from the perspective of the the SurfaceTexture, if there are additional
+ // references on the buffers (e.g. if a buffer is referenced by a client or
+ // by OpenGL ES as a texture) then those buffer will remain allocated.
+ void abandon();
+
// dump our state in a String
void dump(String8& result) const;
void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@@ -343,8 +354,7 @@ private:
// mCurrentTextureBuf is the graphic buffer of the current texture. It's
// possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to properly use
- // IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+ // must track it separately in order to support the getCurrentBuffer method.
sp<GraphicBuffer> mCurrentTextureBuf;
// mCurrentCrop is the crop rectangle that applies to the current texture.
@@ -412,6 +422,13 @@ private:
typedef Vector<int> Fifo;
Fifo mQueue;
+ // mAbandoned indicates that the SurfaceTexture will no longer be used to
+ // consume images buffers pushed to it using the ISurfaceTexture interface.
+ // It is initialized to false, and set to true in the abandon method. A
+ // SurfaceTexture that has been abandoned will return the NO_INIT error from
+ // all ISurfaceTexture methods capable of returning an error.
+ bool mAbandoned;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 829d8abf70..56f029f0c2 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -106,10 +106,6 @@ private:
// interactions with the server using this interface.
sp<ISurfaceTexture> mSurfaceTexture;
- // mAllocator is the binder object that is referenced to prevent the
- // dequeued buffers from being freed prematurely.
- sp<IBinder> mAllocator;
-
// mSlots stores the buffers that have been allocated for each buffer slot.
// It is initialized to null pointers, and gets filled in with the result of
// ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 6e9a654642..02cabc1cdc 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -45,9 +45,6 @@ public:
struct surface_data_t {
int32_t token;
int32_t identity;
- uint32_t width;
- uint32_t height;
- uint32_t format;
status_t readFromParcel(const Parcel& parcel);
status_t writeToParcel(Parcel* parcel) const;
};
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index c2a494de41..9c352ad9ab 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -57,7 +57,6 @@ public:
static bool isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
- uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
// release surface data from java
@@ -86,25 +85,13 @@ private:
SurfaceControl& operator = (SurfaceControl& rhs);
SurfaceControl(const SurfaceControl& rhs);
-
friend class SurfaceComposerClient;
-
- // camera and camcorder need access to the ISurface binder interface for preview
- friend class CameraService;
- friend class MediaRecorder;
- // mediaplayer needs access to ISurface for display
- friend class MediaPlayer;
- // for testing
- friend class Test;
- // videoEditor preview classes
- friend class VideoEditorPreviewController;
friend class Surface;
SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<ISurface>& surface,
- const ISurfaceComposerClient::surface_data_t& data,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+ const ISurfaceComposerClient::surface_data_t& data);
~SurfaceControl();
@@ -115,10 +102,6 @@ private:
sp<ISurface> mSurface;
SurfaceID mToken;
uint32_t mIdentity;
- uint32_t mWidth;
- uint32_t mHeight;
- PixelFormat mFormat;
- uint32_t mFlags;
mutable Mutex mLock;
mutable sp<Surface> mSurfaceData;
@@ -139,17 +122,13 @@ public:
uint32_t reserved[2];
};
- static status_t writeToParcel(
- const sp<Surface>& control, Parcel* parcel);
-
+ static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
static sp<Surface> readFromParcel(const Parcel& data);
-
static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid();
}
bool isValid();
- uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
sp<ISurfaceTexture> getSurfaceTexture();
@@ -176,22 +155,14 @@ private:
* private stuff...
*/
void init();
- status_t validate(bool inCancelBuffer = false) const;
static void cleanCachedSurfacesLocked();
virtual int query(int what, int* value) const;
// constants
- status_t mInitCheck;
sp<ISurface> mSurface;
uint32_t mIdentity;
- PixelFormat mFormat;
- uint32_t mFlags;
-
- // query() must be called from dequeueBuffer() thread
- uint32_t mWidth;
- uint32_t mHeight;
// A cache of Surface objects that have been deserialized into this process.
static Mutex sCachedSurfacesLock;
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index f46f25c36d..848c5a1149 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -55,7 +55,7 @@ enum {
PIXEL_FORMAT_OPAQUE = -1,
// System chooses an opaque format (no alpha bits required)
-
+
// real pixel formats supported for rendering -----------------------------
PIXEL_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, // 4x8-bit RGBA
@@ -84,7 +84,7 @@ struct PixelFormatInfo
INDEX_GREEN = 2,
INDEX_BLUE = 3
};
-
+
enum { // components
ALPHA = 1,
RGB = 2,
@@ -98,10 +98,10 @@ struct PixelFormatInfo
uint8_t h;
uint8_t l;
};
-
+
inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { }
size_t getScanlineSize(unsigned int width) const;
- size_t getSize(size_t ci) const {
+ size_t getSize(size_t ci) const {
return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0;
}
size_t version;
@@ -112,7 +112,7 @@ struct PixelFormatInfo
szinfo cinfo[4];
struct {
uint8_t h_alpha;
- uint8_t l_alpha;
+ uint8_t l_alpha;
uint8_t h_red;
uint8_t l_red;
uint8_t h_green;
diff --git a/include/utils/Pool.h b/include/utils/Pool.h
deleted file mode 100644
index 2ee768eef1..0000000000
--- a/include/utils/Pool.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef UTILS_POOL_H
-#define UTILS_POOL_H
-
-#include <utils/TypeHelpers.h>
-
-namespace android {
-
-class PoolImpl {
-public:
- PoolImpl(size_t objSize);
- ~PoolImpl();
-
- void* allocImpl();
- void freeImpl(void* obj);
-
-private:
- size_t mObjSize;
-};
-
-/*
- * A homogeneous typed memory pool for fixed size objects.
- * Not intended to be thread-safe.
- */
-template<typename T>
-class Pool : private PoolImpl {
-public:
- /* Creates an initially empty pool. */
- Pool() : PoolImpl(sizeof(T)) { }
-
- /* Destroys the pool.
- * Assumes that the pool is empty. */
- ~Pool() { }
-
- /* Allocates an object from the pool, growing the pool if needed. */
- inline T* alloc() {
- void* mem = allocImpl();
- if (! traits<T>::has_trivial_ctor) {
- return new (mem) T();
- } else {
- return static_cast<T*>(mem);
- }
- }
-
- /* Frees an object from the pool. */
- inline void free(T* obj) {
- if (! traits<T>::has_trivial_dtor) {
- obj->~T();
- }
- freeImpl(obj);
- }
-};
-
-} // namespace android
-
-#endif // UTILS_POOL_H
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index bc97cacbe0..ace16aaae4 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -132,9 +132,6 @@ status_t ISurfaceComposerClient::surface_data_t::readFromParcel(const Parcel& pa
{
token = parcel.readInt32();
identity = parcel.readInt32();
- width = parcel.readInt32();
- height = parcel.readInt32();
- format = parcel.readInt32();
return NO_ERROR;
}
@@ -142,9 +139,6 @@ status_t ISurfaceComposerClient::surface_data_t::writeToParcel(Parcel* parcel) c
{
parcel->writeInt32(token);
parcel->writeInt32(identity);
- parcel->writeInt32(width);
- parcel->writeInt32(height);
- parcel->writeInt32(format);
return NO_ERROR;
}
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index be90e2eec0..55246dc902 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -38,7 +38,6 @@ enum {
CANCEL_BUFFER,
SET_CROP,
SET_TRANSFORM,
- GET_ALLOCATOR,
QUERY,
SET_SYNCHRONOUS_MODE,
CONNECT,
@@ -55,18 +54,18 @@ public:
{
}
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
+ virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
remote()->transact(REQUEST_BUFFER, data, &reply);
- sp<GraphicBuffer> buffer;
bool nonNull = reply.readInt32();
if (nonNull) {
- buffer = new GraphicBuffer();
- reply.read(*buffer);
+ *buf = new GraphicBuffer();
+ reply.read(**buf);
}
- return buffer;
+ status_t result = reply.readInt32();
+ return result;
}
virtual status_t setBufferCount(int bufferCount)
@@ -144,13 +143,6 @@ public:
return result;
}
- virtual sp<IBinder> getAllocator() {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
- remote()->transact(GET_ALLOCATOR, data, &reply);
- return reply.readStrongBinder();
- }
-
virtual int query(int what, int* value) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
@@ -200,11 +192,13 @@ status_t BnSurfaceTexture::onTransact(
case REQUEST_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int bufferIdx = data.readInt32();
- sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
+ sp<GraphicBuffer> buffer;
+ int result = requestBuffer(bufferIdx, &buffer);
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
}
+ reply->writeInt32(result);
return NO_ERROR;
} break;
case SET_BUFFER_COUNT: {
@@ -270,12 +264,6 @@ status_t BnSurfaceTexture::onTransact(
reply->writeInt32(result);
return NO_ERROR;
} break;
- case GET_ALLOCATOR: {
- CHECK_INTERFACE(ISurfaceTexture, data, reply);
- sp<IBinder> result = getAllocator();
- reply->writeStrongBinder(result);
- return NO_ERROR;
- } break;
case QUERY: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int value;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index dabe643f27..c4f9e53d5d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -26,15 +26,12 @@
#include <utils/Log.h>
#include <utils/threads.h>
-#include <binder/IMemory.h>
#include <binder/IPCThreadState.h>
#include <gui/SurfaceTextureClient.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <ui/GraphicLog.h>
#include <ui/Rect.h>
#include <surfaceflinger/ISurface.h>
@@ -42,8 +39,6 @@
#include <surfaceflinger/Surface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
-#include <private/surfaceflinger/LayerState.h>
-
namespace android {
// ============================================================================
@@ -53,12 +48,9 @@ namespace android {
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<ISurface>& surface,
- const ISurfaceComposerClient::surface_data_t& data,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+ const ISurfaceComposerClient::surface_data_t& data)
: mClient(client), mSurface(surface),
- mToken(data.token), mIdentity(data.identity),
- mWidth(data.width), mHeight(data.height), mFormat(data.format),
- mFlags(flags)
+ mToken(data.token), mIdentity(data.identity)
{
}
@@ -187,24 +179,12 @@ status_t SurfaceControl::writeSurfaceToParcel(
{
sp<ISurface> sur;
uint32_t identity = 0;
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t format = 0;
- uint32_t flags = 0;
if (SurfaceControl::isValid(control)) {
sur = control->mSurface;
identity = control->mIdentity;
- width = control->mWidth;
- height = control->mHeight;
- format = control->mFormat;
- flags = control->mFlags;
}
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(identity);
- parcel->writeInt32(width);
- parcel->writeInt32(height);
- parcel->writeInt32(format);
- parcel->writeInt32(flags);
return NO_ERROR;
}
@@ -225,25 +205,17 @@ sp<Surface> SurfaceControl::getSurface() const
Surface::Surface(const sp<SurfaceControl>& surface)
: SurfaceTextureClient(),
- mInitCheck(NO_INIT),
mSurface(surface->mSurface),
- mIdentity(surface->mIdentity),
- mFormat(surface->mFormat), mFlags(surface->mFlags),
- mWidth(surface->mWidth), mHeight(surface->mHeight)
+ mIdentity(surface->mIdentity)
{
init();
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
- : SurfaceTextureClient(),
- mInitCheck(NO_INIT)
+ : SurfaceTextureClient()
{
mSurface = interface_cast<ISurface>(ref);
mIdentity = parcel.readInt32();
- mWidth = parcel.readInt32();
- mHeight = parcel.readInt32();
- mFormat = parcel.readInt32();
- mFlags = parcel.readInt32();
init();
}
@@ -252,31 +224,16 @@ status_t Surface::writeToParcel(
{
sp<ISurface> sur;
uint32_t identity = 0;
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t format = 0;
- uint32_t flags = 0;
if (Surface::isValid(surface)) {
sur = surface->mSurface;
identity = surface->mIdentity;
- width = surface->mWidth;
- height = surface->mHeight;
- format = surface->mFormat;
- flags = surface->mFlags;
} else if (surface != 0 && surface->mSurface != 0) {
LOGW("Parceling invalid surface with non-NULL ISurface as NULL: "
- "mSurface = %p, mIdentity = %d, mWidth = %d, mHeight = %d, "
- "mFormat = %d, mFlags = 0x%08x, mInitCheck = %d",
- surface->mSurface.get(), surface->mIdentity, surface->mWidth,
- surface->mHeight, surface->mFormat, surface->mFlags,
- surface->mInitCheck);
+ "mSurface = %p, mIdentity = %d",
+ surface->mSurface.get(), surface->mIdentity);
}
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(identity);
- parcel->writeInt32(width);
- parcel->writeInt32(height);
- parcel->writeInt32(format);
- parcel->writeInt32(flags);
return NO_ERROR;
}
@@ -325,10 +282,6 @@ void Surface::init()
const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
const_cast<uint32_t&>(ANativeWindow::flags) = 0;
-
- if (surfaceTexture != NULL) {
- mInitCheck = NO_ERROR;
- }
}
}
@@ -341,21 +294,11 @@ Surface::~Surface()
}
bool Surface::isValid() {
- return mInitCheck == NO_ERROR;
-}
-
-status_t Surface::validate(bool inCancelBuffer) const
-{
- // check that we initialized ourself properly
- if (mInitCheck != NO_ERROR) {
- LOGE("invalid token (identity=%u)", mIdentity);
- return mInitCheck;
- }
- return NO_ERROR;
+ return getISurfaceTexture() != NULL;
}
sp<ISurfaceTexture> Surface::getSurfaceTexture() {
- return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL;
+ return getISurfaceTexture();
}
sp<IBinder> Surface::asBinder() const {
@@ -367,7 +310,6 @@ sp<IBinder> Surface::asBinder() const {
int Surface::query(int what, int* value) const {
switch (what) {
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
- // TODO: this is not needed anymore
*value = 1;
return NO_ERROR;
case NATIVE_WINDOW_CONCRETE_TYPE:
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8cead808a1..3b0ffea0ff 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -339,7 +339,7 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
sp<ISurface> surface = mClient->createSurface(&data, name,
display, w, h, format, flags);
if (surface != 0) {
- result = new SurfaceControl(this, surface, data, w, h, format, flags);
+ result = new SurfaceControl(this, surface, data);
}
}
return result;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 0f08570ef7..c190195b53 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -94,7 +94,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
mTexName(tex),
mSynchronousMode(false),
mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API) {
+ mConnectedApi(NO_CONNECTED_API),
+ mAbandoned(false) {
LOGV("SurfaceTexture::SurfaceTexture");
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -150,6 +151,11 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
LOGV("SurfaceTexture::setBufferCount");
Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ LOGE("setBufferCount: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
if (bufferCount > NUM_BUFFER_SLOTS) {
LOGE("setBufferCount: bufferCount larger than slots available");
return BAD_VALUE;
@@ -199,22 +205,32 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
return OK;
}
-sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) {
+status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
LOGV("SurfaceTexture::requestBuffer");
Mutex::Autolock lock(mMutex);
- if (buf < 0 || mBufferCount <= buf) {
+ if (mAbandoned) {
+ LOGE("requestBuffer: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+ if (slot < 0 || mBufferCount <= slot) {
LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return 0;
+ mBufferCount, slot);
+ return BAD_VALUE;
}
- mSlots[buf].mRequestBufferCalled = true;
- return mSlots[buf].mGraphicBuffer;
+ mSlots[slot].mRequestBufferCalled = true;
+ *buf = mSlots[slot].mGraphicBuffer;
+ return NO_ERROR;
}
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
uint32_t format, uint32_t usage) {
LOGV("SurfaceTexture::dequeueBuffer");
+ if (mAbandoned) {
+ LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
if ((w && !h) || (!w && h)) {
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
return BAD_VALUE;
@@ -252,6 +268,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
// wait for the FIFO to drain
while (!mQueue.isEmpty()) {
mDequeueCondition.wait(mMutex);
+ if (mAbandoned) {
+ LOGE("dequeueBuffer: SurfaceTexture was abandoned while "
+ "blocked!");
+ return NO_INIT;
+ }
}
minBufferCountNeeded = mSynchronousMode ?
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
@@ -380,6 +401,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
status_t SurfaceTexture::setSynchronousMode(bool enabled) {
Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
status_t err = OK;
if (!mAllowSynchronousMode && enabled)
return err;
@@ -410,6 +436,10 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
{ // scope for the lock
Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ LOGE("queueBuffer: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
if (buf < 0 || buf >= mBufferCount) {
LOGE("queueBuffer: slot index out of range [0, %d]: %d",
mBufferCount, buf);
@@ -475,6 +505,12 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
void SurfaceTexture::cancelBuffer(int buf) {
LOGV("SurfaceTexture::cancelBuffer");
Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
+ return;
+ }
+
if (buf < 0 || buf >= mBufferCount) {
LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
mBufferCount, buf);
@@ -491,6 +527,10 @@ void SurfaceTexture::cancelBuffer(int buf) {
status_t SurfaceTexture::setCrop(const Rect& crop) {
LOGV("SurfaceTexture::setCrop");
Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ LOGE("setCrop: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
mNextCrop = crop;
return OK;
}
@@ -498,6 +538,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) {
status_t SurfaceTexture::setTransform(uint32_t transform) {
LOGV("SurfaceTexture::setTransform");
Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ LOGE("setTransform: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
mNextTransform = transform;
return OK;
}
@@ -505,6 +549,12 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {
status_t SurfaceTexture::connect(int api) {
LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ LOGE("connect: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
@@ -529,6 +579,12 @@ status_t SurfaceTexture::connect(int api) {
status_t SurfaceTexture::disconnect(int api) {
LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ LOGE("connect: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
int err = NO_ERROR;
switch (api) {
case NATIVE_WINDOW_API_EGL:
@@ -786,11 +842,6 @@ void SurfaceTexture::setFrameAvailableListener(
mFrameAvailableListener = listener;
}
-sp<IBinder> SurfaceTexture::getAllocator() {
- LOGV("SurfaceTexture::getAllocator");
- return mGraphicBufferAlloc->asBinder();
-}
-
void SurfaceTexture::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mGraphicBuffer = 0;
@@ -842,6 +893,12 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
int SurfaceTexture::query(int what, int* outValue)
{
Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ LOGE("query: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
int value;
switch (what) {
case NATIVE_WINDOW_WIDTH:
@@ -868,6 +925,13 @@ int SurfaceTexture::query(int what, int* outValue)
return NO_ERROR;
}
+void SurfaceTexture::abandon() {
+ Mutex::Autolock lock(mMutex);
+ freeAllBuffers();
+ mAbandoned = true;
+ mDequeueCondition.signal();
+}
+
void SurfaceTexture::dump(String8& result) const
{
char buffer[1024];
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 1dc6cd2cf7..df0ad5abe3 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -55,6 +55,9 @@ void SurfaceTextureClient::init() {
mQueryWidth = 0;
mQueryHeight = 0;
mQueryFormat = 0;
+ mDefaultWidth = 0;
+ mDefaultHeight = 0;
+ mTransformHint = 0;
mConnectedToCpu = false;
}
@@ -62,9 +65,6 @@ void SurfaceTextureClient::setISurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture)
{
mSurfaceTexture = surfaceTexture;
-
- // Get a reference to the allocator.
- mAllocator = mSurfaceTexture->getAllocator();
}
sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const {
@@ -148,10 +148,11 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
}
if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
- gbuf = mSurfaceTexture->requestBuffer(buf);
- if (gbuf == 0) {
- LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
- return NO_MEMORY;
+ result = mSurfaceTexture->requestBuffer(buf, &gbuf);
+ if (result != NO_ERROR) {
+ LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
+ result);
+ return result;
}
mQueryWidth = gbuf->width;
mQueryHeight = gbuf->height;
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 2b8f204563..c1a3c98d6a 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -116,11 +116,6 @@ TEST_F(SurfaceTextureClientTest, ConcreteTypeIsSurfaceTextureClient) {
EXPECT_EQ(NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, result);
}
-TEST_F(SurfaceTextureClientTest, ANativeWindowLockFails) {
- ANativeWindow_Buffer buf;
- ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(mANW.get(), &buf, NULL));
-}
-
TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 9abe89d970..0fac6cda05 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -1018,6 +1018,83 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
}
+TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
+ class ProducerThread : public Thread {
+ public:
+ ProducerThread(const sp<ANativeWindow>& anw):
+ mANW(anw),
+ mDequeueError(NO_ERROR) {
+ }
+
+ virtual ~ProducerThread() {
+ }
+
+ virtual bool threadLoop() {
+ Mutex::Autolock lock(mMutex);
+ ANativeWindowBuffer* anb;
+
+ // Frame 1
+ if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+ return false;
+ }
+ if (anb == NULL) {
+ return false;
+ }
+ if (mANW->queueBuffer(mANW.get(), anb)
+ != NO_ERROR) {
+ return false;
+ }
+
+ // Frame 2
+ if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+ return false;
+ }
+ if (anb == NULL) {
+ return false;
+ }
+ if (mANW->queueBuffer(mANW.get(), anb)
+ != NO_ERROR) {
+ return false;
+ }
+
+ // Frame 3 - error expected
+ mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb);
+ return false;
+ }
+
+ status_t getDequeueError() {
+ Mutex::Autolock lock(mMutex);
+ return mDequeueError;
+ }
+
+ private:
+ sp<ANativeWindow> mANW;
+ status_t mDequeueError;
+ Mutex mMutex;
+ };
+
+ sp<FrameWaiter> fw(new FrameWaiter);
+ mST->setFrameAvailableListener(fw);
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, mST->setBufferCountServer(2));
+
+ sp<Thread> pt(new ProducerThread(mANW));
+ pt->run();
+
+ fw->waitForFrame();
+ fw->waitForFrame();
+
+ // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
+ // block waiting for a buffer to become available.
+ usleep(100000);
+
+ mST->abandon();
+
+ pt->requestExitAndWait();
+ ASSERT_EQ(NO_INIT,
+ reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
+}
+
/*
* This test is for testing GL -> GL texture streaming via SurfaceTexture. It
* contains functionality to create a producer thread that will perform GL
@@ -1205,7 +1282,7 @@ protected:
sp<FrameCondition> mFC;
};
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
class PT : public ProducerThread {
virtual void render() {
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1223,7 +1300,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
// TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
class PT : public ProducerThread {
virtual void render() {
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1241,7 +1318,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
// TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
enum { NUM_ITERATIONS = 1024 };
class PT : public ProducerThread {
@@ -1269,7 +1346,7 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks)
}
}
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
enum { NUM_ITERATIONS = 1024 };
class PT : public ProducerThread {
@@ -1297,4 +1374,70 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks)
}
}
+// XXX: This test is disabled because it is currently hanging on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
+ enum { NUM_ITERATIONS = 64 };
+
+ class PT : public ProducerThread {
+ virtual void render() {
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ LOGV("+swapBuffers");
+ swapBuffers();
+ LOGV("-swapBuffers");
+ }
+ }
+ };
+
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, mST->setBufferCountServer(2));
+
+ runProducerThread(new PT());
+
+ // Allow three frames to be rendered and queued before starting the
+ // rendering in this thread. For the latter two frames we don't call
+ // updateTexImage so the next dequeue from the producer thread will block
+ // waiting for a frame to become available.
+ mFC->waitForFrame();
+ mFC->finishFrame();
+
+ // We must call updateTexImage to consume the first frame so that the
+ // SurfaceTexture is able to reduce the buffer count to 2. This is because
+ // the GL driver may dequeue a buffer when the EGLSurface is created, and
+ // that happens before we call setBufferCountServer. It's possible that the
+ // driver does not dequeue a buffer at EGLSurface creation time, so we
+ // cannot rely on this to cause the second dequeueBuffer call to block.
+ mST->updateTexImage();
+
+ mFC->waitForFrame();
+ mFC->finishFrame();
+ mFC->waitForFrame();
+ mFC->finishFrame();
+
+ // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
+ // block waiting for a buffer to become available.
+ usleep(100000);
+
+ // Render and present a number of images. This thread should not be blocked
+ // by the fact that the producer thread is blocking in dequeue.
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ glClear(GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers(mEglDisplay, mEglSurface);
+ }
+
+ // Consume the two pending buffers to unblock the producer thread.
+ mST->updateTexImage();
+ mST->updateTexImage();
+
+ // Consume the remaining buffers from the producer thread.
+ for (int i = 0; i < NUM_ITERATIONS-3; i++) {
+ mFC->waitForFrame();
+ mFC->finishFrame();
+ LOGV("+updateTexImage");
+ mST->updateTexImage();
+ LOGV("-updateTexImage");
+ }
+}
+
} // namespace android
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 412552ec8e..0e8ae619fc 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -310,35 +310,21 @@ int FramebufferNativeWindow::perform(ANativeWindow* window,
int operation, ...)
{
switch (operation) {
- case NATIVE_WINDOW_SET_USAGE:
- // TODO: we should implement this
- return NO_ERROR;
case NATIVE_WINDOW_CONNECT:
- // TODO: we should implement this
- return NO_ERROR;
case NATIVE_WINDOW_DISCONNECT:
- // TODO: we should implement this
+ case NATIVE_WINDOW_SET_USAGE:
+ case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+ case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
+ case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+ case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+ // TODO: we should implement these
return NO_ERROR;
+
case NATIVE_WINDOW_LOCK:
- return INVALID_OPERATION;
case NATIVE_WINDOW_UNLOCK_AND_POST:
- return INVALID_OPERATION;
case NATIVE_WINDOW_SET_CROP:
- return INVALID_OPERATION;
case NATIVE_WINDOW_SET_BUFFER_COUNT:
- // TODO: we should implement this
- return INVALID_OPERATION;
- case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
- return INVALID_OPERATION;
- case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
- return INVALID_OPERATION;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
- return INVALID_OPERATION;
- case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
- return INVALID_OPERATION;
- case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
- // TODO: we should implement this
- return NO_ERROR;
case NATIVE_WINDOW_SET_SCALING_MODE:
return INVALID_OPERATION;
}
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index f6333576a1..e4eadbd004 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -29,7 +29,6 @@ commonSources:= \
Flattenable.cpp \
LinearTransform.cpp \
ObbFile.cpp \
- Pool.cpp \
PropertyMap.cpp \
RefBase.cpp \
ResourceTypes.cpp \
diff --git a/libs/utils/Pool.cpp b/libs/utils/Pool.cpp
deleted file mode 100644
index 8f18cb913e..0000000000
--- a/libs/utils/Pool.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// A simple memory pool.
-//
-#define LOG_TAG "Pool"
-
-//#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-#include <utils/Pool.h>
-
-#include <stdlib.h>
-
-namespace android {
-
-// TODO Provide a real implementation of a pool. This is just a stub for initial development.
-
-PoolImpl::PoolImpl(size_t objSize) :
- mObjSize(objSize) {
-}
-
-PoolImpl::~PoolImpl() {
-}
-
-void* PoolImpl::allocImpl() {
- void* ptr = malloc(mObjSize);
- LOG_ALWAYS_FATAL_IF(ptr == NULL, "Cannot allocate new pool object.");
- return ptr;
-}
-
-void PoolImpl::freeImpl(void* obj) {
- LOG_ALWAYS_FATAL_IF(obj == NULL, "Caller attempted to free NULL pool object.");
- return free(obj);
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 680814cf23..4a27701910 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1318,9 +1318,6 @@ sp<ISurface> SurfaceFlinger::createSurface(
if (surfaceHandle != 0) {
params->token = token;
params->identity = layer->getIdentity();
- params->width = w;
- params->height = h;
- params->format = format;
if (normalLayer != 0) {
Mutex::Autolock _l(mStateLock);
mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 11f61ccb1a..91e010f90f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -60,7 +60,11 @@ status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp,
sp<Layer> layer(mLayer.promote());
if (layer != NULL) {
- *outTransform = layer->getOrientation();
+ uint32_t orientation = layer->getOrientation();
+ if (orientation & Transform::ROT_INVALID) {
+ orientation = 0;
+ }
+ *outTransform = orientation;
}
return res;