|
1 /* |
|
2 * Copyright (C) 2012 The Android Open Source Project |
|
3 * Copyright (C) 2013 Mozilla Foundation |
|
4 * |
|
5 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 * you may not use this file except in compliance with the License. |
|
7 * You may obtain a copy of the License at |
|
8 * |
|
9 * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 * |
|
11 * Unless required by applicable law or agreed to in writing, software |
|
12 * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 * See the License for the specific language governing permissions and |
|
15 * limitations under the License. |
|
16 */ |
|
17 |
|
18 //#define LOG_NDEBUG 0 |
|
19 #define LOG_TAG "GonkNativeWindow" |
|
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS |
|
21 #include <utils/Log.h> |
|
22 |
|
23 #include "GonkNativeWindowJB.h" |
|
24 #include "GrallocImages.h" |
|
25 #include "mozilla/layers/ImageBridgeChild.h" |
|
26 #include "mozilla/RefPtr.h" |
|
27 |
|
28 #define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) |
|
29 #define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) |
|
30 #define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) |
|
31 #define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) |
|
32 #define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) |
|
33 |
|
34 using namespace mozilla; |
|
35 using namespace mozilla::layers; |
|
36 |
|
37 namespace android { |
|
38 |
|
39 GonkNativeWindow::GonkNativeWindow() : |
|
40 GonkConsumerBase(new GonkBufferQueue(true) ) |
|
41 { |
|
42 mBufferQueue->setMaxAcquiredBufferCount(GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS); |
|
43 } |
|
44 |
|
45 GonkNativeWindow::~GonkNativeWindow() { |
|
46 } |
|
47 |
|
48 void GonkNativeWindow::setName(const String8& name) { |
|
49 Mutex::Autolock _l(mMutex); |
|
50 mName = name; |
|
51 mBufferQueue->setConsumerName(name); |
|
52 } |
|
53 #if ANDROID_VERSION >= 18 |
|
54 status_t GonkNativeWindow::acquireBuffer(BufferItem *item, bool waitForFence) { |
|
55 status_t err; |
|
56 |
|
57 if (!item) return BAD_VALUE; |
|
58 |
|
59 Mutex::Autolock _l(mMutex); |
|
60 |
|
61 err = acquireBufferLocked(item); |
|
62 if (err != OK) { |
|
63 if (err != NO_BUFFER_AVAILABLE) { |
|
64 BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); |
|
65 } |
|
66 return err; |
|
67 } |
|
68 |
|
69 if (waitForFence) { |
|
70 err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); |
|
71 if (err != OK) { |
|
72 BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", |
|
73 strerror(-err), err); |
|
74 return err; |
|
75 } |
|
76 } |
|
77 |
|
78 item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; |
|
79 |
|
80 return OK; |
|
81 } |
|
82 |
|
83 status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, |
|
84 const sp<Fence>& releaseFence) { |
|
85 status_t err; |
|
86 |
|
87 Mutex::Autolock _l(mMutex); |
|
88 |
|
89 err = addReleaseFenceLocked(item.mBuf, releaseFence); |
|
90 |
|
91 err = releaseBufferLocked(item.mBuf); |
|
92 if (err != OK) { |
|
93 BI_LOGE("Failed to release buffer: %s (%d)", |
|
94 strerror(-err), err); |
|
95 } |
|
96 return err; |
|
97 } |
|
98 #endif |
|
99 |
|
100 status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { |
|
101 Mutex::Autolock _l(mMutex); |
|
102 return mBufferQueue->setDefaultBufferSize(w, h); |
|
103 } |
|
104 |
|
105 status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { |
|
106 Mutex::Autolock _l(mMutex); |
|
107 return mBufferQueue->setDefaultBufferFormat(defaultFormat); |
|
108 } |
|
109 |
|
110 TemporaryRef<TextureClient> |
|
111 GonkNativeWindow::getCurrentBuffer() { |
|
112 Mutex::Autolock _l(mMutex); |
|
113 GonkBufferQueue::BufferItem item; |
|
114 |
|
115 // In asynchronous mode the list is guaranteed to be one buffer |
|
116 // deep, while in synchronous mode we use the oldest buffer. |
|
117 status_t err = acquireBufferLocked(&item); |
|
118 if (err != NO_ERROR) { |
|
119 return NULL; |
|
120 } |
|
121 |
|
122 RefPtr<TextureClient> textureClient = |
|
123 mBufferQueue->getTextureClientFromBuffer(item.mGraphicBuffer.get()); |
|
124 if (!textureClient) { |
|
125 return NULL; |
|
126 } |
|
127 textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); |
|
128 return textureClient; |
|
129 } |
|
130 |
|
131 /* static */ void |
|
132 GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { |
|
133 GonkNativeWindow* nativeWindow = |
|
134 static_cast<GonkNativeWindow*>(closure); |
|
135 |
|
136 client->ClearRecycleCallback(); |
|
137 nativeWindow->returnBuffer(client); |
|
138 } |
|
139 |
|
140 void GonkNativeWindow::returnBuffer(TextureClient* client) { |
|
141 BI_LOGD("GonkNativeWindow::returnBuffer"); |
|
142 Mutex::Autolock lock(mMutex); |
|
143 |
|
144 int index = mBufferQueue->getSlotFromTextureClientLocked(client); |
|
145 if (index < 0) { |
|
146 } |
|
147 |
|
148 sp<Fence> fence = client->GetReleaseFenceHandle().mFence; |
|
149 if (!fence.get()) { |
|
150 fence = Fence::NO_FENCE; |
|
151 } |
|
152 |
|
153 status_t err; |
|
154 err = addReleaseFenceLocked(index, fence); |
|
155 |
|
156 err = releaseBufferLocked(index); |
|
157 } |
|
158 |
|
159 TemporaryRef<TextureClient> |
|
160 GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { |
|
161 Mutex::Autolock lock(mMutex); |
|
162 return mBufferQueue->getTextureClientFromBuffer(buffer); |
|
163 } |
|
164 |
|
165 void GonkNativeWindow::setNewFrameCallback( |
|
166 GonkNativeWindowNewFrameCallback* callback) { |
|
167 BI_LOGD("setNewFrameCallback"); |
|
168 Mutex::Autolock lock(mMutex); |
|
169 mNewFrameCallback = callback; |
|
170 } |
|
171 |
|
172 void GonkNativeWindow::onFrameAvailable() { |
|
173 GonkConsumerBase::onFrameAvailable(); |
|
174 |
|
175 if (mNewFrameCallback) { |
|
176 mNewFrameCallback->OnNewFrame(); |
|
177 } |
|
178 } |
|
179 |
|
180 } // namespace android |