replicant-frameworks_native/libs/gui/ISurfaceTexture.cpp
Mathias Agopian c04f153353 Fix a bug where setgeometry couldn't be undone
This change the binder protocol between SurfaceTextureClient
and SurfaceTexture. dequeueBuffer() now takes the requested
parameters for the buffer. SurfaceTexture decides if the
buffer needs to be reallocated and does the allocation
if needed. In that case it returns BUFFER_NEEDS_REALLOCATION
to tell SurfaceTextureClient that it needs to call
requestBuffer (which all parameters have been removed) to
acquire a pointer to the buffer.

dequeueBuffer and requestBuffer could be folded into a single
IPC call, but we chose to optimize the case where buffers are
not created and avoid some complexity in the marshalling code.

Change-Id: I097a7f6f40a3491e10f3f3742eab33999286c304
2011-05-11 18:01:51 -07:00

219 lines
7.1 KiB
C++

/*
* 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.
*/
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
#include <utils/Timers.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>
#include <gui/ISurfaceTexture.h>
namespace android {
// ----------------------------------------------------------------------------
enum {
REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
SET_BUFFER_COUNT,
DEQUEUE_BUFFER,
QUEUE_BUFFER,
CANCEL_BUFFER,
SET_CROP,
SET_TRANSFORM,
GET_ALLOCATOR,
};
class BpSurfaceTexture : public BpInterface<ISurfaceTexture>
{
public:
BpSurfaceTexture(const sp<IBinder>& impl)
: BpInterface<ISurfaceTexture>(impl)
{
}
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) {
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);
}
return buffer;
}
virtual status_t setBufferCount(int bufferCount)
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(bufferCount);
remote()->transact(SET_BUFFER_COUNT, data, &reply);
status_t err = reply.readInt32();
return err;
}
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
uint32_t format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(w);
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
remote()->transact(DEQUEUE_BUFFER, data, &reply);
*buf = reply.readInt32();
int result = reply.readInt32();
return result;
}
virtual status_t queueBuffer(int buf, int64_t timestamp) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
data.writeInt64(timestamp);
remote()->transact(QUEUE_BUFFER, data, &reply);
status_t result = reply.readInt32();
return result;
}
virtual void cancelBuffer(int buf) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
remote()->transact(CANCEL_BUFFER, data, &reply);
}
virtual status_t setCrop(const Rect& reg) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeFloat(reg.left);
data.writeFloat(reg.top);
data.writeFloat(reg.right);
data.writeFloat(reg.bottom);
remote()->transact(SET_CROP, data, &reply);
status_t result = reply.readInt32();
return result;
}
virtual status_t setTransform(uint32_t transform) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(transform);
remote()->transact(SET_TRANSFORM, data, &reply);
status_t result = reply.readInt32();
return result;
}
virtual sp<IBinder> getAllocator() {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
remote()->transact(GET_ALLOCATOR, data, &reply);
return reply.readStrongBinder();
}
};
IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
// ----------------------------------------------------------------------
status_t BnSurfaceTexture::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case REQUEST_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx));
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
}
return NO_ERROR;
} break;
case SET_BUFFER_COUNT: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int bufferCount = data.readInt32();
int result = setBufferCount(bufferCount);
reply->writeInt32(result);
return NO_ERROR;
} break;
case DEQUEUE_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
uint32_t w = data.readInt32();
uint32_t h = data.readInt32();
uint32_t format = data.readInt32();
uint32_t usage = data.readInt32();
int buf;
int result = dequeueBuffer(&buf, w, h, format, usage);
reply->writeInt32(buf);
reply->writeInt32(result);
return NO_ERROR;
} break;
case QUEUE_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int buf = data.readInt32();
int64_t timestamp = data.readInt64();
status_t result = queueBuffer(buf, timestamp);
reply->writeInt32(result);
return NO_ERROR;
} break;
case CANCEL_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int buf = data.readInt32();
cancelBuffer(buf);
return NO_ERROR;
} break;
case SET_CROP: {
Rect reg;
CHECK_INTERFACE(ISurfaceTexture, data, reply);
reg.left = data.readFloat();
reg.top = data.readFloat();
reg.right = data.readFloat();
reg.bottom = data.readFloat();
status_t result = setCrop(reg);
reply->writeInt32(result);
return NO_ERROR;
} break;
case SET_TRANSFORM: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
uint32_t transform = data.readInt32();
status_t result = setTransform(transform);
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;
}
return BBinder::onTransact(code, data, reply, flags);
}
// ----------------------------------------------------------------------------
}; // namespace android