OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include <GLES2/gl2.h> | |
6 #include <GLES2/gl2chromium.h> | |
7 #include <GLES2/gl2ext.h> | |
8 #include <GLES2/gl2extchromium.h> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/process/process_handle.h" | |
13 #include "gpu/command_buffer/client/gles2_implementation.h" | |
14 #include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" | |
15 #include "gpu/command_buffer/service/command_buffer_service.h" | |
16 #include "gpu/command_buffer/service/image_manager.h" | |
17 #include "gpu/command_buffer/tests/gl_manager.h" | |
18 #include "gpu/command_buffer/tests/gl_test_utils.h" | |
19 #include "testing/gmock/include/gmock/gmock.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 #include "ui/gl/gl_image.h" | |
22 | |
23 using testing::_; | |
24 using testing::IgnoreResult; | |
25 using testing::InvokeWithoutArgs; | |
26 using testing::Invoke; | |
27 using testing::Return; | |
28 using testing::SetArgPointee; | |
29 using testing::StrictMock; | |
30 | |
31 namespace gpu { | |
32 namespace gles2 { | |
33 | |
34 static const int kImageWidth = 32; | |
35 static const int kImageHeight = 32; | |
36 static const int kImageBytesPerPixel = 4; | |
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, size_t, unsigned)); | |
63 | |
64 private: | |
65 DISALLOW_COPY_AND_ASSIGN(MockGpuMemoryBufferFactory); | |
66 }; | |
67 | |
68 class MockGpuMemoryBufferTest : public testing::Test { | |
69 protected: | |
70 virtual void SetUp() { | |
71 GLManager::Options options; | |
72 image_manager_ = new ImageManager; | |
73 gpu_memory_buffer_factory_.reset(new MockGpuMemoryBufferFactory); | |
74 options.image_manager = image_manager_.get(); | |
75 options.gpu_memory_buffer_factory = gpu_memory_buffer_factory_.get(); | |
76 | |
77 gl_.Initialize(options); | |
78 gl_.MakeCurrent(); | |
79 | |
80 glGenTextures(2, texture_ids_); | |
81 glBindTexture(GL_TEXTURE_2D, texture_ids_[1]); | |
82 | |
83 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
84 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
85 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
86 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
87 | |
88 glGenFramebuffers(1, &framebuffer_id_); | |
89 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_); | |
90 glFramebufferTexture2D(GL_FRAMEBUFFER, | |
91 GL_COLOR_ATTACHMENT0, | |
92 GL_TEXTURE_2D, | |
93 texture_ids_[1], | |
94 0); | |
95 } | |
96 | |
97 virtual void TearDown() { | |
98 glDeleteTextures(2, texture_ids_); | |
99 glDeleteFramebuffers(1, &framebuffer_id_); | |
100 | |
101 gl_.Destroy(); | |
102 } | |
103 | |
104 scoped_refptr<ImageManager> image_manager_; | |
105 scoped_ptr<MockGpuMemoryBufferFactory> gpu_memory_buffer_factory_; | |
106 GLManager gl_; | |
107 GLuint texture_ids_[2]; | |
108 GLuint framebuffer_id_; | |
109 }; | |
110 | |
111 // An end to end test that tests the whole GpuMemoryBuffer lifecycle. | |
112 TEST_F(MockGpuMemoryBufferTest, Lifecycle) { | |
113 size_t bytes = kImageWidth * kImageHeight * kImageBytesPerPixel; | |
114 uint8 pixels[1 * 4] = { 255u, 0u, 0u, 255u }; | |
115 | |
116 // Buffer is owned and freed by GpuMemoryBufferTracker. | |
117 StrictMock<MockGpuMemoryBuffer>* gpu_memory_buffer = | |
118 new StrictMock<MockGpuMemoryBuffer>(kImageWidth, kImageHeight); | |
119 base::SharedMemory shared_memory; | |
120 shared_memory.CreateAnonymous(bytes); | |
121 | |
122 base::SharedMemoryHandle duped_shared_memory_handle; | |
123 shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), | |
124 &duped_shared_memory_handle); | |
125 gfx::GpuMemoryBufferHandle handle; | |
126 handle.type = gfx::SHARED_MEMORY_BUFFER; | |
127 handle.handle = duped_shared_memory_handle; | |
128 | |
129 EXPECT_CALL(*gpu_memory_buffer_factory_.get(), CreateGpuMemoryBuffer( | |
130 kImageWidth, kImageHeight, GL_RGBA8_OES)) | |
131 .Times(1) | |
132 .WillOnce(Return(gpu_memory_buffer)) | |
133 .RetiresOnSaturation(); | |
134 EXPECT_CALL(*gpu_memory_buffer, GetHandle()) | |
135 .Times(1) | |
136 .WillOnce(Return(handle)) | |
137 .RetiresOnSaturation(); | |
138 | |
139 // Create the image. This should add the image ID to the ImageManager. | |
140 GLuint image_id = glCreateImageCHROMIUM( | |
141 kImageWidth, kImageHeight, GL_RGBA8_OES); | |
142 EXPECT_NE(0u, image_id); | |
143 EXPECT_TRUE(image_manager_->LookupImage(image_id) != NULL); | |
144 | |
145 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) | |
146 .WillOnce(Return(false)) | |
147 .RetiresOnSaturation(); | |
148 | |
149 shared_memory.Map(bytes); | |
150 EXPECT_TRUE(shared_memory.memory()); | |
151 | |
152 EXPECT_CALL(*gpu_memory_buffer, Map(_, _)) | |
153 .Times(1) | |
154 .WillOnce(SetArgPointee<1>(shared_memory.memory())) | |
155 .RetiresOnSaturation(); | |
156 uint8* mapped_buffer = static_cast<uint8*>( | |
157 glMapImageCHROMIUM(image_id, GL_READ_WRITE)); | |
158 ASSERT_TRUE(mapped_buffer != NULL); | |
159 | |
160 // Assign a value to each pixel. | |
161 int stride = kImageWidth * kImageBytesPerPixel; | |
162 for (int x = 0; x < kImageWidth; ++x) { | |
163 for (int y = 0; y < kImageHeight; ++y) { | |
164 mapped_buffer[y * stride + x * kImageBytesPerPixel + 0] = pixels[0]; | |
165 mapped_buffer[y * stride + x * kImageBytesPerPixel + 1] = pixels[1]; | |
166 mapped_buffer[y * stride + x * kImageBytesPerPixel + 2] = pixels[2]; | |
167 mapped_buffer[y * stride + x * kImageBytesPerPixel + 3] = pixels[3]; | |
168 } | |
169 } | |
170 | |
171 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) | |
172 .WillOnce(Return(true)) | |
173 .RetiresOnSaturation(); | |
174 | |
175 // Unmap the image. | |
176 EXPECT_CALL(*gpu_memory_buffer, Unmap()) | |
177 .Times(1) | |
178 .RetiresOnSaturation(); | |
179 glUnmapImageCHROMIUM(image_id); | |
180 | |
181 // Bind the texture and the image. | |
182 glBindTexture(GL_TEXTURE_2D, texture_ids_[0]); | |
183 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); | |
184 | |
185 // Copy texture so we can verify result using CheckPixels. | |
186 glCopyTextureCHROMIUM(GL_TEXTURE_2D, | |
187 texture_ids_[0], | |
188 texture_ids_[1], | |
189 0, | |
190 GL_RGBA, | |
191 GL_UNSIGNED_BYTE); | |
192 EXPECT_TRUE(glGetError() == GL_NO_ERROR); | |
193 | |
194 // Check if pixels match the values that were assigned to the mapped buffer. | |
195 GLTestHelper::CheckPixels(0, 0, kImageWidth, kImageHeight, 0, pixels); | |
196 EXPECT_TRUE(GL_NO_ERROR == glGetError()); | |
197 | |
198 // Release the image. | |
199 glReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); | |
200 | |
201 // Destroy the image. | |
202 EXPECT_CALL(*gpu_memory_buffer, Die()) | |
203 .Times(1) | |
204 .RetiresOnSaturation(); | |
205 glDestroyImageCHROMIUM(image_id); | |
206 } | |
207 | |
208 } // namespace gles2 | |
209 } // namespace gpu | |
OLD | NEW |