michael@0: /* michael@0: * Copyright (C) 2010 The Android Open Source Project michael@0: * Copyright (C) 2012 Mozilla Foundation 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: #ifndef NATIVEWINDOW_GONKNATIVEWINDOW_ICS_H michael@0: #define NATIVEWINDOW_GONKNATIVEWINDOW_ICS_H michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "CameraCommon.h" michael@0: #include "GrallocImages.h" michael@0: #include "mozilla/layers/LayersSurfaces.h" michael@0: #include "mozilla/layers/TextureClient.h" michael@0: michael@0: namespace android { michael@0: michael@0: // The user of GonkNativeWindow who wants to receive notification of michael@0: // new frames should implement this interface. michael@0: class GonkNativeWindowNewFrameCallback { michael@0: public: michael@0: virtual void OnNewFrame() = 0; michael@0: }; michael@0: michael@0: class GonkNativeWindow : public BnSurfaceTexture michael@0: { michael@0: friend class GonkNativeWindowClient; michael@0: michael@0: typedef mozilla::layers::TextureClient TextureClient; michael@0: michael@0: public: michael@0: enum { MIN_UNDEQUEUED_BUFFERS = 2 }; michael@0: enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS }; michael@0: enum { NUM_BUFFER_SLOTS = 32 }; michael@0: enum { NO_CONNECTED_API = 0 }; michael@0: enum { NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000 }; michael@0: michael@0: GonkNativeWindow(); michael@0: ~GonkNativeWindow(); // this class cannot be overloaded michael@0: michael@0: // Get next frame from the queue and mark it as RENDERING, caller michael@0: // owns the returned buffer. michael@0: mozilla::TemporaryRef getCurrentBuffer(); michael@0: michael@0: // Return the buffer to the queue and mark it as FREE. After that michael@0: // the buffer is useable again for the decoder. michael@0: void returnBuffer(TextureClient* client); michael@0: michael@0: // setBufferCount updates the number of available buffer slots. After michael@0: // calling this all buffer slots are owned by the GonkNativeWindow object michael@0: // (i.e. they are not owned by the client). michael@0: virtual status_t setBufferCount(int bufferCount); michael@0: michael@0: // requestBuffer requests a new buffer for the given index. michael@0: virtual status_t requestBuffer(int slot, sp* buf); michael@0: michael@0: // dequeueBuffer gets the next buffer slot index for the client to use. If a michael@0: // buffer slot is available then that slot index is written to the location michael@0: // pointed to by the buf argument and a status of OK is returned. If no michael@0: // slot is available then a status of -EBUSY is returned and buf is michael@0: // unmodified. michael@0: virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height, michael@0: uint32_t format, uint32_t usage); michael@0: michael@0: // queueBuffer returns a filled buffer to the GonkNativeWindow. In addition, michael@0: // a timestamp must be provided for the buffer. The timestamp is in michael@0: // nanoseconds, and must be monotonically increasing. Its other semantics michael@0: // (zero point, etc) are client-dependent and should be documented by the michael@0: // client. michael@0: virtual status_t queueBuffer(int buf, int64_t timestamp, michael@0: uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); michael@0: virtual void cancelBuffer(int buf); michael@0: virtual status_t setCrop(const Rect& reg); michael@0: virtual status_t setTransform(uint32_t transform); michael@0: virtual status_t setScalingMode(int mode); michael@0: michael@0: virtual int query(int what, int* value); michael@0: michael@0: // Qcom specific function michael@0: virtual int performQcomOperation(int operation, int arg1, int arg2, int arg3) { michael@0: return OK; michael@0: } michael@0: michael@0: // GonkNativeWindow do not implement the function and always works in michael@0: // synchronous mode. michael@0: virtual status_t setSynchronousMode(bool enabled); michael@0: michael@0: // connect attempts to connect a client API to the GonkNativeWindow. michael@0: // michael@0: // This method will fail if the connect was previously called on the michael@0: // GonkNativeWindow and no corresponding disconnect call was made. michael@0: virtual status_t connect(int api, michael@0: uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); michael@0: michael@0: // disconnect attempts to disconnect a client API from the GonkNativeWindow. michael@0: // This method will fail if the the GonkNativeWindow is not currently michael@0: // connected to the specified client API. michael@0: virtual status_t disconnect(int api); michael@0: michael@0: void setNewFrameCallback(GonkNativeWindowNewFrameCallback* aCallback); michael@0: michael@0: // setDefaultBufferSize is used to set the size of buffers returned by michael@0: // requestBuffers when a with and height of zero is requested. michael@0: // A call to setDefaultBufferSize() may trigger requestBuffers() to michael@0: // be called from the client. michael@0: status_t setDefaultBufferSize(uint32_t width, uint32_t height); michael@0: michael@0: // abandon frees all the buffers and puts the GonkNativeWindow into the michael@0: // 'abandoned' state. Once put in this state the GonkNativeWindow can never michael@0: // leave it. When in the 'abandoned' state, all methods of the michael@0: // ISurfaceTexture interface will fail with the NO_INIT error. michael@0: // michael@0: // Note that while calling this method causes all the buffers to be freed michael@0: // from the perspective of the the GonkNativeWindow, if there are additional michael@0: // references on the buffers (e.g. if a buffer is referenced by a client) michael@0: // then those buffer will remain allocated. michael@0: void abandon(); michael@0: michael@0: mozilla::TemporaryRef getTextureClientFromBuffer(ANativeWindowBuffer* buffer); michael@0: michael@0: static void RecycleCallback(TextureClient* client, void* closure); michael@0: michael@0: protected: michael@0: michael@0: // freeAllBuffersLocked frees the resources (both GraphicBuffer and michael@0: // EGLImage) for all slots by removing them from the slots and appending michael@0: // then to the freeList. This must be called with mMutex locked. michael@0: void freeAllBuffersLocked(); michael@0: michael@0: // clearRenderingStateBuffersLocked clear the resources in RENDERING state; michael@0: // But do not destroy the gralloc buffer. It is still in the video stream michael@0: // awaiting rendering. michael@0: // this must be called with mMutex locked. michael@0: void clearRenderingStateBuffersLocked(); michael@0: michael@0: private: michael@0: void init(); michael@0: michael@0: int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; michael@0: michael@0: int getSlotFromTextureClientLocked(TextureClient* client) const; michael@0: michael@0: enum { INVALID_BUFFER_SLOT = -1 }; michael@0: michael@0: struct BufferSlot { michael@0: michael@0: BufferSlot() michael@0: : mBufferState(BufferSlot::FREE), michael@0: mTimestamp(0), michael@0: mFrameNumber(0){ michael@0: } michael@0: michael@0: // mGraphicBuffer points to the buffer allocated for this slot or is NULL michael@0: // if no buffer has been allocated. michael@0: sp mGraphicBuffer; michael@0: michael@0: // mTextureClient is a thin abstraction over remotely allocated GraphicBuffer. michael@0: mozilla::RefPtr mTextureClient; michael@0: michael@0: // BufferState represents the different states in which a buffer slot michael@0: // can be. michael@0: enum BufferState { michael@0: // FREE indicates that the buffer is not currently being used and michael@0: // will not be used in the future until it gets dequeued and michael@0: // subsequently queued by the client. michael@0: FREE = 0, michael@0: michael@0: // DEQUEUED indicates that the buffer has been dequeued by the michael@0: // client, but has not yet been queued or canceled. The buffer is michael@0: // considered 'owned' by the client, and the server should not use michael@0: // it for anything. michael@0: // michael@0: // Note that when in synchronous-mode (mSynchronousMode == true), michael@0: // the buffer that's currently attached to the texture may be michael@0: // dequeued by the client. That means that the current buffer can michael@0: // be in either the DEQUEUED or QUEUED state. In asynchronous mode, michael@0: // however, the current buffer is always in the QUEUED state. michael@0: DEQUEUED = 1, michael@0: michael@0: // QUEUED indicates that the buffer has been queued by the client, michael@0: // and has not since been made available for the client to dequeue. michael@0: // Attaching the buffer to the texture does NOT transition the michael@0: // buffer away from the QUEUED state. However, in Synchronous mode michael@0: // the current buffer may be dequeued by the client under some michael@0: // circumstances. See the note about the current buffer in the michael@0: // documentation for DEQUEUED. michael@0: QUEUED = 2, michael@0: michael@0: // RENDERING indicates that the buffer has been sent to michael@0: // the compositor, and has not yet available for the michael@0: // client to dequeue. When the compositor has finished its michael@0: // job, the buffer will be returned to FREE state. michael@0: RENDERING = 3, michael@0: }; michael@0: michael@0: // mBufferState is the current state of this buffer slot. michael@0: BufferState mBufferState; michael@0: michael@0: // mRequestBufferCalled is used for validating that the client did michael@0: // call requestBuffer() when told to do so. Technically this is not michael@0: // needed but useful for debugging and catching client bugs. michael@0: bool mRequestBufferCalled; michael@0: michael@0: // mTimestamp is the current timestamp for this buffer slot. This gets michael@0: // to set by queueBuffer each time this slot is queued. michael@0: int64_t mTimestamp; michael@0: michael@0: // mFrameNumber is the number of the queued frame for this slot. michael@0: uint64_t mFrameNumber; michael@0: }; michael@0: michael@0: // mSlots is the array of buffer slots that must be mirrored on the client michael@0: // side. This allows buffer ownership to be transferred between the client michael@0: // and server without sending a GraphicBuffer over binder. The entire array michael@0: // is initialized to NULL at construction time, and buffers are allocated michael@0: // for a slot when requestBuffer is called with that slot's index. michael@0: BufferSlot mSlots[NUM_BUFFER_SLOTS]; michael@0: michael@0: // mDequeueCondition condition used for dequeueBuffer in synchronous mode michael@0: mutable Condition mDequeueCondition; michael@0: michael@0: // mAbandoned indicates that the GonkNativeWindow will no longer be used to michael@0: // consume buffers pushed to it. michael@0: // It is initialized to false, and set to true in the abandon method. A michael@0: // GonkNativeWindow that has been abandoned will return the NO_INIT error michael@0: // from all control methods capable of returning an error. michael@0: bool mAbandoned; michael@0: michael@0: // mTimestamp is the timestamp that will be used for the next buffer queue michael@0: // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that michael@0: // a timestamp is auto-generated when queueBuffer is called. michael@0: int64_t mTimestamp; michael@0: michael@0: // mDefaultWidth holds the default width of allocated buffers. It is used michael@0: // in requestBuffers() if a width and height of zero is specified. michael@0: uint32_t mDefaultWidth; michael@0: michael@0: // mDefaultHeight holds the default height of allocated buffers. It is used michael@0: // in requestBuffers() if a width and height of zero is specified. michael@0: uint32_t mDefaultHeight; michael@0: michael@0: // mPixelFormat holds the pixel format of allocated buffers. It is used michael@0: // in requestBuffers() if a format of zero is specified. michael@0: uint32_t mPixelFormat; michael@0: michael@0: // mBufferCount is the number of buffer slots that the client and server michael@0: // must maintain. It defaults to MIN_BUFFER_SLOTS + 1 and can be changed michael@0: // by calling setBufferCount or setBufferCountServer michael@0: int mBufferCount; michael@0: michael@0: // mConnectedApi indicates the API that is currently connected to this michael@0: // GonkNativeWindow. It defaults to NO_CONNECTED_API (= 0), and gets updated michael@0: // by the connect and disconnect methods. michael@0: int mConnectedApi; michael@0: michael@0: // mQueue is a FIFO of queued buffers used in synchronous mode michael@0: // GonkNativeWindow always works in synchronous mode michael@0: typedef Vector Fifo; michael@0: Fifo mQueue; michael@0: michael@0: // mMutex is the mutex used to prevent concurrent access to the member michael@0: // variables of GonkNativeWindow objects. It must be locked whenever the michael@0: // member variables are accessed. michael@0: mutable Mutex mMutex; michael@0: michael@0: // mFrameCounter is the free running counter, incremented for every buffer queued michael@0: uint64_t mFrameCounter; michael@0: michael@0: GonkNativeWindowNewFrameCallback* mNewFrameCallback; michael@0: }; michael@0: michael@0: }; // namespace android michael@0: michael@0: #endif // NATIVEWINDOW_GONKNATIVEWINDOW_ICS_H