1cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza/*
2cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * Copyright 2013 The Android Open Source Project
3cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza *
4cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * Licensed under the Apache License, Version 2.0 (the "License");
5cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * you may not use this file except in compliance with the License.
6cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * You may obtain a copy of the License at
7cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza *
8cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza *      http://www.apache.org/licenses/LICENSE-2.0
9cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza *
10cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * Unless required by applicable law or agreed to in writing, software
11cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * distributed under the License is distributed on an "AS IS" BASIS,
12cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * See the License for the specific language governing permissions and
14cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza * limitations under the License.
15cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza */
16cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza
17f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza#include "GLTest.h"
18f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
19f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza#include <gui/Surface.h>
20f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
21f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza#include <GLES2/gl2.h>
22f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
23f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozanamespace android {
24f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
25f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozastatic int abs(int value) {
26f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return value > 0 ? value : -value;
27f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
28f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
29f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozavoid GLTest::SetUp() {
30f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    const ::testing::TestInfo* const testInfo =
31f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ::testing::UnitTest::GetInstance()->current_test_info();
32f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
33f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
34f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
35f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
36f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
37f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
38f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EGLint majorVersion;
39f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EGLint minorVersion;
40f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
41f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
42f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    RecordProperty("EglVersionMajor", majorVersion);
43f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    RecordProperty("EglVersionMinor", minorVersion);
44f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
45f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EGLint numConfigs = 0;
46f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig, 1,
47f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            &numConfigs));
48f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
49f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
50f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
51f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (displaySecsEnv != NULL) {
52f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mDisplaySecs = atoi(displaySecsEnv);
53f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (mDisplaySecs < 0) {
54f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            mDisplaySecs = 0;
55f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
56f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    } else {
57f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mDisplaySecs = 0;
58f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
59f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
60f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mDisplaySecs > 0) {
61f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mComposerClient = new SurfaceComposerClient;
62f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
63f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
64f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mSurfaceControl = mComposerClient->createSurface(
65f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                String8("Test Surface"), getSurfaceWidth(), getSurfaceHeight(),
66f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                PIXEL_FORMAT_RGB_888, 0);
67f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
68f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_TRUE(mSurfaceControl != NULL);
69f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_TRUE(mSurfaceControl->isValid());
70f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
71f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        SurfaceComposerClient::openGlobalTransaction();
72f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
73f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
74f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        SurfaceComposerClient::closeGlobalTransaction();
75f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
76f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        sp<ANativeWindow> window = mSurfaceControl->getSurface();
77f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
78f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    } else {
79f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGLint pbufferAttribs[] = {
80f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            EGL_WIDTH, getSurfaceWidth(),
81f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            EGL_HEIGHT, getSurfaceHeight(),
82f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            EGL_NONE };
83f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
84f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
85f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                pbufferAttribs);
86f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
87f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
88f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
89f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
90f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
91f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            getContextAttribs());
92f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
93f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
94f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
95f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
96f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            mEglContext));
97f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
98f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
99f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EGLint w, h;
100f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
101f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
102f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
103f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
104f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    RecordProperty("EglSurfaceWidth", w);
105f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    RecordProperty("EglSurfaceHeight", h);
106f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
107f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    glViewport(0, 0, w, h);
108f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
109f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
110f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
111f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozavoid GLTest::TearDown() {
112f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    // Display the result
113f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
114f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        eglSwapBuffers(mEglDisplay, mEglSurface);
115f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        sleep(mDisplaySecs);
116f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
117f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
118f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mComposerClient != NULL) {
119f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        mComposerClient->dispose();
120f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
121f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mEglContext != EGL_NO_CONTEXT) {
122f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        eglDestroyContext(mEglDisplay, mEglContext);
123f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
124f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mEglSurface != EGL_NO_SURFACE) {
125f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        eglDestroySurface(mEglDisplay, mEglSurface);
126f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
127f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (mEglDisplay != EGL_NO_DISPLAY) {
128f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
129f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                EGL_NO_CONTEXT);
130f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        eglTerminate(mEglDisplay);
131f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
132f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(EGL_SUCCESS, eglGetError());
133f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
134f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    const ::testing::TestInfo* const testInfo =
135f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ::testing::UnitTest::GetInstance()->current_test_info();
136f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ALOGV("End test:   %s.%s", testInfo->test_case_name(), testInfo->name());
137f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
138f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
139f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan StozaEGLint const* GLTest::getConfigAttribs() {
140f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    static const EGLint sDefaultConfigAttribs[] = {
141f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
142f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
143f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_RED_SIZE, 8,
144f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_GREEN_SIZE, 8,
145f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_BLUE_SIZE, 8,
146f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_ALPHA_SIZE, 8,
147f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_DEPTH_SIZE, 16,
148f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_STENCIL_SIZE, 8,
149f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_NONE };
150f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
151f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return sDefaultConfigAttribs;
152f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
153f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
154f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan StozaEGLint const* GLTest::getContextAttribs() {
155f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    static const EGLint sDefaultContextAttribs[] = {
156f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_CONTEXT_CLIENT_VERSION, 2,
157f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        EGL_NONE };
158f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
159f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return sDefaultContextAttribs;
160f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
161f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
162f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan StozaEGLint GLTest::getSurfaceWidth() {
163f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return 512;
164f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
165f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
166f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan StozaEGLint GLTest::getSurfaceHeight() {
167f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return 512;
168f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
169f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
170f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan StozaEGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config,
171f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                                       sp<ANativeWindow>& window) const {
172f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    return eglCreateWindowSurface(display, config, window.get(), NULL);
173f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
174f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
175f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza::testing::AssertionResult GLTest::checkPixel(int x, int y,
176f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        int r, int g, int b, int a, int tolerance) {
177f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    GLubyte pixel[4];
178f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    String8 msg;
179f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
180f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    GLenum err = glGetError();
181f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (err != GL_NO_ERROR) {
182f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("error reading pixel: %#x", err);
183f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        while ((err = glGetError()) != GL_NO_ERROR) {
184f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += String8::format(", %#x", err);
185f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
186f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        return ::testing::AssertionFailure(::testing::Message(msg.string()));
187f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
188f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
189f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("r(%d isn't %d)", pixel[0], r);
190f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
191f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
192f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
193f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
194f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
195f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("g(%d isn't %d)", pixel[1], g);
196f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
197f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
198f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
199f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
200f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
201f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("b(%d isn't %d)", pixel[2], b);
202f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
203f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
204f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
205f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
206f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
207f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("a(%d isn't %d)", pixel[3], a);
208f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
209f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (!msg.isEmpty()) {
210f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        return ::testing::AssertionFailure(::testing::Message(msg.string()));
211f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    } else {
212f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        return ::testing::AssertionSuccess();
213f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
214f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
215f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
216f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza::testing::AssertionResult GLTest::assertRectEq(const Rect &r1, const Rect &r2,
217f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                                                int tolerance) {
218f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    String8 msg;
219f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
220f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (abs(r1.left - r2.left) > tolerance) {
221f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("left(%d isn't %d)", r1.left, r2.left);
222f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
223f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (abs(r1.top - r2.top) > tolerance) {
224f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
225f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
226f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
227f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("top(%d isn't %d)", r1.top, r2.top);
228f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
229f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (abs(r1.right - r2.right) > tolerance) {
230f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
231f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
232f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
233f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("right(%d isn't %d)", r1.right, r2.right);
234f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
235f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (abs(r1.bottom - r2.bottom) > tolerance) {
236f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!msg.isEmpty()) {
237f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            msg += " ";
238f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
239f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom);
240f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
241f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (!msg.isEmpty()) {
242f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]",
243f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                               r1.left, r1.top, r1.right, r1.bottom,
244f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                               r2.left, r2.top, r2.right, r2.bottom);
245f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        fprintf(stderr, "assertRectEq: %s\n", msg.string());
246f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        return ::testing::AssertionFailure(::testing::Message(msg.string()));
247f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    } else {
248f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        return ::testing::AssertionSuccess();
249f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
250f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
251f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
252f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozavoid GLTest::loadShader(GLenum shaderType, const char* pSource,
253f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        GLuint* outShader) {
254f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    GLuint shader = glCreateShader(shaderType);
255f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
256f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (shader) {
257f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glShaderSource(shader, 1, &pSource, NULL);
258f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
259f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glCompileShader(shader);
260f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
261f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        GLint compiled = 0;
262f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
263f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
264f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (!compiled) {
265f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            GLint infoLen = 0;
266f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
267f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
268f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            if (infoLen) {
269f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                char* buf = (char*) malloc(infoLen);
270f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                if (buf) {
271f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
272f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    printf("Shader compile log:\n%s\n", buf);
273f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    free(buf);
274f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    FAIL();
275f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                }
276f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            } else {
277f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                char* buf = (char*) malloc(0x1000);
278f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                if (buf) {
279f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    glGetShaderInfoLog(shader, 0x1000, NULL, buf);
280f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    printf("Shader compile log:\n%s\n", buf);
281f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    free(buf);
282f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    FAIL();
283f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                }
284f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            }
285f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            glDeleteShader(shader);
286f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            shader = 0;
287f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
288f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
289f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_TRUE(shader != 0);
290f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    *outShader = shader;
291f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
292f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
293f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stozavoid GLTest::createProgram(const char* pVertexSource,
294f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        const char* pFragmentSource, GLuint* outPgm) {
295f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    GLuint vertexShader, fragmentShader;
296f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    {
297f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        SCOPED_TRACE("compiling vertex shader");
298f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_NO_FATAL_FAILURE(loadShader(GL_VERTEX_SHADER, pVertexSource,
299f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                &vertexShader));
300f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
301f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    {
302f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        SCOPED_TRACE("compiling fragment shader");
303f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_NO_FATAL_FAILURE(loadShader(GL_FRAGMENT_SHADER, pFragmentSource,
304f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                &fragmentShader));
305f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
306f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
307f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    GLuint program = glCreateProgram();
308f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
309f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    if (program) {
310f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glAttachShader(program, vertexShader);
311f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
312f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glAttachShader(program, fragmentShader);
313f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
314f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glLinkProgram(program);
315f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        GLint linkStatus = GL_FALSE;
316f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
317f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        if (linkStatus != GL_TRUE) {
318f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            GLint bufLength = 0;
319f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
320f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            if (bufLength) {
321f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                char* buf = (char*) malloc(bufLength);
322f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                if (buf) {
323f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    glGetProgramInfoLog(program, bufLength, NULL, buf);
324f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    printf("Program link log:\n%s\n", buf);
325f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    free(buf);
326f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                    FAIL();
327f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza                }
328f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            }
329f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            glDeleteProgram(program);
330f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza            program = 0;
331f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza        }
332f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    }
333f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    glDeleteShader(vertexShader);
334f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    glDeleteShader(fragmentShader);
335f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    ASSERT_TRUE(program != 0);
336f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza    *outPgm = program;
337f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza}
338f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza
339f3730fb8f7da368740f9e5ed2603b405aeb4be72Dan Stoza} // namespace android
340