Beatmup
operator.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "operator.h"
20 #include "bitmap_access.h"
21 #include "mask_bitmap_access.h"
22 
23 
24 using namespace Beatmup;
25 
26 
27 namespace Kernels {
28 
29  template<class in_t, class out_t> class BinaryOpBody {
30  public:
31 
32  /**
33  Performs a binary operation on two bitmaps
34  */
35  static void process(
36  in_t op1, in_t op2, out_t out,
38  int width, int height,
39  const IntPoint& op1Origin,
40  const IntPoint& op2Origin,
41  const IntPoint& outOrigin,
42  const TaskThread& tt
43  ) {
45  return;
46 
47  for (int y = tt.currentThread(); y < height; y += tt.numThreads()) {
48  op1.goTo(op1Origin.x, op1Origin.y + y);
49  op2.goTo(op2Origin.x, op2Origin.y + y);
50  out.goTo(outOrigin.x, outOrigin.y + y);
51 
52  switch (operation) {
54  for (int x = 0; x < width; ++x, op1++, op2++, out++) {
55  out = op1() + op2();
56  }
57  break;
58 
60  for (int x = 0; x < width; ++x, op1++, op2++, out++) {
61  out = op1() * op2();
62  }
63  break;
64 
65  default: return;
66  }
67 
68  if (tt.isTaskAborted())
69  return;
70  }
71  }
72 
73 
74  /**
75  Performs a binary operation on two binary masks
76  */
78  in_t op1, in_t op2, out_t out,
80  int width, int height,
81  const IntPoint &op1Origin,
82  const IntPoint &op2Origin,
83  const IntPoint &outOrigin,
84  const TaskThread &tt
85  ) {
87  return;
88 
89  BEATMUP_ASSERT_DEBUG(op1Origin.x % 8 == 0);
90  BEATMUP_ASSERT_DEBUG(op2Origin.x % 8 == 0);
92 
93  for (int y = tt.currentThread(); y < height; y += tt.numThreads()) {
94  int x = 0;
95 
96  // running aligned part first
97  op1.goTo(op1Origin.x, op1Origin.y + y);
98  op2.goTo(op2Origin.x, op2Origin.y + y);
99  out.goTo(outOrigin.x, outOrigin.y + y);
100 
102  *p1 = (pixint_platform*)*op1,
103  *p2 = (pixint_platform*)*op2,
104  *po = (pixint_platform*)*out;
105 
106  static const int step = 8 * sizeof(pixint_platform);
107 
108  switch (operation) {
110  for (x = 0; x + step <= width; x += step, p1++, p2++, po++) {
111  *po = *p1 | *p2;
112  }
113  break;
114 
116  for (x = 0; x + step <= width; x += step, p1++, p2++, po++) {
117  *po = *p1 & *p2;
118  }
119  break;
120 
121  default: return;
122  }
123 
124  // if unaligned reminder, deal with it
125  if (x < width) {
126  op1.goTo(op1Origin.x + x, op1Origin.y + y);
127  op2.goTo(op2Origin.x + x, op2Origin.y + y);
128  out.goTo(outOrigin.x + x, outOrigin.y + y);
129 
130  switch (operation) {
132  for (; x < width; ++x, op1++, op2++, out++) {
133  out = op1() + op2();
134  }
135  break;
136 
138  for (; x < width; ++x, op1++, op2++, out++) {
139  out = op1() * op2();
140  }
141  break;
142 
143  default: return;
144  }
145 
146  }
147 
148  if (tt.isTaskAborted())
149  return;
150  }
151  }
152  };
153 }
154 
155 
157  op1(nullptr), op2(nullptr), output(nullptr),
158  operation(Operation::NONE)
159 {}
160 
161 
163  this->op1 = bitmap;
164 }
165 
166 
168  this->op2 = bitmap;
169 }
170 
171 
173  this->output = bitmap;
174 }
175 
176 
178  this->operation = operation;
179 }
180 
181 
183  this->cropWidth = width;
184  this->cropHeight = height;
185 }
186 
187 
189  this->op1Origin = origin;
190 }
191 
192 
194  this->op2Origin = origin;
195 }
196 
197 
199  this->outputOrigin = origin;
200 }
201 
202 
204  if (op1 && op2 && output) {
208  }
209 }
210 
211 
214 }
215 
216 
218  NullTaskInput::check(op1, "operand 1 bitmap");
219  NullTaskInput::check(op2, "operand 2 bitmap");
220  NullTaskInput::check(output, "output bitmap");
221  RuntimeError::check(op1->getPixelFormat() == op2->getPixelFormat(), "operands pixel formats do not match");
222  RuntimeError::check(op1->getPixelFormat() == output->getPixelFormat(), "output pixel format does not match operands pixel format");
223  RuntimeError::check(op1Origin.x + cropWidth <= op1->getWidth(), "operand 1 width exceeded");
224  RuntimeError::check(op1Origin.y + cropHeight <= op1->getHeight(), "operand 1 height exceeded");
225  RuntimeError::check(op2Origin.x + cropWidth <= op2->getWidth(), "operand 2 width exceeded");
226  RuntimeError::check(op2Origin.y + cropHeight <= op2->getHeight(), "operand 2 height exceeded");
227  RuntimeError::check(outputOrigin.x + cropWidth <= output->getWidth(), "operand 1 width exceeded");
228  RuntimeError::check(outputOrigin.y + cropHeight <= output->getHeight(), "operand 1 height exceeded");
229 
230 
231  lock<ProcessingTarget::CPU>(gpu, { op1, op2 }, { output });
232 }
233 
234 
236  unlock(output, op1, op2);
237 }
238 
239 
241 #define PROCESS(IN_T, OUT_T) \
242  Kernels::BinaryOpBody<IN_T, OUT_T>::process( \
243  IN_T(*op1), IN_T(*op2), OUT_T(*output), \
244  operation, cropWidth, cropHeight, op1Origin, op2Origin, outputOrigin, thread);
245 
246  switch (output->getPixelFormat()) {
247  case SingleByte:
249  break;
250  case TripleByte:
252  break;
253  case QuadByte:
255  break;
256  case SingleFloat:
258  break;
259  case TripleFloat:
261  break;
262  case QuadFloat:
264  break;
265  case BinaryMask:
266  if (op1Origin.x % 8 == 0 && op2Origin.x % 8 == 0 && outputOrigin.x % 8 == 0)
270  thread);
271  else
273  break;
274  case QuaternaryMask:
276  break;
277  case HexMask:
279  break;
280  }
281  return true;
282 }
A very basic class for any image.
virtual const PixelFormat getPixelFormat() const =0
Pixel format of the bitmap.
static ThreadIndex validThreadCount(int number)
Valid thread count from a given integer value.
Definition: parallelism.cpp:45
virtual void beforeProcessing(ThreadIndex, ProcessingTarget target, GraphicPipeline *)
Instruction called before the task is executed.
Definition: operator.cpp:217
void setOp1Origin(const IntPoint origin)
Definition: operator.cpp:188
AbstractBitmap * output
input and output bitmaps
Definition: operator.h:44
void setCropSize(int width, int height)
Definition: operator.cpp:182
void setOperand1(AbstractBitmap *op1)
Definition: operator.cpp:162
Operation
Binary operation specification.
Definition: operator.h:35
@ MULTIPLY
the input images are multiplied
@ ADD
the input images are added
@ NONE
bypass; the output bitmap remains unchanged
virtual void afterProcessing(ThreadIndex, GraphicPipeline *, bool)
Instruction called after the task is executed.
Definition: operator.cpp:235
void setOperation(const Operation operation)
Definition: operator.cpp:177
void setOutputOrigin(const IntPoint origin)
Definition: operator.cpp:198
AbstractBitmap * op2
Definition: operator.h:44
virtual ThreadIndex getMaxThreads() const
Gives the upper limint on the number of threads the task may be performed by.
Definition: operator.cpp:212
const int MIN_PIXEL_COUNT_PER_THREAD
minimum number of pixels per worker
Definition: operator.h:42
void setOutput(AbstractBitmap *output)
Definition: operator.cpp:172
AbstractBitmap * op1
Definition: operator.h:44
void setOp2Origin(const IntPoint origin)
Definition: operator.cpp:193
void setOperand2(AbstractBitmap *op2)
Definition: operator.cpp:167
virtual bool process(TaskThread &thread)
Executes the task on CPU within a given thread.
Definition: operator.cpp:240
void unlock(AbstractBitmap *bitmap)
Drops a lock to the bitmap.
static const CustomPoint ZERO
Definition: geometry.h:122
virtual const int getHeight() const =0
Height of the texture in pixels.
virtual const int getWidth() const =0
Width of the texture in pixels.
Internal low-level GPU control API.
Definition: pipeline.h:33
A generic to access sub-byte mask bitmap data.
A generic to write mask bitmap data lookup tables for masks values.
static void check(const void *pointer, const char *which)
Definition: exception.h:115
Quad byte bitmap reader.
Quad byte bitmap writer.
Quad float bitmap reader.
Quad float bitmap writer.
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Single byte bitmap reader.
Single byte bitmap writer.
Single float bitmap reader.
Single float bitmap writer.
Thread executing tasks.
Definition: parallelism.h:154
virtual ThreadIndex numThreads() const =0
ThreadIndex currentThread() const
Definition: parallelism.h:165
virtual bool isTaskAborted() const =0
Returns true if the task is asked to stop from outside.
Triple byte bitmap reader.
Triple byte bitmap writer.
Triple float bitmap reader.
Triple float bitmap writer.
static void process(in_t op1, in_t op2, out_t out, BitmapBinaryOperation::Operation operation, int width, int height, const IntPoint &op1Origin, const IntPoint &op2Origin, const IntPoint &outOrigin, const TaskThread &tt)
Performs a binary operation on two bitmaps.
Definition: operator.cpp:35
static void processAlignedBinaryMask(in_t op1, in_t op2, out_t out, BitmapBinaryOperation::Operation operation, int width, int height, const IntPoint &op1Origin, const IntPoint &op2Origin, const IntPoint &outOrigin, const TaskThread &tt)
Performs a binary operation on two binary masks.
Definition: operator.cpp:77
#define BEATMUP_ASSERT_DEBUG(C)
Definition: exception.h:163
@ NONE
no extension
Definition: program.h:64
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
LookupMaskWriter< 1, MASK_LUT_1_BIT > BinaryMaskWriter
uint32_t pixint_platform
Definition: basic_types.h:31
LookupMaskScanner< 1, MASK_LUT_1_BIT > BinaryMaskReader
@ SingleByte
single channel of 8 bits per pixel (like grayscale), unsigned integer values
@ SingleFloat
single channel of 32 bits per pixel (like grayscale), single precision floating point values
@ QuaternaryMask
2 bits per pixel
@ QuadFloat
4 channels of 32 bits per pixel, single precision floating point values,
@ TripleFloat
3 channels of 32 bits per pixel, single precision floating point values
@ QuadByte
4 channels of 8 bits per pixel (like RGBA), unsigned integer values
@ TripleByte
3 channels of 8 bits per pixel (like RGB), unsigned integer values
@ BinaryMask
1 bit per pixel
@ HexMask
4 bits per pixel
ProcessingTarget
Definition: basic_types.h:55
Operations kernels.
Definition: basic_types.h:85
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
#define PROCESS(IN_T, OUT_T)
jobject jlong jint jint y
jlong jint width
jlong jint jint height
jobject jlong jint x
JNIEnv jlong jint out
Beatmup::InternalBitmap * bitmap
Beatmup::IntPoint outOrigin(left, top)
return bitmap getWidth()
jlong jobject jobject jobject op2Origin
return bitmap getHeight()
jlong jint jfloat step
jlong jobject jobject op1Origin