1d01a12e71
API addition: The timestamps are represented as nanoseconds from some arbitrary time point. Like the SurfaceTexture transform matrix, the timestamp retrieved by getTimestamp is for the last frame sent to the GL texture using updateTexImage(). Camera HAL change: Expect vendors to set these timestamps using native_window_set_buffers_timestamp(). For now, they are autogenerated by SurfaceTextureClient if set_buffers_timestamp() is never called, but such timing is likely not accurate enough to pass a CTS test. bug:3300707 Change-Id: Ife131a0c2a826ac27342e11b8a6c42ff49e1bea7
220 lines
7.1 KiB
C++
220 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,
|
|
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
|
|
Parcel data, reply;
|
|
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
|
|
data.writeInt32(bufferIdx);
|
|
data.writeInt32(w);
|
|
data.writeInt32(h);
|
|
data.writeInt32(format);
|
|
data.writeInt32(usage);
|
|
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) {
|
|
Parcel data, reply;
|
|
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
|
|
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();
|
|
uint32_t w = data.readInt32();
|
|
uint32_t h = data.readInt32();
|
|
uint32_t format = data.readInt32();
|
|
uint32_t usage = data.readInt32();
|
|
sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
|
|
usage));
|
|
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);
|
|
int buf;
|
|
int result = dequeueBuffer(&buf);
|
|
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
|