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.
6 #include <GLES2/gl2chromium.h>
7 #include <GLES2/gl2ext.h>
8 #include <GLES2/gl2extchromium.h>
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/service/image_manager.h"
15 #include "gpu/command_buffer/tests/gl_manager.h"
16 #include "gpu/command_buffer/tests/gl_test_utils.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/gl/gl_image.h"
22 using testing::IgnoreResult
;
23 using testing::InvokeWithoutArgs
;
24 using testing::Invoke
;
25 using testing::Return
;
26 using testing::SetArgPointee
;
27 using testing::StrictMock
;
32 static const int kImageWidth
= 32;
33 static const int kImageHeight
= 32;
34 static const int kImageBytesPerPixel
= 4;
36 class MockGpuMemoryBuffer
: public gfx::GpuMemoryBuffer
{
38 MockGpuMemoryBuffer(int width
, int height
) {}
39 virtual ~MockGpuMemoryBuffer() {
43 MOCK_METHOD2(Map
, void(gfx::GpuMemoryBuffer::AccessMode
, void**));
44 MOCK_METHOD0(Unmap
, void());
45 MOCK_CONST_METHOD0(IsMapped
, bool());
46 MOCK_CONST_METHOD0(GetStride
, uint32());
47 MOCK_CONST_METHOD0(GetHandle
, gfx::GpuMemoryBufferHandle());
48 MOCK_METHOD0(Die
, void());
51 DISALLOW_COPY_AND_ASSIGN(MockGpuMemoryBuffer
);
54 class MockImageFactory
: public ImageFactory
{
56 MockImageFactory(ImageManager
* image_manager
) {}
57 virtual ~MockImageFactory() {}
59 MOCK_METHOD4(CreateGpuMemoryBufferMock
, gfx::GpuMemoryBuffer
*(
60 int width
, int height
, GLenum internalformat
, unsigned* image_id
));
61 MOCK_METHOD1(DeleteGpuMemoryBuffer
, void(unsigned));
62 // Workaround for mocking methods that return scoped_ptrs
63 virtual scoped_ptr
<gfx::GpuMemoryBuffer
> CreateGpuMemoryBuffer(
64 int width
, int height
, GLenum internalformat
,
65 unsigned* image_id
) OVERRIDE
{
66 return scoped_ptr
<gfx::GpuMemoryBuffer
>(CreateGpuMemoryBufferMock(
67 width
, height
, internalformat
, image_id
));
71 DISALLOW_COPY_AND_ASSIGN(MockImageFactory
);
74 class MockGpuMemoryBufferTest
: public testing::Test
{
76 virtual void SetUp() {
77 GLManager::Options options
;
78 image_manager_
= new ImageManager
;
80 new StrictMock
<MockImageFactory
>(image_manager_
.get()));
81 options
.image_manager
= image_manager_
.get();
82 options
.image_factory
= image_factory_
.get();
84 gl_
.Initialize(options
);
87 glGenTextures(2, texture_ids_
);
88 glBindTexture(GL_TEXTURE_2D
, texture_ids_
[1]);
90 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
91 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
92 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
93 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
95 glGenFramebuffers(1, &framebuffer_id_
);
96 glBindFramebuffer(GL_FRAMEBUFFER
, framebuffer_id_
);
97 glFramebufferTexture2D(GL_FRAMEBUFFER
,
104 virtual void TearDown() {
105 glDeleteTextures(2, texture_ids_
);
106 glDeleteFramebuffers(1, &framebuffer_id_
);
111 scoped_ptr
<StrictMock
<MockImageFactory
> > image_factory_
;
112 scoped_refptr
<ImageManager
> image_manager_
;
114 GLuint texture_ids_
[2];
115 GLuint framebuffer_id_
;
118 // An end to end test that tests the whole GpuMemoryBuffer lifecycle.
119 TEST_F(MockGpuMemoryBufferTest
, Lifecycle
) {
120 size_t bytes
= kImageWidth
* kImageHeight
* kImageBytesPerPixel
;
121 uint8 pixels
[1 * 4] = { 255u, 0u, 0u, 255u };
123 // Buffer is owned and freed by GpuMemoryBufferTracker.
124 StrictMock
<MockGpuMemoryBuffer
>* gpu_memory_buffer
=
125 new StrictMock
<MockGpuMemoryBuffer
>(kImageWidth
, kImageHeight
);
126 base::SharedMemory shared_memory
;
127 shared_memory
.CreateAnonymous(bytes
);
129 base::SharedMemoryHandle duped_shared_memory_handle
;
130 shared_memory
.ShareToProcess(base::GetCurrentProcessHandle(),
131 &duped_shared_memory_handle
);
132 gfx::GpuMemoryBufferHandle handle
;
133 handle
.type
= gfx::SHARED_MEMORY_BUFFER
;
134 handle
.handle
= duped_shared_memory_handle
;
136 const GLuint kImageId
= 345u;
138 EXPECT_CALL(*image_factory_
.get(), CreateGpuMemoryBufferMock(
139 kImageWidth
, kImageHeight
, GL_RGBA8_OES
, _
))
141 .WillOnce(DoAll(SetArgPointee
<3>(kImageId
), Return(gpu_memory_buffer
)))
142 .RetiresOnSaturation();
144 // Create the GLImage and insert it into the ImageManager, which
145 // would be done within CreateGpuMemoryBufferMock if it weren't a mock.
146 GLuint image_id
= glCreateImageCHROMIUM(
147 kImageWidth
, kImageHeight
, GL_RGBA8_OES
);
148 EXPECT_EQ(kImageId
, image_id
);
150 EXPECT_CALL(*gpu_memory_buffer
, GetHandle())
151 .WillOnce(Return(handle
))
152 .RetiresOnSaturation();
154 gfx::Size
size(kImageWidth
, kImageHeight
);
155 scoped_refptr
<gfx::GLImage
> gl_image(
156 gfx::GLImage::CreateGLImageForGpuMemoryBuffer(
157 gpu_memory_buffer
->GetHandle(), size
));
158 image_manager_
->AddImage(gl_image
.get(), image_id
);
160 EXPECT_CALL(*gpu_memory_buffer
, IsMapped())
161 .WillOnce(Return(false))
162 .RetiresOnSaturation();
164 shared_memory
.Map(bytes
);
165 EXPECT_TRUE(shared_memory
.memory());
167 EXPECT_CALL(*gpu_memory_buffer
, Map(_
, _
))
169 .WillOnce(SetArgPointee
<1>(shared_memory
.memory()))
170 .RetiresOnSaturation();
171 uint8
* mapped_buffer
= static_cast<uint8
*>(
172 glMapImageCHROMIUM(image_id
, GL_READ_WRITE
));
173 ASSERT_TRUE(mapped_buffer
!= NULL
);
175 // Assign a value to each pixel.
176 int stride
= kImageWidth
* kImageBytesPerPixel
;
177 for (int x
= 0; x
< kImageWidth
; ++x
) {
178 for (int y
= 0; y
< kImageHeight
; ++y
) {
179 mapped_buffer
[y
* stride
+ x
* kImageBytesPerPixel
+ 0] = pixels
[0];
180 mapped_buffer
[y
* stride
+ x
* kImageBytesPerPixel
+ 1] = pixels
[1];
181 mapped_buffer
[y
* stride
+ x
* kImageBytesPerPixel
+ 2] = pixels
[2];
182 mapped_buffer
[y
* stride
+ x
* kImageBytesPerPixel
+ 3] = pixels
[3];
186 EXPECT_CALL(*gpu_memory_buffer
, IsMapped())
187 .WillOnce(Return(true))
188 .RetiresOnSaturation();
191 EXPECT_CALL(*gpu_memory_buffer
, Unmap())
193 .RetiresOnSaturation();
194 glUnmapImageCHROMIUM(image_id
);
196 // Bind the texture and the image.
197 glBindTexture(GL_TEXTURE_2D
, texture_ids_
[0]);
198 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D
, image_id
);
200 // Copy texture so we can verify result using CheckPixels.
201 glCopyTextureCHROMIUM(GL_TEXTURE_2D
,
207 EXPECT_TRUE(glGetError() == GL_NO_ERROR
);
209 // Check if pixels match the values that were assigned to the mapped buffer.
210 GLTestHelper::CheckPixels(0, 0, kImageWidth
, kImageHeight
, 0, pixels
);
211 EXPECT_TRUE(GL_NO_ERROR
== glGetError());
213 // Release the image.
214 glReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, image_id
);
216 // Destroy the image.
217 EXPECT_CALL(*gpu_memory_buffer
, Die())
219 .RetiresOnSaturation();
221 EXPECT_CALL(*image_factory_
.get(), DeleteGpuMemoryBuffer(image_id
))
223 .RetiresOnSaturation();
225 glDestroyImageCHROMIUM(image_id
);