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/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 23using testing::_; 24using testing::IgnoreResult; 25using testing::InvokeWithoutArgs; 26using testing::Invoke; 27using testing::Return; 28using testing::SetArgPointee; 29using testing::StrictMock; 30 31namespace gpu { 32namespace gles2 { 33 34static const int kImageWidth = 32; 35static const int kImageHeight = 32; 36static const int kImageBytesPerPixel = 4; 37 38class MockGpuMemoryBuffer : public gfx::GpuMemoryBuffer { 39 public: 40 MockGpuMemoryBuffer(int width, int height) {} 41 virtual ~MockGpuMemoryBuffer() { 42 Die(); 43 } 44 45 MOCK_METHOD0(Map, 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 56class MockGpuMemoryBufferFactory : public GpuMemoryBufferFactory { 57 public: 58 MockGpuMemoryBufferFactory() {} 59 virtual ~MockGpuMemoryBufferFactory() {} 60 61 MOCK_METHOD4(CreateGpuMemoryBuffer, 62 gfx::GpuMemoryBuffer*(size_t, size_t, unsigned, unsigned)); 63 64 private: 65 DISALLOW_COPY_AND_ASSIGN(MockGpuMemoryBufferFactory); 66}; 67 68class 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. 112TEST_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( 130 *gpu_memory_buffer_factory_.get(), 131 CreateGpuMemoryBuffer( 132 kImageWidth, kImageHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM)) 133 .Times(1) 134 .WillOnce(Return(gpu_memory_buffer)) 135 .RetiresOnSaturation(); 136 EXPECT_CALL(*gpu_memory_buffer, GetHandle()) 137 .Times(1) 138 .WillOnce(Return(handle)) 139 .RetiresOnSaturation(); 140 141 // Create the image. This should add the image ID to the ImageManager. 142 GLuint image_id = glCreateImageCHROMIUM( 143 kImageWidth, kImageHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM); 144 EXPECT_NE(0u, image_id); 145 EXPECT_TRUE(image_manager_->LookupImage(image_id) != NULL); 146 147 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) 148 .WillOnce(Return(false)) 149 .RetiresOnSaturation(); 150 151 shared_memory.Map(bytes); 152 EXPECT_TRUE(shared_memory.memory()); 153 154 EXPECT_CALL(*gpu_memory_buffer, Map()) 155 .Times(1) 156 .WillOnce(Return(shared_memory.memory())) 157 .RetiresOnSaturation(); 158 uint8* mapped_buffer = static_cast<uint8*>(glMapImageCHROMIUM(image_id)); 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[0]; 166 mapped_buffer[y * stride + x * kImageBytesPerPixel + 1] = pixels[1]; 167 mapped_buffer[y * stride + x * kImageBytesPerPixel + 2] = pixels[2]; 168 mapped_buffer[y * stride + x * kImageBytesPerPixel + 3] = pixels[3]; 169 } 170 } 171 172 EXPECT_CALL(*gpu_memory_buffer, IsMapped()) 173 .WillOnce(Return(true)) 174 .RetiresOnSaturation(); 175 176 // Unmap the image. 177 EXPECT_CALL(*gpu_memory_buffer, Unmap()) 178 .Times(1) 179 .RetiresOnSaturation(); 180 glUnmapImageCHROMIUM(image_id); 181 182 // Bind the texture and the image. 183 glBindTexture(GL_TEXTURE_2D, texture_ids_[0]); 184 glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); 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 202 // Destroy the image. 203 EXPECT_CALL(*gpu_memory_buffer, Die()) 204 .Times(1) 205 .RetiresOnSaturation(); 206 glDestroyImageCHROMIUM(image_id); 207} 208 209} // namespace gles2 210} // namespace gpu 211