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 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/client/share_group.h" 6 7 #include "base/logging.h" 8 #include "base/synchronization/lock.h" 9 #include "gpu/command_buffer/client/gles2_implementation.h" 10 #include "gpu/command_buffer/client/program_info_manager.h" 11 #include "gpu/command_buffer/common/id_allocator.h" 12 13 namespace gpu { 14 namespace gles2 { 15 16 COMPILE_ASSERT(gpu::kInvalidResource == 0, 17 INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS); 18 19 // The standard id handler. 20 class IdHandler : public IdHandlerInterface { 21 public: 22 IdHandler() { } 23 virtual ~IdHandler() { } 24 25 // Overridden from IdHandlerInterface. 26 virtual void MakeIds( 27 GLES2Implementation* /* gl_impl */, 28 GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE { 29 if (id_offset == 0) { 30 for (GLsizei ii = 0; ii < n; ++ii) { 31 ids[ii] = id_allocator_.AllocateID(); 32 } 33 } else { 34 for (GLsizei ii = 0; ii < n; ++ii) { 35 ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset); 36 id_offset = ids[ii] + 1; 37 } 38 } 39 } 40 41 // Overridden from IdHandlerInterface. 42 virtual bool FreeIds( 43 GLES2Implementation* gl_impl, 44 GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE { 45 for (GLsizei ii = 0; ii < n; ++ii) { 46 id_allocator_.FreeID(ids[ii]); 47 } 48 (gl_impl->*delete_fn)(n, ids); 49 // We need to ensure that the delete call is evaluated on the service side 50 // before any other contexts issue commands using these client ids. 51 gl_impl->helper()->CommandBufferHelper::Flush(); 52 return true; 53 } 54 55 // Overridden from IdHandlerInterface. 56 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE { 57 return id == 0 ? true : id_allocator_.MarkAsUsed(id); 58 } 59 protected: 60 IdAllocator id_allocator_; 61 }; 62 63 // An id handler that require Gen before Bind. 64 class StrictIdHandler : public IdHandler { 65 public: 66 StrictIdHandler() {} 67 virtual ~StrictIdHandler() {} 68 69 // Overridden from IdHandler. 70 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE { 71 DCHECK(id == 0 || id_allocator_.InUse(id)); 72 return IdHandler::MarkAsUsedForBind(id); 73 } 74 }; 75 76 // An id handler for ids that are never reused. 77 class NonReusedIdHandler : public IdHandlerInterface { 78 public: 79 NonReusedIdHandler() : last_id_(0) {} 80 virtual ~NonReusedIdHandler() {} 81 82 // Overridden from IdHandlerInterface. 83 virtual void MakeIds( 84 GLES2Implementation* /* gl_impl */, 85 GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE { 86 for (GLsizei ii = 0; ii < n; ++ii) { 87 ids[ii] = ++last_id_ + id_offset; 88 } 89 } 90 91 // Overridden from IdHandlerInterface. 92 virtual bool FreeIds( 93 GLES2Implementation* gl_impl, 94 GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE { 95 // Ids are never freed. 96 (gl_impl->*delete_fn)(n, ids); 97 return true; 98 } 99 100 // Overridden from IdHandlerInterface. 101 virtual bool MarkAsUsedForBind(GLuint /* id */) OVERRIDE { 102 // This is only used for Shaders and Programs which have no bind. 103 return false; 104 } 105 106 private: 107 GLuint last_id_; 108 }; 109 110 // An id handler for shared ids. 111 class SharedIdHandler : public IdHandlerInterface { 112 public: 113 SharedIdHandler( 114 id_namespaces::IdNamespaces id_namespace) 115 : id_namespace_(id_namespace) { 116 } 117 118 virtual ~SharedIdHandler() {} 119 120 virtual void MakeIds(GLES2Implementation* gl_impl, 121 GLuint id_offset, 122 GLsizei n, 123 GLuint* ids) OVERRIDE { 124 gl_impl->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids); 125 } 126 127 virtual bool FreeIds(GLES2Implementation* gl_impl, 128 GLsizei n, 129 const GLuint* ids, 130 DeleteFn delete_fn) OVERRIDE { 131 gl_impl->DeleteSharedIdsCHROMIUM(id_namespace_, n, ids); 132 (gl_impl->*delete_fn)(n, ids); 133 // We need to ensure that the delete call is evaluated on the service side 134 // before any other contexts issue commands using these client ids. 135 gl_impl->helper()->CommandBufferHelper::Flush(); 136 return true; 137 } 138 139 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE { 140 // This has no meaning for shared resources. 141 return true; 142 } 143 144 private: 145 id_namespaces::IdNamespaces id_namespace_; 146 }; 147 148 class ThreadSafeIdHandlerWrapper : public IdHandlerInterface { 149 public: 150 ThreadSafeIdHandlerWrapper(IdHandlerInterface* id_handler) 151 : id_handler_(id_handler) { 152 } 153 virtual ~ThreadSafeIdHandlerWrapper() { } 154 155 // Overridden from IdHandlerInterface. 156 virtual void MakeIds(GLES2Implementation* gl_impl, 157 GLuint id_offset, 158 GLsizei n, 159 GLuint* ids) OVERRIDE { 160 base::AutoLock auto_lock(lock_); 161 id_handler_->MakeIds(gl_impl, id_offset, n, ids); 162 } 163 164 // Overridden from IdHandlerInterface. 165 virtual bool FreeIds(GLES2Implementation* gl_impl, 166 GLsizei n, 167 const GLuint* ids, 168 DeleteFn delete_fn) OVERRIDE { 169 base::AutoLock auto_lock(lock_); 170 return id_handler_->FreeIds(gl_impl, n, ids, delete_fn); 171 } 172 173 // Overridden from IdHandlerInterface. 174 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE { 175 base::AutoLock auto_lock(lock_); 176 return id_handler_->MarkAsUsedForBind(id); 177 } 178 179 private: 180 scoped_ptr<IdHandlerInterface> id_handler_; 181 base::Lock lock_; 182 }; 183 184 ShareGroup::ShareGroup(bool bind_generates_resource) 185 : bind_generates_resource_(bind_generates_resource) { 186 if (bind_generates_resource) { 187 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) { 188 if (i == id_namespaces::kProgramsAndShaders) { 189 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper( 190 new NonReusedIdHandler())); 191 } else { 192 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper( 193 new IdHandler())); 194 } 195 } 196 } else { 197 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) { 198 if (i == id_namespaces::kProgramsAndShaders) { 199 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper( 200 new NonReusedIdHandler())); 201 } else { 202 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper( 203 new StrictIdHandler())); 204 } 205 } 206 } 207 program_info_manager_.reset(ProgramInfoManager::Create(false)); 208 } 209 210 void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) { 211 program_info_manager_.reset(manager); 212 } 213 214 ShareGroup::~ShareGroup() {} 215 216 } // namespace gles2 217 } // namespace gpu 218