1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ppapi/tests/test_graphics_3d.h" 6 7 #include <GLES2/gl2.h> 8 #include <GLES2/gl2ext.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include "ppapi/c/ppb_opengles2.h" 14 #include "ppapi/cpp/graphics_3d.h" 15 #include "ppapi/cpp/module.h" 16 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" 17 #include "ppapi/tests/test_case.h" 18 #include "ppapi/tests/test_utils.h" 19 #include "ppapi/tests/testing_instance.h" 20 21 const int32_t kInvalidContext = 0; 22 23 REGISTER_TEST_CASE(Graphics3D); 24 25 bool TestGraphics3D::Init() { 26 opengl_es2_ = static_cast<const PPB_OpenGLES2*>( 27 pp::Module::Get()->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); 28 glInitializePPAPI(pp::Module::Get()->get_browser_interface()); 29 return opengl_es2_ && CheckTestingInterface(); 30 } 31 32 void TestGraphics3D::RunTests(const std::string& filter) { 33 RUN_CALLBACK_TEST(TestGraphics3D, FramePPAPI, filter); 34 RUN_CALLBACK_TEST(TestGraphics3D, FrameGL, filter); 35 RUN_CALLBACK_TEST(TestGraphics3D, ExtensionsGL, filter); 36 RUN_CALLBACK_TEST(TestGraphics3D, BadResource, filter); 37 } 38 39 std::string TestGraphics3D::TestFramePPAPI() { 40 const int width = 16; 41 const int height = 16; 42 const int32_t attribs[] = { 43 PP_GRAPHICS3DATTRIB_WIDTH, width, 44 PP_GRAPHICS3DATTRIB_HEIGHT, height, 45 PP_GRAPHICS3DATTRIB_NONE 46 }; 47 pp::Graphics3D context(instance_, attribs); 48 ASSERT_FALSE(context.is_null()); 49 50 const uint8_t red_color[4] = {255, 0, 0, 255}; 51 52 // Access OpenGLES API through the PPAPI interface. 53 // Clear color buffer to opaque red. 54 opengl_es2_->ClearColor(context.pp_resource(), 1.0f, 0.0f, 0.0f, 1.0f); 55 opengl_es2_->Clear(context.pp_resource(), GL_COLOR_BUFFER_BIT); 56 // Check if the color buffer has opaque red. 57 std::string error = CheckPixelPPAPI(&context, width/2, height/2, red_color); 58 if (!error.empty()) 59 return error; 60 61 int32_t rv = SwapBuffersSync(&context); 62 ASSERT_EQ(rv, PP_OK); 63 64 PASS(); 65 } 66 67 std::string TestGraphics3D::TestFrameGL() { 68 const int width = 16; 69 const int height = 16; 70 const int32_t attribs[] = { 71 PP_GRAPHICS3DATTRIB_WIDTH, width, 72 PP_GRAPHICS3DATTRIB_HEIGHT, height, 73 PP_GRAPHICS3DATTRIB_NONE 74 }; 75 pp::Graphics3D context(instance_, attribs); 76 ASSERT_FALSE(context.is_null()); 77 78 const uint8_t red_color[4] = {255, 0, 0, 255}; 79 // Perform same operations as TestFramePPAPI, but use OpenGLES API directly. 80 // This is how most developers will use OpenGLES. 81 glSetCurrentContextPPAPI(context.pp_resource()); 82 glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 83 glClear(GL_COLOR_BUFFER_BIT); 84 std::string error = CheckPixelGL(width/2, height/2, red_color); 85 glSetCurrentContextPPAPI(kInvalidContext); 86 if (!error.empty()) 87 return error; 88 89 int32_t rv = SwapBuffersSync(&context); 90 ASSERT_EQ(rv, PP_OK); 91 92 PASS(); 93 } 94 95 std::string TestGraphics3D::TestExtensionsGL() { 96 const int width = 16; 97 const int height = 16; 98 const int32_t attribs[] = { 99 PP_GRAPHICS3DATTRIB_WIDTH, width, 100 PP_GRAPHICS3DATTRIB_HEIGHT, height, 101 PP_GRAPHICS3DATTRIB_NONE 102 }; 103 pp::Graphics3D context(instance_, attribs); 104 ASSERT_FALSE(context.is_null()); 105 106 glSetCurrentContextPPAPI(context.pp_resource()); 107 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 108 glClear(GL_COLOR_BUFFER_BIT); 109 110 // Ask about a couple of extensions via glGetString. If an extension is 111 // available, try a couple of trivial calls. This test is not intended 112 // to be exhaustive; check the source can compile, link, and run without 113 // crashing. 114 ASSERT_NE(glGetString(GL_VERSION), NULL); 115 const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); 116 if (strstr(ext, "GL_EXT_occlusion_query_boolean")) { 117 GLuint a_query; 118 GLboolean is_a_query; 119 glGenQueriesEXT(1, &a_query); 120 ASSERT_NE(a_query, 0); 121 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, a_query); 122 is_a_query = glIsQueryEXT(a_query); 123 ASSERT_EQ(is_a_query, GL_TRUE); 124 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 125 glDeleteQueriesEXT(1, &a_query); 126 } 127 if (strstr(ext, "GL_ANGLE_instanced_arrays")) { 128 glDrawArraysInstancedANGLE(GL_TRIANGLE_STRIP, 0, 0, 0); 129 } 130 glSetCurrentContextPPAPI(kInvalidContext); 131 132 int32_t rv = SwapBuffersSync(&context); 133 ASSERT_EQ(rv, PP_OK); 134 135 PASS(); 136 } 137 138 int32_t TestGraphics3D::SwapBuffersSync(pp::Graphics3D* context) { 139 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 140 callback.WaitForResult(context->SwapBuffers(callback.GetCallback())); 141 return callback.result(); 142 } 143 144 std::string TestGraphics3D::CheckPixelPPAPI( 145 pp::Graphics3D* context, 146 int x, int y, const uint8_t expected_color[4]) { 147 GLubyte pixel_color[4]; 148 opengl_es2_->ReadPixels(context->pp_resource(), 149 x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel_color); 150 151 ASSERT_EQ(pixel_color[0], expected_color[0]); 152 ASSERT_EQ(pixel_color[1], expected_color[1]); 153 ASSERT_EQ(pixel_color[2], expected_color[2]); 154 ASSERT_EQ(pixel_color[3], expected_color[3]); 155 PASS(); 156 } 157 158 std::string TestGraphics3D::CheckPixelGL( 159 int x, int y, const uint8_t expected_color[4]) { 160 GLubyte pixel_color[4]; 161 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel_color); 162 163 ASSERT_EQ(pixel_color[0], expected_color[0]); 164 ASSERT_EQ(pixel_color[1], expected_color[1]); 165 ASSERT_EQ(pixel_color[2], expected_color[2]); 166 ASSERT_EQ(pixel_color[3], expected_color[3]); 167 PASS(); 168 } 169 170 std::string TestGraphics3D::TestBadResource() { 171 // The point of this test is mostly just to make sure that we don't crash and 172 // provide reasonable (error) results when the resource is bad. 173 const PP_Resource kBadResource = 123; 174 175 // Access OpenGLES API through the PPAPI interface. 176 opengl_es2_->ClearColor(kBadResource, 0.0f, 0.0f, 0.0f, 0.0f); 177 opengl_es2_->Clear(kBadResource, GL_COLOR_BUFFER_BIT); 178 ASSERT_EQ(0, opengl_es2_->GetError(kBadResource)); 179 ASSERT_EQ(NULL, opengl_es2_->GetString(kBadResource, GL_VERSION)); 180 ASSERT_EQ(-1, opengl_es2_->GetUniformLocation(kBadResource, 0, NULL)); 181 ASSERT_EQ(GL_FALSE, opengl_es2_->IsBuffer(kBadResource, 0)); 182 ASSERT_EQ(0, opengl_es2_->CheckFramebufferStatus(kBadResource, 183 GL_DRAW_FRAMEBUFFER)); 184 185 glSetCurrentContextPPAPI(kBadResource); 186 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 187 glClear(GL_COLOR_BUFFER_BIT); 188 ASSERT_EQ(0, glGetError()); 189 ASSERT_EQ(NULL, glGetString(GL_VERSION)); 190 ASSERT_EQ(-1, glGetUniformLocation(0, NULL)); 191 ASSERT_EQ(GL_FALSE, glIsBuffer(0)); 192 ASSERT_EQ(0, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); 193 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 194 glClear(GL_COLOR_BUFFER_BIT); 195 196 PASS(); 197 } 198 199