1 // Copyright 2014 The Chromium 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.
6 #include <GLES2/gl2chromium.h>
7 #include <GLES2/gl2ext.h>
8 #include <GLES2/gl2extchromium.h>
10 #include "base/bind.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/process/process_handle.h"
13 #include "gpu/command_buffer/client/gles2_implementation.h"
14 #include "gpu/command_buffer/service/command_buffer_service.h"
15 #include "gpu/command_buffer/service/image_manager.h"
16 #include "gpu/command_buffer/tests/gl_manager.h"
17 #include "gpu/command_buffer/tests/gl_test_utils.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/gpu_memory_buffer.h"
21 #include "ui/gl/gl_image.h"
24 using testing::IgnoreResult
;
25 using testing::InvokeWithoutArgs
;
26 using testing::Invoke
;
27 using testing::Return
;
28 using testing::SetArgPointee
;
29 using testing::StrictMock
;
34 static const int kImageWidth
= 32;
35 static const int kImageHeight
= 32;
37 class GpuMemoryBufferTest
: public testing::TestWithParam
<gfx::BufferFormat
> {
39 void SetUp() override
{
40 GLManager::Options options
;
41 options
.size
= gfx::Size(kImageWidth
, kImageHeight
);
42 gl_
.Initialize(options
);
46 void TearDown() override
{
55 #define SHADER(Src) #Src
58 const char kVertexShader
[] =
60 attribute vec4 a_position
;
61 varying vec2 v_texCoord
;
63 gl_Position
= a_position
;
64 v_texCoord
= vec2((a_position
.x
+ 1.0) * 0.5, (a_position
.y
+ 1.0) * 0.5);
68 const char* kFragmentShader
=
70 precision mediump
float;
71 uniform sampler2D a_texture
;
72 varying vec2 v_texCoord
;
74 gl_FragColor
= texture2D(a_texture
, v_texCoord
);
79 void SetRow(gfx::BufferFormat format
,
84 case gfx::BufferFormat::R_8
:
85 for (int i
= 0; i
< width
; ++i
)
88 case gfx::BufferFormat::RGBA_4444
:
89 for (int i
= 0; i
< width
* 2; i
+= 2) {
90 buffer
[i
+ 0] = (pixel
[1] << 4) | (pixel
[0] & 0xf);
91 buffer
[i
+ 1] = (pixel
[3] << 4) | (pixel
[2] & 0xf);
94 case gfx::BufferFormat::RGBA_8888
:
95 for (int i
= 0; i
< width
* 4; i
+= 4) {
96 buffer
[i
+ 0] = pixel
[0];
97 buffer
[i
+ 1] = pixel
[1];
98 buffer
[i
+ 2] = pixel
[2];
99 buffer
[i
+ 3] = pixel
[3];
102 case gfx::BufferFormat::BGRA_8888
:
103 for (int i
= 0; i
< width
* 4; i
+= 4) {
104 buffer
[i
+ 0] = pixel
[2];
105 buffer
[i
+ 1] = pixel
[1];
106 buffer
[i
+ 2] = pixel
[0];
107 buffer
[i
+ 3] = pixel
[3];
110 case gfx::BufferFormat::ATC
:
111 case gfx::BufferFormat::ATCIA
:
112 case gfx::BufferFormat::DXT1
:
113 case gfx::BufferFormat::DXT5
:
114 case gfx::BufferFormat::ETC1
:
115 case gfx::BufferFormat::BGRX_8888
:
116 case gfx::BufferFormat::YUV_420
:
117 case gfx::BufferFormat::YUV_420_BIPLANAR
:
118 case gfx::BufferFormat::UYVY_422
:
126 GLenum
InternalFormat(gfx::BufferFormat format
) {
128 case gfx::BufferFormat::R_8
:
130 case gfx::BufferFormat::RGBA_4444
:
131 case gfx::BufferFormat::RGBA_8888
:
133 case gfx::BufferFormat::BGRA_8888
:
135 case gfx::BufferFormat::ATC
:
136 case gfx::BufferFormat::ATCIA
:
137 case gfx::BufferFormat::DXT1
:
138 case gfx::BufferFormat::DXT5
:
139 case gfx::BufferFormat::ETC1
:
140 case gfx::BufferFormat::BGRX_8888
:
141 case gfx::BufferFormat::YUV_420
:
142 case gfx::BufferFormat::YUV_420_BIPLANAR
:
143 case gfx::BufferFormat::UYVY_422
:
154 // An end to end test that tests the whole GpuMemoryBuffer lifecycle.
155 TEST_P(GpuMemoryBufferTest
, Lifecycle
) {
156 ASSERT_TRUE((GetParam() != gfx::BufferFormat::R_8
) ||
157 gl_
.GetCapabilities().texture_rg
);
159 GLuint texture_id
= 0;
160 glGenTextures(1, &texture_id
);
161 ASSERT_NE(0u, texture_id
);
162 glBindTexture(GL_TEXTURE_2D
, texture_id
);
163 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
164 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
165 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
166 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
168 // Create the gpu memory buffer.
169 scoped_ptr
<gfx::GpuMemoryBuffer
> buffer(gl_
.CreateGpuMemoryBuffer(
170 gfx::Size(kImageWidth
, kImageHeight
), GetParam()));
172 // Map buffer for writing.
174 bool rv
= buffer
->Map(&data
);
177 uint8_t* mapped_buffer
= static_cast<uint8_t*>(data
);
178 ASSERT_TRUE(mapped_buffer
!= NULL
);
180 uint8_t pixel
[] = {255u, 0u, 0u, 255u};
182 // Assign a value to each pixel.
184 buffer
->GetStride(&stride
);
185 ASSERT_NE(stride
, 0);
186 for (int y
= 0; y
< kImageHeight
; ++y
)
187 SetRow(GetParam(), mapped_buffer
+ y
* stride
, kImageWidth
, pixel
);
192 // Create the image. This should add the image ID to the ImageManager.
194 glCreateImageCHROMIUM(buffer
->AsClientBuffer(), kImageWidth
, kImageHeight
,
195 InternalFormat(GetParam()));
196 ASSERT_NE(0u, image_id
);
197 ASSERT_TRUE(gl_
.decoder()->GetImageManager()->LookupImage(image_id
) != NULL
);
200 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D
, image_id
);
202 // Build program, buffers and draw the texture.
203 GLuint vertex_shader
=
204 GLTestHelper::LoadShader(GL_VERTEX_SHADER
, kVertexShader
);
205 GLuint fragment_shader
=
206 GLTestHelper::LoadShader(GL_FRAGMENT_SHADER
, kFragmentShader
);
207 GLuint program
= GLTestHelper::SetupProgram(vertex_shader
, fragment_shader
);
208 ASSERT_NE(0u, program
);
209 glUseProgram(program
);
211 GLint sampler_location
= glGetUniformLocation(program
, "a_texture");
212 ASSERT_NE(-1, sampler_location
);
213 glUniform1i(sampler_location
, 0);
216 GLTestHelper::SetupUnitQuad(glGetAttribLocation(program
, "a_position"));
218 glViewport(0, 0, kImageWidth
, kImageHeight
);
219 glDrawArrays(GL_TRIANGLES
, 0, 6);
220 ASSERT_TRUE(glGetError() == GL_NO_ERROR
);
222 // Check if pixels match the values that were assigned to the mapped buffer.
223 GLTestHelper::CheckPixels(0, 0, kImageWidth
, kImageHeight
, 0, pixel
);
224 EXPECT_TRUE(GL_NO_ERROR
== glGetError());
226 // Release the image.
227 glReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, image_id
);
230 glDeleteProgram(program
);
231 glDeleteShader(vertex_shader
);
232 glDeleteShader(fragment_shader
);
233 glDeleteBuffers(1, &vbo
);
234 glDestroyImageCHROMIUM(image_id
);
235 glDeleteTextures(1, &texture_id
);
238 INSTANTIATE_TEST_CASE_P(GpuMemoryBufferTests
,
240 ::testing::Values(gfx::BufferFormat::R_8
,
241 gfx::BufferFormat::RGBA_4444
,
242 gfx::BufferFormat::RGBA_8888
,
243 gfx::BufferFormat::BGRA_8888
));