Beatmup
Beatmup::BitmapContentLock Class Reference

Makes sure the bitmap content is accessible within an image processing task. More...

#include <content_lock.h>

Inheritance diagram for Beatmup::BitmapContentLock:
Beatmup::Audio::SignalPlot Beatmup::BitmapBinaryOperation Beatmup::BitmapFromChunk Beatmup::BitmapResampler Beatmup::Crop Beatmup::Filters::PixelwiseFilter Beatmup::FloodFill Beatmup::FormatConverter Beatmup::GLES31X2UpsamplingNetwork Beatmup::Metric Beatmup::NNets::InferenceTask Beatmup::RenderingContext Beatmup::ShaderApplicator

Classes

struct  LockDescriptor
 

Public Member Functions

 BitmapContentLock ()
 
 ~BitmapContentLock ()
 
void readLock (GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
 Locks content of a bitmap for reading using a specific processing target device. More...
 
void writeLock (GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
 Locks content of a bitmap for writing using a specific processing target device. More...
 
void unlock (AbstractBitmap *bitmap)
 Drops a lock to the bitmap. More...
 
void unlockAll ()
 Unlocks all the locked bitmaps unconditionally. More...
 
template<const ProcessingTarget target>
void lock (GraphicPipeline *gpu, AbstractBitmap *input, AbstractBitmap *output)
 
void lock (GraphicPipeline *gpu, ProcessingTarget target, AbstractBitmap *input, AbstractBitmap *output)
 
template<const ProcessingTarget target>
void lock (GraphicPipeline *gpu, std::initializer_list< AbstractBitmap * > read, std::initializer_list< AbstractBitmap * > write)
 
template<typename ... Args>
void unlock (AbstractBitmap *first, Args ... others)
 

Private Member Functions

 BitmapContentLock (const BitmapContentLock &)=delete
 

Private Attributes

std::map< AbstractBitmap *, LockDescriptorbitmaps
 

Detailed Description

Makes sure the bitmap content is accessible within an image processing task.

To enable direct access to pixels, a specific operation of locking the bitmap content is typically required. When done, the bitmap content needs to be unlocked. Depending on the access type (reading/writing) an the processing target (CPU or GPU), a memory allocation and/or data transfer may be required. BitmapContentLock performs the data transfer if necessary. It also handles multiple locking of the same bitmap by reference counting.

Definition at line 34 of file content_lock.h.

Constructor & Destructor Documentation

◆ BitmapContentLock() [1/2]

Beatmup::BitmapContentLock::BitmapContentLock ( const BitmapContentLock )
privatedelete

◆ BitmapContentLock() [2/2]

Beatmup::BitmapContentLock::BitmapContentLock ( )
inline

Definition at line 48 of file content_lock.h.

48 {}

◆ ~BitmapContentLock()

BitmapContentLock::~BitmapContentLock ( )

Definition at line 29 of file content_lock.cpp.

29  {
30 #ifdef BEATMUP_DEBUG
31  if (!bitmaps.empty())
32  BEATMUP_DEBUG_E("Destroying a content lock having %d locked bitmaps", (int)bitmaps.size());
33 #endif
34 }
std::map< AbstractBitmap *, LockDescriptor > bitmaps
Definition: content_lock.h:45
#define BEATMUP_DEBUG_E(...)
Definition: debug.h:34

Member Function Documentation

◆ readLock()

void BitmapContentLock::readLock ( GraphicPipeline gpu,
AbstractBitmap bitmap,
ProcessingTarget  target 
)

Locks content of a bitmap for reading using a specific processing target device.

If the lock is already acquired, only increases the counter. If the bitmap was previously locked for a different target device, an exception is thrown.

Parameters
gpuA graphic pipeline instance. Used to transfer the pixel data between CPU and GPU if needed.
bitmapThe bitmap to lock
targetTarget processing device to make the pixel content readable for (CPU or GPU)

Definition at line 37 of file content_lock.cpp.

37  {
38 #ifdef BEATMUP_DEBUG
39  DebugAssertion::check(!bitmap->isDirty(), "Reading a dirty bitmap");
40  if (target == ProcessingTarget::GPU)
41  DebugAssertion::check(gpu, "Cannot lock a bitmap on GPU: no graphic pipeline instance available");
42 #endif
43 
44  bool transferToGpuNeeded = false;
45  bool transferFromGpuNeeded = false;
46 
47  auto it = bitmaps.find(bitmap);
48  if (it == bitmaps.end()) {
49  // creating a lock descriptor
50  LockDescriptor lock{
51  true, false,
52  target == ProcessingTarget::CPU,
53  target == ProcessingTarget::GPU,
54  false,
55  1
56  };
57 
58  // pixel transfer to GPU is needed if the bitmap is not up to date on GPU
59  transferToGpuNeeded = lock.gpu && !bitmap->isUpToDate(ProcessingTarget::GPU);
60  transferFromGpuNeeded = lock.cpu && !bitmap->isUpToDate(ProcessingTarget::CPU);
61 
62  // locking pixel data in RAM
63  if (lock.cpu || transferToGpuNeeded || transferFromGpuNeeded) {
65  lock.isDataLocked = true;
66  }
67 
68  bitmaps.emplace(bitmap, lock);
69  }
70 
71  else {
72  // already locked, just increase reference counter
73  auto& lock = it->second;
74 
75  RuntimeError::check(((target == ProcessingTarget::CPU) == lock.cpu) && ((target == ProcessingTarget::GPU) == lock.gpu),
76  "Lock target mismatch: a bitmap was previously locked for a different target");
77 
78  // It is allowed to lock a bitmap for writing first and for reading later.
79  if (!lock.read) {
80  transferToGpuNeeded = lock.gpu && !bitmap->isUpToDate(ProcessingTarget::GPU);
81  transferFromGpuNeeded = lock.cpu && !bitmap->isUpToDate(ProcessingTarget::CPU);
82 
83  if (!lock.isDataLocked && (transferToGpuNeeded || transferFromGpuNeeded)) {
85  lock.isDataLocked = true;
86  }
87 
88  lock.read = true;
89  }
90  lock.refs++;
91  }
92 
93  // do pixel transfer if required
94  if (transferToGpuNeeded)
95  gpu->pushPixels(*bitmap);
96  else if (transferFromGpuNeeded)
97  gpu->pullPixels(*bitmap);
98 }
bool isDirty() const
Returns true if the bitmap does not contain any valid content.
bool isUpToDate(ProcessingTarget) const
void lock(GraphicPipeline *gpu, AbstractBitmap *input, AbstractBitmap *output)
Definition: content_lock.h:84
void pullPixels(AbstractBitmap &bitmap)
Transfers bitmap pixels from GPU to CPU.
Definition: pipeline.cpp:921
void pushPixels(AbstractBitmap &bitmap)
Transfers bitmap pixels from CPU to GPU.
Definition: pipeline.cpp:926
void lockPixelData()
Locks access to the CPU memory buffer containing pixel data.
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Beatmup::InternalBitmap * bitmap

◆ writeLock()

void BitmapContentLock::writeLock ( GraphicPipeline gpu,
AbstractBitmap bitmap,
ProcessingTarget  target 
)

Locks content of a bitmap for writing using a specific processing target device.

If the lock is already acquired, only increases the counter. If the bitmap was previously locked for reading, an exception is thrown. However, it is allowed to lock for different devices, or to lock for writing first and reading later.

Parameters
gpuA graphic pipeline instance
bitmapThe bitmap to lock
targetTarget processing device to make the pixel content readable for (CPU or GPU)

Definition at line 101 of file content_lock.cpp.

101  {
102 #ifdef BEATMUP_DEBUG
103  if (target == ProcessingTarget::GPU)
104  DebugAssertion::check(gpu, "Cannot lock a bitmap on GPU: no graphic pipeline instance available");
105 #endif
106 
107  auto it = bitmaps.find(bitmap);
108  if (it == bitmaps.end()) {
109  // creating a lock descriptor
110  LockDescriptor lock{
111  false, true,
112  target == ProcessingTarget::CPU,
113  target == ProcessingTarget::GPU,
114  target == ProcessingTarget::CPU, // data is locked if writing on CPU
115  1
116  };
117  bitmaps.emplace(bitmap, lock);
118 
119  // locking pixel data in RAM
120  if (lock.isDataLocked)
122  }
123 
124  else {
125  // already locked, just increase reference counter
126  auto& lock = it->second;
127 
128  if (lock.read && !lock.write)
129  throw RuntimeError("Cannot a bitmap for writing: it was locked for reading before. Lock it for writing first.");
130 
131  // lock data if needed and not yet
132  if (!lock.isDataLocked && target == ProcessingTarget::CPU) {
134  lock.isDataLocked = true;
135  }
136 
137  lock.gpu |= (target == ProcessingTarget::GPU);
138  lock.cpu |= (target == ProcessingTarget::CPU);
139 
140  lock.refs++;
141  }
142 }

◆ unlock() [1/2]

void BitmapContentLock::unlock ( AbstractBitmap bitmap)

Drops a lock to the bitmap.

If no other locks own the content, the bitmap is unlocked.

Definition at line 145 of file content_lock.cpp.

145  {
146  auto it = bitmaps.find(bitmap);
147 #ifdef BEATMUP_DEBUG
148  DebugAssertion::check(it != bitmaps.end(), "Trying to unlock a bitmap that is not locked.");
149 #endif
150 
151  auto& lock = it->second;
152  lock.refs--;
153  if (lock.refs == 0) {
154  if (lock.isDataLocked)
156 
157  if (lock.write) {
160  }
161 
162  bitmaps.erase(it);
163  }
164 }
bool upToDate[2]
bitmap up-to-date state on CPU and GPU
void unlockPixelData()
Unlocks access to the CPU memory buffer containing pixel data.

◆ unlockAll()

void BitmapContentLock::unlockAll ( )

Unlocks all the locked bitmaps unconditionally.

Definition at line 167 of file content_lock.cpp.

167  {
168  for (auto it : bitmaps) {
169  auto& lock = it.second;
170  if (lock.isDataLocked)
171  it.first->unlockPixelData();
172 
173  if (lock.write) {
174  it.first->upToDate[ProcessingTarget::CPU] = lock.cpu;
175  it.first->upToDate[ProcessingTarget::GPU] = lock.gpu;
176  }
177  }
178 
179  bitmaps.clear();
180 }

◆ lock() [1/3]

template<const ProcessingTarget target>
void Beatmup::BitmapContentLock::lock ( GraphicPipeline gpu,
AbstractBitmap input,
AbstractBitmap output 
)
inline

Definition at line 84 of file content_lock.h.

84  {
85  writeLock(gpu, output, target);
86  readLock(gpu, input, target);
87  }
void readLock(GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
Locks content of a bitmap for reading using a specific processing target device.
void writeLock(GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
Locks content of a bitmap for writing using a specific processing target device.

◆ lock() [2/3]

void Beatmup::BitmapContentLock::lock ( GraphicPipeline gpu,
ProcessingTarget  target,
AbstractBitmap input,
AbstractBitmap output 
)
inline

Definition at line 89 of file content_lock.h.

89  {
90  writeLock(gpu, output, target);
91  readLock(gpu, input, target);
92  }

◆ lock() [3/3]

template<const ProcessingTarget target>
void Beatmup::BitmapContentLock::lock ( GraphicPipeline gpu,
std::initializer_list< AbstractBitmap * >  read,
std::initializer_list< AbstractBitmap * >  write 
)
inline

Definition at line 95 of file content_lock.h.

95  {
96  for (auto bmp : write)
97  writeLock(gpu, bmp, target);
98  for (auto bmp : read)
99  readLock(gpu, bmp, target);
100  }
void write(Bitmap &bitmap, Args &&... args)
Calls a Func< WriterClass >::process(access, params) that writes to a bitmap of any kind,...
Definition: processing.h:90
void read(Bitmap &bitmap, Args &&... args)
Calls a Func< ReaderClass >::process(access, params), where.
Definition: processing.h:49

◆ unlock() [2/2]

template<typename ... Args>
void Beatmup::BitmapContentLock::unlock ( AbstractBitmap first,
Args ...  others 
)
inline

Definition at line 103 of file content_lock.h.

103  {
104  unlock(first);
105  unlock(others...);
106  }
void unlock(AbstractBitmap *bitmap)
Drops a lock to the bitmap.

Member Data Documentation

◆ bitmaps

std::map<AbstractBitmap*, LockDescriptor> Beatmup::BitmapContentLock::bitmaps
private

Definition at line 45 of file content_lock.h.


The documentation for this class was generated from the following files: