OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdio.h> | 5 #include <stdio.h> |
6 #include <sys/mman.h> | 6 #include <sys/mman.h> |
7 | 7 |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/scoped_ptr.h" |
9 | 10 |
10 #include "main.h" | 11 #include "main.h" |
11 #include "testbase.h" | 12 #include "testbase.h" |
12 #include "utils.h" | 13 #include "utils.h" |
13 #include "yuv2rgb.h" | 14 #include "yuv2rgb.h" |
14 | 15 |
15 namespace glbench { | 16 namespace glbench { |
16 | 17 |
17 class YuvToRgbTest : public DrawArraysTestFunc { | 18 class YuvToRgbTest : public DrawArraysTestFunc { |
18 public: | 19 public: |
19 YuvToRgbTest(int type, const char* name) : type_(type), name_(name) {} | 20 YuvToRgbTest() { |
20 virtual ~YuvToRgbTest() {} | 21 memset(textures_, 0, sizeof(textures_)); |
| 22 } |
| 23 virtual ~YuvToRgbTest() { |
| 24 glDeleteTextures(arraysize(textures_), textures_); |
| 25 } |
21 virtual bool Run(); | 26 virtual bool Run(); |
22 | 27 |
| 28 enum YuvTestFlavor { |
| 29 YUV_PLANAR_ONE_TEXTURE_SLOW, |
| 30 YUV_PLANAR_ONE_TEXTURE_FASTER, |
| 31 YUV_PLANAR_THREE_TEXTURES, |
| 32 YUV_SEMIPLANAR_TWO_TEXTURES, |
| 33 }; |
| 34 |
23 private: | 35 private: |
24 int type_; | 36 GLuint textures_[6]; |
25 const char* name_; | 37 YuvTestFlavor flavor_; |
| 38 GLuint YuvToRgbShaderProgram(GLuint vertex_buffer, int width, int height); |
| 39 bool SetupTextures(); |
26 DISALLOW_COPY_AND_ASSIGN(YuvToRgbTest); | 40 DISALLOW_COPY_AND_ASSIGN(YuvToRgbTest); |
27 }; | 41 }; |
28 | 42 |
29 | 43 |
30 GLuint YuvToRgbShaderProgram(int type, GLuint vertex_buffer, | 44 GLuint YuvToRgbTest::YuvToRgbShaderProgram(GLuint vertex_buffer, |
31 int width, int height) { | 45 int width, int height) { |
32 const char *vertex = type == 1 ? YUV2RGB_VERTEX_1 : YUV2RGB_VERTEX_2; | 46 const char *vertex = NULL; |
33 const char *fragment = type == 1 ? YUV2RGB_FRAGMENT_1 : YUV2RGB_FRAGMENT_2; | 47 const char *fragment = NULL; |
| 48 |
| 49 switch (flavor_) { |
| 50 case YUV_PLANAR_ONE_TEXTURE_SLOW: |
| 51 vertex = YUV2RGB_VERTEX_1; |
| 52 fragment = YUV2RGB_FRAGMENT_1; |
| 53 break; |
| 54 case YUV_PLANAR_ONE_TEXTURE_FASTER: |
| 55 vertex = YUV2RGB_VERTEX_2; |
| 56 fragment = YUV2RGB_FRAGMENT_2; |
| 57 break; |
| 58 case YUV_PLANAR_THREE_TEXTURES: |
| 59 vertex = YUV2RGB_VERTEX_34; |
| 60 fragment = YUV2RGB_FRAGMENT_3; |
| 61 break; |
| 62 case YUV_SEMIPLANAR_TWO_TEXTURES: |
| 63 vertex = YUV2RGB_VERTEX_34; |
| 64 fragment = YUV2RGB_FRAGMENT_4; |
| 65 break; |
| 66 } |
| 67 |
34 size_t size_vertex = 0; | 68 size_t size_vertex = 0; |
35 size_t size_fragment = 0; | 69 size_t size_fragment = 0; |
36 char *yuv_to_rgb_vertex = static_cast<char *>( | 70 char *yuv_to_rgb_vertex = static_cast<char *>( |
37 MmapFile(vertex, &size_vertex)); | 71 MmapFile(vertex, &size_vertex)); |
38 char *yuv_to_rgb_fragment = static_cast<char *>( | 72 char *yuv_to_rgb_fragment = static_cast<char *>( |
39 MmapFile(fragment, &size_fragment)); | 73 MmapFile(fragment, &size_fragment)); |
40 GLuint program = 0; | 74 GLuint program = 0; |
41 | 75 |
42 if (!yuv_to_rgb_fragment || !yuv_to_rgb_vertex) | 76 if (!yuv_to_rgb_fragment || !yuv_to_rgb_vertex) |
43 goto done; | 77 goto done; |
44 | 78 |
45 { | 79 { |
46 #if defined(I915_WORKAROUND) | 80 #if defined(I915_WORKAROUND) |
47 const char* header = "#define I915_WORKAROUND 1\n"; | 81 const char* header = "#define I915_WORKAROUND 1\n"; |
48 #else | 82 #else |
49 const char* header = NULL; | 83 const char* header = NULL; |
50 #endif | 84 #endif |
51 program = InitShaderProgramWithHeader(header, yuv_to_rgb_vertex, | 85 program = InitShaderProgramWithHeader(header, yuv_to_rgb_vertex, |
52 yuv_to_rgb_fragment); | 86 yuv_to_rgb_fragment); |
53 | 87 |
54 int imageWidthUniform = glGetUniformLocation(program, "imageWidth"); | 88 int imageWidthUniform = glGetUniformLocation(program, "imageWidth"); |
55 int imageHeightUniform = glGetUniformLocation(program, "imageHeight"); | 89 int imageHeightUniform = glGetUniformLocation(program, "imageHeight"); |
| 90 |
56 int textureSampler = glGetUniformLocation(program, "textureSampler"); | 91 int textureSampler = glGetUniformLocation(program, "textureSampler"); |
57 int evenLinesSampler = glGetUniformLocation(program, "paritySampler"); | 92 int evenLinesSampler = glGetUniformLocation(program, "paritySampler"); |
| 93 int ySampler = glGetUniformLocation(program, "ySampler"); |
| 94 int uSampler = glGetUniformLocation(program, "uSampler"); |
| 95 int vSampler = glGetUniformLocation(program, "vSampler"); |
| 96 int uvSampler = glGetUniformLocation(program, "uvSampler"); |
58 | 97 |
59 glUniform1f(imageWidthUniform, width); | 98 glUniform1f(imageWidthUniform, width); |
60 glUniform1f(imageHeightUniform, height); | 99 glUniform1f(imageHeightUniform, height); |
61 glUniform1i(textureSampler, 0); | 100 glUniform1i(textureSampler, 0); |
62 glUniform1i(evenLinesSampler, 1); | 101 glUniform1i(evenLinesSampler, 1); |
63 | 102 |
| 103 glUniform1i(ySampler, 2); |
| 104 glUniform1i(uSampler, 3); |
| 105 glUniform1i(vSampler, 4); |
| 106 glUniform1i(uvSampler, 5); |
| 107 |
| 108 { |
| 109 // This is used only if USE_UNIFORM_MATRIX is enabled in fragment |
| 110 // shaders. |
| 111 float c[] = { |
| 112 1.0, 1.0, 1.0, 0.0, |
| 113 0.0, -0.344, 1.772, 0.0, |
| 114 1.402, -0.714, 0.0, 0.0, |
| 115 -0.701, 0.529, -0.886, 1.0 |
| 116 }; |
| 117 int conversion = glGetUniformLocation(program, "conversion"); |
| 118 glUniformMatrix4fv(conversion, 1, GL_FALSE, c); |
| 119 assert(glGetError() == 0); |
| 120 } |
| 121 |
64 int attribute_index = glGetAttribLocation(program, "c"); | 122 int attribute_index = glGetAttribLocation(program, "c"); |
65 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); | 123 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); |
66 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL); | 124 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL); |
67 glEnableVertexAttribArray(attribute_index); | 125 glEnableVertexAttribArray(attribute_index); |
68 return program; | 126 return program; |
69 } | 127 } |
70 | 128 |
71 | 129 |
72 done: | 130 done: |
73 munmap(yuv_to_rgb_fragment, size_fragment); | 131 munmap(yuv_to_rgb_fragment, size_fragment); |
74 munmap(yuv_to_rgb_fragment, size_vertex); | 132 munmap(yuv_to_rgb_fragment, size_vertex); |
75 return program; | 133 return program; |
76 } | 134 } |
77 | 135 |
78 | 136 |
79 bool YuvToRgbTest::Run() { | 137 bool YuvToRgbTest::SetupTextures() { |
| 138 bool ret = false; |
80 size_t size = 0; | 139 size_t size = 0; |
81 GLuint texture[2]; | |
82 GLuint program = 0; | |
83 GLuint vertex_buffer = 0; | |
84 GLfloat vertices[8] = { | |
85 0.f, 0.f, | |
86 1.f, 0.f, | |
87 0.f, 1.f, | |
88 1.f, 1.f, | |
89 }; | |
90 char evenodd[2] = {0, 255}; | 140 char evenodd[2] = {0, 255}; |
91 const int pixel_height = YUV2RGB_HEIGHT * 2 / 3; | 141 char* pixels = static_cast<char *>(MmapFile(YUV2RGB_NAME, &size)); |
92 | 142 const int luma_size = YUV2RGB_WIDTH * YUV2RGB_PIXEL_HEIGHT; |
93 char *pixels = static_cast<char *>(MmapFile(YUV2RGB_NAME, &size)); | 143 const int chroma_size = YUV2RGB_WIDTH/2 * YUV2RGB_PIXEL_HEIGHT/2; |
| 144 const char* u_plane = pixels + luma_size; |
| 145 const char* v_plane = pixels + luma_size + chroma_size; |
94 if (!pixels) { | 146 if (!pixels) { |
95 printf("# Could not open image file: %s\n", YUV2RGB_NAME); | 147 printf("# Could not open image file: %s\n", YUV2RGB_NAME); |
96 goto done; | 148 goto done; |
97 } | 149 } |
98 if (size != YUV2RGB_SIZE) { | 150 if (size != YUV2RGB_SIZE) { |
99 printf("# Image file of wrong size, got %d, expected %d\n", | 151 printf("# Image file of wrong size, got %d, expected %d\n", |
100 static_cast<int>(size), YUV2RGB_SIZE); | 152 static_cast<int>(size), YUV2RGB_SIZE); |
101 goto done; | 153 goto done; |
102 } | 154 } |
103 | 155 |
104 glGenTextures(2, texture); | 156 glGenTextures(arraysize(textures_), textures_); |
105 glActiveTexture(GL_TEXTURE0); | 157 glActiveTexture(GL_TEXTURE0); |
106 glBindTexture(GL_TEXTURE_2D, texture[0]); | 158 glBindTexture(GL_TEXTURE_2D, textures_[0]); |
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
109 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, YUV2RGB_WIDTH, YUV2RGB_HEIGHT, | 159 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, YUV2RGB_WIDTH, YUV2RGB_HEIGHT, |
110 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); | 160 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); |
111 | 161 |
112 glActiveTexture(GL_TEXTURE1); | 162 glActiveTexture(GL_TEXTURE1); |
113 glBindTexture(GL_TEXTURE_2D, texture[1]); | 163 glBindTexture(GL_TEXTURE_2D, textures_[1]); |
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 1, | 164 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 1, |
117 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, evenodd); | 165 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, evenodd); |
118 | 166 |
119 glViewport(-YUV2RGB_WIDTH, -pixel_height, YUV2RGB_WIDTH*2, pixel_height * 2); | 167 glActiveTexture(GL_TEXTURE2); |
| 168 glBindTexture(GL_TEXTURE_2D, textures_[2]); |
| 169 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, |
| 170 YUV2RGB_WIDTH, YUV2RGB_PIXEL_HEIGHT, |
| 171 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels); |
| 172 |
| 173 glActiveTexture(GL_TEXTURE3); |
| 174 glBindTexture(GL_TEXTURE_2D, textures_[3]); |
| 175 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, |
| 176 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2, |
| 177 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u_plane); |
| 178 |
| 179 glActiveTexture(GL_TEXTURE4); |
| 180 glBindTexture(GL_TEXTURE_2D, textures_[4]); |
| 181 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, |
| 182 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2, |
| 183 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v_plane); |
| 184 |
| 185 { |
| 186 scoped_array<char> buf_uv(new char[chroma_size * 2]); |
| 187 char* buf_uv_ptr = buf_uv.get(); |
| 188 for (int i = 0; i < chroma_size; i++) { |
| 189 *buf_uv_ptr++ = u_plane[i]; |
| 190 *buf_uv_ptr++ = v_plane[i]; |
| 191 } |
| 192 |
| 193 glActiveTexture(GL_TEXTURE5); |
| 194 glBindTexture(GL_TEXTURE_2D, textures_[5]); |
| 195 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, |
| 196 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2, |
| 197 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf_uv.get()); |
| 198 } |
| 199 |
| 200 for (unsigned int i = 0; i < arraysize(textures_); i++) { |
| 201 glActiveTexture(GL_TEXTURE0 + i); |
| 202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 204 } |
| 205 |
| 206 ret = true; |
| 207 |
| 208 done: |
| 209 munmap(pixels, size); |
| 210 return ret; |
| 211 } |
| 212 |
| 213 |
| 214 bool YuvToRgbTest::Run() { |
| 215 GLuint program = 0; |
| 216 GLuint vertex_buffer = 0; |
| 217 GLfloat vertices[8] = { |
| 218 0.f, 0.f, |
| 219 1.f, 0.f, |
| 220 0.f, 1.f, |
| 221 1.f, 1.f, |
| 222 }; |
120 vertex_buffer = SetupVBO(GL_ARRAY_BUFFER, sizeof(vertices), vertices); | 223 vertex_buffer = SetupVBO(GL_ARRAY_BUFFER, sizeof(vertices), vertices); |
121 | 224 |
122 program = YuvToRgbShaderProgram(type_, vertex_buffer, | 225 if (!SetupTextures()) |
123 YUV2RGB_WIDTH, pixel_height); | 226 return false; |
124 | 227 |
125 if (program) { | 228 glViewport(-YUV2RGB_WIDTH, -YUV2RGB_PIXEL_HEIGHT, |
126 FillRateTestNormalSubWindow(name_, std::min(YUV2RGB_WIDTH, g_width), | 229 YUV2RGB_WIDTH*2, YUV2RGB_PIXEL_HEIGHT * 2); |
127 std::min(pixel_height, g_height)); | 230 |
128 } else { | 231 YuvTestFlavor flavors[] = { |
129 printf("# Could not set up YUV shader.\n"); | 232 YUV_PLANAR_ONE_TEXTURE_SLOW, YUV_PLANAR_ONE_TEXTURE_FASTER, |
| 233 YUV_PLANAR_THREE_TEXTURES, YUV_SEMIPLANAR_TWO_TEXTURES |
| 234 }; |
| 235 const char* flavor_names[] = { |
| 236 "yuv_shader_1", "yuv_shader_2", "yuv_shader_3", "yuv_shader_4" |
| 237 }; |
| 238 for (unsigned int f = 0; f < arraysize(flavors); f++) { |
| 239 flavor_ = flavors[f]; |
| 240 |
| 241 program = YuvToRgbShaderProgram(vertex_buffer, |
| 242 YUV2RGB_WIDTH, YUV2RGB_PIXEL_HEIGHT); |
| 243 if (program) { |
| 244 FillRateTestNormalSubWindow(flavor_names[f], |
| 245 std::min(YUV2RGB_WIDTH, g_width), |
| 246 std::min(YUV2RGB_PIXEL_HEIGHT, g_height)); |
| 247 } else { |
| 248 printf("# Could not set up YUV shader.\n"); |
| 249 } |
| 250 |
| 251 glDeleteProgram(program); |
130 } | 252 } |
131 | 253 |
132 done: | |
133 glDeleteProgram(program); | |
134 glDeleteTextures(2, texture); | |
135 glDeleteBuffers(1, &vertex_buffer); | 254 glDeleteBuffers(1, &vertex_buffer); |
136 munmap(pixels, size); | |
137 | 255 |
138 return true; | 256 return true; |
139 } | 257 } |
140 | 258 |
141 | 259 |
142 TestBase* GetYuvToRgbTest(int type, const char* name) { | 260 TestBase* GetYuvToRgbTest() { |
143 return new YuvToRgbTest(type, name); | 261 return new YuvToRgbTest(); |
144 } | 262 } |
145 | 263 |
146 } // namespace glbench | 264 } // namespace glbench |
OLD | NEW |