Bug 836782 - reduce gralloc buffer reallocation in camera StartPreview(), r=kchen
[gecko.git] / dom / camera / GonkNativeWindow.cpp
blobc992e5651f4cf5f87f1eb64fae7e407dbb09285f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=4 et sw=4 tw=80: */
3 /*
4 * Copyright (C) 2010 The Android Open Source Project
5 * Copyright (C) 2012 Mozilla Foundation
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include "base/basictypes.h"
21 #include "GonkCameraHwMgr.h"
22 #include "mozilla/layers/ShadowLayers.h"
23 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
24 #include "mozilla/layers/ImageBridgeChild.h"
25 #include "GonkNativeWindow.h"
26 #include "nsDebug.h"
28 /**
29 * DOM_CAMERA_LOGI() is enabled in debug builds, and turned on by setting
30 * NSPR_LOG_MODULES=Camera:N environment variable, where N >= 3.
32 * CNW_LOGE() is always enabled.
34 #define CNW_LOGD(...) DOM_CAMERA_LOGI(__VA_ARGS__)
35 #define CNW_LOGE(...) {(void)printf_stderr(__VA_ARGS__);}
37 using namespace android;
38 using namespace mozilla::layers;
40 GonkNativeWindow::GonkNativeWindow(GonkNativeWindowNewFrameCallback* aCallback)
41 : mNewFrameCallback(aCallback)
43 GonkNativeWindow::init();
46 GonkNativeWindow::GonkNativeWindow()
47 : mNewFrameCallback(nullptr)
49 GonkNativeWindow::init();
52 GonkNativeWindow::~GonkNativeWindow()
54 nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
55 freeAllBuffersLocked(freeList);
56 releaseBufferFreeListUnlocked(freeList);
59 void GonkNativeWindow::abandon()
61 nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
63 Mutex::Autolock lock(mMutex);
64 mAbandoned = true;
65 freeAllBuffersLocked(freeList);
68 releaseBufferFreeListUnlocked(freeList);
69 mDequeueCondition.signal();
72 void GonkNativeWindow::init()
74 // Initialize the ANativeWindow function pointers.
75 ANativeWindow::setSwapInterval = hook_setSwapInterval;
76 ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
77 ANativeWindow::cancelBuffer = hook_cancelBuffer;
78 ANativeWindow::lockBuffer = hook_lockBuffer;
79 ANativeWindow::queueBuffer = hook_queueBuffer;
80 ANativeWindow::query = hook_query;
81 ANativeWindow::perform = hook_perform;
83 mDefaultWidth = 0;
84 mDefaultHeight = 0;
85 mPixelFormat = 0;
86 mUsage = 0;
87 mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
88 mBufferCount = MIN_BUFFER_SLOTS;
89 mFrameCounter = 0;
90 mGeneration = 0;
91 mAbandoned =false;
95 int GonkNativeWindow::hook_setSwapInterval(ANativeWindow* window, int interval)
97 GonkNativeWindow* c = getSelf(window);
98 return c->setSwapInterval(interval);
101 int GonkNativeWindow::hook_dequeueBuffer(ANativeWindow* window,
102 ANativeWindowBuffer** buffer)
104 GonkNativeWindow* c = getSelf(window);
105 return c->dequeueBuffer(buffer);
108 int GonkNativeWindow::hook_cancelBuffer(ANativeWindow* window,
109 ANativeWindowBuffer* buffer)
111 GonkNativeWindow* c = getSelf(window);
112 return c->cancelBuffer(buffer);
115 int GonkNativeWindow::hook_lockBuffer(ANativeWindow* window,
116 ANativeWindowBuffer* buffer)
118 GonkNativeWindow* c = getSelf(window);
119 return c->lockBuffer(buffer);
122 int GonkNativeWindow::hook_queueBuffer(ANativeWindow* window,
123 ANativeWindowBuffer* buffer)
125 GonkNativeWindow* c = getSelf(window);
126 return c->queueBuffer(buffer);
129 int GonkNativeWindow::hook_query(const ANativeWindow* window,
130 int what, int* value)
132 const GonkNativeWindow* c = getSelf(window);
133 return c->query(what, value);
136 int GonkNativeWindow::hook_perform(ANativeWindow* window, int operation, ...)
138 va_list args;
139 va_start(args, operation);
140 GonkNativeWindow* c = getSelf(window);
141 return c->perform(operation, args);
144 void GonkNativeWindow::freeAllBuffersLocked(nsTArray<SurfaceDescriptor>& freeList)
146 CNW_LOGD("freeAllBuffersLocked: from generation %d", mGeneration);
147 ++mGeneration;
149 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
150 if (mSlots[i].mGraphicBuffer != NULL) {
151 // Don't try to destroy the gralloc buffer if it is still in the
152 // video stream awaiting rendering.
153 if (mSlots[i].mBufferState != BufferSlot::RENDERING) {
154 SurfaceDescriptor* desc = freeList.AppendElement();
155 *desc = mSlots[i].mSurfaceDescriptor;
157 mSlots[i].mGraphicBuffer = NULL;
158 mSlots[i].mBufferState = BufferSlot::FREE;
159 mSlots[i].mFrameNumber = 0;
164 void GonkNativeWindow::releaseBufferFreeListUnlocked(nsTArray<SurfaceDescriptor>& freeList)
166 // This function MUST ONLY be called with mMutex unlocked; else there
167 // is a risk of deadlock with the ImageBridge thread.
169 CNW_LOGD("releaseBufferFreeListUnlocked: E");
170 ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
172 for (uint32_t i = 0; i < freeList.Length(); ++i) {
173 ibc->DeallocSurfaceDescriptorGralloc(freeList[i]);
176 freeList.Clear();
177 CNW_LOGD("releaseBufferFreeListUnlocked: X");
180 void GonkNativeWindow::clearRenderingStateBuffersLocked()
182 ++mGeneration;
184 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
185 if (mSlots[i].mGraphicBuffer != NULL) {
186 // Don't try to destroy the gralloc buffer if it is still in the
187 // video stream awaiting rendering.
188 if (mSlots[i].mBufferState == BufferSlot::RENDERING) {
189 mSlots[i].mGraphicBuffer = NULL;
190 mSlots[i].mBufferState = BufferSlot::FREE;
191 mSlots[i].mFrameNumber = 0;
197 int GonkNativeWindow::setBufferCount(int bufferCount)
199 CNW_LOGD("setBufferCount: count=%d", bufferCount);
200 nsAutoTArray<SurfaceDescriptor, NUM_BUFFER_SLOTS> freeList;
203 Mutex::Autolock lock(mMutex);
205 if (mAbandoned) {
206 CNW_LOGE("setBufferCount: GonkNativeWindow has been abandoned!");
207 return NO_INIT;
210 if (bufferCount > NUM_BUFFER_SLOTS) {
211 CNW_LOGE("setBufferCount: bufferCount larger than slots available");
212 return BAD_VALUE;
215 if (bufferCount < MIN_BUFFER_SLOTS) {
216 CNW_LOGE("setBufferCount: requested buffer count (%d) is less than "
217 "minimum (%d)", bufferCount, MIN_BUFFER_SLOTS);
218 return BAD_VALUE;
221 // Error out if the user has dequeued buffers.
222 for (int i=0 ; i<mBufferCount ; i++) {
223 if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
224 CNW_LOGE("setBufferCount: client owns some buffers");
225 return -EINVAL;
229 if (bufferCount >= mBufferCount) {
230 mBufferCount = bufferCount;
231 //clear only buffers in RENDERING state.
232 clearRenderingStateBuffersLocked();
233 mDequeueCondition.signal();
234 return OK;
237 // reducing the number of buffers
238 // here we're guaranteed that the client doesn't have dequeued buffers
239 // and will release all of its buffer references.
240 freeAllBuffersLocked(freeList);
241 mBufferCount = bufferCount;
242 mDequeueCondition.signal();
245 releaseBufferFreeListUnlocked(freeList);
246 return OK;
249 int GonkNativeWindow::dequeueBuffer(android_native_buffer_t** buffer)
251 uint32_t defaultWidth;
252 uint32_t defaultHeight;
253 uint32_t pixelFormat;
254 uint32_t usage;
255 uint32_t generation;
256 bool alloc = false;
257 int buf = INVALID_BUFFER_SLOT;
258 SurfaceDescriptor descOld;
261 Mutex::Autolock lock(mMutex);
262 generation = mGeneration;
264 int found = -1;
265 int dequeuedCount = 0;
266 bool tryAgain = true;
268 CNW_LOGD("dequeueBuffer: E");
269 while (tryAgain) {
270 if (mAbandoned) {
271 CNW_LOGE("dequeueBuffer: GonkNativeWindow has been abandoned!");
272 return NO_INIT;
274 // look for a free buffer to give to the client
275 found = INVALID_BUFFER_SLOT;
276 dequeuedCount = 0;
277 for (int i = 0; i < mBufferCount; i++) {
278 const int state = mSlots[i].mBufferState;
279 if (state == BufferSlot::DEQUEUED) {
280 dequeuedCount++;
282 else if (state == BufferSlot::FREE) {
283 /* We return the oldest of the free buffers to avoid
284 * stalling the producer if possible. This is because
285 * the consumer may still have pending reads of the
286 * buffers in flight.
288 if (found < 0 ||
289 mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
290 found = i;
295 // we're in synchronous mode and didn't find a buffer, we need to
296 // wait for some buffers to be consumed
297 tryAgain = (found == INVALID_BUFFER_SLOT);
298 if (tryAgain) {
299 CNW_LOGD("dequeueBuffer: Try again");
300 mDequeueCondition.wait(mMutex);
301 CNW_LOGD("dequeueBuffer: Now");
305 if (found == INVALID_BUFFER_SLOT) {
306 // This should not happen.
307 CNW_LOGE("dequeueBuffer: no available buffer slots");
308 return -EBUSY;
311 buf = found;
313 // buffer is now in DEQUEUED
314 mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
316 const sp<GraphicBuffer>& gbuf(mSlots[buf].mGraphicBuffer);
317 alloc = (gbuf == NULL);
318 if ((gbuf!=NULL) &&
319 ((uint32_t(gbuf->width) != mDefaultWidth) ||
320 (uint32_t(gbuf->height) != mDefaultHeight) ||
321 (uint32_t(gbuf->format) != mPixelFormat) ||
322 ((uint32_t(gbuf->usage) & mUsage) != mUsage))) {
323 alloc = true;
324 descOld = mSlots[buf].mSurfaceDescriptor;
327 if (alloc) {
328 // get local copies for graphics buffer allocations
329 defaultWidth = mDefaultWidth;
330 defaultHeight = mDefaultHeight;
331 pixelFormat = mPixelFormat;
332 usage = mUsage;
336 // At this point, the buffer is now marked DEQUEUED, and no one else
337 // should touch it, except for freeAllBuffersLocked(); we handle that
338 // after trying to create the surface descriptor below.
340 // So we don't need mMutex locked, which would otherwise run the risk
341 // of a deadlock on calling AllocSurfaceDescriptorGralloc().
343 SurfaceDescriptor desc;
344 ImageBridgeChild* ibc;
345 sp<GraphicBuffer> graphicBuffer;
346 if (alloc) {
347 status_t error;
348 ibc = ImageBridgeChild::GetSingleton();
349 CNW_LOGD("dequeueBuffer: about to alloc surface descriptor");
350 ibc->AllocSurfaceDescriptorGralloc(gfxIntSize(defaultWidth, defaultHeight),
351 pixelFormat,
352 usage,
353 &desc);
354 // We can only use a gralloc buffer here. If we didn't get
355 // one back, something went wrong.
356 CNW_LOGD("dequeueBuffer: got surface descriptor");
357 if (SurfaceDescriptor::TSurfaceDescriptorGralloc != desc.type()) {
358 MOZ_ASSERT(SurfaceDescriptor::T__None == desc.type());
359 CNW_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
360 return -ENOMEM;
362 graphicBuffer = GrallocBufferActor::GetFrom(desc.get_SurfaceDescriptorGralloc());
363 error = graphicBuffer->initCheck();
364 if (error != NO_ERROR) {
365 CNW_LOGE("dequeueBuffer: createGraphicBuffer failed with error %d", error);
366 return error;
370 bool tooOld = false;
372 Mutex::Autolock lock(mMutex);
373 if (generation == mGeneration) {
374 if (alloc) {
375 mSlots[buf].mGraphicBuffer = graphicBuffer;
376 mSlots[buf].mSurfaceDescriptor = desc;
377 mSlots[buf].mSurfaceDescriptor.get_SurfaceDescriptorGralloc().external() = true;
379 *buffer = mSlots[buf].mGraphicBuffer.get();
381 CNW_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
382 mSlots[buf].mGraphicBuffer->handle);
383 } else {
384 *buffer = nullptr;
385 tooOld = true;
389 if (alloc && IsSurfaceDescriptorValid(descOld)) {
390 ibc->DeallocSurfaceDescriptorGralloc(descOld);
393 if (alloc && tooOld) {
394 ibc->DeallocSurfaceDescriptorGralloc(desc);
397 CNW_LOGD("dequeueBuffer: X");
398 return NO_ERROR;
401 int GonkNativeWindow::getSlotFromBufferLocked(
402 android_native_buffer_t* buffer) const
404 if (buffer == NULL) {
405 CNW_LOGE("getSlotFromBufferLocked: encountered NULL buffer");
406 return BAD_VALUE;
409 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
410 if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
411 return i;
414 CNW_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
415 return BAD_VALUE;
418 mozilla::layers::SurfaceDescriptor *
419 GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
421 int buf = getSlotFromBufferLocked(buffer);
422 if (buf < 0 || buf >= mBufferCount ||
423 mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
424 return nullptr;
427 return &mSlots[buf].mSurfaceDescriptor;
430 int GonkNativeWindow::queueBuffer(ANativeWindowBuffer* buffer)
433 Mutex::Autolock lock(mMutex);
434 CNW_LOGD("queueBuffer: E");
436 if (mAbandoned) {
437 CNW_LOGE("queueBuffer: GonkNativeWindow has been abandoned!");
438 return NO_INIT;
441 int buf = getSlotFromBufferLocked(buffer);
443 if (buf < 0 || buf >= mBufferCount) {
444 CNW_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
445 mBufferCount, buf);
446 return -EINVAL;
447 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
448 CNW_LOGE("queueBuffer: slot %d is not owned by the client "
449 "(state=%d)", buf, mSlots[buf].mBufferState);
450 return -EINVAL;
453 int64_t timestamp;
454 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
455 timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
456 } else {
457 timestamp = mTimestamp;
460 mSlots[buf].mBufferState = BufferSlot::QUEUED;
461 mSlots[buf].mTimestamp = timestamp;
462 mFrameCounter++;
463 mSlots[buf].mFrameNumber = mFrameCounter;
465 mDequeueCondition.signal();
468 // OnNewFrame might call lockCurrentBuffer so we must release the
469 // mutex first.
470 if (mNewFrameCallback) {
471 mNewFrameCallback->OnNewFrame();
473 CNW_LOGD("queueBuffer: X");
474 return OK;
478 already_AddRefed<GraphicBufferLocked>
479 GonkNativeWindow::getCurrentBuffer()
481 CNW_LOGD("GonkNativeWindow::getCurrentBuffer");
482 Mutex::Autolock lock(mMutex);
484 if (mAbandoned) {
485 CNW_LOGE("getCurrentBuffer: GonkNativeWindow has been abandoned!");
486 return NULL;
489 int found = -1;
490 for (int i = 0; i < mBufferCount; i++) {
491 const int state = mSlots[i].mBufferState;
492 if (state == BufferSlot::QUEUED) {
493 if (found < 0 ||
494 mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
495 found = i;
500 if (found < 0) {
501 mDequeueCondition.signal();
502 return NULL;
505 mSlots[found].mBufferState = BufferSlot::RENDERING;
507 nsRefPtr<GraphicBufferLocked> ret =
508 new CameraGraphicBuffer(this, found, mGeneration, mSlots[found].mSurfaceDescriptor);
509 mDequeueCondition.signal();
510 return ret.forget();
513 bool
514 GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration)
516 CNW_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", aIndex, aGeneration);
517 Mutex::Autolock lock(mMutex);
519 if (mAbandoned) {
520 CNW_LOGD("returnBuffer: GonkNativeWindow has been abandoned!");
521 return false;
524 if (aGeneration != mGeneration) {
525 CNW_LOGD("returnBuffer: buffer is from generation %d (current is %d)",
526 aGeneration, mGeneration);
527 return false;
529 if (aIndex >= mBufferCount) {
530 CNW_LOGE("returnBuffer: slot index out of range [0, %d]: %d",
531 mBufferCount, aIndex);
532 return false;
534 if (mSlots[aIndex].mBufferState != BufferSlot::RENDERING) {
535 CNW_LOGE("returnBuffer: slot %d is not owned by the compositor (state=%d)",
536 aIndex, mSlots[aIndex].mBufferState);
537 return false;
540 mSlots[aIndex].mBufferState = BufferSlot::FREE;
541 mDequeueCondition.signal();
542 return true;
545 int GonkNativeWindow::lockBuffer(ANativeWindowBuffer* buffer)
547 CNW_LOGD("GonkNativeWindow::lockBuffer");
548 Mutex::Autolock lock(mMutex);
550 if (mAbandoned) {
551 CNW_LOGE("lockBuffer: GonkNativeWindow has been abandoned!");
552 return NO_INIT;
554 return OK;
557 int GonkNativeWindow::cancelBuffer(ANativeWindowBuffer* buffer)
559 Mutex::Autolock lock(mMutex);
561 if (mAbandoned) {
562 CNW_LOGD("cancelBuffer: GonkNativeWindow has been abandoned!");
563 return NO_INIT;
565 int buf = getSlotFromBufferLocked(buffer);
567 CNW_LOGD("cancelBuffer: slot=%d", buf);
568 if (buf < 0 || buf >= mBufferCount) {
569 CNW_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
570 mBufferCount, buf);
571 return -EINVAL;
572 } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
573 CNW_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
574 buf, mSlots[buf].mBufferState);
575 return -EINVAL;
577 mSlots[buf].mBufferState = BufferSlot::FREE;
578 mSlots[buf].mFrameNumber = 0;
579 mDequeueCondition.signal();
580 return OK;
583 int GonkNativeWindow::perform(int operation, va_list args)
585 switch (operation) {
586 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
587 case NATIVE_WINDOW_SET_BUFFERS_SIZE:
588 case NATIVE_WINDOW_SET_SCALING_MODE:
589 case NATIVE_WINDOW_SET_CROP:
590 case NATIVE_WINDOW_CONNECT:
591 case NATIVE_WINDOW_DISCONNECT:
592 // deprecated. must return NO_ERROR.
593 return NO_ERROR;
594 case NATIVE_WINDOW_SET_USAGE:
595 return dispatchSetUsage(args);
596 case NATIVE_WINDOW_SET_BUFFER_COUNT:
597 return dispatchSetBufferCount(args);
598 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
599 return dispatchSetBuffersGeometry(args);
600 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
601 return dispatchSetBuffersTimestamp(args);
602 case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
603 return dispatchSetBuffersDimensions(args);
604 case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
605 return dispatchSetBuffersFormat(args);
606 case NATIVE_WINDOW_LOCK:
607 case NATIVE_WINDOW_UNLOCK_AND_POST:
608 case NATIVE_WINDOW_API_CONNECT:
609 case NATIVE_WINDOW_API_DISCONNECT:
610 default:
611 NS_WARNING("Unsupported operation");
612 return INVALID_OPERATION;
616 int GonkNativeWindow::query(int what, int* outValue) const
618 Mutex::Autolock lock(mMutex);
620 if (mAbandoned) {
621 CNW_LOGE("query: GonkNativeWindow has been abandoned!");
622 return NO_INIT;
625 int value;
626 switch (what) {
627 case NATIVE_WINDOW_WIDTH:
628 value = mDefaultWidth;
629 break;
630 case NATIVE_WINDOW_HEIGHT:
631 value = mDefaultHeight;
632 break;
633 case NATIVE_WINDOW_FORMAT:
634 value = mPixelFormat;
635 break;
636 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
637 value = MIN_UNDEQUEUED_BUFFERS;
638 break;
639 default:
640 return BAD_VALUE;
642 outValue[0] = value;
643 return NO_ERROR;
646 int GonkNativeWindow::setSwapInterval(int interval)
648 return NO_ERROR;
651 int GonkNativeWindow::dispatchSetUsage(va_list args)
653 int usage = va_arg(args, int);
654 return setUsage(usage);
657 int GonkNativeWindow::dispatchSetBufferCount(va_list args)
659 size_t bufferCount = va_arg(args, size_t);
660 return setBufferCount(bufferCount);
663 int GonkNativeWindow::dispatchSetBuffersGeometry(va_list args)
665 int w = va_arg(args, int);
666 int h = va_arg(args, int);
667 int f = va_arg(args, int);
668 int err = setBuffersDimensions(w, h);
669 if (err != 0) {
670 return err;
672 return setBuffersFormat(f);
675 int GonkNativeWindow::dispatchSetBuffersDimensions(va_list args)
677 int w = va_arg(args, int);
678 int h = va_arg(args, int);
679 return setBuffersDimensions(w, h);
682 int GonkNativeWindow::dispatchSetBuffersFormat(va_list args)
684 int f = va_arg(args, int);
685 return setBuffersFormat(f);
688 int GonkNativeWindow::dispatchSetBuffersTimestamp(va_list args)
690 int64_t timestamp = va_arg(args, int64_t);
691 return setBuffersTimestamp(timestamp);
694 int GonkNativeWindow::setUsage(uint32_t reqUsage)
696 CNW_LOGD("GonkNativeWindow::setUsage");
697 Mutex::Autolock lock(mMutex);
699 if (mAbandoned) {
700 CNW_LOGE("setUsage: GonkNativeWindow has been abandoned!");
701 return NO_INIT;
703 mUsage = reqUsage;
704 return OK;
707 int GonkNativeWindow::setBuffersDimensions(int w, int h)
709 CNW_LOGD("GonkNativeWindow::setBuffersDimensions");
710 Mutex::Autolock lock(mMutex);
712 if (mAbandoned) {
713 CNW_LOGE("setBuffersDimensions: GonkNativeWindow has been abandoned!");
714 return NO_INIT;
717 if (w<0 || h<0)
718 return BAD_VALUE;
720 if ((w && !h) || (!w && h))
721 return BAD_VALUE;
723 mDefaultWidth = w;
724 mDefaultHeight = h;
726 return OK;
729 int GonkNativeWindow::setBuffersFormat(int format)
731 CNW_LOGD("GonkNativeWindow::setBuffersFormat");
732 Mutex::Autolock lock(mMutex);
734 if (mAbandoned) {
735 CNW_LOGE("setBuffersFormat: GonkNativeWindow has been abandoned!");
736 return NO_INIT;
739 if (format<0)
740 return BAD_VALUE;
742 mPixelFormat = format;
744 return NO_ERROR;
747 int GonkNativeWindow::setBuffersTimestamp(int64_t timestamp)
749 CNW_LOGD("GonkNativeWindow::setBuffersTimestamp");
750 Mutex::Autolock lock(mMutex);
752 if (mAbandoned) {
753 CNW_LOGE("setBuffersTimestamp: GonkNativeWindow has been abandoned!");
754 return NO_INIT;
757 mTimestamp = timestamp;
758 return OK;