OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <GLES2/gl2.h> | 5 #include <GLES2/gl2.h> |
6 #include <GLES2/gl2chromium.h> | 6 #include <GLES2/gl2chromium.h> |
7 #include <GLES2/gl2ext.h> | 7 #include <GLES2/gl2ext.h> |
8 #include <GLES2/gl2extchromium.h> | 8 #include <GLES2/gl2extchromium.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/process_util.h" |
12 #include "gpu/command_buffer/client/gles2_implementation.h" | 13 #include "gpu/command_buffer/client/gles2_implementation.h" |
13 #include "gpu/command_buffer/client/gpu_memory_buffer_mock.h" | 14 #include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" |
14 #include "gpu/command_buffer/client/image_factory_mock.h" | 15 #include "gpu/command_buffer/service/command_buffer_service.h" |
15 #include "gpu/command_buffer/service/image_manager.h" | 16 #include "gpu/command_buffer/service/image_manager.h" |
16 #include "gpu/command_buffer/tests/gl_manager.h" | 17 #include "gpu/command_buffer/tests/gl_manager.h" |
17 #include "gpu/command_buffer/tests/gl_test_utils.h" | 18 #include "gpu/command_buffer/tests/gl_test_utils.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "ui/gfx/native_widget_types.h" | |
21 #include "ui/gl/gl_image.h" | 21 #include "ui/gl/gl_image.h" |
22 #include "ui/gl/gl_image_mock.h" | |
23 | 22 |
24 using testing::_; | 23 using testing::_; |
25 using testing::IgnoreResult; | 24 using testing::IgnoreResult; |
26 using testing::InvokeWithoutArgs; | 25 using testing::InvokeWithoutArgs; |
27 using testing::Invoke; | 26 using testing::Invoke; |
28 using testing::Return; | 27 using testing::Return; |
29 using testing::SetArgPointee; | 28 using testing::SetArgPointee; |
30 using testing::StrictMock; | 29 using testing::StrictMock; |
31 | 30 |
32 namespace gpu { | 31 namespace gpu { |
33 namespace gles2 { | 32 namespace gles2 { |
34 | 33 |
35 static const int kImageWidth = 256; | 34 static const int kImageWidth = 32; |
36 static const int kImageHeight = 256; | 35 static const int kImageHeight = 32; |
37 static const int kImageBytesPerPixel = 4; | 36 static const int kImageBytesPerPixel = 4; |
38 | 37 |
| 38 class MockGpuMemoryBuffer : public gfx::GpuMemoryBuffer { |
| 39 public: |
| 40 MockGpuMemoryBuffer(int width, int height) {} |
| 41 virtual ~MockGpuMemoryBuffer() { |
| 42 Die(); |
| 43 } |
| 44 |
| 45 MOCK_METHOD2(Map, void(gfx::GpuMemoryBuffer::AccessMode, void**)); |
| 46 MOCK_METHOD0(Unmap, void()); |
| 47 MOCK_CONST_METHOD0(IsMapped, bool()); |
| 48 MOCK_CONST_METHOD0(GetStride, uint32()); |
| 49 MOCK_CONST_METHOD0(GetHandle, gfx::GpuMemoryBufferHandle()); |
| 50 MOCK_METHOD0(Die, void()); |
| 51 |
| 52 private: |
| 53 DISALLOW_COPY_AND_ASSIGN(MockGpuMemoryBuffer); |
| 54 }; |
| 55 |
| 56 class MockGpuMemoryBufferFactory : public GpuMemoryBufferFactory { |
| 57 public: |
| 58 MockGpuMemoryBufferFactory() {} |
| 59 virtual ~MockGpuMemoryBufferFactory() {} |
| 60 |
| 61 MOCK_METHOD3(CreateGpuMemoryBuffer, |
| 62 gfx::GpuMemoryBuffer*(size_t width, |
| 63 size_t height, |
| 64 unsigned internalformat)); |
| 65 |
| 66 private: |
| 67 DISALLOW_COPY_AND_ASSIGN(MockGpuMemoryBufferFactory); |
| 68 }; |
| 69 |
39 class MockGpuMemoryBufferTest : public testing::Test { | 70 class MockGpuMemoryBufferTest : public testing::Test { |
40 protected: | 71 protected: |
41 virtual void SetUp() { | 72 virtual void SetUp() { |
42 GLManager::Options options; | 73 GLManager::Options options; |
43 image_manager_ = new ImageManager; | 74 image_manager_ = new ImageManager; |
44 image_factory_.reset( | 75 gpu_memory_buffer_factory_.reset(new MockGpuMemoryBufferFactory); |
45 new StrictMock<ImageFactoryMock>(image_manager_.get())); | |
46 options.image_manager = image_manager_.get(); | 76 options.image_manager = image_manager_.get(); |
47 options.image_factory = image_factory_.get(); | 77 options.gpu_memory_buffer_factory = gpu_memory_buffer_factory_.get(); |
48 | 78 |
49 gl_.Initialize(options); | 79 gl_.Initialize(options); |
50 gl_.MakeCurrent(); | 80 gl_.MakeCurrent(); |
| 81 |
| 82 glGenTextures(2, texture_ids_); |
| 83 glBindTexture(GL_TEXTURE_2D, texture_ids_[1]); |
| 84 |
| 85 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 86 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 89 |
| 90 glGenFramebuffers(1, &framebuffer_id_); |
| 91 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_); |
| 92 glFramebufferTexture2D(GL_FRAMEBUFFER, |
| 93 GL_COLOR_ATTACHMENT0, |
| 94 GL_TEXTURE_2D, |
| 95 texture_ids_[1], |
| 96 0); |
51 } | 97 } |
52 | 98 |
53 virtual void TearDown() { | 99 virtual void TearDown() { |
| 100 glDeleteTextures(2, texture_ids_); |
| 101 glDeleteFramebuffers(1, &framebuffer_id_); |
| 102 |
54 gl_.Destroy(); | 103 gl_.Destroy(); |
55 } | 104 } |
56 | 105 |
57 scoped_ptr<StrictMock<ImageFactoryMock> > image_factory_; | |
58 scoped_refptr<ImageManager> image_manager_; | 106 scoped_refptr<ImageManager> image_manager_; |
| 107 scoped_ptr<MockGpuMemoryBufferFactory> gpu_memory_buffer_factory_; |
59 GLManager gl_; | 108 GLManager gl_; |
| 109 GLuint texture_ids_[2]; |
| 110 GLuint framebuffer_id_; |
60 }; | 111 }; |
61 | 112 |
62 // An end to end test that tests the whole GpuMemoryBuffer lifecycle. | 113 // An end to end test that tests the whole GpuMemoryBuffer lifecycle. |
63 TEST_F(MockGpuMemoryBufferTest, Lifecycle) { | 114 TEST_F(MockGpuMemoryBufferTest, Lifecycle) { |
64 // Create a client texture id. | 115 size_t bytes = kImageWidth * kImageHeight * kImageBytesPerPixel; |
65 GLuint texture_id; | 116 uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u }; |
66 glGenTextures(1, &texture_id); | |
67 | 117 |
68 // Buffer is owned and freed by GpuMemoryBufferTracker. | 118 // Buffer is owned and freed by GpuMemoryBufferTracker. |
69 StrictMock<GpuMemoryBufferMock>* gpu_memory_buffer = | 119 StrictMock<MockGpuMemoryBuffer>* gpu_memory_buffer = |
70 new StrictMock<GpuMemoryBufferMock>(kImageWidth, kImageHeight); | 120 new StrictMock<MockGpuMemoryBuffer>(kImageWidth, kImageHeight); |
| 121 base::SharedMemory shared_memory; |
| 122 shared_memory.CreateAnonymous(bytes); |
71 | 123 |
72 const GLuint kImageId = 345u; | 124 base::SharedMemoryHandle duped_shared_memory_handle; |
| 125 shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), |
| 126 &duped_shared_memory_handle); |
| 127 gfx::GpuMemoryBufferHandle handle( |
| 128 duped_shared_memory_handle, gfx::SHARED_MEMORY_BUFFER); |
73 | 129 |
74 EXPECT_CALL(*image_factory_.get(), CreateGpuMemoryBufferMock( | 130 EXPECT_CALL(*gpu_memory_buffer_factory_.get(), CreateGpuMemoryBuffer( |
75 kImageWidth, kImageHeight, GL_RGBA8_OES, _)) | 131 kImageWidth, kImageHeight, GL_RGBA8_OES)) |
76 .Times(1) | 132 .Times(1) |
77 .WillOnce(DoAll(SetArgPointee<3>(kImageId), | 133 .WillOnce(Return(gpu_memory_buffer)) |
78 Return(gpu_memory_buffer))) | 134 .RetiresOnSaturation(); |
| 135 EXPECT_CALL(*gpu_memory_buffer, GetHandle()) |
| 136 .Times(1) |
| 137 .WillOnce(Return(handle)) |
79 .RetiresOnSaturation(); | 138 .RetiresOnSaturation(); |
80 | 139 |
81 // Create the GLImage and insert it into the ImageManager, which | 140 // Create the image. This should add the image ID to the ImageManager. |
82 // would be done within CreateGpuMemoryBufferMock if it weren't a mock. | |
83 GLuint image_id = glCreateImageCHROMIUM( | 141 GLuint image_id = glCreateImageCHROMIUM( |
84 kImageWidth, kImageHeight, GL_RGBA8_OES); | 142 kImageWidth, kImageHeight, GL_RGBA8_OES); |
85 EXPECT_EQ(kImageId, image_id); | 143 EXPECT_NE(0u, image_id); |
86 | 144 EXPECT_TRUE(image_manager_->LookupImage(image_id) != NULL); |
87 gfx::Size size(kImageWidth, kImageHeight); | |
88 scoped_refptr<gfx::GLImageMock> gl_image( | |
89 new gfx::GLImageMock(gpu_memory_buffer, size)); | |
90 image_manager_->AddImage(gl_image.get(), image_id); | |
91 | 145 |
92 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) | 146 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) |
93 .WillOnce(Return(false)) | 147 .WillOnce(Return(false)) |
94 .RetiresOnSaturation(); | 148 .RetiresOnSaturation(); |
95 | 149 |
96 scoped_ptr<uint8[]> buffer_pixels(new uint8[ | 150 shared_memory.Map(bytes); |
97 kImageWidth * kImageHeight * kImageBytesPerPixel]); | 151 EXPECT_TRUE(shared_memory.memory()); |
98 | 152 |
99 EXPECT_CALL(*gpu_memory_buffer, Map(_, _)) | 153 EXPECT_CALL(*gpu_memory_buffer, Map(_, _)) |
100 .Times(1) | 154 .Times(1) |
101 .WillOnce(SetArgPointee<1>(buffer_pixels.get())) | 155 .WillOnce(SetArgPointee<1>(shared_memory.memory())) |
102 .RetiresOnSaturation(); | 156 .RetiresOnSaturation(); |
103 void* mapped_buffer = | 157 uint8* mapped_buffer = static_cast<uint8*>( |
104 glMapImageCHROMIUM(image_id, GL_WRITE_ONLY); | 158 glMapImageCHROMIUM(image_id, GL_WRITE_ONLY)); |
105 EXPECT_EQ(buffer_pixels.get(), mapped_buffer); | 159 ASSERT_TRUE(mapped_buffer != NULL); |
| 160 |
| 161 // Assign a value to each pixel. |
| 162 int stride = kImageWidth * kImageBytesPerPixel; |
| 163 for (int x = 0; x < kImageWidth; ++x) { |
| 164 for (int y = 0; y < kImageHeight; ++y) { |
| 165 mapped_buffer[y * stride + x * kImageBytesPerPixel + 0] = pixels[2]; |
| 166 mapped_buffer[y * stride + x * kImageBytesPerPixel + 1] = pixels[1]; |
| 167 mapped_buffer[y * stride + x * kImageBytesPerPixel + 2] = pixels[0]; |
| 168 mapped_buffer[y * stride + x * kImageBytesPerPixel + 3] = pixels[3]; |
| 169 } |
| 170 } |
106 | 171 |
107 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) | 172 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) |
108 .WillOnce(Return(true)) | 173 .WillOnce(Return(true)) |
109 .RetiresOnSaturation(); | 174 .RetiresOnSaturation(); |
110 | 175 |
111 // Unmap the image. | 176 // Unmap the image. |
112 EXPECT_CALL(*gpu_memory_buffer, Unmap()) | 177 EXPECT_CALL(*gpu_memory_buffer, Unmap()) |
113 .Times(1) | 178 .Times(1) |
114 .RetiresOnSaturation(); | 179 .RetiresOnSaturation(); |
115 glUnmapImageCHROMIUM(image_id); | 180 glUnmapImageCHROMIUM(image_id); |
116 | 181 |
117 // Bind the texture and the image. | 182 // Bind the texture and the image. |
118 glBindTexture(GL_TEXTURE_2D, texture_id); | 183 glBindTexture(GL_TEXTURE_2D, texture_ids_[0]); |
119 EXPECT_CALL(*gl_image.get(), BindTexImage()).Times(1).WillOnce(Return(true)) | |
120 .RetiresOnSaturation(); | |
121 EXPECT_CALL(*gl_image.get(), GetSize()).Times(1).WillOnce(Return(size)) | |
122 .RetiresOnSaturation(); | |
123 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); | 184 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); |
124 | 185 |
| 186 // Copy texture so we can verify result using CheckPixels. |
| 187 glCopyTextureCHROMIUM(GL_TEXTURE_2D, |
| 188 texture_ids_[0], |
| 189 texture_ids_[1], |
| 190 0, |
| 191 GL_RGBA, |
| 192 GL_UNSIGNED_BYTE); |
| 193 EXPECT_TRUE(glGetError() == GL_NO_ERROR); |
| 194 |
| 195 // Check if pixels match the values that were assigned to the mapped buffer. |
| 196 GLTestHelper::CheckPixels(0, 0, kImageWidth, kImageHeight, 0, pixels); |
| 197 EXPECT_TRUE(GL_NO_ERROR == glGetError()); |
| 198 |
| 199 // Release the image. |
| 200 glReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); |
| 201 |
125 // Destroy the image. | 202 // Destroy the image. |
126 EXPECT_CALL(*gpu_memory_buffer, Die()) | 203 EXPECT_CALL(*gpu_memory_buffer, Die()) |
127 .Times(1) | 204 .Times(1) |
128 .RetiresOnSaturation(); | 205 .RetiresOnSaturation(); |
129 | |
130 EXPECT_CALL(*image_factory_.get(), DeleteGpuMemoryBuffer(image_id)) | |
131 .Times(1) | |
132 .RetiresOnSaturation(); | |
133 | |
134 glDestroyImageCHROMIUM(image_id); | 206 glDestroyImageCHROMIUM(image_id); |
135 | |
136 // Delete the texture. | |
137 glDeleteTextures(1, &texture_id); | |
138 } | 207 } |
139 | 208 |
140 } // namespace gles2 | 209 } // namespace gles2 |
141 } // namespace gpu | 210 } // namespace gpu |
OLD | NEW |