1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139

gpu / command_buffer / common / discardable_handle.h [blame]

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_
#define GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_

#include "base/atomicops.h"
#include "base/memory/ref_counted.h"
#include "base/types/id_type.h"
#include "gpu/gpu_export.h"

namespace gpu {

class Buffer;

struct SerializableSkiaHandle {
  SerializableSkiaHandle() = default;
  SerializableSkiaHandle(uint32_t handle_id,
                         uint32_t shm_id,
                         uint32_t byte_offset)
      : handle_id(handle_id), shm_id(shm_id), byte_offset(byte_offset) {}
  ~SerializableSkiaHandle() = default;

  uint32_t handle_id = 0u;
  uint32_t shm_id = 0u;
  uint32_t byte_offset = 0u;
};

// DiscardableHandleBase is the base class for the discardable handle
// implementation. In order to facilitate transfering handles across the
// command buffer, DiscardableHandleBase is backed by a gpu::Buffer and an
// offset into that buffer. It uses a single uint32_t of data at the given
// offset.
//
// DiscardableHandleBase is never used directly, but is instead modified by the
// Client/ServiceDiscardableHandle subclasses. These subclasses implement the
// Lock/Unlock/Delete functionality, making it explicit which operations occur
// in which process.
//
// Via these subclasses, a discardable handle can be transitioned between one
// of three states:
//  ╔════════════╗         ╔════════════╗         ╔═══════════╗
//  ║   Locked   ║ ──────> ║  Unlocked  ║ ──────> ║  Deleted  ║
//  ╚════════════╝         ╚════════════╝         ╚═══════════╝
//         └───────────<──────────┘
//
// Note that a handle can be locked multiple times, and stores a lock-count.
class GPU_EXPORT DiscardableHandleBase {
 public:
  int32_t shm_id() const { return shm_id_; }
  uint32_t byte_offset() const { return byte_offset_; }

  // Ensures this is a valid allocation for use with a DiscardableHandleBase.
  static bool ValidateParameters(const Buffer* buffer, uint32_t byte_offset);

  // Functions for tracing only.
  bool IsDeletedForTracing() const;

  // Test only functions.
  bool IsLockedForTesting() const;
  bool IsDeletedForTesting() const;
  scoped_refptr<Buffer> BufferForTesting() const;

 protected:
  DiscardableHandleBase(scoped_refptr<Buffer> buffer,
                        uint32_t byte_offset,
                        int32_t shm_id);
  DiscardableHandleBase(const DiscardableHandleBase& other);
  DiscardableHandleBase(DiscardableHandleBase&& other);
  DiscardableHandleBase& operator=(const DiscardableHandleBase& other);
  DiscardableHandleBase& operator=(DiscardableHandleBase&& other);
  ~DiscardableHandleBase();

  volatile base::subtle::Atomic32* AsAtomic() const;

 private:
  scoped_refptr<Buffer> buffer_;
  uint32_t byte_offset_ = 0;
  uint32_t shm_id_ = 0;
};

// ClientDiscardableHandle enables the instantiation of a new discardable
// handle (via the constructor), and can Lock an existing handle.
class GPU_EXPORT ClientDiscardableHandle : public DiscardableHandleBase {
 public:
  using Id = base::IdType32<ClientDiscardableHandle>;

  ClientDiscardableHandle();  // Constructs an invalid handle.
  ClientDiscardableHandle(scoped_refptr<Buffer> buffer,
                          uint32_t byte_offset,
                          int32_t shm_id);
  ClientDiscardableHandle(const ClientDiscardableHandle& other);
  ClientDiscardableHandle(ClientDiscardableHandle&& other);
  ClientDiscardableHandle& operator=(const ClientDiscardableHandle& other);
  ClientDiscardableHandle& operator=(ClientDiscardableHandle&& other);

  // Tries to lock the handle. Returns true if successfully locked. Returns
  // false if the handle has already been deleted on the service.
  bool Lock();

  // Returns true if the handle has been deleted on service side and can be
  // re-used on the client.
  bool CanBeReUsed() const;

  // Returns true if this handle is backed by valid shared memory.
  bool IsValid() const { return shm_id() > 0; }
};

// ServiceDiscardableHandle can wrap an existing handle (via the constructor),
// and can unlock and delete this handle.
class GPU_EXPORT ServiceDiscardableHandle : public DiscardableHandleBase {
 public:
  ServiceDiscardableHandle();  // Constructs an invalid handle.
  ServiceDiscardableHandle(scoped_refptr<Buffer> buffer,
                           uint32_t byte_offset,
                           int32_t shm_id);
  ServiceDiscardableHandle(const ServiceDiscardableHandle& other);
  ServiceDiscardableHandle(ServiceDiscardableHandle&& other);
  ServiceDiscardableHandle& operator=(const ServiceDiscardableHandle& other);
  ServiceDiscardableHandle& operator=(ServiceDiscardableHandle&& other);

  // Unlocks the handle. This should always be paired with a client-side call
  // to lock, or with a new handle, which starts locked.
  void Unlock();

  // Tries to delete the handle. Returns true if successfully deleted. Returns
  // false if the handle is locked client-side and cannot be deleted.
  bool Delete();

  // Deletes the handle, regardless of the handle's state. This should be
  // called in response to glDeleteTextures, which may be called while the
  // handle is in the locked or unlocked state.
  void ForceDelete();
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_COMMON_DISCARDABLE_HANDLE_H_