michael@0: /* michael@0: * Copyright (C) 2013 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #define EGL_EGLEXT_PROTOTYPES michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: #include "IGonkGraphicBufferConsumer.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: michael@0: namespace android { michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: IGonkGraphicBufferConsumer::BufferItem::BufferItem() : michael@0: mTransform(0), michael@0: mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), michael@0: mTimestamp(0), michael@0: mIsAutoTimestamp(false), michael@0: mFrameNumber(0), michael@0: mBuf(INVALID_BUFFER_SLOT), michael@0: mIsDroppable(false), michael@0: mAcquireCalled(false), michael@0: mTransformToDisplayInverse(false) { michael@0: mCrop.makeInvalid(); michael@0: } michael@0: michael@0: size_t IGonkGraphicBufferConsumer::BufferItem::getPodSize() const { michael@0: size_t c = sizeof(mCrop) + michael@0: sizeof(mTransform) + michael@0: sizeof(mScalingMode) + michael@0: sizeof(mTimestamp) + michael@0: sizeof(mIsAutoTimestamp) + michael@0: sizeof(mFrameNumber) + michael@0: sizeof(mBuf) + michael@0: sizeof(mIsDroppable) + michael@0: sizeof(mAcquireCalled) + michael@0: sizeof(mTransformToDisplayInverse); michael@0: return c; michael@0: } michael@0: michael@0: size_t IGonkGraphicBufferConsumer::BufferItem::getFlattenedSize() const { michael@0: size_t c = 0; michael@0: if (mGraphicBuffer != 0) { michael@0: c += mGraphicBuffer->getFlattenedSize(); michael@0: FlattenableUtils::align<4>(c); michael@0: } michael@0: if (mFence != 0) { michael@0: c += mFence->getFlattenedSize(); michael@0: FlattenableUtils::align<4>(c); michael@0: } michael@0: return sizeof(int32_t) + c + getPodSize(); michael@0: } michael@0: michael@0: size_t IGonkGraphicBufferConsumer::BufferItem::getFdCount() const { michael@0: size_t c = 0; michael@0: if (mGraphicBuffer != 0) { michael@0: c += mGraphicBuffer->getFdCount(); michael@0: } michael@0: if (mFence != 0) { michael@0: c += mFence->getFdCount(); michael@0: } michael@0: return c; michael@0: } michael@0: michael@0: status_t IGonkGraphicBufferConsumer::BufferItem::flatten( michael@0: void*& buffer, size_t& size, int*& fds, size_t& count) const { michael@0: michael@0: // make sure we have enough space michael@0: if (count < BufferItem::getFlattenedSize()) { michael@0: return NO_MEMORY; michael@0: } michael@0: michael@0: // content flags are stored first michael@0: uint32_t& flags = *static_cast(buffer); michael@0: michael@0: // advance the pointer michael@0: FlattenableUtils::advance(buffer, size, sizeof(uint32_t)); michael@0: michael@0: flags = 0; michael@0: if (mGraphicBuffer != 0) { michael@0: status_t err = mGraphicBuffer->flatten(buffer, size, fds, count); michael@0: if (err) return err; michael@0: size -= FlattenableUtils::align<4>(buffer); michael@0: flags |= 1; michael@0: } michael@0: if (mFence != 0) { michael@0: status_t err = mFence->flatten(buffer, size, fds, count); michael@0: if (err) return err; michael@0: size -= FlattenableUtils::align<4>(buffer); michael@0: flags |= 2; michael@0: } michael@0: michael@0: // check we have enough space (in case flattening the fence/graphicbuffer lied to us) michael@0: if (size < getPodSize()) { michael@0: return NO_MEMORY; michael@0: } michael@0: michael@0: FlattenableUtils::write(buffer, size, mCrop); michael@0: FlattenableUtils::write(buffer, size, mTransform); michael@0: FlattenableUtils::write(buffer, size, mScalingMode); michael@0: FlattenableUtils::write(buffer, size, mTimestamp); michael@0: FlattenableUtils::write(buffer, size, mIsAutoTimestamp); michael@0: FlattenableUtils::write(buffer, size, mFrameNumber); michael@0: FlattenableUtils::write(buffer, size, mBuf); michael@0: FlattenableUtils::write(buffer, size, mIsDroppable); michael@0: FlattenableUtils::write(buffer, size, mAcquireCalled); michael@0: FlattenableUtils::write(buffer, size, mTransformToDisplayInverse); michael@0: michael@0: return NO_ERROR; michael@0: } michael@0: michael@0: status_t IGonkGraphicBufferConsumer::BufferItem::unflatten( michael@0: void const*& buffer, size_t& size, int const*& fds, size_t& count) { michael@0: michael@0: if (size < sizeof(uint32_t)) michael@0: return NO_MEMORY; michael@0: michael@0: uint32_t flags = 0; michael@0: FlattenableUtils::read(buffer, size, flags); michael@0: michael@0: if (flags & 1) { michael@0: mGraphicBuffer = new GraphicBuffer(); michael@0: status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count); michael@0: if (err) return err; michael@0: size -= FlattenableUtils::align<4>(buffer); michael@0: } michael@0: michael@0: if (flags & 2) { michael@0: mFence = new Fence(); michael@0: status_t err = mFence->unflatten(buffer, size, fds, count); michael@0: if (err) return err; michael@0: size -= FlattenableUtils::align<4>(buffer); michael@0: } michael@0: michael@0: // check we have enough space michael@0: if (size < getPodSize()) { michael@0: return NO_MEMORY; michael@0: } michael@0: michael@0: FlattenableUtils::read(buffer, size, mCrop); michael@0: FlattenableUtils::read(buffer, size, mTransform); michael@0: FlattenableUtils::read(buffer, size, mScalingMode); michael@0: FlattenableUtils::read(buffer, size, mTimestamp); michael@0: FlattenableUtils::read(buffer, size, mIsAutoTimestamp); michael@0: FlattenableUtils::read(buffer, size, mFrameNumber); michael@0: FlattenableUtils::read(buffer, size, mBuf); michael@0: FlattenableUtils::read(buffer, size, mIsDroppable); michael@0: FlattenableUtils::read(buffer, size, mAcquireCalled); michael@0: FlattenableUtils::read(buffer, size, mTransformToDisplayInverse); michael@0: michael@0: return NO_ERROR; michael@0: } michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: enum { michael@0: ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION, michael@0: RELEASE_BUFFER, michael@0: CONSUMER_CONNECT, michael@0: CONSUMER_DISCONNECT, michael@0: GET_RELEASED_BUFFERS, michael@0: SET_DEFAULT_BUFFER_SIZE, michael@0: SET_DEFAULT_MAX_BUFFER_COUNT, michael@0: DISABLE_ASYNC_BUFFER, michael@0: SET_MAX_ACQUIRED_BUFFER_COUNT, michael@0: SET_CONSUMER_NAME, michael@0: SET_DEFAULT_BUFFER_FORMAT, michael@0: SET_CONSUMER_USAGE_BITS, michael@0: SET_TRANSFORM_HINT, michael@0: DUMP, michael@0: }; michael@0: michael@0: class BpGonkGraphicBufferConsumer : public BpInterface michael@0: { michael@0: public: michael@0: BpGonkGraphicBufferConsumer(const sp& impl) michael@0: : BpInterface(impl) michael@0: { michael@0: } michael@0: michael@0: virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt64(presentWhen); michael@0: status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: result = reply.read(*buffer); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t releaseBuffer(int buf, uint64_t frameNumber, michael@0: const sp& releaseFence) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(buf); michael@0: data.writeInt64(frameNumber); michael@0: data.write(*releaseFence); michael@0: status_t result = remote()->transact(RELEASE_BUFFER, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t consumerConnect(const sp& consumer, bool controlledByApp) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeStrongBinder(consumer->asBinder()); michael@0: data.writeInt32(controlledByApp); michael@0: status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t consumerDisconnect() { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t getReleasedBuffers(uint32_t* slotMask) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: *slotMask = reply.readInt32(); michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(w); michael@0: data.writeInt32(h); michael@0: status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t setDefaultMaxBufferCount(int bufferCount) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(bufferCount); michael@0: status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t disableAsyncBuffer() { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(maxAcquiredBuffers); michael@0: status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual void setConsumerName(const String8& name) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeString8(name); michael@0: remote()->transact(SET_CONSUMER_NAME, data, &reply); michael@0: } michael@0: michael@0: virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(defaultFormat); michael@0: status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t setConsumerUsageBits(uint32_t usage) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(usage); michael@0: status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual status_t setTransformHint(uint32_t hint) { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeInt32(hint); michael@0: status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply); michael@0: if (result != NO_ERROR) { michael@0: return result; michael@0: } michael@0: return reply.readInt32(); michael@0: } michael@0: michael@0: virtual void dump(String8& result, const char* prefix) const { michael@0: Parcel data, reply; michael@0: data.writeInterfaceToken(IGonkGraphicBufferConsumer::getInterfaceDescriptor()); michael@0: data.writeString8(result); michael@0: data.writeString8(String8(prefix ? prefix : "")); michael@0: remote()->transact(DUMP, data, &reply); michael@0: reply.readString8(); michael@0: } michael@0: }; michael@0: michael@0: IMPLEMENT_META_INTERFACE(GonkGraphicBufferConsumer, "android.gui.IGonkGraphicBufferConsumer"); michael@0: // ---------------------------------------------------------------------- michael@0: michael@0: status_t BnGonkGraphicBufferConsumer::onTransact( michael@0: uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) michael@0: { michael@0: switch(code) { michael@0: case ACQUIRE_BUFFER: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: BufferItem item; michael@0: int64_t presentWhen = data.readInt64(); michael@0: status_t result = acquireBuffer(&item, presentWhen); michael@0: status_t err = reply->write(item); michael@0: if (err) return err; michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case RELEASE_BUFFER: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: int buf = data.readInt32(); michael@0: uint64_t frameNumber = data.readInt64(); michael@0: sp releaseFence = new Fence(); michael@0: status_t err = data.read(*releaseFence); michael@0: if (err) return err; michael@0: status_t result = releaseBuffer(buf, frameNumber, releaseFence); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: michael@0: case CONSUMER_CONNECT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: sp consumer = IConsumerListener::asInterface( data.readStrongBinder() ); michael@0: bool controlledByApp = data.readInt32(); michael@0: status_t result = consumerConnect(consumer, controlledByApp); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: michael@0: case CONSUMER_DISCONNECT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: status_t result = consumerDisconnect(); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case GET_RELEASED_BUFFERS: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t slotMask; michael@0: status_t result = getReleasedBuffers(&slotMask); michael@0: reply->writeInt32(slotMask); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_DEFAULT_BUFFER_SIZE: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t w = data.readInt32(); michael@0: uint32_t h = data.readInt32(); michael@0: status_t result = setDefaultBufferSize(w, h); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_DEFAULT_MAX_BUFFER_COUNT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t bufferCount = data.readInt32(); michael@0: status_t result = setDefaultMaxBufferCount(bufferCount); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case DISABLE_ASYNC_BUFFER: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: status_t result = disableAsyncBuffer(); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_MAX_ACQUIRED_BUFFER_COUNT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t maxAcquiredBuffers = data.readInt32(); michael@0: status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_CONSUMER_NAME: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: setConsumerName( data.readString8() ); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_DEFAULT_BUFFER_FORMAT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t defaultFormat = data.readInt32(); michael@0: status_t result = setDefaultBufferFormat(defaultFormat); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_CONSUMER_USAGE_BITS: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t usage = data.readInt32(); michael@0: status_t result = setConsumerUsageBits(usage); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: case SET_TRANSFORM_HINT: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: uint32_t hint = data.readInt32(); michael@0: status_t result = setTransformHint(hint); michael@0: reply->writeInt32(result); michael@0: return NO_ERROR; michael@0: } break; michael@0: michael@0: case DUMP: { michael@0: CHECK_INTERFACE(IGonkGraphicBufferConsumer, data, reply); michael@0: String8 result = data.readString8(); michael@0: String8 prefix = data.readString8(); michael@0: static_cast(this)->dump(result, prefix); michael@0: reply->writeString8(result); michael@0: return NO_ERROR; michael@0: } michael@0: } michael@0: return BBinder::onTransact(code, data, reply, flags); michael@0: } michael@0: michael@0: }; // namespace android