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
TextureMetaDataInit()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
Run()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