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/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
);
45 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
47 glBindFramebuffer(GL_FRAMEBUFFER
, old_fbo
);
49 glDeleteFramebuffers(1, &fbo
);
55 class GLTextureMailboxTest
: public testing::Test
{
57 void SetUp() override
{
58 gl1_
.Initialize(GLManager::Options());
59 GLManager::Options options
;
60 options
.share_mailbox_manager
= &gl1_
;
61 gl2_
.Initialize(options
);
64 void TearDown() override
{
73 TEST_F(GLTextureMailboxTest
, ProduceAndConsumeTexture
) {
76 GLbyte mailbox1
[GL_MAILBOX_SIZE_CHROMIUM
];
77 glGenMailboxCHROMIUM(mailbox1
);
79 GLbyte mailbox2
[GL_MAILBOX_SIZE_CHROMIUM
];
80 glGenMailboxCHROMIUM(mailbox2
);
83 glGenTextures(1, &tex1
);
85 glBindTexture(GL_TEXTURE_2D
, tex1
);
86 uint32 source_pixel
= 0xFF0000FF;
87 glTexImage2D(GL_TEXTURE_2D
,
96 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
102 glGenTextures(1, &tex2
);
104 glBindTexture(GL_TEXTURE_2D
, tex2
);
105 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
106 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
107 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
112 glBindTexture(GL_TEXTURE_2D
, tex1
);
113 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
114 EXPECT_EQ(source_pixel
, ReadTexel(tex1
, 0, 0));
117 TEST_F(GLTextureMailboxTest
, ProduceAndConsumeTextureRGB
) {
120 GLbyte mailbox1
[GL_MAILBOX_SIZE_CHROMIUM
];
121 glGenMailboxCHROMIUM(mailbox1
);
123 GLbyte mailbox2
[GL_MAILBOX_SIZE_CHROMIUM
];
124 glGenMailboxCHROMIUM(mailbox2
);
127 glGenTextures(1, &tex1
);
129 glBindTexture(GL_TEXTURE_2D
, tex1
);
130 uint32 source_pixel
= 0xFF000000;
131 glTexImage2D(GL_TEXTURE_2D
,
140 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
146 glGenTextures(1, &tex2
);
148 glBindTexture(GL_TEXTURE_2D
, tex2
);
149 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
150 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
151 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
156 glBindTexture(GL_TEXTURE_2D
, tex1
);
157 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
158 EXPECT_EQ(source_pixel
, ReadTexel(tex1
, 0, 0));
161 TEST_F(GLTextureMailboxTest
, ProduceAndConsumeTextureDirect
) {
164 GLbyte mailbox1
[GL_MAILBOX_SIZE_CHROMIUM
];
165 glGenMailboxCHROMIUM(mailbox1
);
167 GLbyte mailbox2
[GL_MAILBOX_SIZE_CHROMIUM
];
168 glGenMailboxCHROMIUM(mailbox2
);
171 glGenTextures(1, &tex1
);
173 glBindTexture(GL_TEXTURE_2D
, tex1
);
174 uint32 source_pixel
= 0xFF0000FF;
175 glTexImage2D(GL_TEXTURE_2D
,
184 glProduceTextureDirectCHROMIUM(tex1
, GL_TEXTURE_2D
, mailbox1
);
189 GLuint tex2
= glCreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox1
);
190 glBindTexture(GL_TEXTURE_2D
, tex2
);
191 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
192 glProduceTextureDirectCHROMIUM(tex2
, GL_TEXTURE_2D
, mailbox2
);
197 GLuint tex3
= glCreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox2
);
198 glBindTexture(GL_TEXTURE_2D
, tex3
);
199 EXPECT_EQ(source_pixel
, ReadTexel(tex3
, 0, 0));
202 TEST_F(GLTextureMailboxTest
, ConsumeTextureValidatesKey
) {
204 glGenTextures(1, &tex
);
206 glBindTexture(GL_TEXTURE_2D
, tex
);
207 uint32 source_pixel
= 0xFF0000FF;
208 glTexImage2D(GL_TEXTURE_2D
,
217 GLbyte invalid_mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
218 glGenMailboxCHROMIUM(invalid_mailbox
);
220 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
221 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, invalid_mailbox
);
222 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
224 // Ensure level 0 is still intact after glConsumeTextureCHROMIUM fails.
225 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
226 EXPECT_EQ(source_pixel
, ReadTexel(tex
, 0, 0));
227 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
230 TEST_F(GLTextureMailboxTest
, SharedTextures
) {
233 glGenTextures(1, &tex1
);
235 glBindTexture(GL_TEXTURE_2D
, tex1
);
236 uint32 source_pixel
= 0xFF0000FF;
237 glTexImage2D(GL_TEXTURE_2D
,
245 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
246 glGenMailboxCHROMIUM(mailbox
);
248 glProduceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
249 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
254 glGenTextures(1, &tex2
);
256 glBindTexture(GL_TEXTURE_2D
, tex2
);
257 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
258 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
260 // Change texture in context 2.
261 source_pixel
= 0xFF00FF00;
262 glTexSubImage2D(GL_TEXTURE_2D
,
269 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
272 // Check it in context 1.
274 EXPECT_EQ(source_pixel
, ReadTexel(tex1
, 0, 0));
275 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
277 // Change parameters (note: ReadTexel will reset those).
278 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
279 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
280 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
281 GL_LINEAR_MIPMAP_NEAREST
);
282 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
285 // Check in context 2.
288 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, ¶meter
);
289 EXPECT_EQ(GL_REPEAT
, parameter
);
291 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, ¶meter
);
292 EXPECT_EQ(GL_LINEAR
, parameter
);
294 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, ¶meter
);
295 EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST
, parameter
);
297 // Delete texture in context 1.
299 glDeleteTextures(1, &tex1
);
300 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
302 // Check texture still exists in context 2.
304 EXPECT_EQ(source_pixel
, ReadTexel(tex2
, 0, 0));
305 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
307 // The mailbox should still exist too.
309 glGenTextures(1, &tex3
);
310 glBindTexture(GL_TEXTURE_2D
, tex3
);
311 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
312 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
314 // Delete both textures.
315 glDeleteTextures(1, &tex2
);
316 glDeleteTextures(1, &tex3
);
317 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
319 // Mailbox should be gone now.
320 glGenTextures(1, &tex2
);
321 glBindTexture(GL_TEXTURE_2D
, tex2
);
322 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
);
323 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
324 glDeleteTextures(1, &tex2
);
325 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
328 TEST_F(GLTextureMailboxTest
, ProduceFrontBuffer
) {
331 glGenMailboxCHROMIUM(mailbox
.name
);
334 gl2_
.decoder()->ProduceFrontBuffer(mailbox
);
338 glGenTextures(1, &tex1
);
339 glBindTexture(GL_TEXTURE_2D
, tex1
);
340 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
341 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
344 glResizeCHROMIUM(10, 10, 1);
345 glClearColor(1, 0, 0, 1);
346 glClear(GL_COLOR_BUFFER_BIT
);
347 ::gles2::GetGLContext()->SwapBuffers();
350 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 0, 0));
351 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 9, 9));
352 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
355 glClearColor(0, 1, 0, 1);
356 glClear(GL_COLOR_BUFFER_BIT
);
360 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex1
, 0, 0));
363 ::gles2::GetGLContext()->SwapBuffers();
366 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex1
, 0, 0));
372 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex1
, 0, 0));
373 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
374 glDeleteTextures(1, &tex1
);
377 TEST_F(GLTextureMailboxTest
, ProduceTextureDirectInvalidTarget
) {
380 GLbyte mailbox1
[GL_MAILBOX_SIZE_CHROMIUM
];
381 glGenMailboxCHROMIUM(mailbox1
);
384 glGenTextures(1, &tex1
);
386 glBindTexture(GL_TEXTURE_CUBE_MAP
, tex1
);
387 uint32 source_pixel
= 0xFF0000FF;
388 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X
,
397 glProduceTextureDirectCHROMIUM(tex1
, GL_TEXTURE_2D
, mailbox1
);
398 EXPECT_EQ(static_cast<GLenum
>(GL_INVALID_OPERATION
), glGetError());
401 // http://crbug.com/281565
402 #if !defined(OS_ANDROID)
403 TEST_F(GLTextureMailboxTest
, ProduceFrontBufferMultipleContexts
) {
406 glGenMailboxCHROMIUM(mailbox
[0].name
);
407 glGenMailboxCHROMIUM(mailbox
[1].name
);
409 glGenTextures(2, tex
);
411 GLManager::Options options
;
412 options
.share_mailbox_manager
= &gl1_
;
413 GLManager other_gl
[2];
414 for (size_t i
= 0; i
< 2; ++i
) {
415 other_gl
[i
].Initialize(options
);
416 other_gl
[i
].MakeCurrent();
417 other_gl
[i
].decoder()->ProduceFrontBuffer(mailbox
[i
]);
418 // Make sure both "other gl" are in the same share group.
419 if (!options
.share_group_manager
)
420 options
.share_group_manager
= other_gl
+i
;
425 for (size_t i
= 0; i
< 2; ++i
) {
426 glBindTexture(GL_TEXTURE_2D
, tex
[i
]);
427 glConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
[i
].name
);
428 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), glGetError());
431 for (size_t i
= 0; i
< 2; ++i
) {
432 other_gl
[i
].MakeCurrent();
433 glResizeCHROMIUM(10, 10, 1);
434 glClearColor(1-i
%2, i
%2, 0, 1);
435 glClear(GL_COLOR_BUFFER_BIT
);
436 ::gles2::GetGLContext()->SwapBuffers();
440 EXPECT_EQ(0xFF0000FFu
, ReadTexel(tex
[0], 0, 0));
441 EXPECT_EQ(0xFF00FF00u
, ReadTexel(tex
[1], 9, 9));
443 for (size_t i
= 0; i
< 2; ++i
) {
444 other_gl
[i
].MakeCurrent();
445 other_gl
[i
].Destroy();
449 glDeleteTextures(2, tex
);