blob: 47f6df7b39718fc313914a128d84ba0197a6795c [file] [log] [blame]
Jamie Gennisd99c0882011-03-10 16:24:46 -08001/*
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
Jamie Gennis2640bfd2011-07-14 17:11:47 -070017#define LOG_TAG "SurfaceTexture_test"
Jamie Gennis5451d152011-06-08 09:40:45 -070018//#define LOG_NDEBUG 0
19
Jamie Gennisd99c0882011-03-10 16:24:46 -080020#include <gtest/gtest.h>
Andy McFadden2adaf042012-12-18 09:49:45 -080021#include <gui/GLConsumer.h>
Jamie Gennisd99c0882011-03-10 16:24:46 -080022#include <ui/GraphicBuffer.h>
23#include <utils/String8.h>
Jamie Gennis5451d152011-06-08 09:40:45 -070024#include <utils/threads.h>
Jamie Gennisd99c0882011-03-10 16:24:46 -080025
Mathias Agopian90ac7992012-02-25 18:48:35 -080026#include <gui/ISurfaceComposer.h>
27#include <gui/Surface.h>
28#include <gui/SurfaceComposerClient.h>
Jamie Gennisd99c0882011-03-10 16:24:46 -080029
30#include <EGL/egl.h>
31#include <EGL/eglext.h>
Mathias Agopianf31510a2013-04-16 23:32:38 -070032#include <GLES/gl.h>
33#include <GLES/glext.h>
Jamie Gennisd99c0882011-03-10 16:24:46 -080034#include <GLES2/gl2.h>
35#include <GLES2/gl2ext.h>
36
37#include <ui/FramebufferNativeWindow.h>
Mathias Agopianf31510a2013-04-16 23:32:38 -070038#include <utils/UniquePtr.h>
39#include <android/native_window.h>
Jamie Gennisd99c0882011-03-10 16:24:46 -080040
41namespace android {
42
43class GLTest : public ::testing::Test {
44protected:
45
46 GLTest():
47 mEglDisplay(EGL_NO_DISPLAY),
48 mEglSurface(EGL_NO_SURFACE),
49 mEglContext(EGL_NO_CONTEXT) {
50 }
51
52 virtual void SetUp() {
Jamie Gennisfa5b40e2012-03-15 14:01:24 -070053 const ::testing::TestInfo* const testInfo =
54 ::testing::UnitTest::GetInstance()->current_test_info();
55 ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
56 testInfo->name());
57
Jamie Gennisd99c0882011-03-10 16:24:46 -080058 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
59 ASSERT_EQ(EGL_SUCCESS, eglGetError());
60 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
61
62 EGLint majorVersion;
63 EGLint minorVersion;
64 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
65 ASSERT_EQ(EGL_SUCCESS, eglGetError());
66 RecordProperty("EglVersionMajor", majorVersion);
67 RecordProperty("EglVersionMajor", minorVersion);
68
Jamie Gennisd99c0882011-03-10 16:24:46 -080069 EGLint numConfigs = 0;
Jamie Gennis1876d132011-03-17 16:32:52 -070070 EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
Jamie Gennisd99c0882011-03-10 16:24:46 -080071 1, &numConfigs));
72 ASSERT_EQ(EGL_SUCCESS, eglGetError());
73
74 char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
75 if (displaySecsEnv != NULL) {
76 mDisplaySecs = atoi(displaySecsEnv);
77 if (mDisplaySecs < 0) {
78 mDisplaySecs = 0;
79 }
80 } else {
81 mDisplaySecs = 0;
82 }
83
84 if (mDisplaySecs > 0) {
85 mComposerClient = new SurfaceComposerClient;
86 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
87
Jamie Gennisfc850122011-04-25 16:40:05 -070088 mSurfaceControl = mComposerClient->createSurface(
Jeff Brown9d4e3d22012-08-24 20:00:51 -070089 String8("Test Surface"),
Jamie Gennisd99c0882011-03-10 16:24:46 -080090 getSurfaceWidth(), getSurfaceHeight(),
91 PIXEL_FORMAT_RGB_888, 0);
92
93 ASSERT_TRUE(mSurfaceControl != NULL);
94 ASSERT_TRUE(mSurfaceControl->isValid());
95
Mathias Agopian698c0872011-06-28 19:09:31 -070096 SurfaceComposerClient::openGlobalTransaction();
Jamie Gennis5dd0c4f2011-06-13 19:06:52 -070097 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
Jamie Gennisd99c0882011-03-10 16:24:46 -080098 ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
Mathias Agopian698c0872011-06-28 19:09:31 -070099 SurfaceComposerClient::closeGlobalTransaction();
Jamie Gennisd99c0882011-03-10 16:24:46 -0800100
101 sp<ANativeWindow> window = mSurfaceControl->getSurface();
Jamie Gennis1876d132011-03-17 16:32:52 -0700102 mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
Jamie Gennisd99c0882011-03-10 16:24:46 -0800103 window.get(), NULL);
104 } else {
105 EGLint pbufferAttribs[] = {
106 EGL_WIDTH, getSurfaceWidth(),
107 EGL_HEIGHT, getSurfaceHeight(),
108 EGL_NONE };
109
Jamie Gennis1876d132011-03-17 16:32:52 -0700110 mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
Jamie Gennisd99c0882011-03-10 16:24:46 -0800111 pbufferAttribs);
112 }
113 ASSERT_EQ(EGL_SUCCESS, eglGetError());
114 ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
115
Jamie Gennis1876d132011-03-17 16:32:52 -0700116 mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
Jamie Gennisd99c0882011-03-10 16:24:46 -0800117 getContextAttribs());
118 ASSERT_EQ(EGL_SUCCESS, eglGetError());
119 ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
120
121 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
122 mEglContext));
123 ASSERT_EQ(EGL_SUCCESS, eglGetError());
124
125 EGLint w, h;
126 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
127 ASSERT_EQ(EGL_SUCCESS, eglGetError());
128 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
129 ASSERT_EQ(EGL_SUCCESS, eglGetError());
130 RecordProperty("EglSurfaceWidth", w);
131 RecordProperty("EglSurfaceHeight", h);
132
133 glViewport(0, 0, w, h);
134 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
135 }
136
137 virtual void TearDown() {
Daniel Lam9abe1eb2012-03-26 20:37:15 -0700138 // Display the result
Jamie Gennisd99c0882011-03-10 16:24:46 -0800139 if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
140 eglSwapBuffers(mEglDisplay, mEglSurface);
141 sleep(mDisplaySecs);
142 }
143
144 if (mComposerClient != NULL) {
145 mComposerClient->dispose();
146 }
147 if (mEglContext != EGL_NO_CONTEXT) {
148 eglDestroyContext(mEglDisplay, mEglContext);
149 }
150 if (mEglSurface != EGL_NO_SURFACE) {
151 eglDestroySurface(mEglDisplay, mEglSurface);
152 }
153 if (mEglDisplay != EGL_NO_DISPLAY) {
154 eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
155 EGL_NO_CONTEXT);
156 eglTerminate(mEglDisplay);
157 }
158 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennisfa5b40e2012-03-15 14:01:24 -0700159
160 const ::testing::TestInfo* const testInfo =
161 ::testing::UnitTest::GetInstance()->current_test_info();
162 ALOGV("End test: %s.%s", testInfo->test_case_name(),
163 testInfo->name());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800164 }
165
166 virtual EGLint const* getConfigAttribs() {
167 static EGLint sDefaultConfigAttribs[] = {
168 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
169 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
170 EGL_RED_SIZE, 8,
171 EGL_GREEN_SIZE, 8,
172 EGL_BLUE_SIZE, 8,
173 EGL_ALPHA_SIZE, 8,
174 EGL_DEPTH_SIZE, 16,
175 EGL_STENCIL_SIZE, 8,
176 EGL_NONE };
177
178 return sDefaultConfigAttribs;
179 }
180
181 virtual EGLint const* getContextAttribs() {
182 static EGLint sDefaultContextAttribs[] = {
183 EGL_CONTEXT_CLIENT_VERSION, 2,
184 EGL_NONE };
185
186 return sDefaultContextAttribs;
187 }
188
189 virtual EGLint getSurfaceWidth() {
Jamie Gennisc8c51522011-06-15 14:24:38 -0700190 return 512;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800191 }
192
193 virtual EGLint getSurfaceHeight() {
Jamie Gennisc8c51522011-06-15 14:24:38 -0700194 return 512;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800195 }
196
Jamie Gennisd99c0882011-03-10 16:24:46 -0800197 ::testing::AssertionResult checkPixel(int x, int y, int r,
Jamie Gennis824efa72011-06-13 13:41:01 -0700198 int g, int b, int a, int tolerance=2) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800199 GLubyte pixel[4];
200 String8 msg;
201 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
202 GLenum err = glGetError();
203 if (err != GL_NO_ERROR) {
204 msg += String8::format("error reading pixel: %#x", err);
205 while ((err = glGetError()) != GL_NO_ERROR) {
206 msg += String8::format(", %#x", err);
207 }
Jamie Gennisd99c0882011-03-10 16:24:46 -0800208 return ::testing::AssertionFailure(
209 ::testing::Message(msg.string()));
210 }
Jamie Gennis824efa72011-06-13 13:41:01 -0700211 if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800212 msg += String8::format("r(%d isn't %d)", pixel[0], r);
213 }
Jamie Gennis824efa72011-06-13 13:41:01 -0700214 if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800215 if (!msg.isEmpty()) {
216 msg += " ";
217 }
218 msg += String8::format("g(%d isn't %d)", pixel[1], g);
219 }
Jamie Gennis824efa72011-06-13 13:41:01 -0700220 if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800221 if (!msg.isEmpty()) {
222 msg += " ";
223 }
224 msg += String8::format("b(%d isn't %d)", pixel[2], b);
225 }
Jamie Gennis824efa72011-06-13 13:41:01 -0700226 if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800227 if (!msg.isEmpty()) {
228 msg += " ";
229 }
230 msg += String8::format("a(%d isn't %d)", pixel[3], a);
231 }
232 if (!msg.isEmpty()) {
Jamie Gennisd99c0882011-03-10 16:24:46 -0800233 return ::testing::AssertionFailure(
234 ::testing::Message(msg.string()));
235 } else {
236 return ::testing::AssertionSuccess();
237 }
238 }
239
Daniel Lam016c8cb2012-04-03 15:54:58 -0700240 ::testing::AssertionResult assertRectEq(const Rect &r1,
241 const Rect &r2, int tolerance=1) {
242
243 String8 msg;
244
245 if (abs(r1.left - r2.left) > tolerance) {
246 msg += String8::format("left(%d isn't %d)", r1.left, r2.left);
247 }
248 if (abs(r1.top - r2.top) > tolerance) {
249 if (!msg.isEmpty()) {
250 msg += " ";
251 }
252 msg += String8::format("top(%d isn't %d)", r1.top, r2.top);
253 }
254 if (abs(r1.right - r2.right) > tolerance) {
255 if (!msg.isEmpty()) {
256 msg += " ";
257 }
258 msg += String8::format("right(%d isn't %d)", r1.right, r2.right);
259 }
260 if (abs(r1.bottom - r2.bottom) > tolerance) {
261 if (!msg.isEmpty()) {
262 msg += " ";
263 }
264 msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom);
265 }
266 if (!msg.isEmpty()) {
267 msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]",
268 r1.left, r1.top, r1.right, r1.bottom,
269 r2.left, r2.top, r2.right, r2.bottom);
270 fprintf(stderr, "assertRectEq: %s\n", msg.string());
271 return ::testing::AssertionFailure(
272 ::testing::Message(msg.string()));
273 } else {
274 return ::testing::AssertionSuccess();
275 }
276 }
277
Jamie Gennisd99c0882011-03-10 16:24:46 -0800278 int mDisplaySecs;
279 sp<SurfaceComposerClient> mComposerClient;
280 sp<SurfaceControl> mSurfaceControl;
281
282 EGLDisplay mEglDisplay;
283 EGLSurface mEglSurface;
284 EGLContext mEglContext;
Jamie Gennis1876d132011-03-17 16:32:52 -0700285 EGLConfig mGlConfig;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800286};
287
Jamie Gennis74bed552012-03-28 19:05:54 -0700288static void loadShader(GLenum shaderType, const char* pSource,
289 GLuint* outShader) {
290 GLuint shader = glCreateShader(shaderType);
291 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
292 if (shader) {
293 glShaderSource(shader, 1, &pSource, NULL);
294 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
295 glCompileShader(shader);
296 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
297 GLint compiled = 0;
298 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
299 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
300 if (!compiled) {
301 GLint infoLen = 0;
302 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
303 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
304 if (infoLen) {
305 char* buf = (char*) malloc(infoLen);
306 if (buf) {
307 glGetShaderInfoLog(shader, infoLen, NULL, buf);
308 printf("Shader compile log:\n%s\n", buf);
309 free(buf);
310 FAIL();
311 }
312 } else {
313 char* buf = (char*) malloc(0x1000);
314 if (buf) {
315 glGetShaderInfoLog(shader, 0x1000, NULL, buf);
316 printf("Shader compile log:\n%s\n", buf);
317 free(buf);
318 FAIL();
319 }
320 }
321 glDeleteShader(shader);
322 shader = 0;
323 }
324 }
325 ASSERT_TRUE(shader != 0);
326 *outShader = shader;
327}
328
329static void createProgram(const char* pVertexSource,
330 const char* pFragmentSource, GLuint* outPgm) {
331 GLuint vertexShader, fragmentShader;
332 {
333 SCOPED_TRACE("compiling vertex shader");
334 ASSERT_NO_FATAL_FAILURE(loadShader(GL_VERTEX_SHADER, pVertexSource,
335 &vertexShader));
336 }
337 {
338 SCOPED_TRACE("compiling fragment shader");
339 ASSERT_NO_FATAL_FAILURE(loadShader(GL_FRAGMENT_SHADER, pFragmentSource,
340 &fragmentShader));
341 }
342
343 GLuint program = glCreateProgram();
344 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
345 if (program) {
346 glAttachShader(program, vertexShader);
347 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
348 glAttachShader(program, fragmentShader);
349 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
350 glLinkProgram(program);
351 GLint linkStatus = GL_FALSE;
352 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
353 if (linkStatus != GL_TRUE) {
354 GLint bufLength = 0;
355 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
356 if (bufLength) {
357 char* buf = (char*) malloc(bufLength);
358 if (buf) {
359 glGetProgramInfoLog(program, bufLength, NULL, buf);
360 printf("Program link log:\n%s\n", buf);
361 free(buf);
362 FAIL();
363 }
364 }
365 glDeleteProgram(program);
366 program = 0;
367 }
368 }
369 glDeleteShader(vertexShader);
370 glDeleteShader(fragmentShader);
371 ASSERT_TRUE(program != 0);
372 *outPgm = program;
373}
374
375static int abs(int value) {
376 return value > 0 ? value : -value;
377}
378
379
Jamie Gennisd99c0882011-03-10 16:24:46 -0800380// XXX: Code above this point should live elsewhere
381
Mathias Agopianf31510a2013-04-16 23:32:38 -0700382class MultiTextureConsumerTest : public GLTest {
383protected:
384 enum { TEX_ID = 123 };
385
386 virtual void SetUp() {
387 GLTest::SetUp();
388 mGlConsumer = new GLConsumer(TEX_ID);
389 mSurface = new Surface(mGlConsumer->getBufferQueue());
390 mANW = mSurface.get();
391
392 }
393 virtual void TearDown() {
394 GLTest::TearDown();
395 }
396 virtual EGLint const* getContextAttribs() {
397 return NULL;
398 }
399 virtual EGLint const* getConfigAttribs() {
400 static EGLint sDefaultConfigAttribs[] = {
401 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
402 EGL_RED_SIZE, 8,
403 EGL_GREEN_SIZE, 8,
404 EGL_BLUE_SIZE, 8,
405 EGL_ALPHA_SIZE, 8,
406 EGL_NONE };
407
408 return sDefaultConfigAttribs;
409 }
410 sp<GLConsumer> mGlConsumer;
411 sp<Surface> mSurface;
412 ANativeWindow* mANW;
413};
414
415
416TEST_F(MultiTextureConsumerTest, EGLImageTargetWorks) {
417 ANativeWindow_Buffer buffer;
418
419 ASSERT_EQ(native_window_set_usage(mANW, GRALLOC_USAGE_SW_WRITE_OFTEN), NO_ERROR);
420 ASSERT_EQ(native_window_set_buffers_format(mANW, HAL_PIXEL_FORMAT_RGBA_8888), NO_ERROR);
421
422 glShadeModel(GL_FLAT);
423 glDisable(GL_DITHER);
424 glDisable(GL_CULL_FACE);
425 glViewport(0, 0, getSurfaceWidth(), getSurfaceHeight());
426 glOrthof(0, getSurfaceWidth(), 0, getSurfaceHeight(), 0, 1);
427 glEnableClientState(GL_VERTEX_ARRAY);
428 glColor4f(1, 1, 1, 1);
429
430 glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
431 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
432 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
433 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
434 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
435
436 uint32_t texel = 0x80808080;
437 glBindTexture(GL_TEXTURE_2D, TEX_ID+1);
438 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texel);
439 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
440 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
441 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
442 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
443
444 glActiveTexture(GL_TEXTURE1);
445 glBindTexture(GL_TEXTURE_2D, TEX_ID+1);
446 glEnable(GL_TEXTURE_2D);
447 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
448
449 glActiveTexture(GL_TEXTURE0);
450 glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
451 glEnable(GL_TEXTURE_EXTERNAL_OES);
452 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
453
454 glClear(GL_COLOR_BUFFER_BIT);
455 for (int i=0 ; i<8 ; i++) {
456 mSurface->lock(&buffer, NULL);
457 memset(buffer.bits, (i&7) * 0x20, buffer.stride * buffer.height * 4);
458 mSurface->unlockAndPost();
459
460 mGlConsumer->updateTexImage();
461
462 GLfloat vertices[][2] = { {i*16.0f, 0}, {(i+1)*16.0f, 0}, {(i+1)*16.0f, 16.0f}, {i*16.0f, 16.0f} };
463 glVertexPointer(2, GL_FLOAT, 0, vertices);
464 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
465
466 ASSERT_EQ( glGetError(), GL_NO_ERROR );
467 }
468 ASSERT_TRUE( eglSwapBuffers(mEglDisplay, mEglSurface) );
469
470 uint32_t* pixels = new uint32_t[8*16*16];
471 glReadPixels(0, 0, 8*16, 16, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
472
473 for (int i=0 ; i<8 ; i++) {
474 uint32_t p = pixels[i*16 + 8 + 8*(8*16)]; // center of each square
475 EXPECT_EQ(p, (i&7) * 0x10101010);
476 }
477
478 delete [] pixels;
479}
480
481
482
Jamie Gennisd99c0882011-03-10 16:24:46 -0800483class SurfaceTextureGLTest : public GLTest {
484protected:
Jamie Gennis79e31252011-10-19 15:19:19 -0700485 enum { TEX_ID = 123 };
Jamie Gennisd99c0882011-03-10 16:24:46 -0800486
487 virtual void SetUp() {
488 GLTest::SetUp();
Andy McFadden2adaf042012-12-18 09:49:45 -0800489 mST = new GLConsumer(TEX_ID);
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800490 mSTC = new Surface(mST->getBufferQueue());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800491 mANW = mSTC;
Jamie Gennis74bed552012-03-28 19:05:54 -0700492 mTextureRenderer = new TextureRenderer(TEX_ID, mST);
493 ASSERT_NO_FATAL_FAILURE(mTextureRenderer->SetUp());
Jamie Gennisefc7ab62012-04-17 19:36:18 -0700494 mFW = new FrameWaiter;
495 mST->setFrameAvailableListener(mFW);
Jamie Gennisd99c0882011-03-10 16:24:46 -0800496 }
497
Jamie Gennis2640bfd2011-07-14 17:11:47 -0700498 virtual void TearDown() {
499 mANW.clear();
500 mSTC.clear();
501 mST.clear();
502 GLTest::TearDown();
503 }
504
Jamie Gennisd99c0882011-03-10 16:24:46 -0800505 void drawTexture() {
Jamie Gennis74bed552012-03-28 19:05:54 -0700506 mTextureRenderer->drawTexture();
Jamie Gennisd99c0882011-03-10 16:24:46 -0800507 }
508
Jamie Gennis74bed552012-03-28 19:05:54 -0700509 class TextureRenderer: public RefBase {
510 public:
Andy McFadden2adaf042012-12-18 09:49:45 -0800511 TextureRenderer(GLuint texName, const sp<GLConsumer>& st):
Jamie Gennis74bed552012-03-28 19:05:54 -0700512 mTexName(texName),
513 mST(st) {
514 }
515
516 void SetUp() {
517 const char vsrc[] =
518 "attribute vec4 vPosition;\n"
519 "varying vec2 texCoords;\n"
520 "uniform mat4 texMatrix;\n"
521 "void main() {\n"
522 " vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
523 " texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
524 " gl_Position = vPosition;\n"
525 "}\n";
526
527 const char fsrc[] =
528 "#extension GL_OES_EGL_image_external : require\n"
529 "precision mediump float;\n"
530 "uniform samplerExternalOES texSampler;\n"
531 "varying vec2 texCoords;\n"
532 "void main() {\n"
533 " gl_FragColor = texture2D(texSampler, texCoords);\n"
534 "}\n";
535
536 {
537 SCOPED_TRACE("creating shader program");
538 ASSERT_NO_FATAL_FAILURE(createProgram(vsrc, fsrc, &mPgm));
539 }
540
541 mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
542 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
543 ASSERT_NE(-1, mPositionHandle);
544 mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
545 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
546 ASSERT_NE(-1, mTexSamplerHandle);
547 mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
548 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
549 ASSERT_NE(-1, mTexMatrixHandle);
550 }
551
Andy McFadden2adaf042012-12-18 09:49:45 -0800552 // drawTexture draws the GLConsumer over the entire GL viewport.
Jamie Gennis74bed552012-03-28 19:05:54 -0700553 void drawTexture() {
Jamie Gennisa96b6bd2012-04-11 17:27:12 -0700554 static const GLfloat triangleVertices[] = {
Jamie Gennis74bed552012-03-28 19:05:54 -0700555 -1.0f, 1.0f,
556 -1.0f, -1.0f,
557 1.0f, -1.0f,
558 1.0f, 1.0f,
559 };
560
561 glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
562 triangleVertices);
563 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
564 glEnableVertexAttribArray(mPositionHandle);
565 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
566
567 glUseProgram(mPgm);
568 glUniform1i(mTexSamplerHandle, 0);
569 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
570 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
571 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
572
573 // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
574 // they're setting the defautls for that target, but when hacking
575 // things to use GL_TEXTURE_2D they are needed to achieve the same
576 // behavior.
577 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER,
578 GL_LINEAR);
579 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
580 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER,
581 GL_LINEAR);
582 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
583 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
584 GL_CLAMP_TO_EDGE);
585 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
586 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
587 GL_CLAMP_TO_EDGE);
588 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
589
590 GLfloat texMatrix[16];
591 mST->getTransformMatrix(texMatrix);
592 glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
593
594 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
595 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
596 }
597
598 GLuint mTexName;
Andy McFadden2adaf042012-12-18 09:49:45 -0800599 sp<GLConsumer> mST;
Jamie Gennis74bed552012-03-28 19:05:54 -0700600 GLuint mPgm;
601 GLint mPositionHandle;
602 GLint mTexSamplerHandle;
603 GLint mTexMatrixHandle;
604 };
605
Andy McFadden2adaf042012-12-18 09:49:45 -0800606 class FrameWaiter : public GLConsumer::FrameAvailableListener {
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700607 public:
608 FrameWaiter():
609 mPendingFrames(0) {
610 }
611
612 void waitForFrame() {
613 Mutex::Autolock lock(mMutex);
614 while (mPendingFrames == 0) {
615 mCondition.wait(mMutex);
616 }
617 mPendingFrames--;
618 }
619
620 virtual void onFrameAvailable() {
621 Mutex::Autolock lock(mMutex);
622 mPendingFrames++;
623 mCondition.signal();
624 }
625
626 int mPendingFrames;
627 Mutex mMutex;
628 Condition mCondition;
629 };
630
Andy McFadden2adaf042012-12-18 09:49:45 -0800631 // Note that GLConsumer will lose the notifications
Daniel Lam9abe1eb2012-03-26 20:37:15 -0700632 // onBuffersReleased and onFrameAvailable as there is currently
633 // no way to forward the events. This DisconnectWaiter will not let the
634 // disconnect finish until finishDisconnect() is called. It will
635 // also block until a disconnect is called
636 class DisconnectWaiter : public BufferQueue::ConsumerListener {
637 public:
638 DisconnectWaiter () :
639 mWaitForDisconnect(false),
640 mPendingFrames(0) {
641 }
642
643 void waitForFrame() {
644 Mutex::Autolock lock(mMutex);
645 while (mPendingFrames == 0) {
646 mFrameCondition.wait(mMutex);
647 }
648 mPendingFrames--;
649 }
650
651 virtual void onFrameAvailable() {
652 Mutex::Autolock lock(mMutex);
653 mPendingFrames++;
654 mFrameCondition.signal();
655 }
656
657 virtual void onBuffersReleased() {
658 Mutex::Autolock lock(mMutex);
659 while (!mWaitForDisconnect) {
660 mDisconnectCondition.wait(mMutex);
661 }
662 }
663
664 void finishDisconnect() {
665 Mutex::Autolock lock(mMutex);
666 mWaitForDisconnect = true;
667 mDisconnectCondition.signal();
668 }
669
670 private:
671 Mutex mMutex;
672
673 bool mWaitForDisconnect;
674 Condition mDisconnectCondition;
675
676 int mPendingFrames;
677 Condition mFrameCondition;
678 };
679
Andy McFadden2adaf042012-12-18 09:49:45 -0800680 sp<GLConsumer> mST;
Mathias Agopiane3c697f2013-02-14 17:11:02 -0800681 sp<Surface> mSTC;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800682 sp<ANativeWindow> mANW;
Jamie Gennis74bed552012-03-28 19:05:54 -0700683 sp<TextureRenderer> mTextureRenderer;
Jamie Gennisefc7ab62012-04-17 19:36:18 -0700684 sp<FrameWaiter> mFW;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800685};
686
687// Fill a YV12 buffer with a multi-colored checkerboard pattern
688void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
689 const int blockWidth = w > 16 ? w / 16 : 1;
690 const int blockHeight = h > 16 ? h / 16 : 1;
691 const int yuvTexOffsetY = 0;
692 int yuvTexStrideY = stride;
693 int yuvTexOffsetV = yuvTexStrideY * h;
694 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
695 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
696 int yuvTexStrideU = yuvTexStrideV;
697 for (int x = 0; x < w; x++) {
698 for (int y = 0; y < h; y++) {
699 int parityX = (x / blockWidth) & 1;
700 int parityY = (y / blockHeight) & 1;
701 unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
702 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
703 if (x < w / 2 && y < h / 2) {
704 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
705 if (x * 2 < w / 2 && y * 2 < h / 2) {
706 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
707 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
708 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
709 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
710 intensity;
711 }
712 }
713 }
714 }
715}
716
717// Fill a YV12 buffer with red outside a given rectangle and green inside it.
718void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
719 const android_native_rect_t& rect) {
720 const int yuvTexOffsetY = 0;
721 int yuvTexStrideY = stride;
722 int yuvTexOffsetV = yuvTexStrideY * h;
723 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
724 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
725 int yuvTexStrideU = yuvTexStrideV;
726 for (int x = 0; x < w; x++) {
727 for (int y = 0; y < h; y++) {
728 bool inside = rect.left <= x && x < rect.right &&
729 rect.top <= y && y < rect.bottom;
730 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
731 if (x < w / 2 && y < h / 2) {
732 bool inside = rect.left <= 2*x && 2*x < rect.right &&
733 rect.top <= 2*y && 2*y < rect.bottom;
734 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
735 buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
736 inside ? 16 : 255;
737 }
738 }
739 }
740}
741
Jamie Gennis1876d132011-03-17 16:32:52 -0700742void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
743 const size_t PIXEL_SIZE = 4;
744 for (int x = 0; x < w; x++) {
745 for (int y = 0; y < h; y++) {
746 off_t offset = (y * stride + x) * PIXEL_SIZE;
747 for (int c = 0; c < 4; c++) {
748 int parityX = (x / (1 << (c+2))) & 1;
749 int parityY = (y / (1 << (c+2))) & 1;
750 buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
751 }
752 }
753 }
754}
755
Jamie Gennisfe27e2f2011-11-11 18:05:11 -0800756void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
757 uint8_t g, uint8_t b, uint8_t a) {
758 const size_t PIXEL_SIZE = 4;
759 for (int y = 0; y < h; y++) {
760 for (int x = 0; x < h; x++) {
761 off_t offset = (y * stride + x) * PIXEL_SIZE;
762 buf[offset + 0] = r;
763 buf[offset + 1] = g;
764 buf[offset + 2] = b;
765 buf[offset + 3] = a;
766 }
767 }
768}
769
Jamie Gennisce561372012-03-19 18:33:05 -0700770// Produce a single RGBA8 frame by filling a buffer with a checkerboard pattern
771// using the CPU. This assumes that the ANativeWindow is already configured to
772// allow this to be done (e.g. the format is set to RGBA8).
773//
774// Calls to this function should be wrapped in an ASSERT_NO_FATAL_FAILURE().
775void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) {
776 android_native_buffer_t* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700777 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
778 &anb));
Jamie Gennisce561372012-03-19 18:33:05 -0700779 ASSERT_TRUE(anb != NULL);
780
781 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisce561372012-03-19 18:33:05 -0700782
783 uint8_t* img = NULL;
784 ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
785 (void**)(&img)));
786 fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride());
787 ASSERT_EQ(NO_ERROR, buf->unlock());
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700788 ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(),
789 -1));
Jamie Gennisce561372012-03-19 18:33:05 -0700790}
791
Jamie Gennisd99c0882011-03-10 16:24:46 -0800792TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
Jamie Gennis1876d132011-03-17 16:32:52 -0700793 const int texWidth = 64;
794 const int texHeight = 66;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800795
796 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
Jamie Gennis1876d132011-03-17 16:32:52 -0700797 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800798 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
799 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
800
Iliyan Malchev697526b2011-05-01 11:33:26 -0700801 ANativeWindowBuffer* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700802 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
803 &anb));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800804 ASSERT_TRUE(anb != NULL);
805
806 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800807
808 // Fill the buffer with the a checkerboard pattern
809 uint8_t* img = NULL;
810 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
Jamie Gennis1876d132011-03-17 16:32:52 -0700811 fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800812 buf->unlock();
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700813 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
814 -1));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800815
Jamie Gennisd69097f2012-08-30 13:28:23 -0700816 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800817
818 glClearColor(0.2, 0.2, 0.2, 0.2);
819 glClear(GL_COLOR_BUFFER_BIT);
820
Jamie Gennisc8c51522011-06-15 14:24:38 -0700821 glViewport(0, 0, texWidth, texHeight);
Jamie Gennisd99c0882011-03-10 16:24:46 -0800822 drawTexture();
823
Jamie Gennise6a0f502013-04-05 17:37:32 -0700824 EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255, 3));
825 EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255, 3));
826 EXPECT_TRUE(checkPixel(63, 65, 0, 133, 0, 255, 3));
827 EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255, 3));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800828
Jamie Gennise6a0f502013-04-05 17:37:32 -0700829 EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255, 3));
830 EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255, 3));
831 EXPECT_TRUE(checkPixel(52, 51, 98, 255, 73, 255, 3));
832 EXPECT_TRUE(checkPixel( 7, 31, 155, 0, 118, 255, 3));
833 EXPECT_TRUE(checkPixel(31, 9, 107, 24, 87, 255, 3));
834 EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255, 3));
835 EXPECT_TRUE(checkPixel(36, 22, 155, 29, 0, 255, 3));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800836}
837
Jamie Gennisd05bb2e2011-06-14 15:41:45 -0700838TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) {
Jamie Gennis1876d132011-03-17 16:32:52 -0700839 const int texWidth = 64;
840 const int texHeight = 64;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800841
842 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
Jamie Gennis1876d132011-03-17 16:32:52 -0700843 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800844 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
845 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
846
Iliyan Malchev697526b2011-05-01 11:33:26 -0700847 ANativeWindowBuffer* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700848 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
849 &anb));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800850 ASSERT_TRUE(anb != NULL);
851
852 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800853
854 // Fill the buffer with the a checkerboard pattern
855 uint8_t* img = NULL;
856 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
Jamie Gennis1876d132011-03-17 16:32:52 -0700857 fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800858 buf->unlock();
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700859 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
860 -1));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800861
Jamie Gennisd69097f2012-08-30 13:28:23 -0700862 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800863
864 glClearColor(0.2, 0.2, 0.2, 0.2);
865 glClear(GL_COLOR_BUFFER_BIT);
866
Jamie Gennisc8c51522011-06-15 14:24:38 -0700867 glViewport(0, 0, texWidth, texHeight);
Jamie Gennisd99c0882011-03-10 16:24:46 -0800868 drawTexture();
869
Jamie Gennisd05bb2e2011-06-14 15:41:45 -0700870 EXPECT_TRUE(checkPixel( 0, 0, 0, 133, 0, 255));
871 EXPECT_TRUE(checkPixel(63, 0, 255, 127, 255, 255));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800872 EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255));
873 EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
874
Jamie Gennisd05bb2e2011-06-14 15:41:45 -0700875 EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255));
876 EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255));
877 EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255));
878 EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
879 EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255));
880 EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255));
881 EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800882}
883
884TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
Jamie Gennis1876d132011-03-17 16:32:52 -0700885 const int texWidth = 64;
886 const int texHeight = 66;
Jamie Gennisd99c0882011-03-10 16:24:46 -0800887
888 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
Jamie Gennis1876d132011-03-17 16:32:52 -0700889 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800890 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
891 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
892
893 android_native_rect_t crops[] = {
894 {4, 6, 22, 36},
895 {0, 6, 22, 36},
896 {4, 0, 22, 36},
Jamie Gennis1876d132011-03-17 16:32:52 -0700897 {4, 6, texWidth, 36},
898 {4, 6, 22, texHeight},
Jamie Gennisd99c0882011-03-10 16:24:46 -0800899 };
900
901 for (int i = 0; i < 5; i++) {
902 const android_native_rect_t& crop(crops[i]);
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -0800903 SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }",
904 crop.left, crop.top, crop.right, crop.bottom).string());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800905
906 ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
907
Iliyan Malchev697526b2011-05-01 11:33:26 -0700908 ANativeWindowBuffer* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700909 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
910 &anb));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800911 ASSERT_TRUE(anb != NULL);
912
913 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800914
915 uint8_t* img = NULL;
916 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
Jamie Gennis1876d132011-03-17 16:32:52 -0700917 fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
Jamie Gennisd99c0882011-03-10 16:24:46 -0800918 buf->unlock();
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -0800919 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700920 buf->getNativeBuffer(), -1));
Jamie Gennisd99c0882011-03-10 16:24:46 -0800921
Jamie Gennisd69097f2012-08-30 13:28:23 -0700922 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisd99c0882011-03-10 16:24:46 -0800923
924 glClearColor(0.2, 0.2, 0.2, 0.2);
925 glClear(GL_COLOR_BUFFER_BIT);
926
Jamie Gennisc8c51522011-06-15 14:24:38 -0700927 glViewport(0, 0, 64, 64);
Jamie Gennisd99c0882011-03-10 16:24:46 -0800928 drawTexture();
929
930 EXPECT_TRUE(checkPixel( 0, 0, 82, 255, 35, 255));
931 EXPECT_TRUE(checkPixel(63, 0, 82, 255, 35, 255));
932 EXPECT_TRUE(checkPixel(63, 63, 82, 255, 35, 255));
933 EXPECT_TRUE(checkPixel( 0, 63, 82, 255, 35, 255));
934
935 EXPECT_TRUE(checkPixel(25, 14, 82, 255, 35, 255));
936 EXPECT_TRUE(checkPixel(35, 31, 82, 255, 35, 255));
937 EXPECT_TRUE(checkPixel(57, 6, 82, 255, 35, 255));
938 EXPECT_TRUE(checkPixel( 5, 42, 82, 255, 35, 255));
939 EXPECT_TRUE(checkPixel(32, 33, 82, 255, 35, 255));
940 EXPECT_TRUE(checkPixel(16, 26, 82, 255, 35, 255));
941 EXPECT_TRUE(checkPixel(46, 51, 82, 255, 35, 255));
942 }
943}
944
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700945// This test is intended to catch synchronization bugs between the CPU-written
946// and GPU-read buffers.
947TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
948 enum { texWidth = 16 };
949 enum { texHeight = 16 };
950 enum { numFrames = 1024 };
951
952 ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
Jamie Gennis31a353d2012-08-24 17:25:13 -0700953 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700954 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
955 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
956 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
957 GRALLOC_USAGE_SW_WRITE_OFTEN));
958
959 struct TestPixel {
960 int x;
961 int y;
962 };
963 const TestPixel testPixels[] = {
964 { 4, 11 },
965 { 12, 14 },
966 { 7, 2 },
967 };
968 enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
969
970 class ProducerThread : public Thread {
971 public:
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -0800972 ProducerThread(const sp<ANativeWindow>& anw,
973 const TestPixel* testPixels):
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700974 mANW(anw),
975 mTestPixels(testPixels) {
976 }
977
978 virtual ~ProducerThread() {
979 }
980
981 virtual bool threadLoop() {
982 for (int i = 0; i < numFrames; i++) {
983 ANativeWindowBuffer* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -0700984 if (native_window_dequeue_buffer_and_wait(mANW.get(),
985 &anb) != NO_ERROR) {
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700986 return false;
987 }
988 if (anb == NULL) {
989 return false;
990 }
991
992 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisdfcff4b2011-06-17 11:39:18 -0700993
994 const int yuvTexOffsetY = 0;
995 int stride = buf->getStride();
996 int yuvTexStrideY = stride;
997 int yuvTexOffsetV = yuvTexStrideY * texHeight;
998 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
999 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
1000 int yuvTexStrideU = yuvTexStrideV;
1001
1002 uint8_t* img = NULL;
1003 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
1004
1005 // Gray out all the test pixels first, so we're more likely to
1006 // see a failure if GL is still texturing from the buffer we
1007 // just dequeued.
1008 for (int j = 0; j < numTestPixels; j++) {
1009 int x = mTestPixels[j].x;
1010 int y = mTestPixels[j].y;
1011 uint8_t value = 128;
1012 img[y*stride + x] = value;
1013 }
1014
1015 // Fill the buffer with gray.
1016 for (int y = 0; y < texHeight; y++) {
1017 for (int x = 0; x < texWidth; x++) {
1018 img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
1019 img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
1020 img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
1021 }
1022 }
1023
1024 // Set the test pixels to either white or black.
1025 for (int j = 0; j < numTestPixels; j++) {
1026 int x = mTestPixels[j].x;
1027 int y = mTestPixels[j].y;
1028 uint8_t value = 0;
1029 if (j == (i % numTestPixels)) {
1030 value = 255;
1031 }
1032 img[y*stride + x] = value;
1033 }
1034
1035 buf->unlock();
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001036 if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)
Jamie Gennisdfcff4b2011-06-17 11:39:18 -07001037 != NO_ERROR) {
1038 return false;
1039 }
1040 }
1041 return false;
1042 }
1043
1044 sp<ANativeWindow> mANW;
1045 const TestPixel* mTestPixels;
1046 };
1047
Jamie Gennisdfcff4b2011-06-17 11:39:18 -07001048 sp<Thread> pt(new ProducerThread(mANW, testPixels));
1049 pt->run();
1050
1051 glViewport(0, 0, texWidth, texHeight);
1052
1053 glClearColor(0.2, 0.2, 0.2, 0.2);
1054 glClear(GL_COLOR_BUFFER_BIT);
1055
1056 // We wait for the first two frames up front so that the producer will be
1057 // likely to dequeue the buffer that's currently being textured from.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001058 mFW->waitForFrame();
1059 mFW->waitForFrame();
Jamie Gennisdfcff4b2011-06-17 11:39:18 -07001060
1061 for (int i = 0; i < numFrames; i++) {
1062 SCOPED_TRACE(String8::format("frame %d", i).string());
1063
1064 // We must wait for each frame to come in because if we ever do an
1065 // updateTexImage call that doesn't consume a newly available buffer
1066 // then the producer and consumer will get out of sync, which will cause
1067 // a deadlock.
1068 if (i > 1) {
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001069 mFW->waitForFrame();
Jamie Gennisdfcff4b2011-06-17 11:39:18 -07001070 }
Jamie Gennisd69097f2012-08-30 13:28:23 -07001071 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisdfcff4b2011-06-17 11:39:18 -07001072 drawTexture();
1073
1074 for (int j = 0; j < numTestPixels; j++) {
1075 int x = testPixels[j].x;
1076 int y = testPixels[j].y;
1077 uint8_t value = 0;
1078 if (j == (i % numTestPixels)) {
1079 // We must y-invert the texture coords
1080 EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
1081 } else {
1082 // We must y-invert the texture coords
1083 EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
1084 }
1085 }
1086 }
1087
1088 pt->requestExitAndWait();
1089}
1090
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001091TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) {
Jamie Gennis1876d132011-03-17 16:32:52 -07001092 const int texWidth = 64;
1093 const int texHeight = 66;
1094
1095 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
1096 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
1097 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
1098 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
1099
Jamie Gennisce561372012-03-19 18:33:05 -07001100 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
Jamie Gennis1876d132011-03-17 16:32:52 -07001101
Jamie Gennisd69097f2012-08-30 13:28:23 -07001102 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis1876d132011-03-17 16:32:52 -07001103
1104 glClearColor(0.2, 0.2, 0.2, 0.2);
1105 glClear(GL_COLOR_BUFFER_BIT);
1106
Jamie Gennisc8c51522011-06-15 14:24:38 -07001107 glViewport(0, 0, texWidth, texHeight);
Jamie Gennis1876d132011-03-17 16:32:52 -07001108 drawTexture();
1109
1110 EXPECT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
1111 EXPECT_TRUE(checkPixel(63, 0, 231, 231, 231, 231));
Jamie Gennisc8c51522011-06-15 14:24:38 -07001112 EXPECT_TRUE(checkPixel(63, 65, 231, 231, 231, 231));
1113 EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35));
Jamie Gennis1876d132011-03-17 16:32:52 -07001114
1115 EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231));
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001116 EXPECT_TRUE(checkPixel(23, 65, 231, 35, 231, 35));
Jamie Gennisc8c51522011-06-15 14:24:38 -07001117 EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35));
Jamie Gennis1876d132011-03-17 16:32:52 -07001118 EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35));
1119 EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231));
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001120 EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231));
Jamie Gennis1876d132011-03-17 16:32:52 -07001121 EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231));
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001122 EXPECT_TRUE(checkPixel(37, 47, 231, 35, 231, 231));
1123 EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35));
1124 EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35));
Jamie Gennis1876d132011-03-17 16:32:52 -07001125 EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231));
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001126 EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231));
1127 EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231));
Jamie Gennis1876d132011-03-17 16:32:52 -07001128 EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231));
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001129 EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35));
Jamie Gennis1876d132011-03-17 16:32:52 -07001130 EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231));
1131}
1132
Jamie Gennis1f8e09f2011-07-19 17:58:43 -07001133TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) {
Jamie Gennis1876d132011-03-17 16:32:52 -07001134 const int texWidth = 64;
1135 const int texHeight = 64;
1136
1137 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
1138 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
1139 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
1140 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
1141
Jamie Gennisce561372012-03-19 18:33:05 -07001142 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
Jamie Gennis1876d132011-03-17 16:32:52 -07001143
Jamie Gennisd69097f2012-08-30 13:28:23 -07001144 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis1876d132011-03-17 16:32:52 -07001145
1146 glClearColor(0.2, 0.2, 0.2, 0.2);
1147 glClear(GL_COLOR_BUFFER_BIT);
1148
Jamie Gennisc8c51522011-06-15 14:24:38 -07001149 glViewport(0, 0, texWidth, texHeight);
Jamie Gennis1876d132011-03-17 16:32:52 -07001150 drawTexture();
1151
1152 EXPECT_TRUE(checkPixel( 0, 0, 231, 231, 231, 231));
1153 EXPECT_TRUE(checkPixel(63, 0, 35, 35, 35, 35));
1154 EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
1155 EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35));
1156
1157 EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231, 35));
1158 EXPECT_TRUE(checkPixel(16, 1, 231, 231, 35, 231));
1159 EXPECT_TRUE(checkPixel(21, 12, 231, 35, 35, 231));
1160 EXPECT_TRUE(checkPixel(26, 51, 231, 35, 231, 35));
1161 EXPECT_TRUE(checkPixel( 5, 32, 35, 231, 231, 35));
1162 EXPECT_TRUE(checkPixel(13, 8, 35, 231, 231, 231));
1163 EXPECT_TRUE(checkPixel(46, 3, 35, 35, 231, 35));
1164 EXPECT_TRUE(checkPixel(30, 33, 35, 35, 35, 35));
1165 EXPECT_TRUE(checkPixel( 6, 52, 231, 231, 35, 35));
1166 EXPECT_TRUE(checkPixel(55, 33, 35, 231, 35, 231));
1167 EXPECT_TRUE(checkPixel(16, 29, 35, 35, 231, 231));
1168 EXPECT_TRUE(checkPixel( 1, 30, 35, 35, 35, 231));
1169 EXPECT_TRUE(checkPixel(41, 37, 35, 35, 231, 231));
1170 EXPECT_TRUE(checkPixel(46, 29, 231, 231, 35, 35));
1171 EXPECT_TRUE(checkPixel(15, 25, 35, 231, 35, 231));
1172 EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35));
1173}
1174
Andy McFadden2adaf042012-12-18 09:49:45 -08001175// Tests if GLConsumer and BufferQueue are robust enough
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001176// to handle a special case where updateTexImage is called
1177// in the middle of disconnect. This ordering is enforced
1178// by blocking in the disconnect callback.
1179TEST_F(SurfaceTextureGLTest, DisconnectStressTest) {
1180
1181 class ProducerThread : public Thread {
1182 public:
1183 ProducerThread(const sp<ANativeWindow>& anw):
1184 mANW(anw) {
1185 }
1186
1187 virtual ~ProducerThread() {
1188 }
1189
1190 virtual bool threadLoop() {
1191 ANativeWindowBuffer* anb;
1192
1193 native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
1194
1195 for (int numFrames =0 ; numFrames < 2; numFrames ++) {
1196
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001197 if (native_window_dequeue_buffer_and_wait(mANW.get(),
1198 &anb) != NO_ERROR) {
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001199 return false;
1200 }
1201 if (anb == NULL) {
1202 return false;
1203 }
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001204 if (mANW->queueBuffer(mANW.get(), anb, -1)
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001205 != NO_ERROR) {
1206 return false;
1207 }
1208 }
1209
1210 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
1211
1212 return false;
1213 }
1214
1215 private:
1216 sp<ANativeWindow> mANW;
1217 };
1218
1219 ASSERT_EQ(OK, mST->setSynchronousMode(true));
1220
1221 sp<DisconnectWaiter> dw(new DisconnectWaiter());
1222 mST->getBufferQueue()->consumerConnect(dw);
1223
1224
1225 sp<Thread> pt(new ProducerThread(mANW));
1226 pt->run();
1227
Andy McFadden2adaf042012-12-18 09:49:45 -08001228 // eat a frame so GLConsumer will own an at least one slot
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001229 dw->waitForFrame();
1230 EXPECT_EQ(OK,mST->updateTexImage());
1231
1232 dw->waitForFrame();
Andy McFadden2adaf042012-12-18 09:49:45 -08001233 // Could fail here as GLConsumer thinks it still owns the slot
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001234 // but bufferQueue has released all slots
1235 EXPECT_EQ(OK,mST->updateTexImage());
1236
1237 dw->finishDisconnect();
1238}
1239
1240
Andy McFadden2adaf042012-12-18 09:49:45 -08001241// This test ensures that the GLConsumer clears the mCurrentTexture
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001242// when it is disconnected and reconnected. Otherwise it will
1243// attempt to release a buffer that it does not owned
1244TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
1245 ASSERT_EQ(OK, mST->setSynchronousMode(true));
1246
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001247 ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1248 NATIVE_WINDOW_API_EGL));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001249
1250 ANativeWindowBuffer *anb;
1251
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001252 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1253 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001254
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001255 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1256 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001257
1258 EXPECT_EQ(OK,mST->updateTexImage());
1259 EXPECT_EQ(OK,mST->updateTexImage());
1260
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001261 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1262 NATIVE_WINDOW_API_EGL));
1263 ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1264 NATIVE_WINDOW_API_EGL));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001265
1266 ASSERT_EQ(OK, mST->setSynchronousMode(true));
1267
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001268 EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1269 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001270
1271 // Will fail here if mCurrentTexture is not cleared properly
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001272 mFW->waitForFrame();
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001273 EXPECT_EQ(OK,mST->updateTexImage());
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001274
1275 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1276 NATIVE_WINDOW_API_EGL));
Daniel Lam9abe1eb2012-03-26 20:37:15 -07001277}
1278
Daniel Lam016c8cb2012-04-03 15:54:58 -07001279TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
1280 ASSERT_EQ(OK, mST->setSynchronousMode(true));
1281
1282 ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
1283 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
1284
1285 // The producer image size
1286 ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));
1287
1288 // The consumer image size (16 x 9) ratio
1289 mST->setDefaultBufferSize(1280, 720);
1290
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001291 ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1292 NATIVE_WINDOW_API_CPU));
Daniel Lam016c8cb2012-04-03 15:54:58 -07001293
1294 ANativeWindowBuffer *anb;
1295
1296 android_native_rect_t odd = {23, 78, 123, 477};
1297 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd));
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001298 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1299 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001300 mFW->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07001301 EXPECT_EQ(OK, mST->updateTexImage());
Daniel Lam016c8cb2012-04-03 15:54:58 -07001302 Rect r = mST->getCurrentCrop();
1303 assertRectEq(Rect(23, 78, 123, 477), r);
1304
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001305 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1306 NATIVE_WINDOW_API_CPU));
Daniel Lam016c8cb2012-04-03 15:54:58 -07001307}
1308
1309// This test ensures the scaling mode does the right thing
1310// ie NATIVE_WINDOW_SCALING_MODE_CROP should crop
1311// the image such that it has the same aspect ratio as the
1312// default buffer size
1313TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
1314 ASSERT_EQ(OK, mST->setSynchronousMode(true));
1315
1316 ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
1317 NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
1318
1319 // The producer image size
1320 ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));
1321
1322 // The consumer image size (16 x 9) ratio
1323 mST->setDefaultBufferSize(1280, 720);
1324
1325 native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU);
1326
1327 ANativeWindowBuffer *anb;
1328
1329 // The crop is in the shape of (320, 180) === 16 x 9
1330 android_native_rect_t standard = {10, 20, 330, 200};
1331 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard));
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001332 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1333 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001334 mFW->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07001335 EXPECT_EQ(OK, mST->updateTexImage());
Daniel Lam016c8cb2012-04-03 15:54:58 -07001336 Rect r = mST->getCurrentCrop();
1337 // crop should be the same as crop (same aspect ratio)
1338 assertRectEq(Rect(10, 20, 330, 200), r);
1339
1340 // make this wider then desired aspect 239 x 100 (2.39:1)
1341 android_native_rect_t wide = {20, 30, 259, 130};
1342 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide));
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001343 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1344 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001345 mFW->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07001346 EXPECT_EQ(OK, mST->updateTexImage());
Daniel Lam016c8cb2012-04-03 15:54:58 -07001347 r = mST->getCurrentCrop();
1348 // crop should be the same height, but have cropped left and right borders
1349 // offset is 30.6 px L+, R-
1350 assertRectEq(Rect(51, 30, 228, 130), r);
1351
1352 // This image is taller then desired aspect 400 x 300 (4:3)
1353 android_native_rect_t narrow = {0, 0, 400, 300};
1354 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow));
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001355 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1356 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001357 mFW->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07001358 EXPECT_EQ(OK, mST->updateTexImage());
Daniel Lam016c8cb2012-04-03 15:54:58 -07001359 r = mST->getCurrentCrop();
1360 // crop should be the same width, but have cropped top and bottom borders
1361 // offset is 37.5 px
1362 assertRectEq(Rect(0, 37, 400, 262), r);
1363
1364 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
1365}
1366
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001367TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
1368 class ProducerThread : public Thread {
1369 public:
1370 ProducerThread(const sp<ANativeWindow>& anw):
1371 mANW(anw),
1372 mDequeueError(NO_ERROR) {
1373 }
1374
1375 virtual ~ProducerThread() {
1376 }
1377
1378 virtual bool threadLoop() {
1379 Mutex::Autolock lock(mMutex);
1380 ANativeWindowBuffer* anb;
1381
1382 // Frame 1
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001383 if (native_window_dequeue_buffer_and_wait(mANW.get(),
1384 &anb) != NO_ERROR) {
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001385 return false;
1386 }
1387 if (anb == NULL) {
1388 return false;
1389 }
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001390 if (mANW->queueBuffer(mANW.get(), anb, -1)
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001391 != NO_ERROR) {
1392 return false;
1393 }
1394
1395 // Frame 2
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001396 if (native_window_dequeue_buffer_and_wait(mANW.get(),
1397 &anb) != NO_ERROR) {
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001398 return false;
1399 }
1400 if (anb == NULL) {
1401 return false;
1402 }
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001403 if (mANW->queueBuffer(mANW.get(), anb, -1)
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001404 != NO_ERROR) {
1405 return false;
1406 }
1407
1408 // Frame 3 - error expected
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001409 mDequeueError = native_window_dequeue_buffer_and_wait(mANW.get(),
1410 &anb);
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001411 return false;
1412 }
1413
1414 status_t getDequeueError() {
1415 Mutex::Autolock lock(mMutex);
1416 return mDequeueError;
1417 }
1418
1419 private:
1420 sp<ANativeWindow> mANW;
1421 status_t mDequeueError;
1422 Mutex mMutex;
1423 };
1424
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001425 ASSERT_EQ(OK, mST->setSynchronousMode(true));
Jamie Gennis31a353d2012-08-24 17:25:13 -07001426 ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001427
1428 sp<Thread> pt(new ProducerThread(mANW));
1429 pt->run();
1430
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001431 mFW->waitForFrame();
1432 mFW->waitForFrame();
Jamie Gennis7b305ff2011-07-19 12:08:33 -07001433
1434 // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
1435 // block waiting for a buffer to become available.
1436 usleep(100000);
1437
1438 mST->abandon();
1439
1440 pt->requestExitAndWait();
1441 ASSERT_EQ(NO_INIT,
1442 reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
1443}
1444
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001445TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
1446 int texHeight = 16;
1447 ANativeWindowBuffer* anb;
1448
1449 GLint maxTextureSize;
1450 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1451
1452 // make sure it works with small textures
1453 mST->setDefaultBufferSize(16, texHeight);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001454 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1455 &anb));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001456 EXPECT_EQ(16, anb->width);
1457 EXPECT_EQ(texHeight, anb->height);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001458 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001459 EXPECT_EQ(NO_ERROR, mST->updateTexImage());
1460
1461 // make sure it works with GL_MAX_TEXTURE_SIZE
1462 mST->setDefaultBufferSize(maxTextureSize, texHeight);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001463 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1464 &anb));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001465 EXPECT_EQ(maxTextureSize, anb->width);
1466 EXPECT_EQ(texHeight, anb->height);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001467 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001468 EXPECT_EQ(NO_ERROR, mST->updateTexImage());
1469
1470 // make sure it fails with GL_MAX_TEXTURE_SIZE+1
1471 mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001472 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1473 &anb));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001474 EXPECT_EQ(maxTextureSize+1, anb->width);
1475 EXPECT_EQ(texHeight, anb->height);
Jamie Gennisd8e812c2012-06-13 16:32:25 -07001476 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001477 ASSERT_NE(NO_ERROR, mST->updateTexImage());
1478}
1479
Jamie Gennis5451d152011-06-08 09:40:45 -07001480/*
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001481 * This test fixture is for testing GL -> GL texture streaming. It creates an
1482 * EGLSurface and an EGLContext for the image producer to use.
1483 */
1484class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
1485protected:
1486 SurfaceTextureGLToGLTest():
1487 mProducerEglSurface(EGL_NO_SURFACE),
1488 mProducerEglContext(EGL_NO_CONTEXT) {
1489 }
1490
1491 virtual void SetUp() {
1492 SurfaceTextureGLTest::SetUp();
1493
Jamie Gennisce561372012-03-19 18:33:05 -07001494 mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001495 mANW.get(), NULL);
1496 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1497 ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
1498
Jamie Gennisce561372012-03-19 18:33:05 -07001499 mProducerEglContext = eglCreateContext(mEglDisplay, mGlConfig,
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001500 EGL_NO_CONTEXT, getContextAttribs());
1501 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1502 ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
1503 }
1504
1505 virtual void TearDown() {
1506 if (mProducerEglContext != EGL_NO_CONTEXT) {
1507 eglDestroyContext(mEglDisplay, mProducerEglContext);
1508 }
1509 if (mProducerEglSurface != EGL_NO_SURFACE) {
1510 eglDestroySurface(mEglDisplay, mProducerEglSurface);
1511 }
1512 SurfaceTextureGLTest::TearDown();
1513 }
1514
1515 EGLSurface mProducerEglSurface;
1516 EGLContext mProducerEglContext;
1517};
1518
Andy McFadden71f683a2012-09-14 17:21:46 -07001519TEST_F(SurfaceTextureGLToGLTest, TransformHintGetsRespected) {
1520 const uint32_t texWidth = 32;
1521 const uint32_t texHeight = 64;
1522
1523 mST->setDefaultBufferSize(texWidth, texHeight);
1524 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1525
1526 // This test requires 3 buffers to avoid deadlock because we're
1527 // both producer and consumer, and only using one thread.
1528 mST->setDefaultMaxBufferCount(3);
1529
1530 // Do the producer side of things
1531 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1532 mProducerEglSurface, mProducerEglContext));
1533 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1534
1535 // Start a buffer with our chosen size and transform hint moving
1536 // through the system.
1537 glClear(GL_COLOR_BUFFER_BIT); // give the driver something to do
1538 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1539 mST->updateTexImage(); // consume it
1540 // Swap again.
1541 glClear(GL_COLOR_BUFFER_BIT);
1542 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1543 mST->updateTexImage();
1544
1545 // The current buffer should either show the effects of the transform
1546 // hint (in the form of an inverse transform), or show that the
1547 // transform hint has been ignored.
1548 sp<GraphicBuffer> buf = mST->getCurrentBuffer();
1549 if (mST->getCurrentTransform() == NATIVE_WINDOW_TRANSFORM_ROT_270) {
1550 ASSERT_EQ(texWidth, buf->getHeight());
1551 ASSERT_EQ(texHeight, buf->getWidth());
1552 } else {
1553 ASSERT_EQ(texWidth, buf->getWidth());
1554 ASSERT_EQ(texHeight, buf->getHeight());
1555 }
1556
1557 // Reset the transform hint and confirm that it takes.
1558 mST->setTransformHint(0);
1559 glClear(GL_COLOR_BUFFER_BIT);
1560 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1561 mST->updateTexImage();
1562 glClear(GL_COLOR_BUFFER_BIT);
1563 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1564 mST->updateTexImage();
1565
1566 buf = mST->getCurrentBuffer();
1567 ASSERT_EQ((uint32_t) 0, mST->getCurrentTransform());
1568 ASSERT_EQ(texWidth, buf->getWidth());
1569 ASSERT_EQ(texHeight, buf->getHeight());
1570}
1571
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001572TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) {
1573 const int texWidth = 64;
1574 const int texHeight = 64;
1575
1576 mST->setDefaultBufferSize(texWidth, texHeight);
1577
Jamie Gennis46975282012-08-30 18:35:50 -07001578 // This test requires 3 buffers to complete run on a single thread.
1579 mST->setDefaultMaxBufferCount(3);
1580
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001581 // Do the producer side of things
1582 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1583 mProducerEglSurface, mProducerEglContext));
1584 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1585
1586 // This is needed to ensure we pick up a buffer of the correct size.
1587 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1588
1589 glClearColor(0.6, 0.6, 0.6, 0.6);
1590 glClear(GL_COLOR_BUFFER_BIT);
1591
1592 glEnable(GL_SCISSOR_TEST);
1593 glScissor(4, 4, 4, 4);
1594 glClearColor(1.0, 0.0, 0.0, 1.0);
1595 glClear(GL_COLOR_BUFFER_BIT);
1596
1597 glScissor(24, 48, 4, 4);
1598 glClearColor(0.0, 1.0, 0.0, 1.0);
1599 glClear(GL_COLOR_BUFFER_BIT);
1600
1601 glScissor(37, 17, 4, 4);
1602 glClearColor(0.0, 0.0, 1.0, 1.0);
1603 glClear(GL_COLOR_BUFFER_BIT);
1604
1605 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1606
1607 // Do the consumer side of things
1608 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1609 mEglContext));
1610 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1611
1612 glDisable(GL_SCISSOR_TEST);
1613
Jamie Gennisd69097f2012-08-30 13:28:23 -07001614 // Skip the first frame, which was empty
1615 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1616 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001617
1618 glClearColor(0.2, 0.2, 0.2, 0.2);
1619 glClear(GL_COLOR_BUFFER_BIT);
1620
1621 glViewport(0, 0, texWidth, texHeight);
1622 drawTexture();
1623
1624 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
1625 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
1626 EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
1627 EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
1628
1629 EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255));
1630 EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255));
1631 EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255));
1632 EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
1633 EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
1634 EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153));
1635 EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153));
1636 EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
1637 EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
1638 EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
1639 EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
1640 EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
1641 EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
1642 EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
1643 EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
1644 EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
1645}
1646
1647TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001648 sp<GraphicBuffer> buffers[2];
1649
Jamie Gennise3603d72011-11-19 21:20:17 -08001650 // This test requires async mode to run on a single thread.
1651 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1652 mProducerEglSurface, mProducerEglContext));
1653 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1654 EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
1655 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1656
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001657 for (int i = 0; i < 2; i++) {
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001658 // Produce a frame
1659 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1660 mProducerEglSurface, mProducerEglContext));
1661 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1662 glClear(GL_COLOR_BUFFER_BIT);
1663 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1664
1665 // Consume a frame
1666 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1667 mEglContext));
1668 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001669 mFW->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07001670 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001671 buffers[i] = mST->getCurrentBuffer();
1672 }
1673
1674 // Destroy the GL texture object to release its ref on buffers[2].
1675 GLuint texID = TEX_ID;
1676 glDeleteTextures(1, &texID);
1677
1678 // Destroy the EGLSurface
1679 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1680 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001681 mProducerEglSurface = EGL_NO_SURFACE;
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001682
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001683 // This test should have the only reference to buffer 0.
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001684 EXPECT_EQ(1, buffers[0]->getStrongCount());
Jamie Gennise3603d72011-11-19 21:20:17 -08001685
Andy McFadden2adaf042012-12-18 09:49:45 -08001686 // The GLConsumer should hold a single reference to buffer 1 in its
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001687 // mCurrentBuffer member. All of the references in the slots should have
1688 // been released.
1689 EXPECT_EQ(2, buffers[1]->getStrongCount());
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001690}
1691
1692TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
1693 sp<GraphicBuffer> buffers[3];
1694
Jamie Gennise3603d72011-11-19 21:20:17 -08001695 // This test requires async mode to run on a single thread.
1696 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1697 mProducerEglSurface, mProducerEglContext));
1698 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1699 EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
1700 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1701
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001702 for (int i = 0; i < 3; i++) {
1703 // Produce a frame
1704 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1705 mProducerEglSurface, mProducerEglContext));
1706 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1707 glClear(GL_COLOR_BUFFER_BIT);
1708 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1709 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1710
1711 // Consume a frame
1712 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1713 mEglContext));
1714 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennisefc7ab62012-04-17 19:36:18 -07001715 mFW->waitForFrame();
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001716 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1717 buffers[i] = mST->getCurrentBuffer();
1718 }
1719
Andy McFadden2adaf042012-12-18 09:49:45 -08001720 // Abandon the GLConsumer, releasing the ref that the GLConsumer has
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001721 // on buffers[2].
1722 mST->abandon();
1723
1724 // Destroy the GL texture object to release its ref on buffers[2].
1725 GLuint texID = TEX_ID;
1726 glDeleteTextures(1, &texID);
1727
1728 // Destroy the EGLSurface.
1729 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1730 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennisfa5b40e2012-03-15 14:01:24 -07001731 mProducerEglSurface = EGL_NO_SURFACE;
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001732
1733 EXPECT_EQ(1, buffers[0]->getStrongCount());
1734 EXPECT_EQ(1, buffers[1]->getStrongCount());
Jamie Gennise3603d72011-11-19 21:20:17 -08001735
1736 // Depending on how lazily the GL driver dequeues buffers, we may end up
1737 // with either two or three total buffers. If there are three, make sure
1738 // the last one was properly down-ref'd.
1739 if (buffers[2] != buffers[0]) {
1740 EXPECT_EQ(1, buffers[2]->getStrongCount());
1741 }
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08001742}
1743
Mathias Agopian7589b2a2013-03-08 13:18:52 -08001744TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentBeforeConsumerDeathUnrefsBuffers) {
1745 sp<GraphicBuffer> buffer;
1746
1747 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1748 mProducerEglSurface, mProducerEglContext));
1749
1750 // Produce a frame
1751 glClear(GL_COLOR_BUFFER_BIT);
1752 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1753 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1754
1755 // Destroy the EGLSurface.
1756 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1757 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1758 mProducerEglSurface = EGL_NO_SURFACE;
1759 mSTC.clear();
1760 mANW.clear();
1761 mTextureRenderer.clear();
1762
1763 // Consume a frame
1764 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1765 buffer = mST->getCurrentBuffer();
1766
1767 // Destroy the GL texture object to release its ref
1768 GLuint texID = TEX_ID;
1769 glDeleteTextures(1, &texID);
1770
1771 // make un-current, all references to buffer should be gone
1772 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
1773 EGL_NO_SURFACE, EGL_NO_CONTEXT));
1774
1775 // Destroy consumer
1776 mST.clear();
1777
1778 EXPECT_EQ(1, buffer->getStrongCount());
1779}
1780
1781TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) {
1782 sp<GraphicBuffer> buffer;
1783
1784 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1785 mProducerEglSurface, mProducerEglContext));
1786
1787 // Produce a frame
1788 glClear(GL_COLOR_BUFFER_BIT);
1789 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1790 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1791
1792 // Destroy the EGLSurface.
1793 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1794 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1795 mProducerEglSurface = EGL_NO_SURFACE;
1796 mSTC.clear();
1797 mANW.clear();
1798 mTextureRenderer.clear();
1799
1800 // Consume a frame
1801 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1802 buffer = mST->getCurrentBuffer();
1803
1804 // Destroy the GL texture object to release its ref
1805 GLuint texID = TEX_ID;
1806 glDeleteTextures(1, &texID);
1807
1808 // Destroy consumer
1809 mST.clear();
1810
1811 // make un-current, all references to buffer should be gone
1812 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
1813 EGL_NO_SURFACE, EGL_NO_CONTEXT));
1814
1815 EXPECT_EQ(1, buffer->getStrongCount());
1816}
1817
1818
Jamie Gennis59769462011-11-19 18:04:43 -08001819TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
1820 // This test requires 3 buffers to run on a single thread.
Jamie Gennis31a353d2012-08-24 17:25:13 -07001821 mST->setDefaultMaxBufferCount(3);
Jamie Gennis59769462011-11-19 18:04:43 -08001822
1823 ASSERT_TRUE(mST->isSynchronousMode());
1824
1825 for (int i = 0; i < 10; i++) {
1826 // Produce a frame
1827 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1828 mProducerEglSurface, mProducerEglContext));
1829 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1830 glClear(GL_COLOR_BUFFER_BIT);
1831 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1832 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1833
1834 // Consume a frame
1835 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1836 mEglContext));
1837 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1838 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1839 }
1840
1841 ASSERT_TRUE(mST->isSynchronousMode());
1842}
1843
Jamie Gennisc2c38022012-04-11 17:20:03 -07001844TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
1845 enum { texWidth = 64 };
1846 enum { texHeight = 64 };
1847
Jamie Gennis46975282012-08-30 18:35:50 -07001848 // This test requires 3 buffers to complete run on a single thread.
1849 mST->setDefaultMaxBufferCount(3);
1850
Jamie Gennisc2c38022012-04-11 17:20:03 -07001851 // Set the user buffer size.
1852 native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
1853
1854 // Do the producer side of things
1855 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1856 mProducerEglSurface, mProducerEglContext));
1857 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1858
1859 // This is needed to ensure we pick up a buffer of the correct size.
1860 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1861
1862 glClearColor(0.6, 0.6, 0.6, 0.6);
1863 glClear(GL_COLOR_BUFFER_BIT);
1864
1865 glEnable(GL_SCISSOR_TEST);
1866 glScissor(4, 4, 1, 1);
1867 glClearColor(1.0, 0.0, 0.0, 1.0);
1868 glClear(GL_COLOR_BUFFER_BIT);
1869
1870 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1871
1872 // Do the consumer side of things
1873 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1874 mEglContext));
1875 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1876
1877 glDisable(GL_SCISSOR_TEST);
1878
Jamie Gennisd69097f2012-08-30 13:28:23 -07001879 // Skip the first frame, which was empty
1880 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1881 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisc2c38022012-04-11 17:20:03 -07001882
1883 glClearColor(0.2, 0.2, 0.2, 0.2);
1884 glClear(GL_COLOR_BUFFER_BIT);
1885
1886 glViewport(0, 0, texWidth, texHeight);
1887 drawTexture();
1888
1889 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
1890 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
1891 EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
1892 EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
1893
1894 EXPECT_TRUE(checkPixel( 4, 4, 255, 0, 0, 255));
1895 EXPECT_TRUE(checkPixel( 5, 5, 153, 153, 153, 153));
1896 EXPECT_TRUE(checkPixel( 3, 3, 153, 153, 153, 153));
1897 EXPECT_TRUE(checkPixel(45, 52, 153, 153, 153, 153));
1898 EXPECT_TRUE(checkPixel(12, 36, 153, 153, 153, 153));
1899}
1900
1901TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedUserSizedGLFilledBuffer) {
1902 enum { texWidth = 64 };
1903 enum { texHeight = 16 };
1904
Jamie Gennis46975282012-08-30 18:35:50 -07001905 // This test requires 3 buffers to complete run on a single thread.
1906 mST->setDefaultMaxBufferCount(3);
1907
Jamie Gennisc2c38022012-04-11 17:20:03 -07001908 // Set the transform hint.
1909 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1910
1911 // Set the user buffer size.
1912 native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
1913
1914 // Do the producer side of things
1915 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1916 mProducerEglSurface, mProducerEglContext));
1917 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1918
1919 // This is needed to ensure we pick up a buffer of the correct size and the
1920 // new rotation hint.
1921 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1922
1923 glClearColor(0.6, 0.6, 0.6, 0.6);
1924 glClear(GL_COLOR_BUFFER_BIT);
1925
1926 glEnable(GL_SCISSOR_TEST);
1927 glScissor(24, 4, 1, 1);
1928 glClearColor(1.0, 0.0, 0.0, 1.0);
1929 glClear(GL_COLOR_BUFFER_BIT);
1930
1931 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1932
1933 // Do the consumer side of things
1934 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1935 mEglContext));
1936 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1937
1938 glDisable(GL_SCISSOR_TEST);
1939
Jamie Gennisd69097f2012-08-30 13:28:23 -07001940 // Skip the first frame, which was empty
1941 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1942 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisc2c38022012-04-11 17:20:03 -07001943
1944 glClearColor(0.2, 0.2, 0.2, 0.2);
1945 glClear(GL_COLOR_BUFFER_BIT);
1946
1947 glViewport(0, 0, texWidth, texHeight);
1948 drawTexture();
1949
1950 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
1951 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
1952 EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
1953 EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
1954
1955 EXPECT_TRUE(checkPixel(24, 4, 255, 0, 0, 255));
1956 EXPECT_TRUE(checkPixel(25, 5, 153, 153, 153, 153));
1957 EXPECT_TRUE(checkPixel(23, 3, 153, 153, 153, 153));
1958 EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
1959 EXPECT_TRUE(checkPixel(12, 8, 153, 153, 153, 153));
1960}
1961
1962TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedGLFilledBuffer) {
1963 enum { texWidth = 64 };
1964 enum { texHeight = 16 };
1965
Jamie Gennis46975282012-08-30 18:35:50 -07001966 // This test requires 3 buffers to complete run on a single thread.
1967 mST->setDefaultMaxBufferCount(3);
1968
Jamie Gennisc2c38022012-04-11 17:20:03 -07001969 // Set the transform hint.
1970 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1971
1972 // Set the default buffer size.
1973 mST->setDefaultBufferSize(texWidth, texHeight);
1974
1975 // Do the producer side of things
1976 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1977 mProducerEglSurface, mProducerEglContext));
1978 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1979
1980 // This is needed to ensure we pick up a buffer of the correct size and the
1981 // new rotation hint.
1982 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1983
1984 glClearColor(0.6, 0.6, 0.6, 0.6);
1985 glClear(GL_COLOR_BUFFER_BIT);
1986
1987 glEnable(GL_SCISSOR_TEST);
1988 glScissor(24, 4, 1, 1);
1989 glClearColor(1.0, 0.0, 0.0, 1.0);
1990 glClear(GL_COLOR_BUFFER_BIT);
1991
1992 eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1993
1994 // Do the consumer side of things
1995 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1996 mEglContext));
1997 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1998
1999 glDisable(GL_SCISSOR_TEST);
2000
Jamie Gennisd69097f2012-08-30 13:28:23 -07002001 // Skip the first frame, which was empty
2002 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2003 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennisc2c38022012-04-11 17:20:03 -07002004
2005 glClearColor(0.2, 0.2, 0.2, 0.2);
2006 glClear(GL_COLOR_BUFFER_BIT);
2007
2008 glViewport(0, 0, texWidth, texHeight);
2009 drawTexture();
2010
2011 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
2012 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
2013 EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
2014 EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
2015
2016 EXPECT_TRUE(checkPixel(24, 4, 255, 0, 0, 255));
2017 EXPECT_TRUE(checkPixel(25, 5, 153, 153, 153, 153));
2018 EXPECT_TRUE(checkPixel(23, 3, 153, 153, 153, 153));
2019 EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
2020 EXPECT_TRUE(checkPixel(12, 8, 153, 153, 153, 153));
2021}
2022
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002023/*
2024 * This test fixture is for testing GL -> GL texture streaming from one thread
2025 * to another. It contains functionality to create a producer thread that will
2026 * perform GL rendering to an ANativeWindow that feeds frames to a
Andy McFadden2adaf042012-12-18 09:49:45 -08002027 * GLConsumer. Additionally it supports interlocking the producer and
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002028 * consumer threads so that a specific sequence of calls can be
2029 * deterministically created by the test.
Jamie Gennis5451d152011-06-08 09:40:45 -07002030 *
2031 * The intended usage is as follows:
2032 *
2033 * TEST_F(...) {
2034 * class PT : public ProducerThread {
2035 * virtual void render() {
2036 * ...
2037 * swapBuffers();
2038 * }
2039 * };
2040 *
2041 * runProducerThread(new PT());
2042 *
2043 * // The order of these calls will vary from test to test and may include
2044 * // multiple frames and additional operations (e.g. GL rendering from the
2045 * // texture).
2046 * fc->waitForFrame();
2047 * mST->updateTexImage();
2048 * fc->finishFrame();
2049 * }
2050 *
2051 */
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002052class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest {
Jamie Gennis5451d152011-06-08 09:40:45 -07002053protected:
2054
2055 // ProducerThread is an abstract base class to simplify the creation of
2056 // OpenGL ES frame producer threads.
2057 class ProducerThread : public Thread {
2058 public:
2059 virtual ~ProducerThread() {
2060 }
2061
2062 void setEglObjects(EGLDisplay producerEglDisplay,
2063 EGLSurface producerEglSurface,
2064 EGLContext producerEglContext) {
2065 mProducerEglDisplay = producerEglDisplay;
2066 mProducerEglSurface = producerEglSurface;
2067 mProducerEglContext = producerEglContext;
2068 }
2069
2070 virtual bool threadLoop() {
2071 eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
2072 mProducerEglSurface, mProducerEglContext);
2073 render();
2074 eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2075 EGL_NO_CONTEXT);
2076 return false;
2077 }
2078
2079 protected:
2080 virtual void render() = 0;
2081
2082 void swapBuffers() {
2083 eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
2084 }
2085
2086 EGLDisplay mProducerEglDisplay;
2087 EGLSurface mProducerEglSurface;
2088 EGLContext mProducerEglContext;
2089 };
2090
2091 // FrameCondition is a utility class for interlocking between the producer
2092 // and consumer threads. The FrameCondition object should be created and
2093 // destroyed in the consumer thread only. The consumer thread should set
Andy McFadden2adaf042012-12-18 09:49:45 -08002094 // the FrameCondition as the FrameAvailableListener of the GLConsumer,
Jamie Gennis5451d152011-06-08 09:40:45 -07002095 // and should call both waitForFrame and finishFrame once for each expected
2096 // frame.
2097 //
2098 // This interlocking relies on the fact that onFrameAvailable gets called
Andy McFadden2adaf042012-12-18 09:49:45 -08002099 // synchronously from GLConsumer::queueBuffer.
2100 class FrameCondition : public GLConsumer::FrameAvailableListener {
Jamie Gennis5451d152011-06-08 09:40:45 -07002101 public:
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002102 FrameCondition():
2103 mFrameAvailable(false),
2104 mFrameFinished(false) {
2105 }
2106
Jamie Gennis5451d152011-06-08 09:40:45 -07002107 // waitForFrame waits for the next frame to arrive. This should be
2108 // called from the consumer thread once for every frame expected by the
2109 // test.
2110 void waitForFrame() {
Jamie Gennis5451d152011-06-08 09:40:45 -07002111 Mutex::Autolock lock(mMutex);
Steve Block6807e592011-10-20 11:56:00 +01002112 ALOGV("+waitForFrame");
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002113 while (!mFrameAvailable) {
2114 mFrameAvailableCondition.wait(mMutex);
2115 }
2116 mFrameAvailable = false;
Steve Block6807e592011-10-20 11:56:00 +01002117 ALOGV("-waitForFrame");
Jamie Gennis5451d152011-06-08 09:40:45 -07002118 }
2119
2120 // Allow the producer to return from its swapBuffers call and continue
2121 // on to produce the next frame. This should be called by the consumer
2122 // thread once for every frame expected by the test.
2123 void finishFrame() {
Jamie Gennis5451d152011-06-08 09:40:45 -07002124 Mutex::Autolock lock(mMutex);
Steve Block6807e592011-10-20 11:56:00 +01002125 ALOGV("+finishFrame");
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002126 mFrameFinished = true;
Jamie Gennis5451d152011-06-08 09:40:45 -07002127 mFrameFinishCondition.signal();
Steve Block6807e592011-10-20 11:56:00 +01002128 ALOGV("-finishFrame");
Jamie Gennis5451d152011-06-08 09:40:45 -07002129 }
2130
Andy McFadden2adaf042012-12-18 09:49:45 -08002131 // This should be called by GLConsumer on the producer thread.
Jamie Gennis5451d152011-06-08 09:40:45 -07002132 virtual void onFrameAvailable() {
Jamie Gennis5451d152011-06-08 09:40:45 -07002133 Mutex::Autolock lock(mMutex);
Steve Block6807e592011-10-20 11:56:00 +01002134 ALOGV("+onFrameAvailable");
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002135 mFrameAvailable = true;
Jamie Gennis5451d152011-06-08 09:40:45 -07002136 mFrameAvailableCondition.signal();
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002137 while (!mFrameFinished) {
2138 mFrameFinishCondition.wait(mMutex);
2139 }
2140 mFrameFinished = false;
Steve Block6807e592011-10-20 11:56:00 +01002141 ALOGV("-onFrameAvailable");
Jamie Gennis5451d152011-06-08 09:40:45 -07002142 }
2143
2144 protected:
Jamie Gennis2640bfd2011-07-14 17:11:47 -07002145 bool mFrameAvailable;
2146 bool mFrameFinished;
2147
Jamie Gennis5451d152011-06-08 09:40:45 -07002148 Mutex mMutex;
2149 Condition mFrameAvailableCondition;
2150 Condition mFrameFinishCondition;
2151 };
2152
Jamie Gennis5451d152011-06-08 09:40:45 -07002153 virtual void SetUp() {
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002154 SurfaceTextureGLToGLTest::SetUp();
Jamie Gennis5451d152011-06-08 09:40:45 -07002155 mFC = new FrameCondition();
2156 mST->setFrameAvailableListener(mFC);
2157 }
2158
2159 virtual void TearDown() {
2160 if (mProducerThread != NULL) {
2161 mProducerThread->requestExitAndWait();
2162 }
Jamie Gennis5451d152011-06-08 09:40:45 -07002163 mProducerThread.clear();
2164 mFC.clear();
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002165 SurfaceTextureGLToGLTest::TearDown();
Jamie Gennis5451d152011-06-08 09:40:45 -07002166 }
2167
2168 void runProducerThread(const sp<ProducerThread> producerThread) {
2169 ASSERT_TRUE(mProducerThread == NULL);
2170 mProducerThread = producerThread;
2171 producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
2172 mProducerEglContext);
2173 producerThread->run();
2174 }
2175
Jamie Gennis5451d152011-06-08 09:40:45 -07002176 sp<ProducerThread> mProducerThread;
2177 sp<FrameCondition> mFC;
2178};
2179
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002180TEST_F(SurfaceTextureGLThreadToGLTest,
2181 UpdateTexImageBeforeFrameFinishedCompletes) {
Jamie Gennis5451d152011-06-08 09:40:45 -07002182 class PT : public ProducerThread {
2183 virtual void render() {
2184 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2185 glClear(GL_COLOR_BUFFER_BIT);
2186 swapBuffers();
2187 }
2188 };
2189
2190 runProducerThread(new PT());
2191
2192 mFC->waitForFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07002193 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis5451d152011-06-08 09:40:45 -07002194 mFC->finishFrame();
2195
2196 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
Jamie Gennisd99c0882011-03-10 16:24:46 -08002197}
Jamie Gennis5451d152011-06-08 09:40:45 -07002198
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002199TEST_F(SurfaceTextureGLThreadToGLTest,
2200 UpdateTexImageAfterFrameFinishedCompletes) {
Jamie Gennis5451d152011-06-08 09:40:45 -07002201 class PT : public ProducerThread {
2202 virtual void render() {
2203 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2204 glClear(GL_COLOR_BUFFER_BIT);
2205 swapBuffers();
2206 }
2207 };
2208
2209 runProducerThread(new PT());
2210
2211 mFC->waitForFrame();
2212 mFC->finishFrame();
Jamie Gennisd69097f2012-08-30 13:28:23 -07002213 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis5451d152011-06-08 09:40:45 -07002214
2215 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2216}
2217
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002218TEST_F(SurfaceTextureGLThreadToGLTest,
2219 RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
Jamie Gennis5451d152011-06-08 09:40:45 -07002220 enum { NUM_ITERATIONS = 1024 };
2221
2222 class PT : public ProducerThread {
2223 virtual void render() {
2224 for (int i = 0; i < NUM_ITERATIONS; i++) {
2225 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2226 glClear(GL_COLOR_BUFFER_BIT);
Steve Block6807e592011-10-20 11:56:00 +01002227 ALOGV("+swapBuffers");
Jamie Gennis5451d152011-06-08 09:40:45 -07002228 swapBuffers();
Steve Block6807e592011-10-20 11:56:00 +01002229 ALOGV("-swapBuffers");
Jamie Gennis5451d152011-06-08 09:40:45 -07002230 }
2231 }
2232 };
2233
2234 runProducerThread(new PT());
2235
2236 for (int i = 0; i < NUM_ITERATIONS; i++) {
2237 mFC->waitForFrame();
Steve Block6807e592011-10-20 11:56:00 +01002238 ALOGV("+updateTexImage");
Jamie Gennisd69097f2012-08-30 13:28:23 -07002239 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Steve Block6807e592011-10-20 11:56:00 +01002240 ALOGV("-updateTexImage");
Jamie Gennis5451d152011-06-08 09:40:45 -07002241 mFC->finishFrame();
2242
2243 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2244 }
2245}
2246
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002247TEST_F(SurfaceTextureGLThreadToGLTest,
2248 RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
Jamie Gennis5451d152011-06-08 09:40:45 -07002249 enum { NUM_ITERATIONS = 1024 };
2250
2251 class PT : public ProducerThread {
2252 virtual void render() {
2253 for (int i = 0; i < NUM_ITERATIONS; i++) {
2254 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2255 glClear(GL_COLOR_BUFFER_BIT);
Steve Block6807e592011-10-20 11:56:00 +01002256 ALOGV("+swapBuffers");
Jamie Gennis5451d152011-06-08 09:40:45 -07002257 swapBuffers();
Steve Block6807e592011-10-20 11:56:00 +01002258 ALOGV("-swapBuffers");
Jamie Gennis5451d152011-06-08 09:40:45 -07002259 }
2260 }
2261 };
2262
2263 runProducerThread(new PT());
2264
2265 for (int i = 0; i < NUM_ITERATIONS; i++) {
2266 mFC->waitForFrame();
2267 mFC->finishFrame();
Steve Block6807e592011-10-20 11:56:00 +01002268 ALOGV("+updateTexImage");
Jamie Gennisd69097f2012-08-30 13:28:23 -07002269 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Steve Block6807e592011-10-20 11:56:00 +01002270 ALOGV("-updateTexImage");
Jamie Gennis5451d152011-06-08 09:40:45 -07002271
2272 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2273 }
2274}
2275
Jamie Gennis6e502192011-07-21 14:31:31 -07002276// XXX: This test is disabled because it is currently hanging on some devices.
Jamie Gennis6f4cdfe2011-11-19 17:49:21 -08002277TEST_F(SurfaceTextureGLThreadToGLTest,
2278 DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
Jamie Gennis6e502192011-07-21 14:31:31 -07002279 enum { NUM_ITERATIONS = 64 };
2280
2281 class PT : public ProducerThread {
2282 virtual void render() {
2283 for (int i = 0; i < NUM_ITERATIONS; i++) {
2284 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2285 glClear(GL_COLOR_BUFFER_BIT);
Steve Block6807e592011-10-20 11:56:00 +01002286 ALOGV("+swapBuffers");
Jamie Gennis6e502192011-07-21 14:31:31 -07002287 swapBuffers();
Steve Block6807e592011-10-20 11:56:00 +01002288 ALOGV("-swapBuffers");
Jamie Gennis6e502192011-07-21 14:31:31 -07002289 }
2290 }
2291 };
2292
2293 ASSERT_EQ(OK, mST->setSynchronousMode(true));
Jamie Gennis31a353d2012-08-24 17:25:13 -07002294 ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
Jamie Gennis6e502192011-07-21 14:31:31 -07002295
2296 runProducerThread(new PT());
2297
2298 // Allow three frames to be rendered and queued before starting the
2299 // rendering in this thread. For the latter two frames we don't call
2300 // updateTexImage so the next dequeue from the producer thread will block
2301 // waiting for a frame to become available.
2302 mFC->waitForFrame();
2303 mFC->finishFrame();
2304
2305 // We must call updateTexImage to consume the first frame so that the
2306 // SurfaceTexture is able to reduce the buffer count to 2. This is because
2307 // the GL driver may dequeue a buffer when the EGLSurface is created, and
Jamie Gennis31a353d2012-08-24 17:25:13 -07002308 // that happens before we call setDefaultMaxBufferCount. It's possible that the
Jamie Gennis6e502192011-07-21 14:31:31 -07002309 // driver does not dequeue a buffer at EGLSurface creation time, so we
2310 // cannot rely on this to cause the second dequeueBuffer call to block.
Jamie Gennisd69097f2012-08-30 13:28:23 -07002311 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis6e502192011-07-21 14:31:31 -07002312
2313 mFC->waitForFrame();
2314 mFC->finishFrame();
2315 mFC->waitForFrame();
2316 mFC->finishFrame();
2317
2318 // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
2319 // block waiting for a buffer to become available.
2320 usleep(100000);
2321
2322 // Render and present a number of images. This thread should not be blocked
2323 // by the fact that the producer thread is blocking in dequeue.
2324 for (int i = 0; i < NUM_ITERATIONS; i++) {
2325 glClear(GL_COLOR_BUFFER_BIT);
2326 eglSwapBuffers(mEglDisplay, mEglSurface);
2327 }
2328
2329 // Consume the two pending buffers to unblock the producer thread.
Jamie Gennisd69097f2012-08-30 13:28:23 -07002330 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2331 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Jamie Gennis6e502192011-07-21 14:31:31 -07002332
2333 // Consume the remaining buffers from the producer thread.
2334 for (int i = 0; i < NUM_ITERATIONS-3; i++) {
2335 mFC->waitForFrame();
2336 mFC->finishFrame();
Steve Block6807e592011-10-20 11:56:00 +01002337 ALOGV("+updateTexImage");
Jamie Gennisd69097f2012-08-30 13:28:23 -07002338 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
Steve Block6807e592011-10-20 11:56:00 +01002339 ALOGV("-updateTexImage");
Jamie Gennis6e502192011-07-21 14:31:31 -07002340 }
2341}
2342
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002343class SurfaceTextureFBOTest : public SurfaceTextureGLTest {
2344protected:
2345
2346 virtual void SetUp() {
2347 SurfaceTextureGLTest::SetUp();
2348
2349 glGenFramebuffers(1, &mFbo);
2350 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2351
2352 glGenTextures(1, &mFboTex);
2353 glBindTexture(GL_TEXTURE_2D, mFboTex);
2354 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(),
2355 getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2356 glBindTexture(GL_TEXTURE_2D, 0);
2357 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2358
2359 glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2360 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2361 GL_TEXTURE_2D, mFboTex, 0);
2362 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2363 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2364 }
2365
2366 virtual void TearDown() {
2367 SurfaceTextureGLTest::TearDown();
2368
2369 glDeleteTextures(1, &mFboTex);
2370 glDeleteFramebuffers(1, &mFbo);
2371 }
2372
2373 GLuint mFbo;
2374 GLuint mFboTex;
2375};
2376
2377// This test is intended to verify that proper synchronization is done when
2378// rendering into an FBO.
2379TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) {
2380 const int texWidth = 64;
2381 const int texHeight = 64;
2382
2383 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
2384 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
2385 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
2386 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
2387
2388 android_native_buffer_t* anb;
Jamie Gennisd8e812c2012-06-13 16:32:25 -07002389 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
2390 &anb));
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002391 ASSERT_TRUE(anb != NULL);
2392
2393 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002394
2395 // Fill the buffer with green
2396 uint8_t* img = NULL;
2397 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2398 fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255,
2399 0, 255);
2400 buf->unlock();
Jamie Gennisd8e812c2012-06-13 16:32:25 -07002401 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
2402 -1));
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002403
2404 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2405
2406 glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2407 drawTexture();
2408 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2409
2410 for (int i = 0; i < 4; i++) {
2411 SCOPED_TRACE(String8::format("frame %d", i).string());
2412
Jamie Gennisd8e812c2012-06-13 16:32:25 -07002413 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
2414 &anb));
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002415 ASSERT_TRUE(anb != NULL);
2416
2417 buf = new GraphicBuffer(anb, false);
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002418
2419 // Fill the buffer with red
2420 ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
2421 (void**)(&img)));
2422 fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0,
2423 0, 255);
2424 ASSERT_EQ(NO_ERROR, buf->unlock());
2425 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
Jamie Gennisd8e812c2012-06-13 16:32:25 -07002426 buf->getNativeBuffer(), -1));
Jamie Gennisfe27e2f2011-11-11 18:05:11 -08002427
2428 ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2429
2430 drawTexture();
2431
2432 EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255));
2433 }
2434
2435 glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2436
2437 EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255));
2438}
2439
Jamie Gennisce561372012-03-19 18:33:05 -07002440class SurfaceTextureMultiContextGLTest : public SurfaceTextureGLTest {
2441protected:
Jamie Gennis74bed552012-03-28 19:05:54 -07002442 enum { SECOND_TEX_ID = 123 };
2443 enum { THIRD_TEX_ID = 456 };
2444
Jamie Gennisce561372012-03-19 18:33:05 -07002445 SurfaceTextureMultiContextGLTest():
2446 mSecondEglContext(EGL_NO_CONTEXT) {
2447 }
2448
2449 virtual void SetUp() {
2450 SurfaceTextureGLTest::SetUp();
2451
Jamie Gennis74bed552012-03-28 19:05:54 -07002452 // Set up the secondary context and texture renderer.
Jamie Gennisce561372012-03-19 18:33:05 -07002453 mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig,
2454 EGL_NO_CONTEXT, getContextAttribs());
2455 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2456 ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext);
Jamie Gennis74bed552012-03-28 19:05:54 -07002457
2458 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2459 mSecondEglContext));
2460 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2461 mSecondTextureRenderer = new TextureRenderer(SECOND_TEX_ID, mST);
2462 ASSERT_NO_FATAL_FAILURE(mSecondTextureRenderer->SetUp());
2463
2464 // Set up the tertiary context and texture renderer.
2465 mThirdEglContext = eglCreateContext(mEglDisplay, mGlConfig,
2466 EGL_NO_CONTEXT, getContextAttribs());
2467 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2468 ASSERT_NE(EGL_NO_CONTEXT, mThirdEglContext);
2469
2470 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2471 mThirdEglContext));
2472 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2473 mThirdTextureRenderer = new TextureRenderer(THIRD_TEX_ID, mST);
2474 ASSERT_NO_FATAL_FAILURE(mThirdTextureRenderer->SetUp());
2475
2476 // Switch back to the primary context to start the tests.
2477 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2478 mEglContext));
Jamie Gennisce561372012-03-19 18:33:05 -07002479 }
2480
2481 virtual void TearDown() {
Jamie Gennis74bed552012-03-28 19:05:54 -07002482 if (mThirdEglContext != EGL_NO_CONTEXT) {
2483 eglDestroyContext(mEglDisplay, mThirdEglContext);
2484 }
Jamie Gennisce561372012-03-19 18:33:05 -07002485 if (mSecondEglContext != EGL_NO_CONTEXT) {
2486 eglDestroyContext(mEglDisplay, mSecondEglContext);
2487 }
2488 SurfaceTextureGLTest::TearDown();
2489 }
2490
2491 EGLContext mSecondEglContext;
Jamie Gennis74bed552012-03-28 19:05:54 -07002492 sp<TextureRenderer> mSecondTextureRenderer;
2493
2494 EGLContext mThirdEglContext;
2495 sp<TextureRenderer> mThirdTextureRenderer;
Jamie Gennisce561372012-03-19 18:33:05 -07002496};
2497
2498TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
Jamie Gennisce561372012-03-19 18:33:05 -07002499 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2500
2501 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002502 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002503 ASSERT_EQ(OK, mST->updateTexImage());
Jamie Gennisce561372012-03-19 18:33:05 -07002504
2505 // Attempt to latch the texture on the secondary context.
Jamie Gennis74bed552012-03-28 19:05:54 -07002506 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
Jamie Gennisce561372012-03-19 18:33:05 -07002507 mSecondEglContext));
2508 ASSERT_EQ(EGL_SUCCESS, eglGetError());
Jamie Gennis74bed552012-03-28 19:05:54 -07002509 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
2510}
2511
2512TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002513 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2514
2515 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002516 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002517 ASSERT_EQ(OK, mST->updateTexImage());
2518
2519 // Detach from the primary context.
2520 ASSERT_EQ(OK, mST->detachFromContext());
2521
2522 // Check that the GL texture was deleted.
2523 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
2524}
2525
2526TEST_F(SurfaceTextureMultiContextGLTest,
2527 DetachFromContextSucceedsAfterProducerDisconnect) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002528 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2529
2530 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002531 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002532 ASSERT_EQ(OK, mST->updateTexImage());
2533
2534 // Detach from the primary context.
2535 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2536 ASSERT_EQ(OK, mST->detachFromContext());
2537
2538 // Check that the GL texture was deleted.
2539 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
2540}
2541
2542TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002543 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2544
2545 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002546 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002547 ASSERT_EQ(OK, mST->updateTexImage());
2548
2549 // Attempt to detach from the primary context.
2550 mST->abandon();
2551 ASSERT_EQ(NO_INIT, mST->detachFromContext());
2552}
2553
2554TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002555 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2556
2557 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002558 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002559 ASSERT_EQ(OK, mST->updateTexImage());
2560
2561 // Detach from the primary context.
2562 ASSERT_EQ(OK, mST->detachFromContext());
2563
2564 // Attempt to detach from the primary context again.
2565 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2566}
2567
2568TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002569 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2570
2571 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002572 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002573 ASSERT_EQ(OK, mST->updateTexImage());
2574
2575 // Make there be no current display.
2576 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2577 EGL_NO_CONTEXT));
2578 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2579
2580 // Attempt to detach from the primary context.
2581 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2582}
2583
2584TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002585 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2586
2587 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002588 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002589 ASSERT_EQ(OK, mST->updateTexImage());
2590
2591 // Make current context be incorrect.
2592 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2593 mSecondEglContext));
2594 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2595
2596 // Attempt to detach from the primary context.
2597 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2598}
2599
2600TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002601 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2602
2603 // Detach from the primary context.
2604 ASSERT_EQ(OK, mST->detachFromContext());
2605
2606 // Attempt to latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002607 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002608 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
2609}
2610
2611TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002612 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2613
2614 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002615 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002616 ASSERT_EQ(OK, mST->updateTexImage());
2617
2618 // Detach from the primary context.
2619 ASSERT_EQ(OK, mST->detachFromContext());
2620
2621 // Attach to the secondary context.
2622 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2623 mSecondEglContext));
2624 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2625
2626 // Verify that the texture object was created and bound.
2627 GLint texBinding = -1;
2628 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2629 EXPECT_EQ(SECOND_TEX_ID, texBinding);
2630
2631 // Try to use the texture from the secondary context.
2632 glClearColor(0.2, 0.2, 0.2, 0.2);
2633 glClear(GL_COLOR_BUFFER_BIT);
2634 glViewport(0, 0, 1, 1);
2635 mSecondTextureRenderer->drawTexture();
2636 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
2637 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2638}
2639
2640TEST_F(SurfaceTextureMultiContextGLTest,
2641 AttachToContextSucceedsAfterProducerDisconnect) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002642 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2643
2644 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002645 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002646 ASSERT_EQ(OK, mST->updateTexImage());
2647
2648 // Detach from the primary context.
2649 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2650 ASSERT_EQ(OK, mST->detachFromContext());
2651
2652 // Attach to the secondary context.
2653 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2654 mSecondEglContext));
2655 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2656
2657 // Verify that the texture object was created and bound.
2658 GLint texBinding = -1;
2659 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2660 EXPECT_EQ(SECOND_TEX_ID, texBinding);
2661
2662 // Try to use the texture from the secondary context.
2663 glClearColor(0.2, 0.2, 0.2, 0.2);
2664 glClear(GL_COLOR_BUFFER_BIT);
2665 glViewport(0, 0, 1, 1);
2666 mSecondTextureRenderer->drawTexture();
2667 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2668 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
2669}
2670
2671TEST_F(SurfaceTextureMultiContextGLTest,
2672 AttachToContextSucceedsBeforeUpdateTexImage) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002673 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2674
2675 // Detach from the primary context.
2676 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2677 ASSERT_EQ(OK, mST->detachFromContext());
2678
2679 // Attach to the secondary context.
2680 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2681 mSecondEglContext));
2682 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2683
2684 // Verify that the texture object was created and bound.
2685 GLint texBinding = -1;
2686 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2687 EXPECT_EQ(SECOND_TEX_ID, texBinding);
2688
2689 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002690 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002691 ASSERT_EQ(OK, mST->updateTexImage());
2692
2693 // Try to use the texture from the secondary context.
2694 glClearColor(0.2, 0.2, 0.2, 0.2);
2695 glClear(GL_COLOR_BUFFER_BIT);
2696 glViewport(0, 0, 1, 1);
2697 mSecondTextureRenderer->drawTexture();
2698 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2699 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
2700}
2701
2702TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002703 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2704
2705 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002706 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002707 ASSERT_EQ(OK, mST->updateTexImage());
2708
2709 // Detach from the primary context.
2710 ASSERT_EQ(OK, mST->detachFromContext());
2711
2712 // Attempt to attach to the secondary context.
2713 mST->abandon();
2714
2715 // Attempt to attach to the primary context.
2716 ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID));
2717}
2718
2719TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002720 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2721
2722 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002723 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002724 ASSERT_EQ(OK, mST->updateTexImage());
2725
2726 // Attempt to attach to the primary context.
2727 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2728}
2729
2730TEST_F(SurfaceTextureMultiContextGLTest,
2731 AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002732 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2733
2734 // Attempt to attach to the primary context.
2735 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2736}
2737
2738TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002739 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2740
2741 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002742 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002743 ASSERT_EQ(OK, mST->updateTexImage());
2744
2745 // Detach from the primary context.
2746 ASSERT_EQ(OK, mST->detachFromContext());
2747
2748 // Make there be no current display.
2749 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2750 EGL_NO_CONTEXT));
2751 ASSERT_EQ(EGL_SUCCESS, eglGetError());
2752
2753 // Attempt to attach with no context current.
2754 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2755}
2756
2757TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002758 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2759
2760 // Latch the texture contents on the primary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002761 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002762 ASSERT_EQ(OK, mST->updateTexImage());
2763
2764 // Detach from the primary context.
2765 ASSERT_EQ(OK, mST->detachFromContext());
2766
2767 // Attach to the secondary context.
2768 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2769 mSecondEglContext));
2770 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2771
2772 // Detach from the secondary context.
2773 ASSERT_EQ(OK, mST->detachFromContext());
2774
2775 // Attach to the tertiary context.
2776 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2777 mThirdEglContext));
2778 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
2779
2780 // Verify that the texture object was created and bound.
2781 GLint texBinding = -1;
2782 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2783 EXPECT_EQ(THIRD_TEX_ID, texBinding);
2784
2785 // Try to use the texture from the tertiary context.
2786 glClearColor(0.2, 0.2, 0.2, 0.2);
2787 glClear(GL_COLOR_BUFFER_BIT);
2788 glViewport(0, 0, 1, 1);
2789 mThirdTextureRenderer->drawTexture();
2790 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2791 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
2792}
2793
2794TEST_F(SurfaceTextureMultiContextGLTest,
2795 AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
Jamie Gennis74bed552012-03-28 19:05:54 -07002796 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2797
2798 // Detach from the primary context.
2799 ASSERT_EQ(OK, mST->detachFromContext());
2800
2801 // Attach to the secondary context.
2802 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2803 mSecondEglContext));
2804 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2805
2806 // Detach from the secondary context.
2807 ASSERT_EQ(OK, mST->detachFromContext());
2808
2809 // Attach to the tertiary context.
2810 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2811 mThirdEglContext));
2812 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
2813
2814 // Verify that the texture object was created and bound.
2815 GLint texBinding = -1;
2816 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2817 EXPECT_EQ(THIRD_TEX_ID, texBinding);
2818
2819 // Latch the texture contents on the tertiary context.
Jamie Gennisefc7ab62012-04-17 19:36:18 -07002820 mFW->waitForFrame();
Jamie Gennis74bed552012-03-28 19:05:54 -07002821 ASSERT_EQ(OK, mST->updateTexImage());
2822
2823 // Try to use the texture from the tertiary context.
2824 glClearColor(0.2, 0.2, 0.2, 0.2);
2825 glClear(GL_COLOR_BUFFER_BIT);
2826 glViewport(0, 0, 1, 1);
2827 mThirdTextureRenderer->drawTexture();
2828 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2829 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
Jamie Gennisce561372012-03-19 18:33:05 -07002830}
2831
Jesse Hall90ed8502012-05-16 23:44:34 -07002832TEST_F(SurfaceTextureMultiContextGLTest,
2833 UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
2834 ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
Jamie Gennis31a353d2012-08-24 17:25:13 -07002835 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
Jesse Hall90ed8502012-05-16 23:44:34 -07002836
2837 // produce two frames and consume them both on the primary context
2838 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2839 mFW->waitForFrame();
2840 ASSERT_EQ(OK, mST->updateTexImage());
2841
2842 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2843 mFW->waitForFrame();
2844 ASSERT_EQ(OK, mST->updateTexImage());
2845
2846 // produce one more frame
2847 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2848
2849 // Detach from the primary context and attach to the secondary context
2850 ASSERT_EQ(OK, mST->detachFromContext());
2851 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2852 mSecondEglContext));
2853 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2854
2855 // Consume final frame on secondary context
2856 mFW->waitForFrame();
2857 ASSERT_EQ(OK, mST->updateTexImage());
2858}
2859
Jamie Gennis5451d152011-06-08 09:40:45 -07002860} // namespace android