blob: 2ae23ab4d2d85effeeee348150f43f515696e918 [file] [log] [blame]
Alexey Marinichev9f9b8732010-05-20 19:33:44 -07001// 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
3// found in the LICENSE file.
4
5#include <stdio.h>
6#include <sys/mman.h>
7
8#include "base/logging.h"
Alexey Marinichevbe37f882010-06-07 20:35:07 -07009#include "base/scoped_ptr.h"
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070010
11#include "main.h"
12#include "testbase.h"
13#include "utils.h"
14#include "yuv2rgb.h"
15
16namespace glbench {
17
18class YuvToRgbTest : public DrawArraysTestFunc {
19 public:
Alexey Marinichevbe37f882010-06-07 20:35:07 -070020 YuvToRgbTest() {
21 memset(textures_, 0, sizeof(textures_));
22 }
23 virtual ~YuvToRgbTest() {
24 glDeleteTextures(arraysize(textures_), textures_);
25 }
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070026 virtual bool Run();
27
Alexey Marinichevbe37f882010-06-07 20:35:07 -070028 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
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070035 private:
Alexey Marinichevbe37f882010-06-07 20:35:07 -070036 GLuint textures_[6];
37 YuvTestFlavor flavor_;
38 GLuint YuvToRgbShaderProgram(GLuint vertex_buffer, int width, int height);
39 bool SetupTextures();
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070040 DISALLOW_COPY_AND_ASSIGN(YuvToRgbTest);
41};
42
43
Alexey Marinichevbe37f882010-06-07 20:35:07 -070044GLuint YuvToRgbTest::YuvToRgbShaderProgram(GLuint vertex_buffer,
45 int width, int height) {
46 const char *vertex = NULL;
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
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070068 size_t size_vertex = 0;
69 size_t size_fragment = 0;
70 char *yuv_to_rgb_vertex = static_cast<char *>(
71 MmapFile(vertex, &size_vertex));
72 char *yuv_to_rgb_fragment = static_cast<char *>(
73 MmapFile(fragment, &size_fragment));
74 GLuint program = 0;
75
76 if (!yuv_to_rgb_fragment || !yuv_to_rgb_vertex)
77 goto done;
78
79 {
Alexey Marinichev219b7082010-05-24 16:18:51 -070080#if defined(I915_WORKAROUND)
81 const char* header = "#define I915_WORKAROUND 1\n";
82#else
83 const char* header = NULL;
84#endif
85 program = InitShaderProgramWithHeader(header, yuv_to_rgb_vertex,
86 yuv_to_rgb_fragment);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070087
88 int imageWidthUniform = glGetUniformLocation(program, "imageWidth");
89 int imageHeightUniform = glGetUniformLocation(program, "imageHeight");
Alexey Marinichevbe37f882010-06-07 20:35:07 -070090
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070091 int textureSampler = glGetUniformLocation(program, "textureSampler");
92 int evenLinesSampler = glGetUniformLocation(program, "paritySampler");
Alexey Marinichevbe37f882010-06-07 20:35:07 -070093 int ySampler = glGetUniformLocation(program, "ySampler");
94 int uSampler = glGetUniformLocation(program, "uSampler");
95 int vSampler = glGetUniformLocation(program, "vSampler");
96 int uvSampler = glGetUniformLocation(program, "uvSampler");
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070097
98 glUniform1f(imageWidthUniform, width);
99 glUniform1f(imageHeightUniform, height);
100 glUniform1i(textureSampler, 0);
101 glUniform1i(evenLinesSampler, 1);
102
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700103 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
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700122 int attribute_index = glGetAttribLocation(program, "c");
123 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
124 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
125 glEnableVertexAttribArray(attribute_index);
126 return program;
127 }
128
129
130done:
131 munmap(yuv_to_rgb_fragment, size_fragment);
132 munmap(yuv_to_rgb_fragment, size_vertex);
133 return program;
134}
135
136
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700137bool YuvToRgbTest::SetupTextures() {
138 bool ret = false;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700139 size_t size = 0;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700140 char evenodd[2] = {0, 255};
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700141 char* pixels = static_cast<char *>(MmapFile(YUV2RGB_NAME, &size));
142 const int luma_size = YUV2RGB_WIDTH * YUV2RGB_PIXEL_HEIGHT;
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;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700146 if (!pixels) {
147 printf("# Could not open image file: %s\n", YUV2RGB_NAME);
148 goto done;
149 }
150 if (size != YUV2RGB_SIZE) {
151 printf("# Image file of wrong size, got %d, expected %d\n",
152 static_cast<int>(size), YUV2RGB_SIZE);
153 goto done;
154 }
155
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700156 glGenTextures(arraysize(textures_), textures_);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700157 glActiveTexture(GL_TEXTURE0);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700158 glBindTexture(GL_TEXTURE_2D, textures_[0]);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700159 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, YUV2RGB_WIDTH, YUV2RGB_HEIGHT,
160 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
161
162 glActiveTexture(GL_TEXTURE1);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700163 glBindTexture(GL_TEXTURE_2D, textures_[1]);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700164 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 1,
165 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, evenodd);
166
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700167 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);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700172
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700173 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);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700178
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700179 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());
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700198 }
199
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700200 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
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700208done:
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700209 munmap(pixels, size);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700210 return ret;
211}
212
213
214bool 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 };
223 vertex_buffer = SetupVBO(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
224
225 if (!SetupTextures())
226 return false;
227
228 glViewport(-YUV2RGB_WIDTH, -YUV2RGB_PIXEL_HEIGHT,
229 YUV2RGB_WIDTH*2, YUV2RGB_PIXEL_HEIGHT * 2);
230
231 YuvTestFlavor flavors[] = {
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);
252 }
253
254 glDeleteBuffers(1, &vertex_buffer);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700255
256 return true;
257}
258
259
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700260TestBase* GetYuvToRgbTest() {
261 return new YuvToRgbTest();
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700262}
263
264} // namespace glbench