1 // Copyright (c) 2012 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/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
9 #include "gpu/command_buffer/client/gles2_lib.h"
10 #include "gpu/command_buffer/common/mailbox.h"
11 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
12 #include "gpu/command_buffer/service/mailbox_manager.h"
13 #include "gpu/command_buffer/tests/gl_manager.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gl/gl_share_group.h"
21 uint32
ReadTexel(GLuint id
, GLint x
, GLint y
) {
23 glGetIntegerv(GL_FRAMEBUFFER_BINDING
, &old_fbo
);
26 glGenFramebuffers(1, &fbo
);
27 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
28 glFramebufferTexture2D(GL_FRAMEBUFFER
,
33 // Some drivers (NVidia/SGX) require texture settings to be a certain way or
34 // they won't report FRAMEBUFFER_COMPLETE.
35 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
36 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
37 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
38 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
40 EXPECT_EQ(static_cast<GLenum
>(GL_FRAMEBUFFER_COMPLETE
),
41 glCheckFramebufferStatus(GL_FRAMEBUFFER
));
44 glReadPixels(x
, y
, 1, 1, GL_RGBA
, GL_UNSIGNED_BYTE
, &texel
);
46 glBindFramebuffer(GL_FRAMEBUFFER
, old_fbo
);
48 glDeleteFramebuffers(1, &fbo
);
54 class GLTextureMailboxTest
: public testing::Test
{
56 virtual void SetUp() {
57 gl1_
.Initialize(GLManager::Options());
58 GLManager::Options options
;
59 options
.share_mailbox_manager
= &gl1_
;
60 gl2_
.Initialize(options
);
63 virtual void TearDown() {
72 TEST_F(GLTextureMailboxTest
, ProduceAndConsumeTexture
) {
75 GLbyte mailbox1
[GL_MAILBOX_SIZE_CHROMIUM
];
76 glGenMailboxCHROMIUM(mailbox1
);
78 GLbyte mailbox2
[GL_MAILBOX_SIZE_CHROMIUM
];
79 glGenMailboxCHROMIUM(mailbox2
);
82 glGenTextures(1, &tex1
);
84 glBindTexture(GL_TEXTURE_2D
, tex1
);
85 uint32 source_pixel
= 0xFF0000FF;
86 glTexImage2D(GL_TEXTURE_2D
,
95 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
101 glGenTextures(1, &tex2
);
103 glBindTexture(GL_TEXTURE_2D
, tex2
);
104 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
105 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
106 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
111 glBindTexture(GL_TEXTURE_2D
, tex1
);
112 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
113 EXPECT_EQ(source_pixel
, ReadTexel(tex1
, 0, 0));
116 TEST_F(GLTextureMailboxTest
, ProduceTextureValidatesKey
) {
118 glGenTextures(1, &tex
);
120 glBindTexture(GL_TEXTURE_2D
, tex
);
121 uint32 source_pixel
= 0xFF0000FF;
122 glTexImage2D(GL_TEXTURE_2D
,
131 GLbyte invalid_mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
132 glGenMailboxCHROMIUM(invalid_mailbox
);
133 ++invalid_mailbox
[GL_MAILBOX_SIZE_CHROMIUM
- 1];
135 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
136 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, invalid_mailbox
);
137 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
139 // Ensure level 0 is still intact after glProduceTextureCHROMIUM fails.
140 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
141 EXPECT_EQ(source_pixel
, ReadTexel(tex
, 0, 0));
142 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
145 TEST_F(GLTextureMailboxTest
, ConsumeTextureValidatesKey
) {
147 glGenTextures(1, &tex
);
149 glBindTexture(GL_TEXTURE_2D
, tex
);
150 uint32 source_pixel
= 0xFF0000FF;
151 glTexImage2D(GL_TEXTURE_2D
,
160 GLbyte invalid_mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
161 glGenMailboxCHROMIUM(invalid_mailbox
);
162 ++invalid_mailbox
[GL_MAILBOX_SIZE_CHROMIUM
- 1];
164 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
165 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, invalid_mailbox
);
166 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
168 // Ensure level 0 is still intact after glConsumeTextureCHROMIUM fails.
169 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
170 EXPECT_EQ(source_pixel
, ReadTexel(tex
, 0, 0));
171 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
174 TEST_F(GLTextureMailboxTest
, SharedTextures
) {
177 glGenTextures(1, &tex1
);
179 glBindTexture(GL_TEXTURE_2D
, tex1
);
180 uint32 source_pixel
= 0xFF0000FF;
181 glTexImage2D(GL_TEXTURE_2D
,
189 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
190 glGenMailboxCHROMIUM(mailbox
);
192 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
193 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
198 glGenTextures(1, &tex2
);
200 glBindTexture(GL_TEXTURE_2D
, tex2
);
201 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
202 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
204 // Change texture in context 2.
205 source_pixel
= 0xFF00FF00;
206 glTexSubImage2D(GL_TEXTURE_2D
,
213 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
216 // Check it in context 1.
218 EXPECT_EQ(source_pixel
, ReadTexel(tex1
, 0, 0));
219 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
221 // Change parameters (note: ReadTexel will reset those).
222 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
223 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
224 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
225 GL_LINEAR_MIPMAP_NEAREST
);
226 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
229 // Check in context 2.
232 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, ¶meter
);
233 EXPECT_EQ(GL_REPEAT
, parameter
);
235 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, ¶meter
);
236 EXPECT_EQ(GL_LINEAR
, parameter
);
238 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, ¶meter
);
239 EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST
, parameter
);
241 // Delete texture in context 1.
243 glDeleteTextures(1, &tex1
);
244 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
246 // Check texture still exists in context 2.
248 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
249 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
251 // The mailbox should still exist too.
253 glGenTextures(1, &tex3
);
254 glBindTexture(GL_TEXTURE_2D
, tex3
);
255 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
256 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
258 // Delete both textures.
259 glDeleteTextures(1, &tex2
);
260 glDeleteTextures(1, &tex3
);
261 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
263 // Mailbox should be gone now.
264 glGenTextures(1, &tex2
);
265 glBindTexture(GL_TEXTURE_2D
, tex2
);
266 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
267 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
268 glDeleteTextures(1, &tex2
);
269 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
272 TEST_F(GLTextureMailboxTest
, ProduceFrontBuffer
) {
275 glGenMailboxCHROMIUM(mailbox
.name
);
278 gl2_
.decoder()->ProduceFrontBuffer(mailbox
);
282 glGenTextures(1, &tex1
);
283 glBindTexture(GL_TEXTURE_2D
, tex1
);
284 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
285 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
288 glResizeCHROMIUM(10, 10, 1);
289 glClearColor(1, 0, 0, 1);
290 glClear(GL_COLOR_BUFFER_BIT
);
291 ::gles2::GetGLContext()->SwapBuffers();
294 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 0, 0));
295 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 9, 9));
296 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
299 glClearColor(0, 1, 0, 1);
300 glClear(GL_COLOR_BUFFER_BIT
);
304 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 0, 0));
307 ::gles2::GetGLContext()->SwapBuffers();
310 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex1
, 0, 0));
316 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex1
, 0, 0));
317 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
318 glDeleteTextures(1, &tex1
);
321 TEST_F(GLTextureMailboxTest
, ProduceFrontBufferMultipleContexts
) {
324 glGenMailboxCHROMIUM(mailbox
[0].name
);
325 glGenMailboxCHROMIUM(mailbox
[1].name
);
327 glGenTextures(2, tex
);
329 GLManager::Options options
;
330 options
.share_mailbox_manager
= &gl1_
;
331 GLManager other_gl
[2];
332 for (size_t i
= 0; i
< 2; ++i
) {
333 other_gl
[i
].Initialize(options
);
334 other_gl
[i
].MakeCurrent();
335 other_gl
[i
].decoder()->ProduceFrontBuffer(mailbox
[i
]);
336 // Make sure both "other gl" are in the same share group.
337 if (!options
.share_group_manager
)
338 options
.share_group_manager
= other_gl
+i
;
343 for (size_t i
= 0; i
< 2; ++i
) {
344 glBindTexture(GL_TEXTURE_2D
, tex
[i
]);
345 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
[i
].name
);
346 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
349 for (size_t i
= 0; i
< 2; ++i
) {
350 other_gl
[i
].MakeCurrent();
351 glResizeCHROMIUM(10, 10, 1);
352 glClearColor(1-i
%2, i
%2, 0, 1);
353 glClear(GL_COLOR_BUFFER_BIT
);
354 ::gles2::GetGLContext()->SwapBuffers();
358 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex
[0], 0, 0));
359 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex
[1], 9, 9));
361 for (size_t i
= 0; i
< 2; ++i
) {
362 other_gl
[i
].MakeCurrent();
363 other_gl
[i
].Destroy();
367 glDeleteTextures(2, tex
);