Home | History | Annotate | Download | only in tests
      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 "gpu/command_buffer/tests/gl_test_utils.h"
      6 #include <string>
      7 #include <stdio.h>
      8 #include "base/basictypes.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "testing/gmock/include/gmock/gmock.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 // GCC requires these declarations, but MSVC requires they not be present.
     14 #ifndef COMPILER_MSVC
     15 const uint8 GLTestHelper::kCheckClearValue;
     16 #endif
     17 
     18 bool GLTestHelper::HasExtension(const char* extension) {
     19   std::string extensions(
     20       reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
     21   return extensions.find(extension) != std::string::npos;
     22 }
     23 
     24 bool GLTestHelper::CheckGLError(const char* msg, int line) {
     25    bool success = true;
     26    GLenum error = GL_NO_ERROR;
     27    while ((error = glGetError()) != GL_NO_ERROR) {
     28      success = false;
     29      EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), error)
     30          << "GL ERROR in " << msg << " at line " << line << " : " << error;
     31    }
     32    return success;
     33 }
     34 
     35 GLuint GLTestHelper::LoadShader(GLenum type, const char* shaderSrc) {
     36   GLuint shader = glCreateShader(type);
     37   // Load the shader source
     38   glShaderSource(shader, 1, &shaderSrc, NULL);
     39   // Compile the shader
     40   glCompileShader(shader);
     41   // Check the compile status
     42   GLint value = 0;
     43   glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
     44   if (value == 0) {
     45     char buffer[1024];
     46     GLsizei length = 0;
     47     glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer);
     48     std::string log(buffer, length);
     49     EXPECT_EQ(1, value) << "Error compiling shader: " << log;
     50     glDeleteShader(shader);
     51     shader = 0;
     52   }
     53   return shader;
     54 }
     55 
     56 GLuint GLTestHelper::SetupProgram(
     57     GLuint vertex_shader, GLuint fragment_shader) {
     58   // Create the program object
     59   GLuint program = glCreateProgram();
     60   glAttachShader(program, vertex_shader);
     61   glAttachShader(program, fragment_shader);
     62   // Link the program
     63   glLinkProgram(program);
     64   // Check the link status
     65   GLint linked = 0;
     66   glGetProgramiv(program, GL_LINK_STATUS, &linked);
     67   if (linked == 0) {
     68     char buffer[1024];
     69     GLsizei length = 0;
     70     glGetProgramInfoLog(program, sizeof(buffer), &length, buffer);
     71     std::string log(buffer, length);
     72     EXPECT_EQ(1, linked) << "Error linking program: " << log;
     73     glDeleteProgram(program);
     74     program = 0;
     75   }
     76   return program;
     77 }
     78 
     79 GLuint GLTestHelper::LoadProgram(
     80     const char* vertex_shader_source,
     81     const char* fragment_shader_source) {
     82   GLuint vertex_shader = LoadShader(
     83       GL_VERTEX_SHADER, vertex_shader_source);
     84   GLuint fragment_shader = LoadShader(
     85       GL_FRAGMENT_SHADER, fragment_shader_source);
     86   if (!vertex_shader || !fragment_shader) {
     87     return 0;
     88   }
     89   return SetupProgram(vertex_shader, fragment_shader);
     90 }
     91 
     92 GLuint GLTestHelper::SetupUnitQuad(GLint position_location) {
     93   GLuint vbo = 0;
     94   glGenBuffers(1, &vbo);
     95   glBindBuffer(GL_ARRAY_BUFFER, vbo);
     96   static float vertices[] = {
     97       1.0f,  1.0f,
     98      -1.0f,  1.0f,
     99      -1.0f, -1.0f,
    100       1.0f,  1.0f,
    101      -1.0f, -1.0f,
    102       1.0f, -1.0f,
    103   };
    104   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    105   glEnableVertexAttribArray(position_location);
    106   glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
    107 
    108   return vbo;
    109 }
    110 
    111 GLuint GLTestHelper::SetupColorsForUnitQuad(
    112     GLint location, const GLfloat color[4], GLenum usage) {
    113   GLuint vbo = 0;
    114   glGenBuffers(1, &vbo);
    115   glBindBuffer(GL_ARRAY_BUFFER, vbo);
    116   GLfloat vertices[6 * 4];
    117   for (int ii = 0; ii < 6; ++ii) {
    118     for (int jj = 0; jj < 4; ++jj) {
    119       vertices[ii * 4 + jj] = color[jj];
    120     }
    121   }
    122   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, usage);
    123   glEnableVertexAttribArray(location);
    124   glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
    125 
    126   return vbo;
    127 }
    128 
    129 bool GLTestHelper::CheckPixels(
    130     GLint x, GLint y, GLsizei width, GLsizei height, GLint tolerance,
    131     const uint8* color) {
    132   GLsizei size = width * height * 4;
    133   scoped_ptr<uint8[]> pixels(new uint8[size]);
    134   memset(pixels.get(), kCheckClearValue, size);
    135   glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
    136   int bad_count = 0;
    137   for (GLint yy = 0; yy < height; ++yy) {
    138     for (GLint xx = 0; xx < width; ++xx) {
    139       int offset = yy * width * 4 + xx * 4;
    140       for (int jj = 0; jj < 4; ++jj) {
    141         uint8 actual = pixels[offset + jj];
    142         uint8 expected = color[jj];
    143         int diff = actual - expected;
    144         diff = diff < 0 ? -diff: diff;
    145         if (diff > tolerance) {
    146           EXPECT_EQ(expected, actual) << " at " << (xx + x) << ", " << (yy + y)
    147                                       << " channel " << jj;
    148           ++bad_count;
    149           // Exit early just so we don't spam the log but we print enough
    150           // to hopefully make it easy to diagnose the issue.
    151           if (bad_count > 16) {
    152             return false;
    153           }
    154         }
    155       }
    156     }
    157   }
    158   return bad_count == 0;
    159 }
    160 
    161 namespace {
    162 
    163 void Set16BitValue(uint8 dest[2], uint16 value) {
    164   dest[0] = value & 0xFFu;
    165   dest[1] = value >> 8;
    166 }
    167 
    168 void Set32BitValue(uint8 dest[4], uint32 value) {
    169   dest[0] = (value >> 0) & 0xFFu;
    170   dest[1] = (value >> 8) & 0xFFu;
    171   dest[2] = (value >> 16) & 0xFFu;
    172   dest[3] = (value >> 24) & 0xFFu;
    173 }
    174 
    175 struct BitmapHeaderFile {
    176   uint8 magic[2];
    177   uint8 size[4];
    178   uint8 reserved[4];
    179   uint8 offset[4];
    180 };
    181 
    182 struct BitmapInfoHeader{
    183   uint8 size[4];
    184   uint8 width[4];
    185   uint8 height[4];
    186   uint8 planes[2];
    187   uint8 bit_count[2];
    188   uint8 compression[4];
    189   uint8 size_image[4];
    190   uint8 x_pels_per_meter[4];
    191   uint8 y_pels_per_meter[4];
    192   uint8 clr_used[4];
    193   uint8 clr_important[4];
    194 };
    195 
    196 }
    197 
    198 bool GLTestHelper::SaveBackbufferAsBMP(
    199     const char* filename, int width, int height) {
    200   FILE* fp = fopen(filename, "wb");
    201   EXPECT_TRUE(fp != NULL);
    202   glPixelStorei(GL_PACK_ALIGNMENT, 1);
    203   int num_pixels = width * height;
    204   int size = num_pixels * 4;
    205   scoped_ptr<uint8[]> data(new uint8[size]);
    206   uint8* pixels = data.get();
    207   glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    208 
    209   // RGBA to BGRA
    210   for (int ii = 0; ii < num_pixels; ++ii) {
    211     int offset = ii * 4;
    212     uint8 t = pixels[offset + 0];
    213     pixels[offset + 0] = pixels[offset + 2];
    214     pixels[offset + 2] = t;
    215   }
    216 
    217   BitmapHeaderFile bhf;
    218   BitmapInfoHeader bih;
    219 
    220   bhf.magic[0] = 'B';
    221   bhf.magic[1] = 'M';
    222   Set32BitValue(bhf.size, 0);
    223   Set32BitValue(bhf.reserved, 0);
    224   Set32BitValue(bhf.offset, sizeof(bhf) + sizeof(bih));
    225 
    226   Set32BitValue(bih.size, sizeof(bih));
    227   Set32BitValue(bih.width, width);
    228   Set32BitValue(bih.height, height);
    229   Set16BitValue(bih.planes, 1);
    230   Set16BitValue(bih.bit_count, 32);
    231   Set32BitValue(bih.compression, 0);
    232   Set32BitValue(bih.x_pels_per_meter, 0);
    233   Set32BitValue(bih.y_pels_per_meter, 0);
    234   Set32BitValue(bih.clr_used, 0);
    235   Set32BitValue(bih.clr_important, 0);
    236 
    237   fwrite(&bhf, sizeof(bhf), 1, fp);
    238   fwrite(&bih, sizeof(bih), 1, fp);
    239   fwrite(pixels, size, 1, fp);
    240   fclose(fp);
    241   return true;
    242 }
    243 
    244 int GLTestHelper::RunTests(int argc, char** argv) {
    245   testing::InitGoogleMock(&argc, argv);
    246   return RUN_ALL_TESTS();
    247 }
    248