Add OpenglRender_unittests, fix glGetTexImage unavailability

glGetTexImage isn't necessarily supported on host, so do a fallback.

TODO: Add the GL snapshot tests back

Bug: 171711491
Change-Id: I94b034c20ed5a48fcff4cae17485e9e9abf0dbd9
diff --git a/stream-servers/tests/GLSnapshotVertexAttributes_unittest.cpp b/stream-servers/tests/GLSnapshotVertexAttributes_unittest.cpp
new file mode 100644
index 0000000..f8438dd
--- /dev/null
+++ b/stream-servers/tests/GLSnapshotVertexAttributes_unittest.cpp
@@ -0,0 +1,305 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "GLSnapshotTestStateUtils.h"
+#include "GLSnapshotTesting.h"
+#include "OpenGLTestContext.h"
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+
+namespace emugl {
+
+enum class GlVertexAttribMode { SingleValue = 0, Array = 1, Buffer = 2 };
+
+struct GlVertexAttrib {
+    GlVertexAttribMode mode;
+    GlValues values;
+    GLint size;
+    GLenum type;
+    GLboolean normalized;
+    GLsizei stride;
+    GLboolean enabled;
+    GLvoid* pointer;
+    GLuint bufferBinding;
+};
+
+static const GlVertexAttrib kGLES2DefaultVertexAttrib = {
+        .mode = GlVertexAttribMode::SingleValue,
+        .values = {.ints = {}, .floats = {0, 0, 0, 1}},
+        .size = 4,
+        .type = GL_FLOAT,
+        .normalized = GL_FALSE,
+        .stride = 0,
+        .enabled = GL_FALSE,
+        .pointer = nullptr,
+        .bufferBinding = 0};
+
+static const GlBufferData kTestAttachedBuffer = {.size = 16,
+                                                 .bytes = nullptr,
+                                                 .usage = GL_STATIC_DRAW};
+
+class SnapshotGlVertexAttributesTest
+    : public SnapshotSetValueTest<GlVertexAttrib> {
+public:
+    virtual void stateCheck(GlVertexAttrib expected) override {
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_ENABLED,
+                                        expected.enabled));
+    }
+
+    virtual void stateChange() override {
+        GlVertexAttrib changed = *m_changed_value;
+        if (changed.enabled) {
+            gl->glEnableVertexAttribArray(m_index);
+        } else {
+            gl->glDisableVertexAttribArray(m_index);
+        }
+        EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+    }
+
+    void selectIndex(GLuint index) {
+        GLint maxAttribs;
+        gl->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
+        EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        if (index >= maxAttribs) {
+            fprintf(stderr,
+                    "cannot select index %d: GL_MAX_VERTEX_ATTRIBS is %d.\n",
+                    index, maxAttribs);
+            return;
+        }
+        m_index = index;
+    }
+
+protected:
+    testing::AssertionResult compareFloatParameter(GLenum paramName,
+                                                   GLfloat expected) {
+        std::vector<GLfloat> v = {expected};
+        return compareFloatParameter(paramName, v);
+    }
+
+    testing::AssertionResult compareFloatParameter(
+            GLenum paramName,
+            const std::vector<GLfloat>& expected) {
+        std::vector<GLfloat> values;
+        values.resize(std::max((GLuint)4, (GLuint)expected.size()));
+        gl->glGetVertexAttribfv(m_index, paramName, &(values[0]));
+        EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        return compareVector<GLfloat>(
+                expected, values,
+                "float(s) for parameter " + describeGlEnum(paramName) +
+                        " of vertex attribute " + std::to_string(m_index));
+    }
+
+    testing::AssertionResult compareIntParameter(GLenum paramName,
+                                                 GLint expected) {
+        std::vector<GLint> v = {expected};
+        return compareIntParameter(paramName, v);
+    }
+
+    testing::AssertionResult compareIntParameter(
+            GLenum paramName,
+            const std::vector<GLint>& expected) {
+        std::vector<GLint> values;
+        values.resize(std::max((GLuint)4, (GLuint)expected.size()));
+        gl->glGetVertexAttribiv(m_index, paramName, &(values[0]));
+        EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        return compareVector<GLint>(
+                expected, values,
+                "int(s) for parameter " + describeGlEnum(paramName) +
+                        " of vertex attribute " + std::to_string(m_index));
+    }
+
+    GLuint m_index = 0;
+};
+
+class SnapshotGlVertexAttribSingleValueTest
+    : public SnapshotGlVertexAttributesTest {
+public:
+    void stateCheck(GlVertexAttrib expected) override {
+        SnapshotGlVertexAttributesTest::stateCheck(expected);
+
+        // check current element value
+        switch (expected.type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_FIXED:
+                EXPECT_TRUE(compareIntParameter(GL_CURRENT_VERTEX_ATTRIB,
+                                                expected.values.ints));
+                break;
+            case GL_FLOAT:
+                EXPECT_TRUE(compareFloatParameter(GL_CURRENT_VERTEX_ATTRIB,
+                                                  expected.values.floats));
+                break;
+            default:
+                ADD_FAILURE() << "Unexpected type " << expected.type
+                              << " for vertex attribute " << m_index;
+        }
+    }
+
+    void stateChange() override {
+        SnapshotGlVertexAttributesTest::stateChange();
+        GlVertexAttrib changed = *m_changed_value;
+        switch (changed.type) {
+            case GL_BYTE:
+            case GL_UNSIGNED_BYTE:
+            case GL_SHORT:
+            case GL_UNSIGNED_SHORT:
+            case GL_FIXED:
+                // TODO(benzene): support GLES3+
+                FAIL() << "GLES2 only supports float vertex attributes "
+                          "(VertexAttrib{1234}f).";
+            case GL_FLOAT:
+                switch (changed.values.floats.size()) {
+                    case 1:
+                        gl->glVertexAttrib1fv(
+                                m_index, (GLfloat*)&changed.values.floats[0]);
+                        break;
+                    case 2:
+                        gl->glVertexAttrib2fv(
+                                m_index, (GLfloat*)&changed.values.floats[0]);
+                        break;
+                    case 3:
+                        gl->glVertexAttrib3fv(
+                                m_index, (GLfloat*)&changed.values.floats[0]);
+                        break;
+                    case 4:
+                        gl->glVertexAttrib4fv(
+                                m_index, (GLfloat*)&changed.values.floats[0]);
+                        break;
+                    default:
+                        ADD_FAILURE() << "Unsupported size " << changed.size
+                                      << " for vertex attribute " << m_index;
+                }
+                break;
+            default:
+                ADD_FAILURE() << "Unsupported type " << changed.type
+                              << " for vertex attribute " << m_index;
+        }
+    }
+};
+
+class SnapshotGlVertexAttribArrayTest : public SnapshotGlVertexAttributesTest {
+public:
+    virtual void stateCheck(GlVertexAttrib expected) override {
+        SnapshotGlVertexAttributesTest::stateCheck(expected);
+        // check parameters
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_SIZE,
+                                        expected.size));
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_TYPE,
+                                        expected.type));
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_STRIDE,
+                                        expected.stride));
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED,
+                                        expected.normalized));
+        EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+                                        expected.bufferBinding));
+
+        GLvoid* pointer;
+        gl->glGetVertexAttribPointerv(m_index, GL_VERTEX_ATTRIB_ARRAY_POINTER,
+                                      &pointer);
+        EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        EXPECT_EQ(expected.pointer, pointer);
+    }
+
+    virtual void stateChange() override {
+        SnapshotGlVertexAttributesTest::stateChange();
+        GlVertexAttrib changed = *m_changed_value;
+        gl->glVertexAttribPointer(m_index, changed.size, changed.type,
+                                  changed.normalized, changed.stride,
+                                  changed.pointer);
+    }
+};
+
+class SnapshotGlVertexAttribBufferTest
+    : public SnapshotGlVertexAttribArrayTest {
+public:
+    void stateCheck(GlVertexAttrib expected) override {
+        SnapshotGlVertexAttribArrayTest::stateCheck(expected);
+    }
+
+    void stateChange() override {
+        GlVertexAttrib changed = *m_changed_value;
+
+        // Set up buffer to be bound before glVertexAttribPointer,
+        // which will copy ARRAY_BUFFER_BINDING into the attrib's binding
+        if (gl->glIsBuffer(changed.bufferBinding) == GL_TRUE) {
+            gl->glBindBuffer(GL_ARRAY_BUFFER, changed.bufferBinding);
+            EXPECT_EQ(GL_NO_ERROR, gl->glGetError())
+                    << "Failed to bind buffer " << changed.bufferBinding;
+            GLint bindresult;
+            gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &bindresult);
+            EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        } else {
+            ADD_FAILURE() << "Tried to bind buffer with vertex attributes but "
+                          << changed.bufferBinding << " is not a valid buffer.";
+        }
+
+        SnapshotGlVertexAttribArrayTest::stateChange();
+
+        if (changed.bufferBinding != 0) {
+            // Clear the array buffer binding
+            gl->glBindBuffer(GL_ARRAY_BUFFER, 0);
+            EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+
+            GLint bindresult;
+            gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &bindresult);
+            EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
+        }
+    }
+};
+
+TEST_F(SnapshotGlVertexAttribSingleValueTest, PreserveCurrentFloatAttrib) {
+    selectIndex(31);
+    GlVertexAttrib testAttrib = kGLES2DefaultVertexAttrib;
+    testAttrib.values = {.ints = {}, .floats = {.1, .3}},
+    setExpectedValues(kGLES2DefaultVertexAttrib, testAttrib);
+    doCheckedSnapshot();
+}
+
+TEST_F(SnapshotGlVertexAttribArrayTest, DISABLED_PreserveArrayProperties) {
+    selectIndex(5);
+    GLfloat testArrayContents[] = {2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f};
+    GlVertexAttrib arrayAttrib = kGLES2DefaultVertexAttrib;
+    arrayAttrib.mode = GlVertexAttribMode::Array;
+    arrayAttrib.size = 3;
+    arrayAttrib.stride = sizeof(GLfloat) * 3;
+    arrayAttrib.normalized = GL_TRUE;
+    arrayAttrib.enabled = GL_TRUE;
+    arrayAttrib.pointer = testArrayContents;
+    setExpectedValues(kGLES2DefaultVertexAttrib, arrayAttrib);
+    doCheckedSnapshot();
+}
+
+TEST_F(SnapshotGlVertexAttribBufferTest, AttachArrayBuffer) {
+    selectIndex(15);
+    GLfloat testBuffContents[] = {
+            0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f,
+            0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f,
+    };
+    GlBufferData data = kTestAttachedBuffer;
+    data.bytes = testBuffContents;
+    GLuint buffer = createBuffer(gl, data);
+    GlVertexAttrib withBuffer = kGLES2DefaultVertexAttrib;
+    withBuffer.mode = GlVertexAttribMode::Buffer;
+    withBuffer.enabled = GL_TRUE;
+    withBuffer.pointer = reinterpret_cast<GLvoid*>(2);  // offset
+    withBuffer.bufferBinding = buffer;
+    setExpectedValues(kGLES2DefaultVertexAttrib, withBuffer);
+    doCheckedSnapshot();
+}
+
+}  // namespace emugl