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 210