blob: 1e197a6a27c696e2559add100b9a8e9894896408 [file] [log] [blame]
// 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 <assert.h>
#include "arraysize.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