Beatmup
pixelwise_filter.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2020, 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 "pixelwise_filter.h"
20 #include "../exception.h"
21 
22 using namespace Beatmup;
23 
24 const std::string Filters::PixelwiseFilter::GLSL_RGBA_INPUT("input");
25 
26 
28  inputBitmap(nullptr), outputBitmap(nullptr), shader(nullptr)
29 {}
30 
31 
33  delete shader;
34 }
35 
36 
38  NullTaskInput::check(inputBitmap, "input bitmap");
39  // if there are few pixels, do not use many threads
40  static const int MIN_PIXEL_COUNT_PER_THREAD = 64;
41  return AbstractTask::validThreadCount(inputBitmap->getWidth() * inputBitmap->getHeight() / MIN_PIXEL_COUNT_PER_THREAD);
42 }
43 
44 
46  NullTaskInput::check(inputBitmap, "input bitmap");
47  NullTaskInput::check(outputBitmap, "output bitmap");
49  inputBitmap->getWidth() == outputBitmap->getWidth() &&
50  inputBitmap->getHeight() <= outputBitmap->getHeight(),
51  "Incompatible input and output bitmaps sizes");
52 
53  // use GPU is available and the input bitmap is up to date on GPU
54  const bool useGpu = (target == ProcessingTarget::GPU && inputBitmap->isUpToDate(ProcessingTarget::GPU));
55 
56  // deferred shader preparation
57  if (useGpu) {
58  RuntimeError::check(inputBitmap->getContext() == outputBitmap->getContext(),
59  "Input and output bitmaps are not attached to the same context");
60  if (shader && !shader->usesContext(inputBitmap->getContext())) {
61  delete shader;
62  shader = nullptr;
63  }
64  if (!shader) {
65  shader = new ImageShader(inputBitmap->getContext());
66  shader->setSourceCode(ImageShader::CODE_HEADER +
67  getGlslDeclarations() + "\n" +
68  "void main() {" +
69  "lowp vec4 " +GLSL_RGBA_INPUT+ " = texture2D(" +
72  ");\n" +
73  getGlslSourceCode() +
74  "}"
75  );
76  }
77  }
78 
79  // lock bitmaps content
80  lock(gpu, useGpu ? ProcessingTarget::GPU : ProcessingTarget::CPU, inputBitmap, outputBitmap);
81 
82  // setup
83  setup(useGpu);
84 }
85 
86 
88  unlock(inputBitmap, outputBitmap);
89 }
90 
91 
93  // each thread receives a single part of bitmap to deal with
94  const int w = inputBitmap->getWidth();
95  const msize
96  nPix = w * inputBitmap->getHeight(),
97  start = nPix * thread.currentThread() / thread.numThreads(),
98  stop = nPix * (1 + thread.currentThread()) / thread.numThreads();
99 
100  apply((int)(start % w), (int)(start / w), stop - start, thread);
101  return true;
102 }
103 
104 
106  shader->prepare(gpu, inputBitmap, outputBitmap);
107  shader->process(gpu);
108  return true;
109 }
110 
111 
113  NullTaskInput::check(inputBitmap, "input bitmap");
114  return inputBitmap->isUpToDate(ProcessingTarget::GPU) ?
115  TaskDeviceRequirement::GPU_ONLY : TaskDeviceRequirement::CPU_ONLY;
116 }
117 
118 
120  return "";
121 }
122 
123 
125  // nothing to do by default
126 }
static ThreadIndex validThreadCount(int number)
Valid thread count from a given integer value.
Definition: parallelism.cpp:45
TaskDeviceRequirement
Specifies which device (CPU and/or GPU) is used to run the task.
Definition: parallelism.h:95
virtual std::string getGlslDeclarations() const
Provides GLSL declarations used in the GLSL code.
virtual void beforeProcessing(ThreadIndex threadCount, ProcessingTarget target, GraphicPipeline *gpu)
Instruction called before the task is executed.
virtual TaskDeviceRequirement getUsedDevices() const final
Communicates devices (CPU and/or GPU) the task is run on.
virtual void afterProcessing(ThreadIndex threadCount, GraphicPipeline *gpu, bool aborted)
Instruction called after the task is executed.
virtual bool processOnGPU(GraphicPipeline &gpu, TaskThread &thread) final
Executes the task on GPU.
virtual void setup(bool useGpu)
A callback run every time before the filter is applied to the image.
virtual bool process(TaskThread &thread) final
Executes the task on CPU within a given thread.
ThreadIndex getMaxThreads() const
Gives the upper limint on the number of threads the task may be performed by.
static const std::string GLSL_RGBA_INPUT
static const char * TEXTURE_COORDINATES_ID
Texture coordinates shader variable name in vertex shader.
Internal low-level GPU control API.
Definition: pipeline.h:33
A GLSL program to process images.
Definition: image_shader.h:34
static const std::string CODE_HEADER
Shader code header containing necessary declarations.
Definition: image_shader.h:114
static const std::string INPUT_IMAGE_ID
Shader variable name referring to the input image.
Definition: image_shader.h:109
static void check(const void *pointer, const char *which)
Definition: exception.h:115
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
Thread executing tasks.
Definition: parallelism.h:154
virtual ThreadIndex numThreads() const =0
ThreadIndex currentThread() const
Definition: parallelism.h:165
uint32_t msize
memory size
Definition: basic_types.h:30
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
ProcessingTarget
Definition: basic_types.h:55
jlong jstring jint jint jint jint w
jlong jint start