Beatmup
external_bitmap.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 "external_bitmap.h"
20 #include <core/context.h>
21 #include <core/gpu/bgl.h>
22 #include <core/debug.h>
23 
24 
25 using namespace Beatmup;
26 using namespace Android;
27 
28 namespace Beatmup {
29  /**
30  Task generating a valid OpenGL texture handle.
31  Used to produce handles for external textures.
32  */
34  private:
37 
39  ctx(ctx)
40  {}
41 
43  glGenTextures(1, &textureHandle);
44  return true;
45  }
46 
47  bool process(TaskThread& thread) {
48  return false;
49  }
50 
52  return TaskDeviceRequirement::GPU_ONLY;
53  }
54 
55  public:
58  ctx.performTask(me);
59  return me.textureHandle;
60  }
61  };
62 }
63 
64 
66  width = height = 0;
68  textureUpdated = false;
69  persistentJEnv = nullptr;
70  jvm = nullptr;
71 }
72 
73 
74 void ExternalBitmap::bind(JNIEnv* jenv, jobject frontend) {
75  jenv->GetJavaVM(&jvm);
76 
77  // grab classes
78  jclass externalBitmapClass = jenv->FindClass("Beatmup/Android/ExternalBitmap");
79  jclass surfaceTextureClass = jenv->FindClass("android/graphics/SurfaceTexture");
80 
81 #ifdef BEATMUP_DEBUG
82  if (!externalBitmapClass) {
83  BEATMUP_DEBUG_E("Cannot find class Beatmup.Android.ExternalImage");
84  return;
85  }
86 
87  if (!surfaceTextureClass) {
88  BEATMUP_DEBUG_E("Cannot find class android.graphics.SurfaceTexture");
89  return;
90  }
91 #endif
92 
93  // grab field id
94  jfieldID surfaceTextureFieldId = jenv->GetFieldID(externalBitmapClass, "surfaceTexture", "Landroid/graphics/SurfaceTexture;");
95 #ifdef BEATMUP_DEBUG
96  if (!surfaceTextureFieldId) {
97  BEATMUP_DEBUG_E("Cannot find field surfaceTexture in Beatmup.Android.ExternalImage");
98  return;
99  }
100 #endif
101 
102  // grab method ids
103  jmethodID surfaceTextureConstructor = jenv->GetMethodID(surfaceTextureClass, "<init>", "(I)V");
104  updateTexImageMethodId = jenv->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
105 #ifdef BEATMUP_DEBUG
106  if (!surfaceTextureConstructor) {
107  BEATMUP_DEBUG_E("Cannot find SurfaceTexture constructor");
108  return;
109  }
110 
111  if (!updateTexImageMethodId) {
112  BEATMUP_DEBUG_E("Cannot find SurfaceTexture.updateTexImage method");
113  return;
114  }
115 #endif
116 
117  // create an instance of SurfaceTexture
118  jobject newSurfaceTextureObject = jenv->NewObject(surfaceTextureClass, surfaceTextureConstructor, this->textureHandle);
119 #ifdef BEATMUP_DEBUG
120  if (!newSurfaceTextureObject) {
121  BEATMUP_DEBUG_E("Cannot create SurfaceTexture instance");
122  return;
123  }
124 #endif
125 
126  // keep a global reference
127  surfaceTexture = jenv->NewGlobalRef(newSurfaceTextureObject);
128 
129  // set field value
130  jenv->SetObjectField(frontend, surfaceTextureFieldId, newSurfaceTextureObject);
131 
132  // clean up
133  jenv->DeleteLocalRef(externalBitmapClass);
134  jenv->DeleteLocalRef(surfaceTextureClass);
135 }
136 
137 
139  if (jvm) {
140  JNIEnv *jenv;
141  jvm->AttachCurrentThread(&jenv, nullptr);
142  jenv->DeleteGlobalRef(surfaceTexture);
143  }
144 }
145 
146 
147 void ExternalBitmap::notifyUpdate(const int width, const int height) {
148  this->width = width;
149  this->height = height;
150  this->textureUpdated = true;
151 }
152 
153 
155  TextureHandler::prepare(gpu);
156 
157  // call updateTexImage()
158  glBindTexture(GL_TEXTURE_EXTERNAL_OES, this->textureHandle);
159  if (textureUpdated && jvm) {
160  if (!persistentJEnv)
161  jvm->AttachCurrentThread(&persistentJEnv, nullptr);
163  textureUpdated = false;
164  }
165 
166  glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
167  glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
168 }
A very basic class for any image.
Task: an operation that can be executed by multiple threads in parallel.
Definition: parallelism.h:90
TaskDeviceRequirement
Specifies which device (CPU and/or GPU) is used to run the task.
Definition: parallelism.h:95
Android context.
Definition: context.h:32
virtual void prepare(GraphicPipeline &gpu)
Prepares (eventually uploads) texture data on GPU.
void bind(JNIEnv *jenv, jobject frontend)
Attaches the bitmap object to its Java frontend and initializes the surface texture in it.
ExternalBitmap(Beatmup::Context &ctx)
Instantiates external image.
void notifyUpdate(const int width, const int height)
Basic class: task and memory management, any kind of static data.
Definition: context.h:59
float performTask(AbstractTask &task, const PoolIndex pool=DEFAULT_POOL)
Performs a given task.
Definition: context.cpp:240
Internal low-level GPU control API.
Definition: pipeline.h:33
Thread executing tasks.
Definition: parallelism.h:154
Task generating a valid OpenGL texture handle.
Beatmup::GL::handle_t textureHandle
bool process(TaskThread &thread)
Executes the task on CPU within a given thread.
TaskDeviceRequirement getUsedDevices() const
Communicates devices (CPU and/or GPU) the task is run on.
bool processOnGPU(GraphicPipeline &gpu, TaskThread &)
Executes the task on GPU.
static Beatmup::GL::handle_t makeHandle(Context &ctx)
#define BEATMUP_DEBUG_E(...)
Definition: debug.h:34
unsigned int handle_t
A reference to a GPU resource.
Definition: basic_types.h:61
JNIEnv jclass
JNIEnv * jenv
JNIEnv jobject
Beatmup::Context * ctx
jlong jint width
jlong jint jint height