OSDN Git Service

Merge "OMX IL header additions for FLAC" into jb-dev
[android-x86/frameworks-native.git] / libs / gui / SurfaceTextureClient.cpp
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define LOG_TAG "SurfaceTextureClient"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
20
21 #include <android/native_window.h>
22
23 #include <utils/Log.h>
24 #include <utils/Trace.h>
25
26 #include <gui/ISurfaceComposer.h>
27 #include <gui/SurfaceComposerClient.h>
28 #include <gui/SurfaceTexture.h>
29 #include <gui/SurfaceTextureClient.h>
30
31 #include <private/gui/ComposerService.h>
32
33 namespace android {
34
35 SurfaceTextureClient::SurfaceTextureClient(
36         const sp<ISurfaceTexture>& surfaceTexture)
37 {
38     SurfaceTextureClient::init();
39     SurfaceTextureClient::setISurfaceTexture(surfaceTexture);
40 }
41
42 // see SurfaceTextureClient.h
43 SurfaceTextureClient::SurfaceTextureClient(const
44          sp<SurfaceTexture>& surfaceTexture)
45 {
46     SurfaceTextureClient::init();
47     SurfaceTextureClient::setISurfaceTexture(surfaceTexture->getBufferQueue());
48 }
49
50 SurfaceTextureClient::SurfaceTextureClient() {
51     SurfaceTextureClient::init();
52 }
53
54 SurfaceTextureClient::~SurfaceTextureClient() {
55     if (mConnectedToCpu) {
56         SurfaceTextureClient::disconnect(NATIVE_WINDOW_API_CPU);
57     }
58 }
59
60 void SurfaceTextureClient::init() {
61     // Initialize the ANativeWindow function pointers.
62     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
63     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
64     ANativeWindow::cancelBuffer     = hook_cancelBuffer;
65     ANativeWindow::lockBuffer       = hook_lockBuffer;
66     ANativeWindow::queueBuffer      = hook_queueBuffer;
67     ANativeWindow::query            = hook_query;
68     ANativeWindow::perform          = hook_perform;
69
70     const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
71     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
72
73     mReqWidth = 0;
74     mReqHeight = 0;
75     mReqFormat = 0;
76     mReqUsage = 0;
77     mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
78     mCrop.clear();
79     mCropNeedsTransform = false;
80     mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
81     mTransform = 0;
82     mDefaultWidth = 0;
83     mDefaultHeight = 0;
84     mUserWidth = 0;
85     mUserHeight = 0;
86     mTransformHint = 0;
87     mConsumerRunningBehind = false;
88     mConnectedToCpu = false;
89 }
90
91 void SurfaceTextureClient::setISurfaceTexture(
92         const sp<ISurfaceTexture>& surfaceTexture)
93 {
94     mSurfaceTexture = surfaceTexture;
95 }
96
97 sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const {
98     return mSurfaceTexture;
99 }
100
101 int SurfaceTextureClient::hook_setSwapInterval(ANativeWindow* window, int interval) {
102     SurfaceTextureClient* c = getSelf(window);
103     return c->setSwapInterval(interval);
104 }
105
106 int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window,
107         ANativeWindowBuffer** buffer) {
108     SurfaceTextureClient* c = getSelf(window);
109     return c->dequeueBuffer(buffer);
110 }
111
112 int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window,
113         ANativeWindowBuffer* buffer) {
114     SurfaceTextureClient* c = getSelf(window);
115     return c->cancelBuffer(buffer);
116 }
117
118 int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window,
119         ANativeWindowBuffer* buffer) {
120     SurfaceTextureClient* c = getSelf(window);
121     return c->lockBuffer(buffer);
122 }
123
124 int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window,
125         ANativeWindowBuffer* buffer) {
126     SurfaceTextureClient* c = getSelf(window);
127     return c->queueBuffer(buffer);
128 }
129
130 int SurfaceTextureClient::hook_query(const ANativeWindow* window,
131                                 int what, int* value) {
132     const SurfaceTextureClient* c = getSelf(window);
133     return c->query(what, value);
134 }
135
136 int SurfaceTextureClient::hook_perform(ANativeWindow* window, int operation, ...) {
137     va_list args;
138     va_start(args, operation);
139     SurfaceTextureClient* c = getSelf(window);
140     return c->perform(operation, args);
141 }
142
143 int SurfaceTextureClient::setSwapInterval(int interval) {
144     ATRACE_CALL();
145     // EGL specification states:
146     //  interval is silently clamped to minimum and maximum implementation
147     //  dependent values before being stored.
148     // Although we don't have to, we apply the same logic here.
149
150     if (interval < minSwapInterval)
151         interval = minSwapInterval;
152
153     if (interval > maxSwapInterval)
154         interval = maxSwapInterval;
155
156     status_t res = mSurfaceTexture->setSynchronousMode(interval ? true : false);
157
158     return res;
159 }
160
161 int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
162     ATRACE_CALL();
163     ALOGV("SurfaceTextureClient::dequeueBuffer");
164     Mutex::Autolock lock(mMutex);
165     int buf = -1;
166     int reqW = mReqWidth ? mReqWidth : mUserWidth;
167     int reqH = mReqHeight ? mReqHeight : mUserHeight;
168     status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH,
169             mReqFormat, mReqUsage);
170     if (result < 0) {
171         ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
172              "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
173              result);
174         return result;
175     }
176     sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
177     if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
178         freeAllBuffers();
179     }
180
181     if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
182         result = mSurfaceTexture->requestBuffer(buf, &gbuf);
183         if (result != NO_ERROR) {
184             ALOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d",
185                     result);
186             return result;
187         }
188     }
189     *buffer = gbuf.get();
190     return OK;
191 }
192
193 int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
194     ATRACE_CALL();
195     ALOGV("SurfaceTextureClient::cancelBuffer");
196     Mutex::Autolock lock(mMutex);
197     int i = getSlotFromBufferLocked(buffer);
198     if (i < 0) {
199         return i;
200     }
201     mSurfaceTexture->cancelBuffer(i);
202     return OK;
203 }
204
205 int SurfaceTextureClient::getSlotFromBufferLocked(
206         android_native_buffer_t* buffer) const {
207     bool dumpedState = false;
208     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
209         if (mSlots[i].buffer != NULL &&
210                 mSlots[i].buffer->handle == buffer->handle) {
211             return i;
212         }
213     }
214     ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
215     return BAD_VALUE;
216 }
217
218 int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
219     ALOGV("SurfaceTextureClient::lockBuffer");
220     Mutex::Autolock lock(mMutex);
221     return OK;
222 }
223
224 int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
225     ATRACE_CALL();
226     ALOGV("SurfaceTextureClient::queueBuffer");
227     Mutex::Autolock lock(mMutex);
228     int64_t timestamp;
229     if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
230         timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
231         ALOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
232              timestamp / 1000000.f);
233     } else {
234         timestamp = mTimestamp;
235     }
236     int i = getSlotFromBufferLocked(buffer);
237     if (i < 0) {
238         return i;
239     }
240
241     Rect crop(mCrop);
242     if (mCropNeedsTransform) {
243         // The crop rect was specified in the post-transform coordinate space,
244         // so we need to transform that rect by the inverse of mTransform to
245         // put it into the buffer pixel space before queuing it.
246         uint32_t invTransform = mTransform;
247         int32_t width = buffer->width;
248         int32_t height = buffer->height;
249         if (mTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
250             invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
251                     NATIVE_WINDOW_TRANSFORM_FLIP_H;
252             width = buffer->height;
253             height = buffer->width;
254         }
255         crop = mCrop.transform(invTransform, width, height);
256     }
257
258     // Make sure the crop rectangle is entirely inside the buffer.
259     crop.intersect(Rect(buffer->width, buffer->height), &crop);
260
261     ISurfaceTexture::QueueBufferOutput output;
262     ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
263             mTransform);
264     status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
265     if (err != OK)  {
266         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
267     }
268     uint32_t numPendingBuffers = 0;
269     output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
270             &numPendingBuffers);
271
272     mConsumerRunningBehind = (numPendingBuffers >= 2);
273
274     return err;
275 }
276
277 int SurfaceTextureClient::query(int what, int* value) const {
278     ATRACE_CALL();
279     ALOGV("SurfaceTextureClient::query");
280     { // scope for the lock
281         Mutex::Autolock lock(mMutex);
282         switch (what) {
283             case NATIVE_WINDOW_FORMAT:
284                 if (mReqFormat) {
285                     *value = mReqFormat;
286                     return NO_ERROR;
287                 }
288                 break;
289             case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
290                 sp<ISurfaceComposer> composer(
291                         ComposerService::getComposerService());
292                 if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
293                     *value = 1;
294                 } else {
295                     *value = 0;
296                 }
297                 return NO_ERROR;
298             }
299             case NATIVE_WINDOW_CONCRETE_TYPE:
300                 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
301                 return NO_ERROR;
302             case NATIVE_WINDOW_DEFAULT_WIDTH:
303                 *value = mUserWidth ? mUserWidth : mDefaultWidth;
304                 return NO_ERROR;
305             case NATIVE_WINDOW_DEFAULT_HEIGHT:
306                 *value = mUserHeight ? mUserHeight : mDefaultHeight;
307                 return NO_ERROR;
308             case NATIVE_WINDOW_TRANSFORM_HINT:
309                 *value = mTransformHint;
310                 return NO_ERROR;
311             case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
312                 status_t err = NO_ERROR;
313                 if (!mConsumerRunningBehind) {
314                     *value = 0;
315                 } else {
316                     err = mSurfaceTexture->query(what, value);
317                     if (err == NO_ERROR) {
318                         mConsumerRunningBehind = *value;
319                     }
320                 }
321                 return err;
322             }
323         }
324     }
325     return mSurfaceTexture->query(what, value);
326 }
327
328 int SurfaceTextureClient::perform(int operation, va_list args)
329 {
330     int res = NO_ERROR;
331     switch (operation) {
332     case NATIVE_WINDOW_CONNECT:
333         // deprecated. must return NO_ERROR.
334         break;
335     case NATIVE_WINDOW_DISCONNECT:
336         // deprecated. must return NO_ERROR.
337         break;
338     case NATIVE_WINDOW_SET_USAGE:
339         res = dispatchSetUsage(args);
340         break;
341     case NATIVE_WINDOW_SET_CROP:
342         res = dispatchSetCrop(args);
343         break;
344     case NATIVE_WINDOW_SET_POST_TRANSFORM_CROP:
345         res = dispatchSetPostTransformCrop(args);
346         break;
347     case NATIVE_WINDOW_SET_BUFFER_COUNT:
348         res = dispatchSetBufferCount(args);
349         break;
350     case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
351         res = dispatchSetBuffersGeometry(args);
352         break;
353     case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
354         res = dispatchSetBuffersTransform(args);
355         break;
356     case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
357         res = dispatchSetBuffersTimestamp(args);
358         break;
359     case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
360         res = dispatchSetBuffersDimensions(args);
361         break;
362     case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
363         res = dispatchSetBuffersUserDimensions(args);
364         break;
365     case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
366         res = dispatchSetBuffersFormat(args);
367         break;
368     case NATIVE_WINDOW_LOCK:
369         res = dispatchLock(args);
370         break;
371     case NATIVE_WINDOW_UNLOCK_AND_POST:
372         res = dispatchUnlockAndPost(args);
373         break;
374     case NATIVE_WINDOW_SET_SCALING_MODE:
375         res = dispatchSetScalingMode(args);
376         break;
377     case NATIVE_WINDOW_API_CONNECT:
378         res = dispatchConnect(args);
379         break;
380     case NATIVE_WINDOW_API_DISCONNECT:
381         res = dispatchDisconnect(args);
382         break;
383     default:
384         res = NAME_NOT_FOUND;
385         break;
386     }
387     return res;
388 }
389
390 int SurfaceTextureClient::dispatchConnect(va_list args) {
391     int api = va_arg(args, int);
392     return connect(api);
393 }
394
395 int SurfaceTextureClient::dispatchDisconnect(va_list args) {
396     int api = va_arg(args, int);
397     return disconnect(api);
398 }
399
400 int SurfaceTextureClient::dispatchSetUsage(va_list args) {
401     int usage = va_arg(args, int);
402     return setUsage(usage);
403 }
404
405 int SurfaceTextureClient::dispatchSetCrop(va_list args) {
406     android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
407     return setCrop(reinterpret_cast<Rect const*>(rect));
408 }
409
410 int SurfaceTextureClient::dispatchSetPostTransformCrop(va_list args) {
411     android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
412     return setPostTransformCrop(reinterpret_cast<Rect const*>(rect));
413 }
414
415 int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
416     size_t bufferCount = va_arg(args, size_t);
417     return setBufferCount(bufferCount);
418 }
419
420 int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {
421     int w = va_arg(args, int);
422     int h = va_arg(args, int);
423     int f = va_arg(args, int);
424     int err = setBuffersDimensions(w, h);
425     if (err != 0) {
426         return err;
427     }
428     return setBuffersFormat(f);
429 }
430
431 int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) {
432     int w = va_arg(args, int);
433     int h = va_arg(args, int);
434     return setBuffersDimensions(w, h);
435 }
436
437 int SurfaceTextureClient::dispatchSetBuffersUserDimensions(va_list args) {
438     int w = va_arg(args, int);
439     int h = va_arg(args, int);
440     return setBuffersUserDimensions(w, h);
441 }
442
443 int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
444     int f = va_arg(args, int);
445     return setBuffersFormat(f);
446 }
447
448 int SurfaceTextureClient::dispatchSetScalingMode(va_list args) {
449     int m = va_arg(args, int);
450     return setScalingMode(m);
451 }
452
453 int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
454     int transform = va_arg(args, int);
455     return setBuffersTransform(transform);
456 }
457
458 int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
459     int64_t timestamp = va_arg(args, int64_t);
460     return setBuffersTimestamp(timestamp);
461 }
462
463 int SurfaceTextureClient::dispatchLock(va_list args) {
464     ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*);
465     ARect* inOutDirtyBounds = va_arg(args, ARect*);
466     return lock(outBuffer, inOutDirtyBounds);
467 }
468
469 int SurfaceTextureClient::dispatchUnlockAndPost(va_list args) {
470     return unlockAndPost();
471 }
472
473
474 int SurfaceTextureClient::connect(int api) {
475     ATRACE_CALL();
476     ALOGV("SurfaceTextureClient::connect");
477     Mutex::Autolock lock(mMutex);
478     ISurfaceTexture::QueueBufferOutput output;
479     int err = mSurfaceTexture->connect(api, &output);
480     if (err == NO_ERROR) {
481         uint32_t numPendingBuffers = 0;
482         output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
483                 &numPendingBuffers);
484         mConsumerRunningBehind = (numPendingBuffers >= 2);
485     }
486     if (!err && api == NATIVE_WINDOW_API_CPU) {
487         mConnectedToCpu = true;
488     }
489     return err;
490 }
491
492 int SurfaceTextureClient::disconnect(int api) {
493     ATRACE_CALL();
494     ALOGV("SurfaceTextureClient::disconnect");
495     Mutex::Autolock lock(mMutex);
496     freeAllBuffers();
497     int err = mSurfaceTexture->disconnect(api);
498     if (!err) {
499         mReqFormat = 0;
500         mReqWidth = 0;
501         mReqHeight = 0;
502         mReqUsage = 0;
503         mCrop.clear();
504         mCropNeedsTransform = false;
505         mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
506         mTransform = 0;
507         if (api == NATIVE_WINDOW_API_CPU) {
508             mConnectedToCpu = false;
509         }
510     }
511     return err;
512 }
513
514 int SurfaceTextureClient::setUsage(uint32_t reqUsage)
515 {
516     ALOGV("SurfaceTextureClient::setUsage");
517     Mutex::Autolock lock(mMutex);
518     mReqUsage = reqUsage;
519     return OK;
520 }
521
522 int SurfaceTextureClient::setCrop(Rect const* rect)
523 {
524     ATRACE_CALL();
525     ALOGV("SurfaceTextureClient::setCrop");
526
527     Rect realRect;
528     if (rect == NULL || rect->isEmpty()) {
529         realRect.clear();
530     } else {
531         realRect = *rect;
532     }
533
534     Mutex::Autolock lock(mMutex);
535     mCrop = realRect;
536     mCropNeedsTransform = false;
537     return NO_ERROR;
538 }
539
540 int SurfaceTextureClient::setPostTransformCrop(Rect const* rect)
541 {
542     ATRACE_CALL();
543     ALOGV("SurfaceTextureClient::setPostTransformCrop");
544
545     Rect realRect;
546     if (rect == NULL || rect->isEmpty()) {
547         realRect.clear();
548     } else {
549         realRect = *rect;
550     }
551
552     Mutex::Autolock lock(mMutex);
553     mCrop = realRect;
554     mCropNeedsTransform = true;
555     return NO_ERROR;
556 }
557
558 int SurfaceTextureClient::setBufferCount(int bufferCount)
559 {
560     ATRACE_CALL();
561     ALOGV("SurfaceTextureClient::setBufferCount");
562     Mutex::Autolock lock(mMutex);
563
564     status_t err = mSurfaceTexture->setBufferCount(bufferCount);
565     ALOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s",
566             bufferCount, strerror(-err));
567
568     if (err == NO_ERROR) {
569         freeAllBuffers();
570     }
571
572     return err;
573 }
574
575 int SurfaceTextureClient::setBuffersDimensions(int w, int h)
576 {
577     ATRACE_CALL();
578     ALOGV("SurfaceTextureClient::setBuffersDimensions");
579
580     if (w<0 || h<0)
581         return BAD_VALUE;
582
583     if ((w && !h) || (!w && h))
584         return BAD_VALUE;
585
586     Mutex::Autolock lock(mMutex);
587     mReqWidth = w;
588     mReqHeight = h;
589     return NO_ERROR;
590 }
591
592 int SurfaceTextureClient::setBuffersUserDimensions(int w, int h)
593 {
594     ATRACE_CALL();
595     ALOGV("SurfaceTextureClient::setBuffersUserDimensions");
596
597     if (w<0 || h<0)
598         return BAD_VALUE;
599
600     if ((w && !h) || (!w && h))
601         return BAD_VALUE;
602
603     Mutex::Autolock lock(mMutex);
604     mUserWidth = w;
605     mUserHeight = h;
606     return NO_ERROR;
607 }
608
609 int SurfaceTextureClient::setBuffersFormat(int format)
610 {
611     ALOGV("SurfaceTextureClient::setBuffersFormat");
612
613     if (format<0)
614         return BAD_VALUE;
615
616     Mutex::Autolock lock(mMutex);
617     mReqFormat = format;
618     return NO_ERROR;
619 }
620
621 int SurfaceTextureClient::setScalingMode(int mode)
622 {
623     ATRACE_CALL();
624     ALOGV("SurfaceTextureClient::setScalingMode(%d)", mode);
625
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         case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
631             break;
632         default:
633             ALOGE("unknown scaling mode: %d", mode);
634             return BAD_VALUE;
635     }
636
637     Mutex::Autolock lock(mMutex);
638     mScalingMode = mode;
639     return NO_ERROR;
640 }
641
642 int SurfaceTextureClient::setBuffersTransform(int transform)
643 {
644     ATRACE_CALL();
645     ALOGV("SurfaceTextureClient::setBuffersTransform");
646     Mutex::Autolock lock(mMutex);
647     mTransform = transform;
648     return NO_ERROR;
649 }
650
651 int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
652 {
653     ALOGV("SurfaceTextureClient::setBuffersTimestamp");
654     Mutex::Autolock lock(mMutex);
655     mTimestamp = timestamp;
656     return NO_ERROR;
657 }
658
659 void SurfaceTextureClient::freeAllBuffers() {
660     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
661         mSlots[i].buffer = 0;
662     }
663 }
664
665 // ----------------------------------------------------------------------
666 // the lock/unlock APIs must be used from the same thread
667
668 static status_t copyBlt(
669         const sp<GraphicBuffer>& dst,
670         const sp<GraphicBuffer>& src,
671         const Region& reg)
672 {
673     // src and dst with, height and format must be identical. no verification
674     // is done here.
675     status_t err;
676     uint8_t const * src_bits = NULL;
677     err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
678     ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
679
680     uint8_t* dst_bits = NULL;
681     err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
682     ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
683
684     Region::const_iterator head(reg.begin());
685     Region::const_iterator tail(reg.end());
686     if (head != tail && src_bits && dst_bits) {
687         const size_t bpp = bytesPerPixel(src->format);
688         const size_t dbpr = dst->stride * bpp;
689         const size_t sbpr = src->stride * bpp;
690
691         while (head != tail) {
692             const Rect& r(*head++);
693             ssize_t h = r.height();
694             if (h <= 0) continue;
695             size_t size = r.width() * bpp;
696             uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
697             uint8_t       * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
698             if (dbpr==sbpr && size==sbpr) {
699                 size *= h;
700                 h = 1;
701             }
702             do {
703                 memcpy(d, s, size);
704                 d += dbpr;
705                 s += sbpr;
706             } while (--h > 0);
707         }
708     }
709
710     if (src_bits)
711         src->unlock();
712
713     if (dst_bits)
714         dst->unlock();
715
716     return err;
717 }
718
719 // ----------------------------------------------------------------------------
720
721 status_t SurfaceTextureClient::lock(
722         ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
723 {
724     if (mLockedBuffer != 0) {
725         ALOGE("Surface::lock failed, already locked");
726         return INVALID_OPERATION;
727     }
728
729     if (!mConnectedToCpu) {
730         int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU);
731         if (err) {
732             return err;
733         }
734         // we're intending to do software rendering from this point
735         setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
736     }
737
738     ANativeWindowBuffer* out;
739     status_t err = dequeueBuffer(&out);
740     ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
741     if (err == NO_ERROR) {
742         sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
743         err = lockBuffer(backBuffer.get());
744         ALOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
745                 backBuffer->handle, strerror(-err));
746         if (err == NO_ERROR) {
747             const Rect bounds(backBuffer->width, backBuffer->height);
748
749             Region newDirtyRegion;
750             if (inOutDirtyBounds) {
751                 newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
752                 newDirtyRegion.andSelf(bounds);
753             } else {
754                 newDirtyRegion.set(bounds);
755             }
756
757             // figure out if we can copy the frontbuffer back
758             const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
759             const bool canCopyBack = (frontBuffer != 0 &&
760                     backBuffer->width  == frontBuffer->width &&
761                     backBuffer->height == frontBuffer->height &&
762                     backBuffer->format == frontBuffer->format);
763
764             if (canCopyBack) {
765                 // copy the area that is invalid and not repainted this round
766                 const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
767                 if (!copyback.isEmpty())
768                     copyBlt(backBuffer, frontBuffer, copyback);
769             } else {
770                 // if we can't copy-back anything, modify the user's dirty
771                 // region to make sure they redraw the whole buffer
772                 newDirtyRegion.set(bounds);
773                 mDirtyRegion.clear();
774                 Mutex::Autolock lock(mMutex);
775                 for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
776                     mSlots[i].dirtyRegion.clear();
777                 }
778             }
779
780
781             { // scope for the lock
782                 Mutex::Autolock lock(mMutex);
783                 int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
784                 if (backBufferSlot >= 0) {
785                     Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
786                     mDirtyRegion.subtract(dirtyRegion);
787                     dirtyRegion = newDirtyRegion;
788                 }
789             }
790
791             mDirtyRegion.orSelf(newDirtyRegion);
792             if (inOutDirtyBounds) {
793                 *inOutDirtyBounds = newDirtyRegion.getBounds();
794             }
795
796             void* vaddr;
797             status_t res = backBuffer->lock(
798                     GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
799                     newDirtyRegion.bounds(), &vaddr);
800
801             ALOGW_IF(res, "failed locking buffer (handle = %p)",
802                     backBuffer->handle);
803
804             mLockedBuffer = backBuffer;
805             outBuffer->width  = backBuffer->width;
806             outBuffer->height = backBuffer->height;
807             outBuffer->stride = backBuffer->stride;
808             outBuffer->format = backBuffer->format;
809             outBuffer->bits   = vaddr;
810         }
811     }
812     return err;
813 }
814
815 status_t SurfaceTextureClient::unlockAndPost()
816 {
817     if (mLockedBuffer == 0) {
818         ALOGE("Surface::unlockAndPost failed, no locked buffer");
819         return INVALID_OPERATION;
820     }
821
822     status_t err = mLockedBuffer->unlock();
823     ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
824
825     err = queueBuffer(mLockedBuffer.get());
826     ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
827             mLockedBuffer->handle, strerror(-err));
828
829     mPostedBuffer = mLockedBuffer;
830     mLockedBuffer = 0;
831     return err;
832 }
833
834 }; // namespace android