blob: 2fcab137286665629a2e5eb517a6f6122e3b83f9 [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"
Chris Masone28cc0252011-05-13 11:45:07 -07009#include "base/memory/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();
Alexey Marinichevf50ecb12010-06-14 15:21:41 -070027 virtual const char* Name() const { return "yuv_to_rgb"; }
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070028
Alexey Marinichevbe37f882010-06-07 20:35:07 -070029 enum YuvTestFlavor {
30 YUV_PLANAR_ONE_TEXTURE_SLOW,
31 YUV_PLANAR_ONE_TEXTURE_FASTER,
32 YUV_PLANAR_THREE_TEXTURES,
33 YUV_SEMIPLANAR_TWO_TEXTURES,
34 };
35
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070036 private:
Alexey Marinichevbe37f882010-06-07 20:35:07 -070037 GLuint textures_[6];
38 YuvTestFlavor flavor_;
39 GLuint YuvToRgbShaderProgram(GLuint vertex_buffer, int width, int height);
40 bool SetupTextures();
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070041 DISALLOW_COPY_AND_ASSIGN(YuvToRgbTest);
42};
43
44
Alexey Marinichevbe37f882010-06-07 20:35:07 -070045GLuint YuvToRgbTest::YuvToRgbShaderProgram(GLuint vertex_buffer,
46 int width, int height) {
47 const char *vertex = NULL;
48 const char *fragment = NULL;
49
50 switch (flavor_) {
51 case YUV_PLANAR_ONE_TEXTURE_SLOW:
52 vertex = YUV2RGB_VERTEX_1;
53 fragment = YUV2RGB_FRAGMENT_1;
54 break;
55 case YUV_PLANAR_ONE_TEXTURE_FASTER:
56 vertex = YUV2RGB_VERTEX_2;
57 fragment = YUV2RGB_FRAGMENT_2;
58 break;
59 case YUV_PLANAR_THREE_TEXTURES:
60 vertex = YUV2RGB_VERTEX_34;
61 fragment = YUV2RGB_FRAGMENT_3;
62 break;
63 case YUV_SEMIPLANAR_TWO_TEXTURES:
64 vertex = YUV2RGB_VERTEX_34;
65 fragment = YUV2RGB_FRAGMENT_4;
66 break;
67 }
68
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070069 size_t size_vertex = 0;
70 size_t size_fragment = 0;
71 char *yuv_to_rgb_vertex = static_cast<char *>(
72 MmapFile(vertex, &size_vertex));
73 char *yuv_to_rgb_fragment = static_cast<char *>(
74 MmapFile(fragment, &size_fragment));
75 GLuint program = 0;
76
77 if (!yuv_to_rgb_fragment || !yuv_to_rgb_vertex)
78 goto done;
79
80 {
Stuart Abercrombieb8f4e7a2011-09-26 18:07:55 -070081 program = InitShaderProgramWithHeader(NULL, yuv_to_rgb_vertex,
Alexey Marinichev219b7082010-05-24 16:18:51 -070082 yuv_to_rgb_fragment);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070083
84 int imageWidthUniform = glGetUniformLocation(program, "imageWidth");
85 int imageHeightUniform = glGetUniformLocation(program, "imageHeight");
Alexey Marinichevbe37f882010-06-07 20:35:07 -070086
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070087 int textureSampler = glGetUniformLocation(program, "textureSampler");
88 int evenLinesSampler = glGetUniformLocation(program, "paritySampler");
Alexey Marinichevbe37f882010-06-07 20:35:07 -070089 int ySampler = glGetUniformLocation(program, "ySampler");
90 int uSampler = glGetUniformLocation(program, "uSampler");
91 int vSampler = glGetUniformLocation(program, "vSampler");
92 int uvSampler = glGetUniformLocation(program, "uvSampler");
Alexey Marinichev9f9b8732010-05-20 19:33:44 -070093
94 glUniform1f(imageWidthUniform, width);
95 glUniform1f(imageHeightUniform, height);
96 glUniform1i(textureSampler, 0);
97 glUniform1i(evenLinesSampler, 1);
98
Alexey Marinichevbe37f882010-06-07 20:35:07 -070099 glUniform1i(ySampler, 2);
100 glUniform1i(uSampler, 3);
101 glUniform1i(vSampler, 4);
102 glUniform1i(uvSampler, 5);
103
104 {
105 // This is used only if USE_UNIFORM_MATRIX is enabled in fragment
106 // shaders.
107 float c[] = {
108 1.0, 1.0, 1.0, 0.0,
109 0.0, -0.344, 1.772, 0.0,
110 1.402, -0.714, 0.0, 0.0,
111 -0.701, 0.529, -0.886, 1.0
112 };
113 int conversion = glGetUniformLocation(program, "conversion");
114 glUniformMatrix4fv(conversion, 1, GL_FALSE, c);
115 assert(glGetError() == 0);
116 }
117
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700118 int attribute_index = glGetAttribLocation(program, "c");
119 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
120 glVertexAttribPointer(attribute_index, 2, GL_FLOAT, GL_FALSE, 0, NULL);
121 glEnableVertexAttribArray(attribute_index);
122 return program;
123 }
124
125
126done:
127 munmap(yuv_to_rgb_fragment, size_fragment);
128 munmap(yuv_to_rgb_fragment, size_vertex);
129 return program;
130}
131
132
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700133bool YuvToRgbTest::SetupTextures() {
134 bool ret = false;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700135 size_t size = 0;
Han Shenc2e0dc32012-07-02 16:15:46 -0700136 char evenodd[2] = {0, static_cast<char>(-1)};
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700137 char* pixels = static_cast<char *>(MmapFile(YUV2RGB_NAME, &size));
138 const int luma_size = YUV2RGB_WIDTH * YUV2RGB_PIXEL_HEIGHT;
139 const int chroma_size = YUV2RGB_WIDTH/2 * YUV2RGB_PIXEL_HEIGHT/2;
140 const char* u_plane = pixels + luma_size;
141 const char* v_plane = pixels + luma_size + chroma_size;
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700142 if (!pixels) {
Ilja H. Friedel8faad302011-04-26 14:40:49 -0700143 printf("# Error: Could not open image file: %s\n", YUV2RGB_NAME);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700144 goto done;
145 }
146 if (size != YUV2RGB_SIZE) {
Ilja H. Friedel8faad302011-04-26 14:40:49 -0700147 printf("# Error: Image file of wrong size, got %d, expected %d\n",
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700148 static_cast<int>(size), YUV2RGB_SIZE);
149 goto done;
150 }
151
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700152 glGenTextures(arraysize(textures_), textures_);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700153 glActiveTexture(GL_TEXTURE0);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700154 glBindTexture(GL_TEXTURE_2D, textures_[0]);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700155 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, YUV2RGB_WIDTH, YUV2RGB_HEIGHT,
156 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
157
158 glActiveTexture(GL_TEXTURE1);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700159 glBindTexture(GL_TEXTURE_2D, textures_[1]);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700160 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 1,
161 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, evenodd);
162
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700163 glActiveTexture(GL_TEXTURE2);
164 glBindTexture(GL_TEXTURE_2D, textures_[2]);
165 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
166 YUV2RGB_WIDTH, YUV2RGB_PIXEL_HEIGHT,
167 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700168
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700169 glActiveTexture(GL_TEXTURE3);
170 glBindTexture(GL_TEXTURE_2D, textures_[3]);
171 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
172 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2,
173 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u_plane);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700174
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700175 glActiveTexture(GL_TEXTURE4);
176 glBindTexture(GL_TEXTURE_2D, textures_[4]);
177 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
178 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2,
179 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v_plane);
180
181 {
Ben Chan88548a12014-01-27 23:38:25 -0800182 scoped_ptr<char[]> buf_uv(new char[chroma_size * 2]);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700183 char* buf_uv_ptr = buf_uv.get();
184 for (int i = 0; i < chroma_size; i++) {
185 *buf_uv_ptr++ = u_plane[i];
186 *buf_uv_ptr++ = v_plane[i];
187 }
188
189 glActiveTexture(GL_TEXTURE5);
190 glBindTexture(GL_TEXTURE_2D, textures_[5]);
191 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
192 YUV2RGB_WIDTH/2, YUV2RGB_PIXEL_HEIGHT/2,
193 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf_uv.get());
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700194 }
195
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700196 for (unsigned int i = 0; i < arraysize(textures_); i++) {
197 glActiveTexture(GL_TEXTURE0 + i);
198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
199 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Allen Martin140559c2011-08-12 14:53:38 -0700200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
201 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700202 }
203
204 ret = true;
205
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700206done:
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700207 munmap(pixels, size);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700208 return ret;
209}
210
211
212bool YuvToRgbTest::Run() {
Stuart Abercrombied5dfe5f2012-08-15 18:42:52 -0700213 glClearColor(0.f, 1.f, 0.f, 1.f);
214
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700215 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
Ilja Friedelc04bdd42013-01-30 18:55:49 -0800228 glViewport(0, 0, YUV2RGB_WIDTH, YUV2RGB_PIXEL_HEIGHT);
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700229
230 YuvTestFlavor flavors[] = {
231 YUV_PLANAR_ONE_TEXTURE_SLOW, YUV_PLANAR_ONE_TEXTURE_FASTER,
232 YUV_PLANAR_THREE_TEXTURES, YUV_SEMIPLANAR_TWO_TEXTURES
233 };
234 const char* flavor_names[] = {
235 "yuv_shader_1", "yuv_shader_2", "yuv_shader_3", "yuv_shader_4"
236 };
237 for (unsigned int f = 0; f < arraysize(flavors); f++) {
238 flavor_ = flavors[f];
239
240 program = YuvToRgbShaderProgram(vertex_buffer,
241 YUV2RGB_WIDTH, YUV2RGB_PIXEL_HEIGHT);
242 if (program) {
243 FillRateTestNormalSubWindow(flavor_names[f],
244 std::min(YUV2RGB_WIDTH, g_width),
245 std::min(YUV2RGB_PIXEL_HEIGHT, g_height));
246 } else {
Ilja H. Friedel8faad302011-04-26 14:40:49 -0700247 printf("# Error: Could not set up YUV shader.\n");
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700248 }
249
250 glDeleteProgram(program);
251 }
252
253 glDeleteBuffers(1, &vertex_buffer);
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700254
255 return true;
256}
257
258
Alexey Marinichevbe37f882010-06-07 20:35:07 -0700259TestBase* GetYuvToRgbTest() {
260 return new YuvToRgbTest();
Alexey Marinichev9f9b8732010-05-20 19:33:44 -0700261}
262
263} // namespace glbench