Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /*
2 * Copyright (C) 2010 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 */
18 #define LOG_TAG "GonkNativeWindowClient"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 //#define LOG_NDEBUG 0
22 #include <android/native_window.h>
23 #if ANDROID_VERSION == 17
24 #include <utils/Trace.h>
25 #else
26 #include <cutils/trace.h>
27 #endif
29 #include <binder/Parcel.h>
30 #include <utils/Log.h>
31 #include <ui/Fence.h>
33 #include "GonkNativeWindowClientJB.h"
35 namespace android {
37 GonkNativeWindowClient::GonkNativeWindowClient(
38 const sp<IGraphicBufferProducer>& bufferProducer)
39 : mBufferProducer(bufferProducer)
40 {
41 // Initialize the ANativeWindow function pointers.
42 ANativeWindow::setSwapInterval = hook_setSwapInterval;
43 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
44 ANativeWindow::cancelBuffer = hook_cancelBuffer;
45 ANativeWindow::queueBuffer = hook_queueBuffer;
46 ANativeWindow::query = hook_query;
47 ANativeWindow::perform = hook_perform;
49 ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
50 ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
51 ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
52 ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
54 const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
55 const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
57 mReqWidth = 0;
58 mReqHeight = 0;
59 mReqFormat = 0;
60 mReqUsage = 0;
61 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
62 mCrop.clear();
63 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
64 mTransform = 0;
65 mDefaultWidth = 0;
66 mDefaultHeight = 0;
67 mUserWidth = 0;
68 mUserHeight = 0;
69 mTransformHint = 0;
70 mConsumerRunningBehind = false;
71 mConnectedToCpu = false;
72 }
74 GonkNativeWindowClient::~GonkNativeWindowClient() {
75 if (mConnectedToCpu) {
76 GonkNativeWindowClient::disconnect(NATIVE_WINDOW_API_CPU);
77 }
78 }
80 #if ANDROID_VERSION == 17
81 sp<IGraphicBufferProducer> GonkNativeWindowClient::getISurfaceTexture() const {
82 #else
83 sp<IGraphicBufferProducer> GonkNativeWindowClient::getIGraphicBufferProducer() const {
84 #endif
85 return mBufferProducer;
86 }
88 int GonkNativeWindowClient::hook_setSwapInterval(ANativeWindow* window, int interval) {
89 GonkNativeWindowClient* c = getSelf(window);
90 return c->setSwapInterval(interval);
91 }
93 int GonkNativeWindowClient::hook_dequeueBuffer(ANativeWindow* window,
94 ANativeWindowBuffer** buffer, int* fenceFd) {
95 GonkNativeWindowClient* c = getSelf(window);
96 return c->dequeueBuffer(buffer, fenceFd);
97 }
99 int GonkNativeWindowClient::hook_cancelBuffer(ANativeWindow* window,
100 ANativeWindowBuffer* buffer, int fenceFd) {
101 GonkNativeWindowClient* c = getSelf(window);
102 return c->cancelBuffer(buffer, fenceFd);
103 }
105 int GonkNativeWindowClient::hook_queueBuffer(ANativeWindow* window,
106 ANativeWindowBuffer* buffer, int fenceFd) {
107 GonkNativeWindowClient* c = getSelf(window);
108 return c->queueBuffer(buffer, fenceFd);
109 }
111 int GonkNativeWindowClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
112 ANativeWindowBuffer** buffer) {
113 GonkNativeWindowClient* c = getSelf(window);
114 ANativeWindowBuffer* buf;
115 int fenceFd = -1;
116 int result = c->dequeueBuffer(&buf, &fenceFd);
117 sp<Fence> fence(new Fence(fenceFd));
118 #if ANDROID_VERSION == 17
119 int waitResult = fence->waitForever(1000, "dequeueBuffer_DEPRECATED");
120 #else
121 int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
122 #endif
123 if (waitResult != OK) {
124 ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
125 waitResult);
126 c->cancelBuffer(buf, -1);
127 return waitResult;
128 }
129 *buffer = buf;
130 return result;
131 }
133 int GonkNativeWindowClient::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
134 ANativeWindowBuffer* buffer) {
135 GonkNativeWindowClient* c = getSelf(window);
136 return c->cancelBuffer(buffer, -1);
137 }
139 int GonkNativeWindowClient::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
140 ANativeWindowBuffer* buffer) {
141 GonkNativeWindowClient* c = getSelf(window);
142 return c->lockBuffer_DEPRECATED(buffer);
143 }
145 int GonkNativeWindowClient::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
146 ANativeWindowBuffer* buffer) {
147 GonkNativeWindowClient* c = getSelf(window);
148 return c->queueBuffer(buffer, -1);
149 }
151 int GonkNativeWindowClient::hook_query(const ANativeWindow* window,
152 int what, int* value) {
153 const GonkNativeWindowClient* c = getSelf(window);
154 return c->query(what, value);
155 }
157 int GonkNativeWindowClient::hook_perform(ANativeWindow* window, int operation, ...) {
158 va_list args;
159 va_start(args, operation);
160 GonkNativeWindowClient* c = getSelf(window);
161 return c->perform(operation, args);
162 }
164 int GonkNativeWindowClient::setSwapInterval(int interval) {
165 // EGL specification states:
166 // interval is silently clamped to minimum and maximum implementation
167 // dependent values before being stored.
168 // Although we don't have to, we apply the same logic here.
170 if (interval < minSwapInterval)
171 interval = minSwapInterval;
173 if (interval > maxSwapInterval)
174 interval = maxSwapInterval;
176 status_t res = mBufferProducer->setSynchronousMode(interval ? true : false);
178 return res;
179 }
181 int GonkNativeWindowClient::dequeueBuffer(android_native_buffer_t** buffer,
182 int* fenceFd) {
183 ALOGV("GonkNativeWindowClient::dequeueBuffer");
184 Mutex::Autolock lock(mMutex);
185 int buf = -1;
186 int reqW = mReqWidth ? mReqWidth : mUserWidth;
187 int reqH = mReqHeight ? mReqHeight : mUserHeight;
188 sp<Fence> fence;
189 #if ANDROID_VERSION == 17
190 status_t result = mBufferProducer->dequeueBuffer(&buf, fence,
191 reqW, reqH, mReqFormat, mReqUsage);
192 #else
193 status_t result = mBufferProducer->dequeueBuffer(&buf, &fence,
194 reqW, reqH, mReqFormat, mReqUsage);
195 #endif
197 if (result < 0) {
198 ALOGV("dequeueBuffer: dequeueBuffer(%d, %d, %d, %d)"
199 "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
200 result);
201 return result;
202 }
203 sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
204 if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
205 freeAllBuffers();
206 }
208 if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
209 result = mBufferProducer->requestBuffer(buf, &gbuf);
211 if (result != NO_ERROR) {
212 ALOGE("dequeueBuffer: requestBuffer failed: %d",
213 result);
214 return result;
215 }
216 }
218 if (fence.get() && fence->isValid()) {
219 *fenceFd = fence->dup();
220 if (*fenceFd == -1) {
221 ALOGE("dequeueBuffer: error duping fence: %d", errno);
222 // dup() should never fail; something is badly wrong. Soldier on
223 // and hope for the best; the worst that should happen is some
224 // visible corruption that lasts until the next frame.
225 }
226 } else {
227 *fenceFd = -1;
228 }
230 *buffer = gbuf.get();
231 return OK;
232 }
234 int GonkNativeWindowClient::cancelBuffer(android_native_buffer_t* buffer,
235 int fenceFd) {
236 ALOGV("GonkNativeWindowClient::cancelBuffer");
237 Mutex::Autolock lock(mMutex);
238 int i = getSlotFromBufferLocked(buffer);
239 if (i < 0) {
240 return i;
241 }
242 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
243 mBufferProducer->cancelBuffer(i, fence);
244 return OK;
245 }
247 int GonkNativeWindowClient::getSlotFromBufferLocked(
248 android_native_buffer_t* buffer) const {
249 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
250 if (mSlots[i].buffer != NULL &&
251 mSlots[i].buffer->handle == buffer->handle) {
252 return i;
253 }
254 }
255 ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
256 return BAD_VALUE;
257 }
259 int GonkNativeWindowClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) {
260 ALOGV("GonkNativeWindowClient::lockBuffer");
261 Mutex::Autolock lock(mMutex);
262 return OK;
263 }
265 int GonkNativeWindowClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
266 ALOGV("GonkNativeWindowClient::queueBuffer");
267 Mutex::Autolock lock(mMutex);
268 int64_t timestamp;
269 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
270 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
271 ALOGV("GonkNativeWindowClient::queueBuffer making up timestamp: %.2f ms",
272 timestamp / 1000000.f);
273 } else {
274 timestamp = mTimestamp;
275 }
276 int i = getSlotFromBufferLocked(buffer);
277 if (i < 0) {
278 return i;
279 }
282 // Make sure the crop rectangle is entirely inside the buffer.
283 Rect crop;
284 mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
286 sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
287 IGraphicBufferProducer::QueueBufferOutput output;
289 IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
290 mTransform, fence);
291 status_t err = mBufferProducer->queueBuffer(i, input, &output);
292 if (err != OK) {
293 ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
294 }
295 uint32_t numPendingBuffers = 0;
296 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
297 &numPendingBuffers);
299 mConsumerRunningBehind = (numPendingBuffers >= 2);
301 return err;
302 }
304 int GonkNativeWindowClient::query(int what, int* value) const {
305 ALOGV("GonkNativeWindowClient::query");
306 { // scope for the lock
307 Mutex::Autolock lock(mMutex);
308 switch (what) {
309 case NATIVE_WINDOW_FORMAT:
310 if (mReqFormat) {
311 *value = mReqFormat;
312 return NO_ERROR;
313 }
314 break;
315 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
316 //sp<ISurfaceComposer> composer(
317 // ComposerService::getComposerService());
318 //if (composer->authenticateSurfaceTexture(mBufferProducer)) {
319 // *value = 1;
320 //} else {
321 *value = 0;
322 //}
323 return NO_ERROR;
324 }
325 case NATIVE_WINDOW_CONCRETE_TYPE:
326 #if ANDROID_VERSION == 17
327 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
328 #else
329 *value = NATIVE_WINDOW_SURFACE;
330 #endif
331 return NO_ERROR;
332 case NATIVE_WINDOW_DEFAULT_WIDTH:
333 *value = mUserWidth ? mUserWidth : mDefaultWidth;
334 return NO_ERROR;
335 case NATIVE_WINDOW_DEFAULT_HEIGHT:
336 *value = mUserHeight ? mUserHeight : mDefaultHeight;
337 return NO_ERROR;
338 case NATIVE_WINDOW_TRANSFORM_HINT:
339 *value = mTransformHint;
340 return NO_ERROR;
341 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
342 status_t err = NO_ERROR;
343 if (!mConsumerRunningBehind) {
344 *value = 0;
345 } else {
346 err = mBufferProducer->query(what, value);
347 if (err == NO_ERROR) {
348 mConsumerRunningBehind = *value;
349 }
350 }
351 return err;
352 }
353 }
354 }
356 return mBufferProducer->query(what, value);
357 }
359 int GonkNativeWindowClient::perform(int operation, va_list args)
360 {
361 int res = NO_ERROR;
362 switch (operation) {
363 case NATIVE_WINDOW_CONNECT:
364 // deprecated. must return NO_ERROR.
365 break;
366 case NATIVE_WINDOW_DISCONNECT:
367 // deprecated. must return NO_ERROR.
368 break;
369 case NATIVE_WINDOW_SET_USAGE:
370 res = dispatchSetUsage(args);
371 break;
372 case NATIVE_WINDOW_SET_CROP:
373 res = dispatchSetCrop(args);
374 break;
375 case NATIVE_WINDOW_SET_BUFFER_COUNT:
376 res = dispatchSetBufferCount(args);
377 break;
378 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
379 res = dispatchSetBuffersGeometry(args);
380 break;
381 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
382 res = dispatchSetBuffersTransform(args);
383 break;
384 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
385 res = dispatchSetBuffersTimestamp(args);
386 break;
387 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
388 res = dispatchSetBuffersDimensions(args);
389 break;
390 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
391 res = dispatchSetBuffersUserDimensions(args);
392 break;
393 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
394 res = dispatchSetBuffersFormat(args);
395 break;
396 case NATIVE_WINDOW_LOCK:
397 res = dispatchLock(args);
398 break;
399 case NATIVE_WINDOW_UNLOCK_AND_POST:
400 res = dispatchUnlockAndPost(args);
401 break;
402 case NATIVE_WINDOW_SET_SCALING_MODE:
403 res = dispatchSetScalingMode(args);
404 break;
405 case NATIVE_WINDOW_API_CONNECT:
406 res = dispatchConnect(args);
407 break;
408 case NATIVE_WINDOW_API_DISCONNECT:
409 res = dispatchDisconnect(args);
410 break;
411 default:
412 res = NAME_NOT_FOUND;
413 break;
414 }
415 return res;
416 }
418 int GonkNativeWindowClient::dispatchConnect(va_list args) {
419 int api = va_arg(args, int);
420 return connect(api);
421 }
423 int GonkNativeWindowClient::dispatchDisconnect(va_list args) {
424 int api = va_arg(args, int);
425 return disconnect(api);
426 }
428 int GonkNativeWindowClient::dispatchSetUsage(va_list args) {
429 int usage = va_arg(args, int);
430 return setUsage(usage);
431 }
433 int GonkNativeWindowClient::dispatchSetCrop(va_list args) {
434 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
435 return setCrop(reinterpret_cast<Rect const*>(rect));
436 }
438 int GonkNativeWindowClient::dispatchSetBufferCount(va_list args) {
439 size_t bufferCount = va_arg(args, size_t);
440 return setBufferCount(bufferCount);
441 }
443 int GonkNativeWindowClient::dispatchSetBuffersGeometry(va_list args) {
444 int w = va_arg(args, int);
445 int h = va_arg(args, int);
446 int f = va_arg(args, int);
447 int err = setBuffersDimensions(w, h);
448 if (err != 0) {
449 return err;
450 }
451 return setBuffersFormat(f);
452 }
454 int GonkNativeWindowClient::dispatchSetBuffersDimensions(va_list args) {
455 int w = va_arg(args, int);
456 int h = va_arg(args, int);
457 return setBuffersDimensions(w, h);
458 }
460 int GonkNativeWindowClient::dispatchSetBuffersUserDimensions(va_list args) {
461 int w = va_arg(args, int);
462 int h = va_arg(args, int);
463 return setBuffersUserDimensions(w, h);
464 }
466 int GonkNativeWindowClient::dispatchSetBuffersFormat(va_list args) {
467 int f = va_arg(args, int);
468 return setBuffersFormat(f);
469 }
471 int GonkNativeWindowClient::dispatchSetScalingMode(va_list args) {
472 int m = va_arg(args, int);
473 return setScalingMode(m);
474 }
476 int GonkNativeWindowClient::dispatchSetBuffersTransform(va_list args) {
477 int transform = va_arg(args, int);
478 return setBuffersTransform(transform);
479 }
481 int GonkNativeWindowClient::dispatchSetBuffersTimestamp(va_list args) {
482 int64_t timestamp = va_arg(args, int64_t);
483 return setBuffersTimestamp(timestamp);
484 }
486 int GonkNativeWindowClient::dispatchLock(va_list args) {
487 ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
488 ARect* inOutDirtyBounds = va_arg(args, ARect*);
489 return lock(outBuffer, inOutDirtyBounds);
490 }
492 int GonkNativeWindowClient::dispatchUnlockAndPost(va_list args) {
493 return unlockAndPost();
494 }
497 int GonkNativeWindowClient::connect(int api) {
498 ALOGV("GonkNativeWindowClient::connect");
500 Mutex::Autolock lock(mMutex);
501 IGraphicBufferProducer::QueueBufferOutput output;
503 int err = mBufferProducer->connect(api, &output);
504 if (err == NO_ERROR) {
505 uint32_t numPendingBuffers = 0;
506 output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
507 &numPendingBuffers);
508 mConsumerRunningBehind = (numPendingBuffers >= 2);
509 }
510 if (!err && api == NATIVE_WINDOW_API_CPU) {
511 mConnectedToCpu = true;
512 }
513 return err;
514 }
516 int GonkNativeWindowClient::disconnect(int api) {
517 ALOGV("GonkNativeWindowClient::disconnect");
518 Mutex::Autolock lock(mMutex);
519 freeAllBuffers();
520 int err = mBufferProducer->disconnect(api);
522 if (!err) {
523 mReqFormat = 0;
524 mReqWidth = 0;
525 mReqHeight = 0;
526 mReqUsage = 0;
527 mCrop.clear();
528 mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
529 mTransform = 0;
530 if (api == NATIVE_WINDOW_API_CPU) {
531 mConnectedToCpu = false;
532 }
533 }
534 return err;
535 }
537 int GonkNativeWindowClient::setUsage(uint32_t reqUsage)
538 {
539 ALOGV("GonkNativeWindowClient::setUsage");
540 Mutex::Autolock lock(mMutex);
541 mReqUsage = reqUsage;
542 return OK;
543 }
545 int GonkNativeWindowClient::setCrop(Rect const* rect)
546 {
547 Rect realRect;
548 if (rect == NULL || rect->isEmpty()) {
549 realRect.clear();
550 } else {
551 realRect = *rect;
552 }
554 ALOGV("GonkNativeWindowClient::setCrop rect=[%d %d %d %d]",
555 realRect.left, realRect.top, realRect.right, realRect.bottom);
557 Mutex::Autolock lock(mMutex);
558 mCrop = realRect;
559 return NO_ERROR;
560 }
562 int GonkNativeWindowClient::setBufferCount(int bufferCount)
563 {
564 ALOGV("GonkNativeWindowClient::setBufferCount");
565 Mutex::Autolock lock(mMutex);
567 status_t err = mBufferProducer->setBufferCount(bufferCount);
568 ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
569 bufferCount, strerror(-err));
571 if (err == NO_ERROR) {
572 freeAllBuffers();
573 }
575 return err;
576 }
578 int GonkNativeWindowClient::setBuffersDimensions(int w, int h)
579 {
580 ALOGV("GonkNativeWindowClient::setBuffersDimensions");
582 if (w<0 || h<0)
583 return BAD_VALUE;
585 if ((w && !h) || (!w && h))
586 return BAD_VALUE;
588 Mutex::Autolock lock(mMutex);
589 mReqWidth = w;
590 mReqHeight = h;
591 return NO_ERROR;
592 }
594 int GonkNativeWindowClient::setBuffersUserDimensions(int w, int h)
595 {
596 ALOGV("GonkNativeWindowClient::setBuffersUserDimensions");
598 if (w<0 || h<0)
599 return BAD_VALUE;
601 if ((w && !h) || (!w && h))
602 return BAD_VALUE;
604 Mutex::Autolock lock(mMutex);
605 mUserWidth = w;
606 mUserHeight = h;
607 return NO_ERROR;
608 }
610 int GonkNativeWindowClient::setBuffersFormat(int format)
611 {
612 ALOGV("GonkNativeWindowClient::setBuffersFormat");
614 if (format<0)
615 return BAD_VALUE;
617 Mutex::Autolock lock(mMutex);
618 mReqFormat = format;
619 return NO_ERROR;
620 }
622 int GonkNativeWindowClient::setScalingMode(int mode)
623 {
624 ALOGV("GonkNativeWindowClient::setScalingMode(%d)", mode);
626 switch (mode) {
627 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
628 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
629 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
630 break;
631 default:
632 ALOGE("unknown scaling mode: %d", mode);
633 return BAD_VALUE;
634 }
636 Mutex::Autolock lock(mMutex);
637 mScalingMode = mode;
638 return NO_ERROR;
639 }
641 int GonkNativeWindowClient::setBuffersTransform(int transform)
642 {
643 ALOGV("GonkNativeWindowClient::setBuffersTransform");
644 Mutex::Autolock lock(mMutex);
645 mTransform = transform;
646 return NO_ERROR;
647 }
649 int GonkNativeWindowClient::setBuffersTimestamp(int64_t timestamp)
650 {
651 ALOGV("GonkNativeWindowClient::setBuffersTimestamp");
652 Mutex::Autolock lock(mMutex);
653 mTimestamp = timestamp;
654 return NO_ERROR;
655 }
657 void GonkNativeWindowClient::freeAllBuffers() {
658 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
659 mSlots[i].buffer = 0;
660 }
661 }
663 // ----------------------------------------------------------------------
664 // the lock/unlock APIs must be used from the same thread
666 // ----------------------------------------------------------------------------
668 status_t GonkNativeWindowClient::lock(
669 ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
670 {
671 return INVALID_OPERATION;
672 }
674 status_t GonkNativeWindowClient::unlockAndPost()
675 {
676 return INVALID_OPERATION;
677 }
679 }; // namespace android