1/*
2 * Copyright (C) 2011 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_test"
18//#define LOG_NDEBUG 0
19
20#include <EGL/egl.h>
21#include <GLES2/gl2.h>
22
23#include <gtest/gtest.h>
24#include <gui/GLConsumer.h>
25#include <gui/Surface.h>
26#include <system/graphics.h>
27#include <utils/Log.h>
28#include <utils/Thread.h>
29
30EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
31#define CROP_EXT_STR "EGL_ANDROID_image_crop"
32
33namespace android {
34
35class SurfaceTextureClientTest : public ::testing::Test {
36protected:
37    SurfaceTextureClientTest():
38            mEglDisplay(EGL_NO_DISPLAY),
39            mEglSurface(EGL_NO_SURFACE),
40            mEglContext(EGL_NO_CONTEXT),
41            mEglConfig(NULL) {
42    }
43
44    virtual void SetUp() {
45        const ::testing::TestInfo* const testInfo =
46            ::testing::UnitTest::GetInstance()->current_test_info();
47        ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
48                testInfo->name());
49
50        sp<IGraphicBufferProducer> producer;
51        sp<IGraphicBufferConsumer> consumer;
52        BufferQueue::createBufferQueue(&producer, &consumer);
53        mST = new GLConsumer(consumer, 123, GLConsumer::TEXTURE_EXTERNAL, true,
54                false);
55        mSTC = new Surface(producer);
56        mANW = mSTC;
57
58        // We need a valid GL context so we can test updateTexImage()
59        // This initializes EGL and create a dummy GL context with a
60        // pbuffer render target.
61        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
62        ASSERT_EQ(EGL_SUCCESS, eglGetError());
63        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
64
65        EGLint majorVersion, minorVersion;
66        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
67        ASSERT_EQ(EGL_SUCCESS, eglGetError());
68
69        EGLConfig myConfig;
70        EGLint numConfigs = 0;
71        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(),
72                &myConfig, 1, &numConfigs));
73        ASSERT_EQ(EGL_SUCCESS, eglGetError());
74
75        mEglConfig = myConfig;
76        EGLint pbufferAttribs[] = {
77            EGL_WIDTH, 16,
78            EGL_HEIGHT, 16,
79            EGL_NONE };
80        mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, pbufferAttribs);
81        ASSERT_EQ(EGL_SUCCESS, eglGetError());
82        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
83
84        mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0);
85        ASSERT_EQ(EGL_SUCCESS, eglGetError());
86        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
87
88        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext));
89        ASSERT_EQ(EGL_SUCCESS, eglGetError());
90    }
91
92    virtual void TearDown() {
93        mST.clear();
94        mSTC.clear();
95        mANW.clear();
96
97        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
98        eglDestroyContext(mEglDisplay, mEglContext);
99        eglDestroySurface(mEglDisplay, mEglSurface);
100        eglTerminate(mEglDisplay);
101
102        const ::testing::TestInfo* const testInfo =
103            ::testing::UnitTest::GetInstance()->current_test_info();
104        ALOGV("End test:   %s.%s", testInfo->test_case_name(),
105                testInfo->name());
106    }
107
108    virtual EGLint const* getConfigAttribs() {
109        static EGLint sDefaultConfigAttribs[] = {
110            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT,
111            EGL_NONE
112        };
113
114        return sDefaultConfigAttribs;
115    }
116
117    sp<GLConsumer> mST;
118    sp<Surface> mSTC;
119    sp<ANativeWindow> mANW;
120
121    EGLDisplay mEglDisplay;
122    EGLSurface mEglSurface;
123    EGLContext mEglContext;
124    EGLConfig  mEglConfig;
125};
126
127TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) {
128    sp<IGraphicBufferProducer> ist(mSTC->getIGraphicBufferProducer());
129    ASSERT_TRUE(ist != NULL);
130}
131
132TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) {
133    int result = -123;
134    int err = mANW->query(mANW.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
135            &result);
136    EXPECT_EQ(NO_ERROR, err);
137    EXPECT_EQ(0, result);
138}
139
140TEST_F(SurfaceTextureClientTest, ConcreteTypeIsSurfaceTextureClient) {
141    int result = -123;
142    int err = mANW->query(mANW.get(), NATIVE_WINDOW_CONCRETE_TYPE, &result);
143    EXPECT_EQ(NO_ERROR, err);
144    EXPECT_EQ(NATIVE_WINDOW_SURFACE, result);
145}
146
147TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
148    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
149    ASSERT_EQ(EGL_SUCCESS, eglGetError());
150    ASSERT_NE(EGL_NO_DISPLAY, dpy);
151
152    EGLint majorVersion;
153    EGLint minorVersion;
154    EXPECT_TRUE(eglInitialize(dpy, &majorVersion, &minorVersion));
155    ASSERT_EQ(EGL_SUCCESS, eglGetError());
156
157    EGLConfig myConfig = {0};
158    EGLint numConfigs = 0;
159    EGLint configAttribs[] = {
160        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
161        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
162        EGL_RED_SIZE, 8,
163        EGL_GREEN_SIZE, 8,
164        EGL_BLUE_SIZE, 8,
165        EGL_ALPHA_SIZE, 8,
166        EGL_DEPTH_SIZE, 16,
167        EGL_STENCIL_SIZE, 8,
168        EGL_NONE };
169    EXPECT_TRUE(eglChooseConfig(dpy, configAttribs, &myConfig, 1,
170            &numConfigs));
171    ASSERT_EQ(EGL_SUCCESS, eglGetError());
172
173    EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, mANW.get(),
174            NULL);
175    EXPECT_NE(EGL_NO_SURFACE, eglSurface);
176    EXPECT_EQ(EGL_SUCCESS, eglGetError());
177
178    if (eglSurface != EGL_NO_SURFACE) {
179        eglDestroySurface(dpy, eglSurface);
180    }
181
182    eglTerminate(dpy);
183}
184
185TEST_F(SurfaceTextureClientTest, EglSwapBuffersAbandonErrorIsEglBadSurface) {
186
187    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, mANW.get(), NULL);
188    EXPECT_NE(EGL_NO_SURFACE, eglSurface);
189    EXPECT_EQ(EGL_SUCCESS, eglGetError());
190
191    EGLBoolean success = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
192    EXPECT_TRUE(success);
193
194    glClear(GL_COLOR_BUFFER_BIT);
195    success = eglSwapBuffers(mEglDisplay, eglSurface);
196    EXPECT_TRUE(success);
197
198    mST->abandon();
199
200    glClear(GL_COLOR_BUFFER_BIT);
201    success = eglSwapBuffers(mEglDisplay, eglSurface);
202    EXPECT_FALSE(success);
203    EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
204
205    success = eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
206    ASSERT_TRUE(success);
207
208    if (eglSurface != EGL_NO_SURFACE) {
209        eglDestroySurface(mEglDisplay, eglSurface);
210    }
211}
212
213TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
214    EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(),  0,  8));
215    EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(),  8,  0));
216}
217
218TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
219    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
220    ANativeWindowBuffer* buf;
221    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
222    EXPECT_EQ(1, buf->width);
223    EXPECT_EQ(1, buf->height);
224    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
225    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
226}
227
228TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
229    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
230    ANativeWindowBuffer* buf;
231    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
232    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
233    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
234    EXPECT_EQ(16, buf->width);
235    EXPECT_EQ(8, buf->height);
236    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
237    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
238}
239
240TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
241    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
242    ANativeWindowBuffer* buf;
243    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
244    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
245    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
246    EXPECT_EQ(1, buf->width);
247    EXPECT_EQ(1, buf->height);
248    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
249    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
250}
251
252TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
253    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
254    ANativeWindowBuffer* buf;
255    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
256    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
257    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
258    EXPECT_EQ(16, buf->width);
259    EXPECT_EQ(8, buf->height);
260    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
261    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
262}
263
264TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
265    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
266    ANativeWindowBuffer* buf;
267    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
268    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
269    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
270    EXPECT_EQ(16, buf->width);
271    EXPECT_EQ(8, buf->height);
272    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
273    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
274    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
275    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
276    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
277    EXPECT_EQ(1, buf->width);
278    EXPECT_EQ(1, buf->height);
279    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
280    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
281}
282
283TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
284    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
285    ANativeWindowBuffer* buf;
286    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
287    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
288    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
289    EXPECT_EQ(1, buf->width);
290    EXPECT_EQ(1, buf->height);
291    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
292    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
293    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
294    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
295    EXPECT_EQ(16, buf->width);
296    EXPECT_EQ(8, buf->height);
297    EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
298    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
299}
300
301TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
302    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
303    sp<GLConsumer> st(mST);
304    ANativeWindowBuffer* buf;
305    EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
306    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
307    EXPECT_EQ(16, buf->width);
308    EXPECT_EQ(8, buf->height);
309    EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
310    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
311}
312
313TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
314    ANativeWindowBuffer* buf[2];
315    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
316    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
317    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
318    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
319    EXPECT_NE(buf[0], buf[1]);
320    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
321    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
322    EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
323    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
324    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
325    EXPECT_NE(buf[0], buf[1]);
326    EXPECT_EQ(16, buf[0]->width);
327    EXPECT_EQ(16, buf[1]->width);
328    EXPECT_EQ(8, buf[0]->height);
329    EXPECT_EQ(8, buf[1]->height);
330    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
331    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
332}
333
334TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
335    ANativeWindowBuffer* buf[2];
336    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
337    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
338    EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
339    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
340    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
341    EXPECT_NE(buf[0], buf[1]);
342    EXPECT_EQ(16, buf[0]->width);
343    EXPECT_EQ(16, buf[1]->width);
344    EXPECT_EQ(8, buf[0]->height);
345    EXPECT_EQ(8, buf[1]->height);
346    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
347    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
348    EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 12, 24));
349    EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
350    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
351    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
352    EXPECT_NE(buf[0], buf[1]);
353    EXPECT_EQ(12, buf[0]->width);
354    EXPECT_EQ(12, buf[1]->width);
355    EXPECT_EQ(24, buf[0]->height);
356    EXPECT_EQ(24, buf[1]->height);
357    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
358    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
359}
360
361TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
362    android_native_buffer_t* buf[3];
363    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
364    ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
365    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
366
367    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
368    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
369    EXPECT_EQ(OK, mST->updateTexImage());
370    EXPECT_EQ(OK, mST->updateTexImage());
371
372    ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 1));
373    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
374
375    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
376    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
377    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
378    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
379
380    EXPECT_EQ(OK, mST->updateTexImage());
381    EXPECT_EQ(OK, mST->updateTexImage());
382    EXPECT_EQ(OK, mST->updateTexImage());
383}
384
385TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
386    android_native_buffer_t* buf[3];
387    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
388    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
389    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
390    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
391    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
392    EXPECT_NE(buf[0], buf[1]);
393    EXPECT_NE(buf[1], buf[2]);
394    EXPECT_NE(buf[2], buf[0]);
395    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
396    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
397    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
398    EXPECT_EQ(OK, mST->updateTexImage());
399    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
400    EXPECT_EQ(OK, mST->updateTexImage());
401    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
402    EXPECT_EQ(OK, mST->updateTexImage());
403    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
404}
405
406TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
407    android_native_buffer_t* buf[3];
408    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
409    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
410    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
411    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
412    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
413    EXPECT_NE(buf[0], buf[1]);
414    EXPECT_NE(buf[1], buf[2]);
415    EXPECT_NE(buf[2], buf[0]);
416    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
417    EXPECT_EQ(OK, mST->updateTexImage());
418    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
419    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
420    EXPECT_EQ(OK, mST->updateTexImage());
421    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
422    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
423    EXPECT_EQ(OK, mST->updateTexImage());
424    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
425}
426
427TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
428    android_native_buffer_t* buf[3];
429    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
430    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
431    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
432    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
433    EXPECT_EQ(OK, mST->updateTexImage());
434    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
435
436    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
437    EXPECT_NE(buf[0], buf[1]);
438    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
439    EXPECT_EQ(OK, mST->updateTexImage());
440    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
441
442    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
443    EXPECT_NE(buf[1], buf[2]);
444    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
445    EXPECT_EQ(OK, mST->updateTexImage());
446    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
447}
448
449// XXX: We currently have no hardware that properly handles dequeuing the
450// buffer that is currently bound to the texture.
451TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
452    android_native_buffer_t* buf[3];
453    android_native_buffer_t* firstBuf;
454    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
455    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
456    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
457    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
458    EXPECT_EQ(OK, mST->updateTexImage());
459    EXPECT_EQ(mST->getCurrentBuffer().get(), firstBuf);
460    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
461    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
462    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
463    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
464    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
465    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
466    EXPECT_NE(buf[0], buf[1]);
467    EXPECT_NE(buf[1], buf[2]);
468    EXPECT_NE(buf[2], buf[0]);
469    EXPECT_EQ(firstBuf, buf[2]);
470}
471
472TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
473    android_native_buffer_t* buf[3];
474    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
475    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
476
477    // We should be able to dequeue all the buffers before we've queued mANWy.
478    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
479    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
480    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
481
482    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
483    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
484
485    EXPECT_EQ(OK, mST->updateTexImage());
486    EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
487
488    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
489
490    // Once we've queued a buffer, however we should not be able to dequeue more
491    // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
492    EXPECT_EQ(INVALID_OPERATION,
493            native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
494
495    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
496    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
497}
498
499TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
500    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
501    android_native_rect_t rect = {-2, -13, 40, 18};
502    native_window_set_crop(mANW.get(), &rect);
503
504    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 4, 4));
505
506    android_native_buffer_t* buf;
507    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
508    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf, -1));
509    ASSERT_EQ(OK, mST->updateTexImage());
510
511    Rect crop = mST->getCurrentCrop();
512    EXPECT_EQ(0, crop.left);
513    EXPECT_EQ(0, crop.top);
514    EXPECT_EQ(4, crop.right);
515    EXPECT_EQ(4, crop.bottom);
516}
517
518// XXX: This is not expected to pass until the synchronization hacks are removed
519// from the SurfaceTexture class.
520TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
521    class MyThread : public Thread {
522        sp<GLConsumer> mST;
523        EGLContext ctx;
524        EGLSurface sur;
525        EGLDisplay dpy;
526        bool mBufferRetired;
527        Mutex mLock;
528        virtual bool threadLoop() {
529            eglMakeCurrent(dpy, sur, sur, ctx);
530            usleep(20000);
531            Mutex::Autolock _l(mLock);
532            mST->updateTexImage();
533            mBufferRetired = true;
534            eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
535            return false;
536        }
537    public:
538        MyThread(const sp<GLConsumer>& mST)
539            : mST(mST), mBufferRetired(false) {
540            ctx = eglGetCurrentContext();
541            sur = eglGetCurrentSurface(EGL_DRAW);
542            dpy = eglGetCurrentDisplay();
543            eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
544        }
545        ~MyThread() {
546            eglMakeCurrent(dpy, sur, sur, ctx);
547        }
548        void bufferDequeued() {
549            Mutex::Autolock _l(mLock);
550            EXPECT_EQ(true, mBufferRetired);
551        }
552    };
553
554    android_native_buffer_t* buf[3];
555    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
556    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
557    // dequeue/queue/update so we have a current buffer
558    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
559    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
560    mST->updateTexImage();
561
562    MyThread* thread = new MyThread(mST);
563    sp<Thread> threadBase(thread);
564
565    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
566    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
567    thread->run("MyThread");
568    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
569    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
570    //ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
571    //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
572    thread->bufferDequeued();
573    thread->requestExitAndWait();
574}
575
576TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
577    android_native_buffer_t* buf[3];
578    float mtx[16] = {};
579    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
580    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
581    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
582    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
583    ASSERT_EQ(OK, mST->updateTexImage());
584    mST->getTransformMatrix(mtx);
585
586    EXPECT_EQ(1.f, mtx[0]);
587    EXPECT_EQ(0.f, mtx[1]);
588    EXPECT_EQ(0.f, mtx[2]);
589    EXPECT_EQ(0.f, mtx[3]);
590
591    EXPECT_EQ(0.f, mtx[4]);
592    EXPECT_EQ(-1.f, mtx[5]);
593    EXPECT_EQ(0.f, mtx[6]);
594    EXPECT_EQ(0.f, mtx[7]);
595
596    EXPECT_EQ(0.f, mtx[8]);
597    EXPECT_EQ(0.f, mtx[9]);
598    EXPECT_EQ(1.f, mtx[10]);
599    EXPECT_EQ(0.f, mtx[11]);
600
601    EXPECT_EQ(0.f, mtx[12]);
602    EXPECT_EQ(1.f, mtx[13]);
603    EXPECT_EQ(0.f, mtx[14]);
604    EXPECT_EQ(1.f, mtx[15]);
605}
606
607TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
608    android_native_buffer_t* buf[3];
609    float mtx[16] = {};
610    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
611    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
612    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
613    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
614    ASSERT_EQ(OK, mST->updateTexImage());
615    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
616    mST->getTransformMatrix(mtx);
617
618    EXPECT_EQ(1.f, mtx[0]);
619    EXPECT_EQ(0.f, mtx[1]);
620    EXPECT_EQ(0.f, mtx[2]);
621    EXPECT_EQ(0.f, mtx[3]);
622
623    EXPECT_EQ(0.f, mtx[4]);
624    EXPECT_EQ(-1.f, mtx[5]);
625    EXPECT_EQ(0.f, mtx[6]);
626    EXPECT_EQ(0.f, mtx[7]);
627
628    EXPECT_EQ(0.f, mtx[8]);
629    EXPECT_EQ(0.f, mtx[9]);
630    EXPECT_EQ(1.f, mtx[10]);
631    EXPECT_EQ(0.f, mtx[11]);
632
633    EXPECT_EQ(0.f, mtx[12]);
634    EXPECT_EQ(1.f, mtx[13]);
635    EXPECT_EQ(0.f, mtx[14]);
636    EXPECT_EQ(1.f, mtx[15]);
637}
638
639TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) {
640    // Query to see if the image crop extension exists
641    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
642    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
643    size_t cropExtLen = strlen(CROP_EXT_STR);
644    size_t extsLen = strlen(exts);
645    bool equal = !strcmp(CROP_EXT_STR, exts);
646    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
647    bool atEnd = (cropExtLen+1) < extsLen &&
648            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
649    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
650    bool hasEglAndroidImageCrop = equal || atStart || atEnd || inMiddle;
651
652    android_native_buffer_t* buf[3];
653    float mtx[16] = {};
654    android_native_rect_t crop;
655    crop.left = 0;
656    crop.top = 0;
657    crop.right = 5;
658    crop.bottom = 5;
659
660    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
661    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
662    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
663    ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
664    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
665    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop));
666    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
667    ASSERT_EQ(OK, mST->updateTexImage());
668    ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
669    mST->getTransformMatrix(mtx);
670
671    // If the egl image crop extension is not present, this accounts for the
672    // .5 texel shrink for each edge that's included in the transform matrix
673    // to avoid texturing outside the crop region. Otherwise the crop is not
674    // included in the transform matrix.
675    EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5, mtx[0]);
676    EXPECT_EQ(0.f, mtx[1]);
677    EXPECT_EQ(0.f, mtx[2]);
678    EXPECT_EQ(0.f, mtx[3]);
679
680    EXPECT_EQ(0.f, mtx[4]);
681    EXPECT_EQ(hasEglAndroidImageCrop ? -1 : -0.5, mtx[5]);
682    EXPECT_EQ(0.f, mtx[6]);
683    EXPECT_EQ(0.f, mtx[7]);
684
685    EXPECT_EQ(0.f, mtx[8]);
686    EXPECT_EQ(0.f, mtx[9]);
687    EXPECT_EQ(1.f, mtx[10]);
688    EXPECT_EQ(0.f, mtx[11]);
689
690    EXPECT_EQ(hasEglAndroidImageCrop ? 0 : 0.0625f, mtx[12]);
691    EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5625f, mtx[13]);
692    EXPECT_EQ(0.f, mtx[14]);
693    EXPECT_EQ(1.f, mtx[15]);
694}
695
696// This test verifies that the buffer format can be queried immediately after
697// it is set.
698TEST_F(SurfaceTextureClientTest, QueryFormatAfterSettingWorks) {
699    sp<ANativeWindow> anw(mSTC);
700    int fmts[] = {
701        // RGBA_8888 should not come first, as it's the default
702        HAL_PIXEL_FORMAT_RGBX_8888,
703        HAL_PIXEL_FORMAT_RGBA_8888,
704        HAL_PIXEL_FORMAT_RGB_888,
705        HAL_PIXEL_FORMAT_RGB_565,
706        HAL_PIXEL_FORMAT_BGRA_8888,
707        HAL_PIXEL_FORMAT_YV12,
708    };
709
710    const int numFmts = (sizeof(fmts) / sizeof(fmts[0]));
711    for (int i = 0; i < numFmts; i++) {
712      int fmt = -1;
713      ASSERT_EQ(OK, native_window_set_buffers_dimensions(anw.get(), 0, 0));
714      ASSERT_EQ(OK, native_window_set_buffers_format(anw.get(), fmts[i]));
715      ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt));
716      EXPECT_EQ(fmts[i], fmt);
717    }
718}
719
720class MultiSurfaceTextureClientTest : public ::testing::Test {
721
722public:
723    MultiSurfaceTextureClientTest() :
724            mEglDisplay(EGL_NO_DISPLAY),
725            mEglContext(EGL_NO_CONTEXT) {
726        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
727            mEglSurfaces[i] = EGL_NO_CONTEXT;
728        }
729    }
730
731protected:
732
733    enum { NUM_SURFACE_TEXTURES = 32 };
734
735    virtual void SetUp() {
736        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
737        ASSERT_EQ(EGL_SUCCESS, eglGetError());
738        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
739
740        EGLint majorVersion, minorVersion;
741        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
742        ASSERT_EQ(EGL_SUCCESS, eglGetError());
743
744        EGLConfig myConfig;
745        EGLint numConfigs = 0;
746        EGLint configAttribs[] = {
747            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
748            EGL_NONE
749        };
750        EXPECT_TRUE(eglChooseConfig(mEglDisplay, configAttribs, &myConfig, 1,
751                &numConfigs));
752        ASSERT_EQ(EGL_SUCCESS, eglGetError());
753
754        mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT,
755                0);
756        ASSERT_EQ(EGL_SUCCESS, eglGetError());
757        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
758
759        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
760            sp<IGraphicBufferProducer> producer;
761            sp<IGraphicBufferConsumer> consumer;
762            BufferQueue::createBufferQueue(&producer, &consumer);
763            sp<GLConsumer> st(new GLConsumer(consumer, i,
764                    GLConsumer::TEXTURE_EXTERNAL, true, false));
765            sp<Surface> stc(new Surface(producer));
766            mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig,
767                    static_cast<ANativeWindow*>(stc.get()), NULL);
768            ASSERT_EQ(EGL_SUCCESS, eglGetError());
769            ASSERT_NE(EGL_NO_SURFACE, mEglSurfaces[i]);
770        }
771    }
772
773    virtual void TearDown() {
774        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
775                EGL_NO_CONTEXT);
776
777        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
778            if (mEglSurfaces[i] != EGL_NO_SURFACE) {
779                eglDestroySurface(mEglDisplay, mEglSurfaces[i]);
780            }
781        }
782
783        if (mEglContext != EGL_NO_CONTEXT) {
784            eglDestroyContext(mEglDisplay, mEglContext);
785        }
786
787        if (mEglDisplay != EGL_NO_DISPLAY) {
788            eglTerminate(mEglDisplay);
789        }
790    }
791
792    EGLDisplay mEglDisplay;
793    EGLSurface mEglSurfaces[NUM_SURFACE_TEXTURES];
794    EGLContext mEglContext;
795};
796
797// XXX: This test is disabled because it causes a hang on some devices.  See bug
798// 5015672.
799TEST_F(MultiSurfaceTextureClientTest, DISABLED_MakeCurrentBetweenSurfacesWorks) {
800    for (int iter = 0; iter < 8; iter++) {
801        for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
802            eglMakeCurrent(mEglDisplay, mEglSurfaces[i], mEglSurfaces[i],
803                    mEglContext);
804            glClear(GL_COLOR_BUFFER_BIT);
805            eglSwapBuffers(mEglDisplay, mEglSurfaces[i]);
806        }
807    }
808}
809
810} // namespace android
811