1 // Copyright (c) 2013 The Chromium OS 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 "texturetest.h" 6 #include "arraysize.h" 7 #include <assert.h> 8 9 namespace glbench { 10 11 namespace { 12 13 // Vertex and fragment shader code. 14 const char* kVertexShader = 15 "attribute vec4 c1;" 16 "attribute vec4 c2;" 17 "varying vec4 v1;" 18 "void main() {" 19 " gl_Position = c1;" 20 " v1 = c2;" 21 "}"; 22 23 const char* kFragmentShader = 24 "varying vec4 v1;" 25 "uniform sampler2D texture;" 26 "void main() {" 27 " gl_FragColor = texture2D(texture, v1.xy);" 28 "}"; 29 30 } // namespace 31 32 bool TextureTest::TextureMetaDataInit() { 33 // TODO(djkurtz): Other formats such as GL_BGRA, GL_RGB, GL_BGR, ... ? 34 // , GL_BGRA, GL_RGB, GL_BGR }; 35 kTexelFormats.push_back(GL_LUMINANCE); 36 kTexelFormats.push_back(GL_RGBA); 37 38 kTexelFormatNames[GL_LUMINANCE] = "luminance"; 39 kTexelFormatNames[GL_RGBA] = "rgba"; 40 41 kTexelFormatSizes[GL_LUMINANCE] = 1; 42 kTexelFormatSizes[GL_RGBA] = 4; 43 44 kFlavors[TEX_IMAGE] = "teximage2d"; 45 kFlavors[TEX_SUBIMAGE] = "texsubimage2d"; 46 return true; 47 } 48 49 bool TextureTest::Run() { 50 TextureMetaDataInit(); 51 // Two triangles that form one pixel at 0, 0. 52 const GLfloat kVertices[8] = { 53 0.f, 0.f, 54 2.f / g_width, 0.f, 55 0.f, 2.f / g_height, 56 2.f / g_width, 2.f / g_height, 57 }; 58 const GLfloat kTexCoords[8] = { 59 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 60 }; 61 62 program_ = InitShaderProgram(kVertexShader, kFragmentShader); 63 64 int attr1 = glGetAttribLocation(program_, "c1"); 65 glVertexAttribPointer(attr1, 2, GL_FLOAT, GL_FALSE, 0, kVertices); 66 glEnableVertexAttribArray(attr1); 67 68 int attr2 = glGetAttribLocation(program_, "c2"); 69 glVertexAttribPointer(attr2, 2, GL_FLOAT, GL_FALSE, 0, kTexCoords); 70 glEnableVertexAttribArray(attr2); 71 72 int texture_sampler = glGetUniformLocation(program_, "texture"); 73 glUniform1i(texture_sampler, 0); 74 glActiveTexture(GL_TEXTURE0); 75 76 glGenTextures(kNumberOfTextures, textures_); 77 for (int i = 0; i < kNumberOfTextures; ++i) { 78 glBindTexture(GL_TEXTURE_2D, textures_[i]); 79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 80 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 81 } 82 83 for (auto fmt : kTexelFormats) { 84 texel_gl_format_ = fmt; 85 std::string texel_gl_format_name = kTexelFormatNames.at(texel_gl_format_); 86 unsigned int texel_size = kTexelFormatSizes[texel_gl_format_]; 87 for (auto flv : kFlavors){ 88 flavor_ = flv.first; 89 std::string flavor_name = flv.second; 90 91 const int sizes[] = {32, 128, 256, 512, 768, 1024, 1536, 2048}; 92 for (unsigned int j = 0; j < arraysize(sizes); j++) { 93 // In hasty mode only do at most 512x512 sized problems. 94 if (g_hasty && sizes[j] > 512) 95 continue; 96 97 std::string name = std::string(Name()) + "_" + texel_gl_format_name + 98 "_" + flavor_name + "_" + 99 IntToString(sizes[j]); 100 101 width_ = height_ = sizes[j]; 102 const unsigned int buffer_size = width_ * height_ * texel_size; 103 for (int i = 0; i < kNumberOfTextures; ++i) { 104 pixels_[i].reset(new char[buffer_size]); 105 memset(pixels_[i].get(), 255, buffer_size); 106 107 // For NPOT texture we must set GL_TEXTURE_WRAP as GL_CLAMP_TO_EDGE 108 glBindTexture(GL_TEXTURE_2D, textures_[i]); 109 glTexImage2D(GL_TEXTURE_2D, 0, texel_gl_format_, width_, height_, 0, 110 texel_gl_format_, GL_UNSIGNED_BYTE, NULL); 111 if (glGetError() != 0) { 112 printf("# Error: Failed to allocate %dx%d %u-byte texel texture.\n", 113 width_, height_, texel_size); 114 } 115 if (IS_NOT_POWER_OF_2(width_) || IS_NOT_POWER_OF_2(height_)) { 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 118 } 119 120 // Only upload the texture here if the test is not intended to test 121 // the texture upload speed. 122 if (!this->IsTextureUploadTest()) { 123 glBindTexture(GL_TEXTURE_2D, textures_[i]); 124 switch (flavor_) { 125 case TEX_IMAGE: 126 glTexImage2D(GL_TEXTURE_2D, 0, texel_gl_format_, 127 width_, height_, 0, 128 texel_gl_format_, GL_UNSIGNED_BYTE, 129 pixels_[i % kNumberOfTextures].get()); 130 break; 131 case TEX_SUBIMAGE: 132 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, 133 texel_gl_format_, GL_UNSIGNED_BYTE, 134 pixels_[i % kNumberOfTextures].get()); 135 break; 136 } 137 } 138 } 139 RunTest(this, name.c_str(), buffer_size, g_width, g_height, true); 140 GLenum error = glGetError(); 141 if (error != GL_NO_ERROR) { 142 printf( 143 "# GL error code %d after RunTest() with %dx%d %d-byte " 144 "texture.\n", 145 error, width_, height_, texel_size); 146 } 147 } 148 } 149 } 150 for (int i = 0; i < kNumberOfTextures; ++i) 151 pixels_[i].reset(); 152 153 glDeleteTextures(kNumberOfTextures, textures_); 154 glDeleteProgram(program_); 155 return true; 156 } 157 158 } // namespace glbench 159