• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <GLES2/gl2.h>
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
8 
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"
17 
18 namespace gpu {
19 
20 namespace {
ReadTexel(GLuint id,GLint x,GLint y)21 uint32 ReadTexel(GLuint id, GLint x, GLint y) {
22   GLint old_fbo = 0;
23   glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo);
24 
25   GLuint fbo;
26   glGenFramebuffers(1, &fbo);
27   glBindFramebuffer(GL_FRAMEBUFFER, fbo);
28   glFramebufferTexture2D(GL_FRAMEBUFFER,
29                          GL_COLOR_ATTACHMENT0,
30                          GL_TEXTURE_2D,
31                          id,
32                          0);
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);
39 
40   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
41             glCheckFramebufferStatus(GL_FRAMEBUFFER));
42 
43   uint32 texel = 0;
44   glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &texel);
45   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
46 
47   glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
48 
49   glDeleteFramebuffers(1, &fbo);
50 
51   return texel;
52 }
53 }
54 
55 class GLTextureMailboxTest : public testing::Test {
56  protected:
SetUp()57   virtual void SetUp() {
58     gl1_.Initialize(GLManager::Options());
59     GLManager::Options options;
60     options.share_mailbox_manager = &gl1_;
61     gl2_.Initialize(options);
62   }
63 
TearDown()64   virtual void TearDown() {
65     gl1_.Destroy();
66     gl2_.Destroy();
67   }
68 
69   GLManager gl1_;
70   GLManager gl2_;
71 };
72 
TEST_F(GLTextureMailboxTest,ProduceAndConsumeTexture)73 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTexture) {
74   gl1_.MakeCurrent();
75 
76   GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM];
77   glGenMailboxCHROMIUM(mailbox1);
78 
79   GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM];
80   glGenMailboxCHROMIUM(mailbox2);
81 
82   GLuint tex1;
83   glGenTextures(1, &tex1);
84 
85   glBindTexture(GL_TEXTURE_2D, tex1);
86   uint32 source_pixel = 0xFF0000FF;
87   glTexImage2D(GL_TEXTURE_2D,
88                0,
89                GL_RGBA,
90                1, 1,
91                0,
92                GL_RGBA,
93                GL_UNSIGNED_BYTE,
94                &source_pixel);
95 
96   glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1);
97   glFlush();
98 
99   gl2_.MakeCurrent();
100 
101   GLuint tex2;
102   glGenTextures(1, &tex2);
103 
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);
108   glFlush();
109 
110   gl1_.MakeCurrent();
111 
112   glBindTexture(GL_TEXTURE_2D, tex1);
113   glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2);
114   EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0));
115 }
116 
TEST_F(GLTextureMailboxTest,ProduceAndConsumeTextureRGB)117 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTextureRGB) {
118   gl1_.MakeCurrent();
119 
120   GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM];
121   glGenMailboxCHROMIUM(mailbox1);
122 
123   GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM];
124   glGenMailboxCHROMIUM(mailbox2);
125 
126   GLuint tex1;
127   glGenTextures(1, &tex1);
128 
129   glBindTexture(GL_TEXTURE_2D, tex1);
130   uint32 source_pixel = 0xFF000000;
131   glTexImage2D(GL_TEXTURE_2D,
132                0,
133                GL_RGB,
134                1, 1,
135                0,
136                GL_RGB,
137                GL_UNSIGNED_BYTE,
138                &source_pixel);
139 
140   glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1);
141   glFlush();
142 
143   gl2_.MakeCurrent();
144 
145   GLuint tex2;
146   glGenTextures(1, &tex2);
147 
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);
152   glFlush();
153 
154   gl1_.MakeCurrent();
155 
156   glBindTexture(GL_TEXTURE_2D, tex1);
157   glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2);
158   EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0));
159 }
160 
TEST_F(GLTextureMailboxTest,ProduceAndConsumeTextureDirect)161 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTextureDirect) {
162   gl1_.MakeCurrent();
163 
164   GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM];
165   glGenMailboxCHROMIUM(mailbox1);
166 
167   GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM];
168   glGenMailboxCHROMIUM(mailbox2);
169 
170   GLuint tex1;
171   glGenTextures(1, &tex1);
172 
173   glBindTexture(GL_TEXTURE_2D, tex1);
174   uint32 source_pixel = 0xFF0000FF;
175   glTexImage2D(GL_TEXTURE_2D,
176                0,
177                GL_RGBA,
178                1, 1,
179                0,
180                GL_RGBA,
181                GL_UNSIGNED_BYTE,
182                &source_pixel);
183 
184   glProduceTextureDirectCHROMIUM(tex1, GL_TEXTURE_2D, mailbox1);
185   glFlush();
186 
187   gl2_.MakeCurrent();
188 
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);
193   glFlush();
194 
195   gl1_.MakeCurrent();
196 
197   GLuint tex3 = glCreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2);
198   glBindTexture(GL_TEXTURE_2D, tex3);
199   EXPECT_EQ(source_pixel, ReadTexel(tex3, 0, 0));
200 }
201 
TEST_F(GLTextureMailboxTest,ConsumeTextureValidatesKey)202 TEST_F(GLTextureMailboxTest, ConsumeTextureValidatesKey) {
203   GLuint tex;
204   glGenTextures(1, &tex);
205 
206   glBindTexture(GL_TEXTURE_2D, tex);
207   uint32 source_pixel = 0xFF0000FF;
208   glTexImage2D(GL_TEXTURE_2D,
209                0,
210                GL_RGBA,
211                1, 1,
212                0,
213                GL_RGBA,
214                GL_UNSIGNED_BYTE,
215                &source_pixel);
216 
217   GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM];
218   glGenMailboxCHROMIUM(invalid_mailbox);
219 
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());
223 
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());
228 }
229 
TEST_F(GLTextureMailboxTest,SharedTextures)230 TEST_F(GLTextureMailboxTest, SharedTextures) {
231   gl1_.MakeCurrent();
232   GLuint tex1;
233   glGenTextures(1, &tex1);
234 
235   glBindTexture(GL_TEXTURE_2D, tex1);
236   uint32 source_pixel = 0xFF0000FF;
237   glTexImage2D(GL_TEXTURE_2D,
238                0,
239                GL_RGBA,
240                1, 1,
241                0,
242                GL_RGBA,
243                GL_UNSIGNED_BYTE,
244                &source_pixel);
245   GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
246   glGenMailboxCHROMIUM(mailbox);
247 
248   glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
249   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
250   glFlush();
251 
252   gl2_.MakeCurrent();
253   GLuint tex2;
254   glGenTextures(1, &tex2);
255 
256   glBindTexture(GL_TEXTURE_2D, tex2);
257   glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox);
258   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
259 
260   // Change texture in context 2.
261   source_pixel = 0xFF00FF00;
262   glTexSubImage2D(GL_TEXTURE_2D,
263                   0,
264                   0, 0,
265                   1, 1,
266                   GL_RGBA,
267                   GL_UNSIGNED_BYTE,
268                   &source_pixel);
269   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
270   glFlush();
271 
272   // Check it in context 1.
273   gl1_.MakeCurrent();
274   EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0));
275   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
276 
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());
283   glFlush();
284 
285   // Check in context 2.
286   gl2_.MakeCurrent();
287   GLint parameter = 0;
288   glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &parameter);
289   EXPECT_EQ(GL_REPEAT, parameter);
290   parameter = 0;
291   glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &parameter);
292   EXPECT_EQ(GL_LINEAR, parameter);
293   parameter = 0;
294   glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &parameter);
295   EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST, parameter);
296 
297   // Delete texture in context 1.
298   gl1_.MakeCurrent();
299   glDeleteTextures(1, &tex1);
300   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
301 
302   // Check texture still exists in context 2.
303   gl2_.MakeCurrent();
304   EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0));
305   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
306 
307   // The mailbox should still exist too.
308   GLuint tex3;
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());
313 
314   // Delete both textures.
315   glDeleteTextures(1, &tex2);
316   glDeleteTextures(1, &tex3);
317   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
318 
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());
326 }
327 
TEST_F(GLTextureMailboxTest,ProduceFrontBuffer)328 TEST_F(GLTextureMailboxTest, ProduceFrontBuffer) {
329   gl1_.MakeCurrent();
330   Mailbox mailbox;
331   glGenMailboxCHROMIUM(mailbox.name);
332 
333   gl2_.MakeCurrent();
334   gl2_.decoder()->ProduceFrontBuffer(mailbox);
335 
336   gl1_.MakeCurrent();
337   GLuint tex1;
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());
342 
343   gl2_.MakeCurrent();
344   glResizeCHROMIUM(10, 10, 1);
345   glClearColor(1, 0, 0, 1);
346   glClear(GL_COLOR_BUFFER_BIT);
347   ::gles2::GetGLContext()->SwapBuffers();
348 
349   gl1_.MakeCurrent();
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());
353 
354   gl2_.MakeCurrent();
355   glClearColor(0, 1, 0, 1);
356   glClear(GL_COLOR_BUFFER_BIT);
357   glFlush();
358 
359   gl1_.MakeCurrent();
360   EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 0, 0));
361 
362   gl2_.MakeCurrent();
363   ::gles2::GetGLContext()->SwapBuffers();
364 
365   gl1_.MakeCurrent();
366   EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0));
367 
368   gl2_.MakeCurrent();
369   gl2_.Destroy();
370 
371   gl1_.MakeCurrent();
372   EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0));
373   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
374   glDeleteTextures(1, &tex1);
375 }
376 
TEST_F(GLTextureMailboxTest,ProduceTextureDirectInvalidTarget)377 TEST_F(GLTextureMailboxTest, ProduceTextureDirectInvalidTarget) {
378   gl1_.MakeCurrent();
379 
380   GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM];
381   glGenMailboxCHROMIUM(mailbox1);
382 
383   GLuint tex1;
384   glGenTextures(1, &tex1);
385 
386   glBindTexture(GL_TEXTURE_CUBE_MAP, tex1);
387   uint32 source_pixel = 0xFF0000FF;
388   glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
389                0,
390                GL_RGBA,
391                1, 1,
392                0,
393                GL_RGBA,
394                GL_UNSIGNED_BYTE,
395                &source_pixel);
396 
397   glProduceTextureDirectCHROMIUM(tex1, GL_TEXTURE_2D, mailbox1);
398   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
399 }
400 
401 // http://crbug.com/281565
402 #if !defined(OS_ANDROID)
TEST_F(GLTextureMailboxTest,ProduceFrontBufferMultipleContexts)403 TEST_F(GLTextureMailboxTest, ProduceFrontBufferMultipleContexts) {
404   gl1_.MakeCurrent();
405   Mailbox mailbox[2];
406   glGenMailboxCHROMIUM(mailbox[0].name);
407   glGenMailboxCHROMIUM(mailbox[1].name);
408   GLuint tex[2];
409   glGenTextures(2, tex);
410 
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;
421   }
422 
423 
424   gl1_.MakeCurrent();
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());
429   }
430 
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();
437   }
438 
439   gl1_.MakeCurrent();
440   EXPECT_EQ(0xFF0000FFu, ReadTexel(tex[0], 0, 0));
441   EXPECT_EQ(0xFF00FF00u, ReadTexel(tex[1], 9, 9));
442 
443   for (size_t i = 0; i < 2; ++i) {
444     other_gl[i].MakeCurrent();
445     other_gl[i].Destroy();
446   }
447 
448   gl1_.MakeCurrent();
449   glDeleteTextures(2, tex);
450 }
451 #endif
452 
453 }  // namespace gpu
454 
455