Fix remote GraphicBuffer allocation in SurfaceFlinger.
This change fixes a horrible hack that I did to allow application processes to create GraphicBuffer objects by making a binder call to SurfaceFlinger. This change introduces a new binder interface specifically for doing this, and does it in such a way that SurfaceFlinger will maintain a reference to the buffers until the app is done with them. Change-Id: Icb240397c6c206d7f69124c1497a829f051cb49b
This commit is contained in:
parent
e5366c567a
commit
9a78c90cd4
@ -26,12 +26,15 @@
|
|||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
|
|
||||||
#include <utils/threads.h>
|
#include <utils/threads.h>
|
||||||
|
#include <utils/Vector.h>
|
||||||
|
|
||||||
#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
|
#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class IGraphicBufferAlloc;
|
||||||
|
|
||||||
class SurfaceTexture : public BnSurfaceTexture {
|
class SurfaceTexture : public BnSurfaceTexture {
|
||||||
public:
|
public:
|
||||||
enum { MIN_BUFFER_SLOTS = 3 };
|
enum { MIN_BUFFER_SLOTS = 3 };
|
||||||
@ -140,6 +143,12 @@ private:
|
|||||||
// reset mCurrentTexture to INVALID_BUFFER_SLOT.
|
// reset mCurrentTexture to INVALID_BUFFER_SLOT.
|
||||||
int mCurrentTexture;
|
int mCurrentTexture;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
sp<GraphicBuffer> mCurrentTextureBuf;
|
||||||
|
|
||||||
// mCurrentCrop is the crop rectangle that applies to the current texture.
|
// mCurrentCrop is the crop rectangle that applies to the current texture.
|
||||||
// It gets set to mLastQueuedCrop each time updateTexImage is called.
|
// It gets set to mLastQueuedCrop each time updateTexImage is called.
|
||||||
Rect mCurrentCrop;
|
Rect mCurrentCrop;
|
||||||
@ -176,6 +185,16 @@ private:
|
|||||||
// changed with a call to setTexName.
|
// changed with a call to setTexName.
|
||||||
const GLuint mTexName;
|
const GLuint mTexName;
|
||||||
|
|
||||||
|
// mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
|
||||||
|
// allocate new GraphicBuffer objects.
|
||||||
|
sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
|
||||||
|
|
||||||
|
// mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is
|
||||||
|
// referencing. This is kept so that gralloc implementations do not need to
|
||||||
|
// properly handle the case where SurfaceFlinger no longer holds a reference
|
||||||
|
// to a buffer, but other processes do.
|
||||||
|
Vector<sp<GraphicBuffer> > mAllocdBuffers;
|
||||||
|
|
||||||
// mMutex is the mutex used to prevent concurrent access to the member
|
// mMutex is the mutex used to prevent concurrent access to the member
|
||||||
// variables of SurfaceTexture objects. It must be locked whenever the
|
// variables of SurfaceTexture objects. It must be locked whenever the
|
||||||
// member variables are accessed.
|
// member variables are accessed.
|
||||||
|
64
include/surfaceflinger/IGraphicBufferAlloc.h
Normal file
64
include/surfaceflinger/IGraphicBufferAlloc.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 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 ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
|
||||||
|
#define ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <utils/RefBase.h>
|
||||||
|
|
||||||
|
#include <binder/IInterface.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class IGraphicBufferAlloc : public IInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_META_INTERFACE(GraphicBufferAlloc);
|
||||||
|
|
||||||
|
/* Create a new GraphicBuffer for the client to use. The server will
|
||||||
|
* maintain a reference to the newly created GraphicBuffer until
|
||||||
|
* freeAllGraphicBuffers is called.
|
||||||
|
*/
|
||||||
|
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
||||||
|
PixelFormat format, uint32_t usage) = 0;
|
||||||
|
|
||||||
|
/* Free all but one of the GraphicBuffer objects that the server is
|
||||||
|
* currently referencing. If bufIndex is not a valid index of the buffers
|
||||||
|
* the server is referencing, then all buffers are freed.
|
||||||
|
*/
|
||||||
|
virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual status_t onTransact( uint32_t code,
|
||||||
|
const Parcel& data,
|
||||||
|
Parcel* reply,
|
||||||
|
uint32_t flags = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
}; // namespace android
|
||||||
|
|
||||||
|
#endif // ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
|
@ -28,6 +28,7 @@
|
|||||||
#include <ui/PixelFormat.h>
|
#include <ui/PixelFormat.h>
|
||||||
|
|
||||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||||
|
#include <surfaceflinger/IGraphicBufferAlloc.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -96,6 +97,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
|
virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
|
||||||
|
|
||||||
|
/* create a graphic buffer allocator
|
||||||
|
*/
|
||||||
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
|
||||||
|
|
||||||
/* retrieve the control block */
|
/* retrieve the control block */
|
||||||
virtual sp<IMemoryHeap> getCblk() const = 0;
|
virtual sp<IMemoryHeap> getCblk() const = 0;
|
||||||
|
|
||||||
@ -131,13 +136,6 @@ public:
|
|||||||
* This is an ASYNCHRONOUS call.
|
* This is an ASYNCHRONOUS call.
|
||||||
*/
|
*/
|
||||||
virtual void signal() const = 0;
|
virtual void signal() const = 0;
|
||||||
|
|
||||||
/* Create a new GraphicBuffer for the client to use. SurfaceFlinger will
|
|
||||||
* not maintain a reference to the GraphicBuffer, so the underlying native
|
|
||||||
* handle will be freed once the client references are released.
|
|
||||||
*/
|
|
||||||
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
|
||||||
PixelFormat format, uint32_t usage) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -151,7 +149,7 @@ public:
|
|||||||
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
|
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
CREATE_CONNECTION,
|
CREATE_CONNECTION,
|
||||||
CREATE_CLIENT_CONNECTION,
|
CREATE_CLIENT_CONNECTION,
|
||||||
CREATE_GRAPHIC_BUFFER,
|
CREATE_GRAPHIC_BUFFER_ALLOC,
|
||||||
GET_CBLK,
|
GET_CBLK,
|
||||||
OPEN_GLOBAL_TRANSACTION,
|
OPEN_GLOBAL_TRANSACTION,
|
||||||
CLOSE_GLOBAL_TRANSACTION,
|
CLOSE_GLOBAL_TRANSACTION,
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <surfaceflinger/ISurfaceComposer.h>
|
#include <surfaceflinger/ISurfaceComposer.h>
|
||||||
#include <surfaceflinger/SurfaceComposerClient.h>
|
#include <surfaceflinger/SurfaceComposerClient.h>
|
||||||
|
#include <surfaceflinger/IGraphicBufferAlloc.h>
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
|
|
||||||
@ -83,6 +84,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex) :
|
|||||||
mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
|
mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
|
||||||
mSlots[i].mOwnedByClient = false;
|
mSlots[i].mOwnedByClient = false;
|
||||||
}
|
}
|
||||||
|
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
||||||
|
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceTexture::~SurfaceTexture() {
|
SurfaceTexture::~SurfaceTexture() {
|
||||||
@ -110,9 +113,8 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
|
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
|
||||||
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
sp<GraphicBuffer> graphicBuffer(
|
||||||
sp<GraphicBuffer> graphicBuffer(composer->createGraphicBuffer(w, h,
|
mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
|
||||||
format, usage));
|
|
||||||
if (graphicBuffer == 0) {
|
if (graphicBuffer == 0) {
|
||||||
LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
|
LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
|
||||||
} else {
|
} else {
|
||||||
@ -122,6 +124,7 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
|
|||||||
mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
|
mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
|
||||||
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
|
mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
|
mAllocdBuffers.add(graphicBuffer);
|
||||||
}
|
}
|
||||||
return graphicBuffer;
|
return graphicBuffer;
|
||||||
}
|
}
|
||||||
@ -204,27 +207,28 @@ status_t SurfaceTexture::updateTexImage() {
|
|||||||
// Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
|
// Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
|
||||||
// so this check will fail until a buffer gets queued.
|
// so this check will fail until a buffer gets queued.
|
||||||
if (mCurrentTexture != mLastQueued) {
|
if (mCurrentTexture != mLastQueued) {
|
||||||
// Update the SurfaceTexture state.
|
|
||||||
mCurrentTexture = mLastQueued;
|
|
||||||
mCurrentCrop = mLastQueuedCrop;
|
|
||||||
mCurrentTransform = mLastQueuedTransform;
|
|
||||||
|
|
||||||
// Update the GL texture object.
|
// Update the GL texture object.
|
||||||
EGLImageKHR image = mSlots[mCurrentTexture].mEglImage;
|
EGLImageKHR image = mSlots[mLastQueued].mEglImage;
|
||||||
if (image == EGL_NO_IMAGE_KHR) {
|
if (image == EGL_NO_IMAGE_KHR) {
|
||||||
EGLDisplay dpy = eglGetCurrentDisplay();
|
EGLDisplay dpy = eglGetCurrentDisplay();
|
||||||
sp<GraphicBuffer> graphicBuffer = mSlots[mCurrentTexture].mGraphicBuffer;
|
sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
|
||||||
image = createImage(dpy, graphicBuffer);
|
image = createImage(dpy, graphicBuffer);
|
||||||
mSlots[mCurrentTexture].mEglImage = image;
|
mSlots[mLastQueued].mEglImage = image;
|
||||||
mSlots[mCurrentTexture].mEglDisplay = dpy;
|
mSlots[mLastQueued].mEglDisplay = dpy;
|
||||||
}
|
}
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
|
||||||
GLint error = glGetError();
|
GLint error = glGetError();
|
||||||
if (error != GL_NO_ERROR) {
|
if (error != GL_NO_ERROR) {
|
||||||
LOGE("error binding external texture image %p (slot %d): %#04x",
|
LOGE("error binding external texture image %p (slot %d): %#04x",
|
||||||
image, mCurrentTexture, error);
|
image, mLastQueued, error);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the SurfaceTexture state.
|
||||||
|
mCurrentTexture = mLastQueued;
|
||||||
|
mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
|
||||||
|
mCurrentCrop = mLastQueuedCrop;
|
||||||
|
mCurrentTransform = mLastQueuedTransform;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -282,6 +286,19 @@ void SurfaceTexture::freeAllBuffers() {
|
|||||||
mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
|
mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int exceptBuf = -1;
|
||||||
|
for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
|
||||||
|
if (mAllocdBuffers[i] == mCurrentTextureBuf) {
|
||||||
|
exceptBuf = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAllocdBuffers.clear();
|
||||||
|
if (exceptBuf >= 0) {
|
||||||
|
mAllocdBuffers.add(mCurrentTextureBuf);
|
||||||
|
}
|
||||||
|
mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
|
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
|
||||||
|
@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
|
|||||||
ISurfaceComposer.cpp \
|
ISurfaceComposer.cpp \
|
||||||
ISurface.cpp \
|
ISurface.cpp \
|
||||||
ISurfaceComposerClient.cpp \
|
ISurfaceComposerClient.cpp \
|
||||||
|
IGraphicBufferAlloc.cpp \
|
||||||
LayerState.cpp \
|
LayerState.cpp \
|
||||||
SharedBufferStack.cpp \
|
SharedBufferStack.cpp \
|
||||||
Surface.cpp \
|
Surface.cpp \
|
||||||
|
108
libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
Normal file
108
libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// tag as surfaceflinger
|
||||||
|
#define LOG_TAG "SurfaceFlinger"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <binder/Parcel.h>
|
||||||
|
|
||||||
|
#include <ui/GraphicBuffer.h>
|
||||||
|
|
||||||
|
#include <surfaceflinger/IGraphicBufferAlloc.h>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
|
FREE_ALL_GRAPHIC_BUFFERS_EXCEPT,
|
||||||
|
};
|
||||||
|
|
||||||
|
class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BpGraphicBufferAlloc(const sp<IBinder>& impl)
|
||||||
|
: BpInterface<IGraphicBufferAlloc>(impl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
||||||
|
PixelFormat format, uint32_t usage) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(
|
||||||
|
IGraphicBufferAlloc::getInterfaceDescriptor());
|
||||||
|
data.writeInt32(w);
|
||||||
|
data.writeInt32(h);
|
||||||
|
data.writeInt32(format);
|
||||||
|
data.writeInt32(usage);
|
||||||
|
remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
|
||||||
|
sp<GraphicBuffer> graphicBuffer;
|
||||||
|
bool nonNull = (bool)reply.readInt32();
|
||||||
|
if (nonNull) {
|
||||||
|
graphicBuffer = new GraphicBuffer();
|
||||||
|
reply.read(*graphicBuffer);
|
||||||
|
}
|
||||||
|
return graphicBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void freeAllGraphicBuffersExcept(int bufIdx) {
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(
|
||||||
|
IGraphicBufferAlloc::getInterfaceDescriptor());
|
||||||
|
data.writeInt32(bufIdx);
|
||||||
|
remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
status_t BnGraphicBufferAlloc::onTransact(
|
||||||
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||||
|
{
|
||||||
|
// codes that don't require permission check
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case CREATE_GRAPHIC_BUFFER: {
|
||||||
|
CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
|
||||||
|
uint32_t w = data.readInt32();
|
||||||
|
uint32_t h = data.readInt32();
|
||||||
|
PixelFormat format = data.readInt32();
|
||||||
|
uint32_t usage = data.readInt32();
|
||||||
|
sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
|
||||||
|
reply->writeInt32(result != 0);
|
||||||
|
if (result != 0) {
|
||||||
|
reply->write(*result);
|
||||||
|
}
|
||||||
|
return NO_ERROR;
|
||||||
|
} break;
|
||||||
|
case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: {
|
||||||
|
CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
|
||||||
|
int bufIdx = data.readInt32();
|
||||||
|
freeAllGraphicBuffersExcept(bufIdx);
|
||||||
|
return NO_ERROR;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
return BBinder::onTransact(code, data, reply, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace android
|
@ -26,7 +26,6 @@
|
|||||||
#include <binder/IServiceManager.h>
|
#include <binder/IServiceManager.h>
|
||||||
|
|
||||||
#include <ui/DisplayInfo.h>
|
#include <ui/DisplayInfo.h>
|
||||||
#include <ui/GraphicBuffer.h>
|
|
||||||
|
|
||||||
#include <surfaceflinger/ISurfaceComposer.h>
|
#include <surfaceflinger/ISurfaceComposer.h>
|
||||||
|
|
||||||
@ -65,6 +64,15 @@ public:
|
|||||||
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
|
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
|
||||||
|
{
|
||||||
|
uint32_t n;
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||||
|
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
|
||||||
|
return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
|
||||||
|
}
|
||||||
|
|
||||||
virtual sp<IMemoryHeap> getCblk() const
|
virtual sp<IMemoryHeap> getCblk() const
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
@ -170,25 +178,6 @@ public:
|
|||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||||
remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
|
remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
|
||||||
PixelFormat format, uint32_t usage) const {
|
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
|
||||||
data.writeInt32(w);
|
|
||||||
data.writeInt32(h);
|
|
||||||
data.writeInt32(format);
|
|
||||||
data.writeInt32(usage);
|
|
||||||
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER, data,
|
|
||||||
&reply);
|
|
||||||
sp<GraphicBuffer> graphicBuffer;
|
|
||||||
bool nonNull = (bool)reply.readInt32();
|
|
||||||
if (nonNull) {
|
|
||||||
graphicBuffer = new GraphicBuffer();
|
|
||||||
reply.read(*graphicBuffer);
|
|
||||||
}
|
|
||||||
return graphicBuffer;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
|
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
|
||||||
@ -209,6 +198,11 @@ status_t BnSurfaceComposer::onTransact(
|
|||||||
sp<IBinder> b = createClientConnection()->asBinder();
|
sp<IBinder> b = createClientConnection()->asBinder();
|
||||||
reply->writeStrongBinder(b);
|
reply->writeStrongBinder(b);
|
||||||
} break;
|
} break;
|
||||||
|
case CREATE_GRAPHIC_BUFFER_ALLOC: {
|
||||||
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
|
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
|
||||||
|
reply->writeStrongBinder(b);
|
||||||
|
} break;
|
||||||
case OPEN_GLOBAL_TRANSACTION: {
|
case OPEN_GLOBAL_TRANSACTION: {
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
openGlobalTransaction();
|
openGlobalTransaction();
|
||||||
@ -267,18 +261,6 @@ status_t BnSurfaceComposer::onTransact(
|
|||||||
reply->writeInt32(f);
|
reply->writeInt32(f);
|
||||||
reply->writeInt32(res);
|
reply->writeInt32(res);
|
||||||
} break;
|
} break;
|
||||||
case CREATE_GRAPHIC_BUFFER: {
|
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
|
||||||
uint32_t w = data.readInt32();
|
|
||||||
uint32_t h = data.readInt32();
|
|
||||||
PixelFormat format = data.readInt32();
|
|
||||||
uint32_t usage = data.readInt32();
|
|
||||||
sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
|
|
||||||
reply->writeInt32(result != 0);
|
|
||||||
if (result != 0) {
|
|
||||||
reply->write(*result);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case TURN_ELECTRON_BEAM_OFF: {
|
case TURN_ELECTRON_BEAM_OFF: {
|
||||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||||
int32_t mode = data.readInt32();
|
int32_t mode = data.readInt32();
|
||||||
|
@ -144,6 +144,11 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
|
|||||||
return bclient;
|
return bclient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
|
||||||
|
{
|
||||||
|
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
|
||||||
|
return gba;
|
||||||
|
}
|
||||||
|
|
||||||
const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
|
const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
|
||||||
{
|
{
|
||||||
@ -2267,25 +2272,6 @@ sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
sp<GraphicBuffer> SurfaceFlinger::createGraphicBuffer(uint32_t w, uint32_t h,
|
|
||||||
PixelFormat format, uint32_t usage) const {
|
|
||||||
// XXX: HACK HACK HACK!!! This should NOT be static, but it is to fix a
|
|
||||||
// race between SurfaceFlinger unref'ing the buffer and the client ref'ing
|
|
||||||
// it.
|
|
||||||
static sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
|
|
||||||
status_t err = graphicBuffer->initCheck();
|
|
||||||
if (err != 0) {
|
|
||||||
LOGE("createGraphicBuffer: init check failed: %d", err);
|
|
||||||
return 0;
|
|
||||||
} else if (graphicBuffer->handle == 0) {
|
|
||||||
LOGE("createGraphicBuffer: unable to create GraphicBuffer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return graphicBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Client::Client(const sp<SurfaceFlinger>& flinger)
|
Client::Client(const sp<SurfaceFlinger>& flinger)
|
||||||
: mFlinger(flinger), mNameGenerator(1)
|
: mFlinger(flinger), mNameGenerator(1)
|
||||||
{
|
{
|
||||||
@ -2465,6 +2451,39 @@ status_t UserClient::setState(int32_t count, const layer_state_t* states) {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
GraphicBufferAlloc::GraphicBufferAlloc() {}
|
||||||
|
|
||||||
|
GraphicBufferAlloc::~GraphicBufferAlloc() {}
|
||||||
|
|
||||||
|
sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
|
||||||
|
PixelFormat format, uint32_t usage) {
|
||||||
|
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
|
||||||
|
status_t err = graphicBuffer->initCheck();
|
||||||
|
if (err != 0) {
|
||||||
|
LOGE("createGraphicBuffer: init check failed: %d", err);
|
||||||
|
return 0;
|
||||||
|
} else if (graphicBuffer->handle == 0) {
|
||||||
|
LOGE("createGraphicBuffer: unable to create GraphicBuffer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
mBuffers.add(graphicBuffer);
|
||||||
|
return graphicBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicBufferAlloc::freeAllGraphicBuffersExcept(int bufIdx) {
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
if (0 <= bufIdx && bufIdx < mBuffers.size()) {
|
||||||
|
sp<GraphicBuffer> b(mBuffers[bufIdx]);
|
||||||
|
mBuffers.clear();
|
||||||
|
mBuffers.add(b);
|
||||||
|
} else {
|
||||||
|
mBuffers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
GraphicPlane::GraphicPlane()
|
GraphicPlane::GraphicPlane()
|
||||||
: mHw(0)
|
: mHw(0)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <ui/PixelFormat.h>
|
#include <ui/PixelFormat.h>
|
||||||
#include <surfaceflinger/ISurfaceComposer.h>
|
#include <surfaceflinger/ISurfaceComposer.h>
|
||||||
#include <surfaceflinger/ISurfaceComposerClient.h>
|
#include <surfaceflinger/ISurfaceComposerClient.h>
|
||||||
|
#include <surfaceflinger/IGraphicBufferAlloc.h>
|
||||||
|
|
||||||
#include "Barrier.h"
|
#include "Barrier.h"
|
||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
@ -119,6 +120,21 @@ private:
|
|||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GraphicBufferAlloc : public BnGraphicBufferAlloc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicBufferAlloc();
|
||||||
|
virtual ~GraphicBufferAlloc();
|
||||||
|
|
||||||
|
virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
||||||
|
PixelFormat format, uint32_t usage);
|
||||||
|
virtual void freeAllGraphicBuffersExcept(int bufIdx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<sp<GraphicBuffer> > mBuffers;
|
||||||
|
Mutex mLock;
|
||||||
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class GraphicPlane
|
class GraphicPlane
|
||||||
@ -184,6 +200,7 @@ public:
|
|||||||
// ISurfaceComposer interface
|
// ISurfaceComposer interface
|
||||||
virtual sp<ISurfaceComposerClient> createConnection();
|
virtual sp<ISurfaceComposerClient> createConnection();
|
||||||
virtual sp<ISurfaceComposerClient> createClientConnection();
|
virtual sp<ISurfaceComposerClient> createClientConnection();
|
||||||
|
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
|
||||||
virtual sp<IMemoryHeap> getCblk() const;
|
virtual sp<IMemoryHeap> getCblk() const;
|
||||||
virtual void bootFinished();
|
virtual void bootFinished();
|
||||||
virtual void openGlobalTransaction();
|
virtual void openGlobalTransaction();
|
||||||
@ -322,8 +339,6 @@ private:
|
|||||||
status_t electronBeamOnAnimationImplLocked();
|
status_t electronBeamOnAnimationImplLocked();
|
||||||
status_t renderScreenToTextureLocked(DisplayID dpy,
|
status_t renderScreenToTextureLocked(DisplayID dpy,
|
||||||
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
|
||||||
sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
|
|
||||||
PixelFormat format, uint32_t usage) const;
|
|
||||||
|
|
||||||
friend class FreezeLock;
|
friend class FreezeLock;
|
||||||
sp<FreezeLock> getFreezeLock() const;
|
sp<FreezeLock> getFreezeLock() const;
|
||||||
|
Loading…
Reference in New Issue
Block a user