|
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 "GonkNativeWindowKK.h" |
|
24 #include "GrallocImages.h" |
|
25 |
|
26 #define BI_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) |
|
27 #define BI_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) |
|
28 #define BI_LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) |
|
29 #define BI_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) |
|
30 #define BI_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) |
|
31 |
|
32 using namespace mozilla; |
|
33 using namespace mozilla::layers; |
|
34 |
|
35 namespace android { |
|
36 |
|
37 GonkNativeWindow::GonkNativeWindow() : |
|
38 GonkConsumerBase(new GonkBufferQueue(true), false) |
|
39 { |
|
40 mConsumer->setMaxAcquiredBufferCount(GonkBufferQueue::MIN_UNDEQUEUED_BUFFERS); |
|
41 } |
|
42 |
|
43 GonkNativeWindow::GonkNativeWindow(const sp<GonkBufferQueue>& bq, |
|
44 uint32_t consumerUsage, int bufferCount, bool controlledByApp) : |
|
45 GonkConsumerBase(bq, controlledByApp) |
|
46 { |
|
47 mConsumer->setConsumerUsageBits(consumerUsage); |
|
48 mConsumer->setMaxAcquiredBufferCount(bufferCount); |
|
49 } |
|
50 |
|
51 GonkNativeWindow::~GonkNativeWindow() { |
|
52 } |
|
53 |
|
54 void GonkNativeWindow::setName(const String8& name) { |
|
55 Mutex::Autolock _l(mMutex); |
|
56 mName = name; |
|
57 mConsumer->setConsumerName(name); |
|
58 } |
|
59 |
|
60 status_t GonkNativeWindow::acquireBuffer(BufferItem *item, |
|
61 nsecs_t presentWhen, bool waitForFence) { |
|
62 status_t err; |
|
63 |
|
64 if (!item) return BAD_VALUE; |
|
65 |
|
66 Mutex::Autolock _l(mMutex); |
|
67 |
|
68 err = acquireBufferLocked(item, presentWhen); |
|
69 if (err != OK) { |
|
70 if (err != NO_BUFFER_AVAILABLE) { |
|
71 BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); |
|
72 } |
|
73 return err; |
|
74 } |
|
75 |
|
76 if (waitForFence) { |
|
77 err = item->mFence->waitForever("GonkNativeWindow::acquireBuffer"); |
|
78 if (err != OK) { |
|
79 BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)", |
|
80 strerror(-err), err); |
|
81 return err; |
|
82 } |
|
83 } |
|
84 |
|
85 item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer; |
|
86 |
|
87 return OK; |
|
88 } |
|
89 |
|
90 status_t GonkNativeWindow::releaseBuffer(const BufferItem &item, |
|
91 const sp<Fence>& releaseFence) { |
|
92 status_t err; |
|
93 |
|
94 Mutex::Autolock _l(mMutex); |
|
95 |
|
96 err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence); |
|
97 |
|
98 err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer); |
|
99 if (err != OK) { |
|
100 BI_LOGE("Failed to release buffer: %s (%d)", |
|
101 strerror(-err), err); |
|
102 } |
|
103 return err; |
|
104 } |
|
105 |
|
106 status_t GonkNativeWindow::setDefaultBufferSize(uint32_t w, uint32_t h) { |
|
107 Mutex::Autolock _l(mMutex); |
|
108 return mConsumer->setDefaultBufferSize(w, h); |
|
109 } |
|
110 |
|
111 status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) { |
|
112 Mutex::Autolock _l(mMutex); |
|
113 return mConsumer->setDefaultBufferFormat(defaultFormat); |
|
114 } |
|
115 |
|
116 TemporaryRef<TextureClient> |
|
117 GonkNativeWindow::getCurrentBuffer() { |
|
118 Mutex::Autolock _l(mMutex); |
|
119 BufferItem item; |
|
120 |
|
121 // In asynchronous mode the list is guaranteed to be one buffer |
|
122 // deep, while in synchronous mode we use the oldest buffer. |
|
123 status_t err = acquireBufferLocked(&item, 0); //??? |
|
124 if (err != NO_ERROR) { |
|
125 return NULL; |
|
126 } |
|
127 |
|
128 RefPtr<TextureClient> textureClient = |
|
129 mConsumer->getTextureClientFromBuffer(item.mGraphicBuffer.get()); |
|
130 if (!textureClient) { |
|
131 return NULL; |
|
132 } |
|
133 textureClient->SetRecycleCallback(GonkNativeWindow::RecycleCallback, this); |
|
134 return textureClient; |
|
135 } |
|
136 |
|
137 /* static */ void |
|
138 GonkNativeWindow::RecycleCallback(TextureClient* client, void* closure) { |
|
139 GonkNativeWindow* nativeWindow = |
|
140 static_cast<GonkNativeWindow*>(closure); |
|
141 |
|
142 client->ClearRecycleCallback(); |
|
143 nativeWindow->returnBuffer(client); |
|
144 } |
|
145 |
|
146 void GonkNativeWindow::returnBuffer(TextureClient* client) { |
|
147 BI_LOGD("GonkNativeWindow::returnBuffer"); |
|
148 Mutex::Autolock lock(mMutex); |
|
149 |
|
150 int index = mConsumer->getSlotFromTextureClientLocked(client); |
|
151 if (index < 0) { |
|
152 } |
|
153 |
|
154 sp<Fence> fence = client->GetReleaseFenceHandle().mFence; |
|
155 if (!fence.get()) { |
|
156 fence = Fence::NO_FENCE; |
|
157 } |
|
158 |
|
159 status_t err; |
|
160 err = addReleaseFenceLocked(index, |
|
161 mSlots[index].mGraphicBuffer, |
|
162 fence); |
|
163 |
|
164 err = releaseBufferLocked(index, mSlots[index].mGraphicBuffer); |
|
165 } |
|
166 |
|
167 TemporaryRef<TextureClient> |
|
168 GonkNativeWindow::getTextureClientFromBuffer(ANativeWindowBuffer* buffer) { |
|
169 Mutex::Autolock lock(mMutex); |
|
170 return mConsumer->getTextureClientFromBuffer(buffer); |
|
171 } |
|
172 |
|
173 void GonkNativeWindow::setNewFrameCallback( |
|
174 GonkNativeWindowNewFrameCallback* callback) { |
|
175 BI_LOGD("setNewFrameCallback"); |
|
176 Mutex::Autolock lock(mMutex); |
|
177 mNewFrameCallback = callback; |
|
178 } |
|
179 |
|
180 void GonkNativeWindow::onFrameAvailable() { |
|
181 GonkConsumerBase::onFrameAvailable(); |
|
182 |
|
183 if (mNewFrameCallback) { |
|
184 mNewFrameCallback->OnNewFrame(); |
|
185 } |
|
186 } |
|
187 |
|
188 } // namespace android |