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 // http://crbug.com/281565
322 #if !defined(OS_ANDROID)
323 TEST_F(GLTextureMailboxTest, ProduceFrontBufferMultipleContexts) {
326 glGenMailboxCHROMIUM(mailbox[0].name);
327 glGenMailboxCHROMIUM(mailbox[1].name);
329 glGenTextures(2, tex);
331 GLManager::Options options;
332 options.share_mailbox_manager = &gl1_;
333 GLManager other_gl[2];
334 for (size_t i = 0; i < 2; ++i) {
335 other_gl[i].Initialize(options);
336 other_gl[i].MakeCurrent();
337 other_gl[i].decoder()->ProduceFrontBuffer(mailbox[i]);
338 // Make sure both "other gl" are in the same share group.
339 if (!options.share_group_manager)
340 options.share_group_manager = other_gl+i;
345 for (size_t i = 0; i < 2; ++i) {
346 glBindTexture(GL_TEXTURE_2D, tex[i]);
347 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox[i].name);
348 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
351 for (size_t i = 0; i < 2; ++i) {
352 other_gl[i].MakeCurrent();
353 glResizeCHROMIUM(10, 10, 1);
354 glClearColor(1-i%2, i%2, 0, 1);
355 glClear(GL_COLOR_BUFFER_BIT);
356 ::gles2::GetGLContext()->SwapBuffers();
360 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex[0], 0, 0));
361 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex[1], 9, 9));
363 for (size_t i = 0; i < 2; ++i) {
364 other_gl[i].MakeCurrent();
365 other_gl[i].Destroy();
369 glDeleteTextures(2, tex);