| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/command_buffer/service/gles2_cmd_decoder.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 6 | 6 |
| 7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
| 8 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 8 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| 9 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 9 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 10 #include "gpu/command_buffer/common/id_allocator.h" | 10 #include "gpu/command_buffer/common/id_allocator.h" |
| 11 #include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" | 11 #include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h" |
| 12 #include "gpu/command_buffer/service/cmd_buffer_engine.h" | 12 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| 13 #include "gpu/command_buffer/service/context_group.h" | 13 #include "gpu/command_buffer/service/context_group.h" |
| 14 #include "gpu/command_buffer/service/gl_surface_mock.h" | 14 #include "gpu/command_buffer/service/gl_surface_mock.h" |
| 15 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" | 15 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h" |
| 16 #include "gpu/command_buffer/service/image_manager.h" | 16 #include "gpu/command_buffer/service/image_manager.h" |
| 17 #include "gpu/command_buffer/service/mailbox_manager.h" | 17 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 18 #include "gpu/command_buffer/service/mocks.h" |
| 18 #include "gpu/command_buffer/service/program_manager.h" | 19 #include "gpu/command_buffer/service/program_manager.h" |
| 19 #include "gpu/command_buffer/service/stream_texture_manager_mock.h" | 20 #include "gpu/command_buffer/service/stream_texture_manager_mock.h" |
| 20 #include "gpu/command_buffer/service/stream_texture_mock.h" | 21 #include "gpu/command_buffer/service/stream_texture_mock.h" |
| 21 #include "gpu/command_buffer/service/test_helper.h" | 22 #include "gpu/command_buffer/service/test_helper.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 #include "ui/gl/gl_implementation.h" | 24 #include "ui/gl/gl_implementation.h" |
| 24 #include "ui/gl/gl_mock.h" | 25 #include "ui/gl/gl_mock.h" |
| 25 #include "ui/gl/gl_surface_stub.h" | 26 #include "ui/gl/gl_surface_stub.h" |
| 26 | 27 |
| 27 | 28 |
| (...skipping 8051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8079 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); | 8080 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); |
| 8080 EXPECT_TRUE(info->GetAsyncTransferState()); | 8081 EXPECT_TRUE(info->GetAsyncTransferState()); |
| 8081 EXPECT_TRUE(info->IsImmutable()); | 8082 EXPECT_TRUE(info->IsImmutable()); |
| 8082 EXPECT_TRUE(info->SafeToRenderFrom()); | 8083 EXPECT_TRUE(info->SafeToRenderFrom()); |
| 8083 } | 8084 } |
| 8084 | 8085 |
| 8085 decoder_->SetAsyncPixelTransferDelegate(NULL); | 8086 decoder_->SetAsyncPixelTransferDelegate(NULL); |
| 8086 info->SetAsyncTransferState(scoped_ptr<gfx::AsyncPixelTransferState>()); | 8087 info->SetAsyncTransferState(scoped_ptr<gfx::AsyncPixelTransferState>()); |
| 8087 } | 8088 } |
| 8088 | 8089 |
| 8090 namespace { |
| 8091 |
| 8092 class SizeOnlyMemoryTracker : public MemoryTracker { |
| 8093 public: |
| 8094 SizeOnlyMemoryTracker() { |
| 8095 // These are the default textures. 1 for TEXTURE_2D and 6 faces for |
| 8096 // TEXTURE_CUBE_MAP. |
| 8097 const size_t kInitialUnmanagedPoolSize = 7 * 4; |
| 8098 const size_t kInitialManagedPoolSize = 0; |
| 8099 pool_infos_[MemoryTracker::kUnmanaged].initial_size = |
| 8100 kInitialUnmanagedPoolSize; |
| 8101 pool_infos_[MemoryTracker::kManaged].initial_size = |
| 8102 kInitialManagedPoolSize; |
| 8103 } |
| 8104 |
| 8105 // Ensure a certain amount of GPU memory is free. Returns true on success. |
| 8106 MOCK_METHOD1(EnsureGPUMemoryAvailable, bool(size_t size_needed)); |
| 8107 |
| 8108 virtual void TrackMemoryAllocatedChange( |
| 8109 size_t old_size, size_t new_size, Pool pool) { |
| 8110 PoolInfo& info = pool_infos_[pool]; |
| 8111 info.size += new_size - old_size; |
| 8112 } |
| 8113 |
| 8114 size_t GetPoolSize(Pool pool) { |
| 8115 const PoolInfo& info = pool_infos_[pool]; |
| 8116 return info.size - info.initial_size; |
| 8117 } |
| 8118 |
| 8119 private: |
| 8120 virtual ~SizeOnlyMemoryTracker() { |
| 8121 } |
| 8122 struct PoolInfo { |
| 8123 PoolInfo() |
| 8124 : initial_size(0), |
| 8125 size(0) { |
| 8126 } |
| 8127 size_t initial_size; |
| 8128 size_t size; |
| 8129 }; |
| 8130 std::map<Pool, PoolInfo> pool_infos_; |
| 8131 }; |
| 8132 |
| 8133 } // anonymous namespace. |
| 8134 |
| 8135 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerInitialSize) { |
| 8136 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8137 new SizeOnlyMemoryTracker(); |
| 8138 set_memory_tracker(memory_tracker.get()); |
| 8139 InitDecoder( |
| 8140 "", // extensions |
| 8141 false, // has alpha |
| 8142 false, // has depth |
| 8143 false, // has stencil |
| 8144 false, // request alpha |
| 8145 false, // request depth |
| 8146 false, // request stencil |
| 8147 true); // bind generates resource |
| 8148 // Expect that initial size - size is 0. |
| 8149 EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8150 EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); |
| 8151 } |
| 8152 |
| 8153 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexImage2D) { |
| 8154 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8155 new SizeOnlyMemoryTracker(); |
| 8156 set_memory_tracker(memory_tracker.get()); |
| 8157 InitDecoder( |
| 8158 "", // extensions |
| 8159 false, // has alpha |
| 8160 false, // has depth |
| 8161 false, // has stencil |
| 8162 false, // request alpha |
| 8163 false, // request depth |
| 8164 false, // request stencil |
| 8165 true); // bind generates resource |
| 8166 DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); |
| 8167 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8168 .WillOnce(Return(true)) |
| 8169 .RetiresOnSaturation(); |
| 8170 DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 8171 kSharedMemoryId, kSharedMemoryOffset); |
| 8172 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8173 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(64)) |
| 8174 .WillOnce(Return(true)) |
| 8175 .RetiresOnSaturation(); |
| 8176 DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 8177 kSharedMemoryId, kSharedMemoryOffset); |
| 8178 EXPECT_EQ(64u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8179 EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| 8180 // Check we get out of memory and no call to glTexImage2D if Ensure fails. |
| 8181 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(64)) |
| 8182 .WillOnce(Return(false)) |
| 8183 .RetiresOnSaturation(); |
| 8184 TexImage2D cmd; |
| 8185 cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| 8186 kSharedMemoryId, kSharedMemoryOffset); |
| 8187 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8188 EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); |
| 8189 EXPECT_EQ(64u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8190 } |
| 8191 |
| 8192 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerTexStorage2DEXT) { |
| 8193 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8194 new SizeOnlyMemoryTracker(); |
| 8195 set_memory_tracker(memory_tracker.get()); |
| 8196 InitDecoder( |
| 8197 "", // extensions |
| 8198 false, // has alpha |
| 8199 false, // has depth |
| 8200 false, // has stencil |
| 8201 false, // request alpha |
| 8202 false, // request depth |
| 8203 false, // request stencil |
| 8204 true); // bind generates resource |
| 8205 DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); |
| 8206 // Check we get out of memory and no call to glTexStorage2DEXT |
| 8207 // if Ensure fails. |
| 8208 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8209 .WillOnce(Return(false)) |
| 8210 .RetiresOnSaturation(); |
| 8211 TexStorage2DEXT cmd; |
| 8212 cmd.Init(GL_TEXTURE_2D, 1, GL_RGBA8, 8, 4); |
| 8213 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8214 EXPECT_EQ(0u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8215 EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); |
| 8216 } |
| 8217 |
| 8218 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerCopyTexImage2D) { |
| 8219 GLenum target = GL_TEXTURE_2D; |
| 8220 GLint level = 0; |
| 8221 GLenum internal_format = GL_RGBA; |
| 8222 GLsizei width = 4; |
| 8223 GLsizei height = 8; |
| 8224 GLint border = 0; |
| 8225 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8226 new SizeOnlyMemoryTracker(); |
| 8227 set_memory_tracker(memory_tracker.get()); |
| 8228 InitDecoder( |
| 8229 "", // extensions |
| 8230 true, // has alpha |
| 8231 false, // has depth |
| 8232 false, // has stencil |
| 8233 true, // request alpha |
| 8234 false, // request depth |
| 8235 false, // request stencil |
| 8236 true); // bind generates resource |
| 8237 DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); |
| 8238 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8239 .WillOnce(Return(true)) |
| 8240 .RetiresOnSaturation(); |
| 8241 EXPECT_CALL(*gl_, GetError()) |
| 8242 .WillOnce(Return(GL_NO_ERROR)) |
| 8243 .WillOnce(Return(GL_NO_ERROR)) |
| 8244 .RetiresOnSaturation(); |
| 8245 EXPECT_CALL(*gl_, CopyTexImage2D( |
| 8246 target, level, internal_format, 0, 0, width, height, border)) |
| 8247 .Times(1) |
| 8248 .RetiresOnSaturation(); |
| 8249 CopyTexImage2D cmd; |
| 8250 cmd.Init(target, level, internal_format, 0, 0, width, height, border); |
| 8251 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8252 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8253 EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| 8254 // Check we get out of memory and no call to glCopyTexImage2D if Ensure fails. |
| 8255 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8256 .WillOnce(Return(false)) |
| 8257 .RetiresOnSaturation(); |
| 8258 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8259 EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); |
| 8260 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8261 } |
| 8262 |
| 8263 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerRenderbufferStorage) { |
| 8264 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8265 new SizeOnlyMemoryTracker(); |
| 8266 set_memory_tracker(memory_tracker.get()); |
| 8267 InitDecoder( |
| 8268 "", // extensions |
| 8269 false, // has alpha |
| 8270 false, // has depth |
| 8271 false, // has stencil |
| 8272 false, // request alpha |
| 8273 false, // request depth |
| 8274 false, // request stencil |
| 8275 true); // bind generates resource |
| 8276 DoBindRenderbuffer(GL_RENDERBUFFER, client_renderbuffer_id_, |
| 8277 kServiceRenderbufferId); |
| 8278 EXPECT_CALL(*gl_, GetError()) |
| 8279 .WillOnce(Return(GL_NO_ERROR)) |
| 8280 .WillOnce(Return(GL_NO_ERROR)) |
| 8281 .RetiresOnSaturation(); |
| 8282 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8283 .WillOnce(Return(true)) |
| 8284 .RetiresOnSaturation(); |
| 8285 EXPECT_CALL(*gl_, RenderbufferStorageEXT( |
| 8286 GL_RENDERBUFFER, GL_RGBA, 8, 4)) |
| 8287 .Times(1) |
| 8288 .RetiresOnSaturation(); |
| 8289 RenderbufferStorage cmd; |
| 8290 cmd.Init(GL_RENDERBUFFER, GL_RGBA4, 8, 4); |
| 8291 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8292 EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| 8293 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8294 // Check we get out of memory and no call to glRenderbufferStorage if Ensure |
| 8295 // fails. |
| 8296 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8297 .WillOnce(Return(false)) |
| 8298 .RetiresOnSaturation(); |
| 8299 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8300 EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); |
| 8301 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kUnmanaged)); |
| 8302 } |
| 8303 |
| 8304 TEST_F(GLES2DecoderManualInitTest, MemoryTrackerBufferData) { |
| 8305 scoped_refptr<SizeOnlyMemoryTracker> memory_tracker = |
| 8306 new SizeOnlyMemoryTracker(); |
| 8307 set_memory_tracker(memory_tracker.get()); |
| 8308 InitDecoder( |
| 8309 "", // extensions |
| 8310 false, // has alpha |
| 8311 false, // has depth |
| 8312 false, // has stencil |
| 8313 false, // request alpha |
| 8314 false, // request depth |
| 8315 false, // request stencil |
| 8316 true); // bind generates resource |
| 8317 DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, |
| 8318 kServiceBufferId); |
| 8319 EXPECT_CALL(*gl_, GetError()) |
| 8320 .WillOnce(Return(GL_NO_ERROR)) |
| 8321 .WillOnce(Return(GL_NO_ERROR)) |
| 8322 .RetiresOnSaturation(); |
| 8323 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8324 .WillOnce(Return(true)) |
| 8325 .RetiresOnSaturation(); |
| 8326 EXPECT_CALL(*gl_, BufferData(GL_ARRAY_BUFFER, 128, _, GL_STREAM_DRAW)) |
| 8327 .Times(1) |
| 8328 .RetiresOnSaturation(); |
| 8329 BufferData cmd; |
| 8330 cmd.Init(GL_ARRAY_BUFFER, 128, 0, 0, GL_STREAM_DRAW); |
| 8331 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8332 EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
| 8333 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); |
| 8334 // Check we get out of memory and no call to glBufferData if Ensure |
| 8335 // fails. |
| 8336 EXPECT_CALL(*memory_tracker, EnsureGPUMemoryAvailable(128)) |
| 8337 .WillOnce(Return(false)) |
| 8338 .RetiresOnSaturation(); |
| 8339 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
| 8340 EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); |
| 8341 EXPECT_EQ(128u, memory_tracker->GetPoolSize(MemoryTracker::kManaged)); |
| 8342 } |
| 8343 |
| 8089 // TODO(gman): Complete this test. | 8344 // TODO(gman): Complete this test. |
| 8090 // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { | 8345 // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { |
| 8091 // } | 8346 // } |
| 8092 | 8347 |
| 8093 // TODO(gman): BufferData | 8348 // TODO(gman): BufferData |
| 8094 | 8349 |
| 8095 // TODO(gman): BufferDataImmediate | 8350 // TODO(gman): BufferDataImmediate |
| 8096 | 8351 |
| 8097 // TODO(gman): BufferSubData | 8352 // TODO(gman): BufferSubData |
| 8098 | 8353 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 8115 // TODO(gman): TexImage2DImmediate | 8370 // TODO(gman): TexImage2DImmediate |
| 8116 | 8371 |
| 8117 // TODO(gman): TexSubImage2DImmediate | 8372 // TODO(gman): TexSubImage2DImmediate |
| 8118 | 8373 |
| 8119 // TODO(gman): UseProgram | 8374 // TODO(gman): UseProgram |
| 8120 | 8375 |
| 8121 // TODO(gman): SwapBuffers | 8376 // TODO(gman): SwapBuffers |
| 8122 | 8377 |
| 8123 } // namespace gles2 | 8378 } // namespace gles2 |
| 8124 } // namespace gpu | 8379 } // namespace gpu |
| OLD | NEW |