普通文本  |  218行  |  6.42 KB

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/client/share_group.h"

#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/program_info_manager.h"
#include "gpu/command_buffer/common/id_allocator.h"

namespace gpu {
namespace gles2 {

COMPILE_ASSERT(gpu::kInvalidResource == 0,
               INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS);

// The standard id handler.
class IdHandler : public IdHandlerInterface {
 public:
  IdHandler() { }
  virtual ~IdHandler() { }

  // Overridden from IdHandlerInterface.
  virtual void MakeIds(
      GLES2Implementation* /* gl_impl */,
      GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE {
    if (id_offset == 0) {
      for (GLsizei ii = 0; ii < n; ++ii) {
        ids[ii] = id_allocator_.AllocateID();
      }
    } else {
      for (GLsizei ii = 0; ii < n; ++ii) {
        ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset);
        id_offset = ids[ii] + 1;
      }
    }
  }

  // Overridden from IdHandlerInterface.
  virtual bool FreeIds(
      GLES2Implementation* gl_impl,
      GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE {
    for (GLsizei ii = 0; ii < n; ++ii) {
      id_allocator_.FreeID(ids[ii]);
    }
    (gl_impl->*delete_fn)(n, ids);
    // We need to ensure that the delete call is evaluated on the service side
    // before any other contexts issue commands using these client ids.
    gl_impl->helper()->CommandBufferHelper::Flush();
    return true;
  }

  // Overridden from IdHandlerInterface.
  virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
    return id == 0 ? true : id_allocator_.MarkAsUsed(id);
  }
 protected:
  IdAllocator id_allocator_;
};

// An id handler that require Gen before Bind.
class StrictIdHandler : public IdHandler {
 public:
  StrictIdHandler() {}
  virtual ~StrictIdHandler() {}

  // Overridden from IdHandler.
  virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
    DCHECK(id == 0 || id_allocator_.InUse(id));
    return IdHandler::MarkAsUsedForBind(id);
  }
};

// An id handler for ids that are never reused.
class NonReusedIdHandler : public IdHandlerInterface {
 public:
  NonReusedIdHandler() : last_id_(0) {}
  virtual ~NonReusedIdHandler() {}

  // Overridden from IdHandlerInterface.
  virtual void MakeIds(
      GLES2Implementation* /* gl_impl */,
      GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE {
    for (GLsizei ii = 0; ii < n; ++ii) {
      ids[ii] = ++last_id_ + id_offset;
    }
  }

  // Overridden from IdHandlerInterface.
  virtual bool FreeIds(
      GLES2Implementation* gl_impl,
      GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE {
    // Ids are never freed.
    (gl_impl->*delete_fn)(n, ids);
    return true;
  }

  // Overridden from IdHandlerInterface.
  virtual bool MarkAsUsedForBind(GLuint /* id */) OVERRIDE {
    // This is only used for Shaders and Programs which have no bind.
    return false;
  }

 private:
  GLuint last_id_;
};

// An id handler for shared ids.
class SharedIdHandler : public IdHandlerInterface {
 public:
  SharedIdHandler(
      id_namespaces::IdNamespaces id_namespace)
      : id_namespace_(id_namespace) {
  }

  virtual ~SharedIdHandler() {}

  virtual void MakeIds(GLES2Implementation* gl_impl,
                       GLuint id_offset,
                       GLsizei n,
                       GLuint* ids) OVERRIDE {
    gl_impl->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids);
  }

  virtual bool FreeIds(GLES2Implementation* gl_impl,
                       GLsizei n,
                       const GLuint* ids,
                       DeleteFn delete_fn) OVERRIDE {
    gl_impl->DeleteSharedIdsCHROMIUM(id_namespace_, n, ids);
    (gl_impl->*delete_fn)(n, ids);
    // We need to ensure that the delete call is evaluated on the service side
    // before any other contexts issue commands using these client ids.
    gl_impl->helper()->CommandBufferHelper::Flush();
    return true;
  }

  virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
    // This has no meaning for shared resources.
    return true;
  }

 private:
  id_namespaces::IdNamespaces id_namespace_;
};

class ThreadSafeIdHandlerWrapper : public IdHandlerInterface {
 public:
  ThreadSafeIdHandlerWrapper(IdHandlerInterface* id_handler)
      : id_handler_(id_handler) {
  }
  virtual ~ThreadSafeIdHandlerWrapper() { }

  // Overridden from IdHandlerInterface.
  virtual void MakeIds(GLES2Implementation* gl_impl,
                       GLuint id_offset,
                       GLsizei n,
                       GLuint* ids) OVERRIDE {
    base::AutoLock auto_lock(lock_);
    id_handler_->MakeIds(gl_impl, id_offset, n, ids);
  }

  // Overridden from IdHandlerInterface.
  virtual bool FreeIds(GLES2Implementation* gl_impl,
                       GLsizei n,
                       const GLuint* ids,
                       DeleteFn delete_fn) OVERRIDE {
    base::AutoLock auto_lock(lock_);
    return id_handler_->FreeIds(gl_impl, n, ids, delete_fn);
  }

  // Overridden from IdHandlerInterface.
  virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
    base::AutoLock auto_lock(lock_);
    return id_handler_->MarkAsUsedForBind(id);
  }

 private:
   scoped_ptr<IdHandlerInterface> id_handler_;
   base::Lock lock_;
};

ShareGroup::ShareGroup(bool bind_generates_resource)
    : bind_generates_resource_(bind_generates_resource) {
  if (bind_generates_resource) {
    for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
      if (i == id_namespaces::kProgramsAndShaders) {
        id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
            new NonReusedIdHandler()));
      } else {
        id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
            new IdHandler()));
      }
    }
  } else {
    for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
      if (i == id_namespaces::kProgramsAndShaders) {
        id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
            new NonReusedIdHandler()));
      } else {
        id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
            new StrictIdHandler()));
      }
    }
  }
  program_info_manager_.reset(ProgramInfoManager::Create(false));
}

void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) {
  program_info_manager_.reset(manager);
}

ShareGroup::~ShareGroup() {}

}  // namespace gles2
}  // namespace gpu