| OLD | NEW | 
|    1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2009 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 // This file contains the implementation of the FencedAllocator class. |    5 // This file contains the implementation of the FencedAllocator class. | 
|    6  |    6  | 
|    7 #include "../client/fenced_allocator.h" |    7 #include "../client/fenced_allocator.h" | 
|    8 #include <algorithm> |    8 #include <algorithm> | 
|    9 #include "../client/cmd_buffer_helper.h" |    9 #include "../client/cmd_buffer_helper.h" | 
|   10  |   10  | 
|   11 namespace gpu { |   11 namespace gpu { | 
|   12  |   12  | 
|   13 #ifndef COMPILER_MSVC |   13 #ifndef COMPILER_MSVC | 
|   14 const FencedAllocator::Offset FencedAllocator::kInvalidOffset; |   14 const FencedAllocator::Offset FencedAllocator::kInvalidOffset; | 
|   15 #endif |   15 #endif | 
|   16  |   16  | 
|   17 FencedAllocator::~FencedAllocator() { |   17 FencedAllocator::~FencedAllocator() { | 
|   18   // Free blocks pending tokens. |   18   // Free blocks pending tokens. | 
|   19   for (unsigned int i = 0; i < blocks_.size(); ++i) { |   19   for (unsigned int i = 0; i < blocks_.size(); ++i) { | 
|   20     if (blocks_[i].state == FREE_PENDING_TOKEN) { |   20     if (blocks_[i].state == FREE_PENDING_TOKEN) { | 
|   21       i = WaitForTokenAndFreeBlock(i); |   21       i = WaitForTokenAndFreeBlock(i); | 
|   22     } |   22     } | 
|   23   } |   23   } | 
|   24   DCHECK_EQ(blocks_.size(), 1u); |   24   // These checks are not valid if the service has crashed or lost the context. | 
|   25   DCHECK_EQ(blocks_[0].state, FREE); |   25   // DCHECK_EQ(blocks_.size(), 1u); | 
 |   26   // DCHECK_EQ(blocks_[0].state, FREE); | 
|   26 } |   27 } | 
|   27  |   28  | 
|   28 // Looks for a non-allocated block that is big enough. Search in the FREE |   29 // Looks for a non-allocated block that is big enough. Search in the FREE | 
|   29 // blocks first (for direct usage), first-fit, then in the FREE_PENDING_TOKEN |   30 // blocks first (for direct usage), first-fit, then in the FREE_PENDING_TOKEN | 
|   30 // blocks, waiting for them. The current implementation isn't smart about |   31 // blocks, waiting for them. The current implementation isn't smart about | 
|   31 // optimizing what to wait for, just looks inside the block in order (first-fit |   32 // optimizing what to wait for, just looks inside the block in order (first-fit | 
|   32 // as well). |   33 // as well). | 
|   33 FencedAllocator::Offset FencedAllocator::Alloc(unsigned int size) { |   34 FencedAllocator::Offset FencedAllocator::Alloc(unsigned int size) { | 
|   34   // Similarly to malloc, an allocation of 0 allocates at least 1 byte, to |   35   // Similarly to malloc, an allocation of 0 allocates at least 1 byte, to | 
|   35   // return different pointers every time. |   36   // return different pointers every time. | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|   58 // Looks for the corresponding block, mark it FREE, and collapse it if |   59 // Looks for the corresponding block, mark it FREE, and collapse it if | 
|   59 // necessary. |   60 // necessary. | 
|   60 void FencedAllocator::Free(FencedAllocator::Offset offset) { |   61 void FencedAllocator::Free(FencedAllocator::Offset offset) { | 
|   61   BlockIndex index = GetBlockByOffset(offset); |   62   BlockIndex index = GetBlockByOffset(offset); | 
|   62   DCHECK_NE(blocks_[index].state, FREE); |   63   DCHECK_NE(blocks_[index].state, FREE); | 
|   63   blocks_[index].state = FREE; |   64   blocks_[index].state = FREE; | 
|   64   CollapseFreeBlock(index); |   65   CollapseFreeBlock(index); | 
|   65 } |   66 } | 
|   66  |   67  | 
|   67 // Looks for the corresponding block, mark it FREE_PENDING_TOKEN. |   68 // Looks for the corresponding block, mark it FREE_PENDING_TOKEN. | 
|   68 void FencedAllocator::FreePendingToken(FencedAllocator::Offset offset, |   69 void FencedAllocator::FreePendingToken( | 
|   69                                        unsigned int token) { |   70     FencedAllocator::Offset offset, int32 token) { | 
|   70   BlockIndex index = GetBlockByOffset(offset); |   71   BlockIndex index = GetBlockByOffset(offset); | 
|   71   Block &block = blocks_[index]; |   72   Block &block = blocks_[index]; | 
|   72   block.state = FREE_PENDING_TOKEN; |   73   block.state = FREE_PENDING_TOKEN; | 
|   73   block.token = token; |   74   block.token = token; | 
|   74 } |   75 } | 
|   75  |   76  | 
|   76 // Gets the max of the size of the blocks marked as free. |   77 // Gets the max of the size of the blocks marked as free. | 
|   77 unsigned int FencedAllocator::GetLargestFreeSize() { |   78 unsigned int FencedAllocator::GetLargestFreeSize() { | 
|   78   unsigned int max_size = 0; |   79   unsigned int max_size = 0; | 
|   79   for (unsigned int i = 0; i < blocks_.size(); ++i) { |   80   for (unsigned int i = 0; i < blocks_.size(); ++i) { | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  147 // Waits for the block's token, then mark the block as free, then collapse it. |  148 // Waits for the block's token, then mark the block as free, then collapse it. | 
|  148 FencedAllocator::BlockIndex FencedAllocator::WaitForTokenAndFreeBlock( |  149 FencedAllocator::BlockIndex FencedAllocator::WaitForTokenAndFreeBlock( | 
|  149     BlockIndex index) { |  150     BlockIndex index) { | 
|  150   Block &block = blocks_[index]; |  151   Block &block = blocks_[index]; | 
|  151   DCHECK_EQ(block.state, FREE_PENDING_TOKEN); |  152   DCHECK_EQ(block.state, FREE_PENDING_TOKEN); | 
|  152   helper_->WaitForToken(block.token); |  153   helper_->WaitForToken(block.token); | 
|  153   block.state = FREE; |  154   block.state = FREE; | 
|  154   return CollapseFreeBlock(index); |  155   return CollapseFreeBlock(index); | 
|  155 } |  156 } | 
|  156  |  157  | 
 |  158 // Frees any blocks pending a token for which the token has been read. | 
 |  159 void FencedAllocator::FreeUnused() { | 
 |  160   int32 last_token_read = helper_->last_token_read(); | 
 |  161   for (unsigned int i = 0; i < blocks_.size();) { | 
 |  162     Block& block = blocks_[i]; | 
 |  163     if (block.state == FREE_PENDING_TOKEN && block.token <= last_token_read) { | 
 |  164       block.state = FREE; | 
 |  165       i = CollapseFreeBlock(i); | 
 |  166     } else { | 
 |  167       ++i; | 
 |  168     } | 
 |  169   } | 
 |  170 } | 
 |  171  | 
|  157 // If the block is exactly the requested size, simply mark it IN_USE, otherwise |  172 // If the block is exactly the requested size, simply mark it IN_USE, otherwise | 
|  158 // split it and mark the first one (of the requested size) IN_USE. |  173 // split it and mark the first one (of the requested size) IN_USE. | 
|  159 FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index, |  174 FencedAllocator::Offset FencedAllocator::AllocInBlock(BlockIndex index, | 
|  160                                                       unsigned int size) { |  175                                                       unsigned int size) { | 
|  161   Block &block = blocks_[index]; |  176   Block &block = blocks_[index]; | 
|  162   DCHECK_GE(block.size, size); |  177   DCHECK_GE(block.size, size); | 
|  163   DCHECK_EQ(block.state, FREE); |  178   DCHECK_EQ(block.state, FREE); | 
|  164   Offset offset = block.offset; |  179   Offset offset = block.offset; | 
|  165   if (block.size == size) { |  180   if (block.size == size) { | 
|  166     block.state = IN_USE; |  181     block.state = IN_USE; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  177 // The blocks are in offset order, so we can do a binary search. |  192 // The blocks are in offset order, so we can do a binary search. | 
|  178 FencedAllocator::BlockIndex FencedAllocator::GetBlockByOffset(Offset offset) { |  193 FencedAllocator::BlockIndex FencedAllocator::GetBlockByOffset(Offset offset) { | 
|  179   Block templ = { IN_USE, offset, 0, kUnusedToken }; |  194   Block templ = { IN_USE, offset, 0, kUnusedToken }; | 
|  180   Container::iterator it = std::lower_bound(blocks_.begin(), blocks_.end(), |  195   Container::iterator it = std::lower_bound(blocks_.begin(), blocks_.end(), | 
|  181                                             templ, OffsetCmp()); |  196                                             templ, OffsetCmp()); | 
|  182   DCHECK(it != blocks_.end() && it->offset == offset); |  197   DCHECK(it != blocks_.end() && it->offset == offset); | 
|  183   return it-blocks_.begin(); |  198   return it-blocks_.begin(); | 
|  184 } |  199 } | 
|  185  |  200  | 
|  186 }  // namespace gpu |  201 }  // namespace gpu | 
| OLD | NEW |