// Copyright (c) 2013 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "texturetest.h" #include "arraysize.h" #include <assert.h> namespace glbench { namespace { // Vertex and fragment shader code. const char* kVertexShader = "attribute vec4 c1;" "attribute vec4 c2;" "varying vec4 v1;" "void main() {" " gl_Position = c1;" " v1 = c2;" "}"; const char* kFragmentShader = "varying vec4 v1;" "uniform sampler2D texture;" "void main() {" " gl_FragColor = texture2D(texture, v1.xy);" "}"; } // namespace bool TextureTest::TextureMetaDataInit() { // TODO(djkurtz): Other formats such as GL_BGRA, GL_RGB, GL_BGR, ... ? // , GL_BGRA, GL_RGB, GL_BGR }; kTexelFormats.push_back(GL_LUMINANCE); kTexelFormats.push_back(GL_RGBA); kTexelFormatNames[GL_LUMINANCE] = "luminance"; kTexelFormatNames[GL_RGBA] = "rgba"; kTexelFormatSizes[GL_LUMINANCE] = 1; kTexelFormatSizes[GL_RGBA] = 4; kFlavors[TEX_IMAGE] = "teximage2d"; kFlavors[TEX_SUBIMAGE] = "texsubimage2d"; return true; } bool TextureTest::Run() { TextureMetaDataInit(); // Two triangles that form one pixel at 0, 0. const GLfloat kVertices[8] = { 0.f, 0.f, 2.f / g_width, 0.f, 0.f, 2.f / g_height, 2.f / g_width, 2.f / g_height, }; const GLfloat kTexCoords[8] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, }; program_ = InitShaderProgram(kVertexShader, kFragmentShader); int attr1 = glGetAttribLocation(program_, "c1"); glVertexAttribPointer(attr1, 2, GL_FLOAT, GL_FALSE, 0, kVertices); glEnableVertexAttribArray(attr1); int attr2 = glGetAttribLocation(program_, "c2"); glVertexAttribPointer(attr2, 2, GL_FLOAT, GL_FALSE, 0, kTexCoords); glEnableVertexAttribArray(attr2); int texture_sampler = glGetUniformLocation(program_, "texture"); glUniform1i(texture_sampler, 0); glActiveTexture(GL_TEXTURE0); glGenTextures(kNumberOfTextures, textures_); for (int i = 0; i < kNumberOfTextures; ++i) { glBindTexture(GL_TEXTURE_2D, textures_[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } for (auto fmt : kTexelFormats) { texel_gl_format_ = fmt; std::string texel_gl_format_name = kTexelFormatNames.at(texel_gl_format_); unsigned int texel_size = kTexelFormatSizes[texel_gl_format_]; for (auto flv : kFlavors){ flavor_ = flv.first; std::string flavor_name = flv.second; const int sizes[] = {32, 128, 256, 512, 768, 1024, 1536, 2048}; for (unsigned int j = 0; j < arraysize(sizes); j++) { // In hasty mode only do at most 512x512 sized problems. if (g_hasty && sizes[j] > 512) continue; std::string name = std::string(Name()) + "_" + texel_gl_format_name + "_" + flavor_name + "_" + IntToString(sizes[j]); width_ = height_ = sizes[j]; const unsigned int buffer_size = width_ * height_ * texel_size; for (int i = 0; i < kNumberOfTextures; ++i) { pixels_[i].reset(new char[buffer_size]); memset(pixels_[i].get(), 255, buffer_size); // For NPOT texture we must set GL_TEXTURE_WRAP as GL_CLAMP_TO_EDGE glBindTexture(GL_TEXTURE_2D, textures_[i]); glTexImage2D(GL_TEXTURE_2D, 0, texel_gl_format_, width_, height_, 0, texel_gl_format_, GL_UNSIGNED_BYTE, NULL); if (glGetError() != 0) { printf("# Error: Failed to allocate %dx%d %u-byte texel texture.\n", width_, height_, texel_size); } if (IS_NOT_POWER_OF_2(width_) || IS_NOT_POWER_OF_2(height_)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } // Only upload the texture here if the test is not intended to test // the texture upload speed. if (!this->IsTextureUploadTest()) { glBindTexture(GL_TEXTURE_2D, textures_[i]); switch (flavor_) { case TEX_IMAGE: glTexImage2D(GL_TEXTURE_2D, 0, texel_gl_format_, width_, height_, 0, texel_gl_format_, GL_UNSIGNED_BYTE, pixels_[i % kNumberOfTextures].get()); break; case TEX_SUBIMAGE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, texel_gl_format_, GL_UNSIGNED_BYTE, pixels_[i % kNumberOfTextures].get()); break; } } } RunTest(this, name.c_str(), buffer_size, g_width, g_height, true); GLenum error = glGetError(); if (error != GL_NO_ERROR) { printf( "# GL error code %d after RunTest() with %dx%d %d-byte " "texture.\n", error, width_, height_, texel_size); } } } } for (int i = 0; i < kNumberOfTextures; ++i) pixels_[i].reset(); glDeleteTextures(kNumberOfTextures, textures_); glDeleteProgram(program_); return true; } } // namespace glbench