Beatmup
Beatmup::GraphicPipeline::Impl Class Reference

Classes

struct  VertexAttribBufferElement
 Vertex attribute buffer entry: vertex coordinates (x,y) and texture coordinates (s,t) More...
 

Public Member Functions

 Impl (GraphicPipeline &front)
 
 ~Impl ()
 
void switchDisplay (void *data)
 Platform-dependent display switching routine. More...
 
void swapBuffers ()
 
void bindImage (GL::TextureHandler &texture, int imageUnit, bool read, bool write)
 Binds a texture handle to an image unit. More...
 
void bind (GL::TextureHandler &texture, size_t unit, const TextureParam param)
 
void bindOutput (AbstractBitmap &bitmap, const IntRectangle &viewport)
 
void bindOutput (GL::TextureHandler &textureHandler)
 
void bindOutput (GL::handle_t texture)
 
void unbindOutput ()
 
const ImageResolutiongetDisplayResolution () const
 
void pullPixels (AbstractBitmap &bitmap)
 Transfers texture data from GPU to CPU. More...
 
void pushPixels (AbstractBitmap &bitmap)
 Transfers texture data from CPU to GPU. More...
 
int getLimit (GraphicPipeline::Limit limit) const
 
int getSharedMemSize () const
 
void switchMode (GraphicPipeline::Mode mode)
 
void setTextureCoordinates (const Rectangle &coords)
 
void setTextureCoordinates (const Point &leftTop, const Point &rightTop, const Point &leftBottom, const Point &rightBottom)
 
int getGlslVersion () const
 
bool isGlEsCompliant () const
 

Private Attributes

GraphicPipelinefront
 
GLuint hFrameBuffer
 
VertexAttribBufferElement vertexAttribBuffer [4]
 
bool isRectangularTextureCoordinates
 if true, the texture coordinates is a rectangle More...
 
GLuint hVertexAttribBuffer
 buffer used when rendering More...
 
ImageResolution displayResolution
 width and height of a display obtained when switching More...
 
bool isGlEs
 if true, the use OpenGL context is GL ES-compliant More...
 
int glslVersion
 GLSL language version to put into shaders code, e.g. 100 for 1.00. More...
 
Display * xDisplay
 
Window xWindow
 
GLXContext glxContext
 
GLXPbuffer glxPbuffer
 
struct {
   int   maxTextureImageUnits
 
   int   maxFragmentUniformVectors
 
   int   maxWorkGroupCount [3]
 
   int   maxWorkGroupSize [3]
 
   int   maxTotalWorkGroupSize
 
   msize   maxSharedMemSize
 
glLimits
 

Detailed Description

Definition at line 59 of file pipeline.cpp.

Constructor & Destructor Documentation

◆ Impl()

Beatmup::GraphicPipeline::Impl::Impl ( GraphicPipeline front)
inline

Definition at line 115 of file pipeline.cpp.

115  : front(front), glslVersion(0) {
116 
117 #ifdef BEATMUP_OPENGLVERSION_GLES
118  // Step 1 - Get the default display.
119  if ((eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
120  throw GpuOperationError("EGL: no display", eglGetError());
121 
122  // Step 2 - Initialize EGL.
123  if (!eglInitialize(eglDisplay, 0, 0)) {
124 
125 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
126  BEATMUP_DEBUG_I("DRM fallback");
127 
128  // set up DRM and GBM resources
129  const char* DRI_DEVICE = std::getenv("BEATMUP_DRI_DEVICE");
130  static const char* DEFAULT_DRI_DEVICE = "/dev/dri/card1";
131  DRM::Device device(DRI_DEVICE ? DRI_DEVICE : DEFAULT_DRI_DEVICE);
132  DRM::ModeResources resources(device);
133  DRM::ModeConnector connector(device, resources);
134  DRM::ModeEncoder encoder(device, connector);
135  DRM::ModeCrtc crtc(device, encoder, connector);
136  DRM::GBMDevice gbmDevice(device, connector);
137  DRM::GBMSurface gbmSurface(gbmDevice, connector);
138 
139  // get display again
140  eglDisplay = eglGetDisplay(gbmDevice.getPointer());
141 
142  if (!eglDisplay) {
143  throw GpuOperationError("EGL/DRM: cannot get display");
144  }
145 
146  if (!eglInitialize(eglDisplay, 0, 0)) {
147  throw GpuOperationError("EGL/DRM: cannot initialize display");
148  }
149 
150  // keep DRM and GBM persistent resources
151  this->drmDevice = std::move(device);
152  this->drmConnector = std::move(connector);
153  this->drmCrtc = std::move(crtc);
154  this->gbmDevice = std::move(gbmDevice);
155  this->gbmSurface = std::move(gbmSurface);
156 #else
157  auto err = eglGetError();
158  if (err == EGL_NOT_INITIALIZED)
159  throw GpuOperationError("EGL: display not initialized", err);
160  else
161  throw GpuOperationError("EGL: initialization failed", err);
162 #endif
163  }
164 
165  // Step 3 - Make OpenGL ES the current API.
166  eglBindAPI(EGL_OPENGL_ES_API);
167 
168  // Step 4 - Specify the required configuration attributes.
169  static const int CONFIG_ATTRIBUTES_LEN = 5;
170  EGLint configAttributes[CONFIG_ATTRIBUTES_LEN] = {
171 #ifdef BEATMUP_OPENGLVERSION_GLES20
172  EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
173 #elif defined BEATMUP_OPENGLVERSION_GLES31
174  EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
175 #endif
176  EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
177  EGL_NONE
178  };
179 
180 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
181  if (drmDevice) {
182  // using DRM: shrinking config attributes at EGL_SURFACE_TYPE
183  configAttributes[CONFIG_ATTRIBUTES_LEN - 3] = EGL_NONE;
184  }
185 #endif
186 
187  // get number of configs
188  int totalConfigCount;
189  eglGetConfigs(eglDisplay, nullptr, 0, &totalConfigCount);
190  std::vector<EGLConfig> configs;
191  configs.resize(totalConfigCount);
192 
193  // get configs themselves
194  int numConfigs;
195  if (!eglChooseConfig(eglDisplay, configAttributes, configs.data(), totalConfigCount, &numConfigs))
196  throw GpuOperationError("EGL: bad configuration", eglGetError());
197  BEATMUP_DEBUG_I("Number of EGL configs got: %d", numConfigs);
198 
199 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
200  if (drmDevice) {
201  // find one matching the GBM format
202  bool found = false;
203  for (int i = 0; i < totalConfigCount && !found; ++i) {
204  EGLint val;
205  if (EGL_TRUE != eglGetConfigAttrib(eglDisplay, configs[i], EGL_RED_SIZE, &val) || val != 8)
206  continue;
207  if (EGL_TRUE != eglGetConfigAttrib(eglDisplay, configs[i], EGL_GREEN_SIZE, &val) || val != 8)
208  continue;
209  if (EGL_TRUE != eglGetConfigAttrib(eglDisplay, configs[i], EGL_BLUE_SIZE, &val) || val != 8)
210  continue;
211  if (EGL_TRUE != eglGetConfigAttrib(eglDisplay, configs[i], EGL_ALPHA_SIZE, &val) || val != 8)
212  continue;
213  eglConfig = configs[i];
214  found = true;
215  }
216  if (!found)
217  throw GpuOperationError("EGL/DRM: no config matching the required surface format");
218  }
219  else
220 #endif
221  {
222  eglConfig = configs[0];
223  }
224 
225 
226  // Step 5 - Create a context.
227  EGLint contextAttributes[] = {
228  EGL_CONTEXT_CLIENT_VERSION,
229 #ifdef BEATMUP_OPENGLVERSION_GLES20
230  2,
231 #elif defined BEATMUP_OPENGLVERSION_GLES31
232  3,
233 #endif
234  EGL_NONE
235  };
236  eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttributes);
237  if (eglContext == EGL_NO_CONTEXT)
238  throw GpuOperationError("EGL: context initialization failed", eglGetError());
239 
240 
241  // Step 6 - Create a surface to draw to.
242  eglDefaultSurface = eglSurface = EGL_NO_SURFACE;
243 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
244  if (drmDevice) {
245  eglDefaultSurface = eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, gbmSurface.getPointer(), nullptr);
246  }
247  else
248 #endif
249  {
250  EGLint surfaceAttributes[] = {
251  EGL_WIDTH, 2, // eglMakeCurrent fails sometimes with zero sizes
252  EGL_HEIGHT, 2,
253  EGL_NONE
254  };
255 
256  eglDefaultSurface = eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttributes);
257  }
258 
259  if (eglSurface == EGL_NO_SURFACE)
260  throw GpuOperationError("EGL: window surface creation failed when init", eglGetError());
261 
262  // Step 7 - Bind the context to the current thread
263  if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
264  throw GpuOperationError("EGL: making current", eglGetError());
265 
266 #ifdef BEATMUP_OPENGLVERSION_GLES20
267  // if ES 2.0, forcing GLSL version; otherwise it is queried later on
268  glslVersion = 100;
269  isGlEs = true;
270 #endif
271 
272 #elif BEATMUP_PLATFORM_WINDOWS
273  PIXELFORMATDESCRIPTOR pfd;
274  memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
275  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
276  pfd.nVersion = 1;
277  pfd.dwFlags = PFD_SUPPORT_OPENGL;
278  pfd.iPixelType = PFD_TYPE_RGBA;
279  pfd.cColorBits = 32;
280  pfd.cDepthBits = 16;
281  pfd.iLayerType = PFD_MAIN_PLANE;
282  hwnd = CreateWindowEx(WS_EX_TOOLWINDOW,
283 #ifdef UNICODE
284  L"STATIC", L"glctx",
285 #else
286  "STATIC", "glctx",
287 #endif
288  WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
289  0, 0, 1, 1, 0, 0, GetModuleHandle(NULL), 0);
290  if (!hwnd)
291  throw GpuOperationError("Unable to initialize GL context");
292 
293  ShowWindow(hwnd, SW_HIDE);
294  HDC hdc = GetDC(hwnd);
295  int pixelFormat = ChoosePixelFormat(hdc, &pfd);
296  SetPixelFormat(hdc, pixelFormat, &pfd);
297  hglrc = wglCreateContext(hdc);
298  wglMakeCurrent(hdc, hglrc);
299  if (!wglGetCurrentContext())
300  throw GpuOperationError("Unable to initialize GL context");
301 
302  // init glew
303  glewExperimental = GL_TRUE;
304  GLenum err = glewInit();
305  if (err != GLEW_OK)
306  throw GpuOperationError((const char*)glewGetErrorString(err));
307 
308 #else
309  // creating a display & a window
310  xDisplay = XOpenDisplay(0);
311  if (xDisplay == nullptr)
312  throw GpuOperationError("Cannot open a display connection to X11 server");
313  xWindow = XCreateSimpleWindow(xDisplay, DefaultRootWindow(xDisplay),
314  0, 0, /* x, y */
315  1, 1, /* width, height */
316  0, 0, /* border_width, border */
317  0); /* background */
318 
319  // setup a bootstrap context to load glew
320  static int bootstapVisualAttrs[] = { GLX_RGBA, None };
321  XVisualInfo* vi = glXChooseVisual(xDisplay, 0, bootstapVisualAttrs);
322  glxContext = glXCreateContext(xDisplay, vi, nullptr, GL_TRUE);
323  glXMakeCurrent(xDisplay, xWindow, glxContext);
324 
325  // power on glew
326  glewExperimental = GL_TRUE;
327  GLenum err = glewInit();
328  if (err != GLEW_OK)
329  throw GpuOperationError((const char*)glewGetErrorString(err));
330 
331  // destroying the bootstrap context
332  glXDestroyContext(xDisplay, glxContext);
333 
334  static int visualAttrs[] = {
335  GLX_DOUBLEBUFFER, false,
336  None
337  };
338  int numFbc = 0;
339  GLXFBConfig *config = glXChooseFBConfig(xDisplay, DefaultScreen(xDisplay),
340  visualAttrs, &numFbc);
341  if (!config)
342  throw GpuOperationError("Choosing framebuffer configuration failed");
343 
344  // create pbuffer
345  static int pbufferAttrs[] = {
346  GLX_PBUFFER_WIDTH, 1,
347  GLX_PBUFFER_HEIGHT, 1,
348  GLX_LARGEST_PBUFFER,
349  None
350  };
351  glxPbuffer = glXCreatePbuffer(xDisplay, config[0], pbufferAttrs);
352 
353  // create main context
354  vi = glXGetVisualFromFBConfig(xDisplay, config[0]);
355  glxContext = glXCreateContext(xDisplay, vi, 0, GL_TRUE);
356  glXMakeCurrent(xDisplay, glxPbuffer, glxContext);
357 
358 #endif
359 
360  // query GL limits
361  glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glLimits.maxTextureImageUnits);
362  glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &glLimits.maxFragmentUniformVectors);
363 #ifndef BEATMUP_OPENGLVERSION_GLES20
364  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, glLimits.maxWorkGroupCount + 0);
365  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, glLimits.maxWorkGroupCount + 1);
366  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, glLimits.maxWorkGroupCount + 2);
367  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, glLimits.maxWorkGroupSize + 0);
368  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, glLimits.maxWorkGroupSize + 1);
369  glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, glLimits.maxWorkGroupSize + 2);
370  glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &glLimits.maxTotalWorkGroupSize);
371  glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, (GLint*)&glLimits.maxSharedMemSize);
372 #else
373  glLimits.maxWorkGroupCount[0] = glLimits.maxWorkGroupCount[1] = glLimits.maxWorkGroupCount[2] = 0;
374  glLimits.maxWorkGroupSize[0] = glLimits.maxWorkGroupSize[1] = glLimits.maxWorkGroupSize[2] = 0;
375  glLimits.maxTotalWorkGroupSize = 0;
376  glLimits.maxSharedMemSize = 0;
377 #endif
378 
379 #ifdef BEATMUP_DEBUG
380  {
381  const char
382  *vendor = (char*)glGetString(GL_VENDOR),
383  *renderer = (char*)glGetString(GL_RENDERER),
384  *glslVersionStr = (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
385  BEATMUP_DEBUG_I("__________________________________________________________");
386  BEATMUP_DEBUG_I("Beatmup GL startup: %s / %s, %s", renderer, vendor, glslVersionStr);
387 #ifndef BEATMUP_OPENGLVERSION_GLES20
388  BEATMUP_DEBUG_I(" - Max workgroups: %d, %d, %d",
389  glLimits.maxWorkGroupCount[0], glLimits.maxWorkGroupCount[1], glLimits.maxWorkGroupCount[2]);
390  BEATMUP_DEBUG_I(" - Max local groups: %d, %d, %d / %d",
391  glLimits.maxWorkGroupSize[0], glLimits.maxWorkGroupSize[1], glLimits.maxWorkGroupSize[2], glLimits.maxTotalWorkGroupSize);
392  BEATMUP_DEBUG_I(" - Shared memory: %lu KB", (unsigned long)(glLimits.maxSharedMemSize / 1024));
393 #endif
394  BEATMUP_DEBUG_I("__________________________________________________________");
395  }
396 #endif
397 
398  // get glsl version if not set
399  if (glslVersion == 0) {
400  // GLSL version can be forced with an environmental variable
401  const char* FORCED_GLSL_VERSION = std::getenv("BEATMUP_GLSL_VERSION");
402  std::string versionStr(FORCED_GLSL_VERSION ? FORCED_GLSL_VERSION : (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
403 
404  // check if running OpenGL ES
405  static const std::string ES_PREFIX = "OpenGL ES GLSL ES ";
406  // according to the standard docs, for GL ES GL_SHADING_LANGUAGE_VERSION starts with this prefix
407  isGlEs = versionStr.substr(0, ES_PREFIX.length()) == ES_PREFIX;
408  if (isGlEs)
409  versionStr = versionStr.substr(ES_PREFIX.length());
410 
411  // getting major and minor version numbers
412  auto spacePos = versionStr.find(" ");
413  if (spacePos == std::string::npos)
414  spacePos = versionStr.length();
415  versionStr = versionStr.substr(0, spacePos);
416  auto dotPos = versionStr.find(".");
417  if (dotPos == std::string::npos)
418  throw GL::GLException("Cannot determine GLSL version from string '" + versionStr + "'");
419  const int majVer = std::stoi(versionStr.substr(0, dotPos));
420  const int minVer = std::stoi(versionStr.substr(dotPos + 1));
421  glslVersion = 100 * majVer + minVer;
422  }
423 
424  // init buffers
425  glGenFramebuffers(1, &hFrameBuffer);
426  GL::GLException::check("initialization");
427 
428  // init attribute buffers
429  glGenBuffers(1, &hVertexAttribBuffer);
430  glBindBuffer(GL_ARRAY_BUFFER, hVertexAttribBuffer);
431  vertexAttribBuffer[0] = { 0.0f, 0.0f, 0.0f, 0.0f };
432  vertexAttribBuffer[1] = { 1.0f, 0.0f, 1.0f, 0.0f };
433  vertexAttribBuffer[2] = { 0.0f, 1.0f, 0.0f, 1.0f };
434  vertexAttribBuffer[3] = { 1.0f, 1.0f, 1.0f, 1.0f };
436 
437  glEnableVertexAttribArray(GraphicPipeline::ATTRIB_VERTEX_COORD);
438  glEnableVertexAttribArray(GraphicPipeline::ATTRIB_TEXTURE_COORD);
439  glVertexAttribPointer(GraphicPipeline::ATTRIB_VERTEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(VertexAttribBufferElement), nullptr);
440  glVertexAttribPointer(GraphicPipeline::ATTRIB_TEXTURE_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(VertexAttribBufferElement), (void*)(2 * sizeof(GLfloat)));
441  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
442  glBufferData(GL_ARRAY_BUFFER, sizeof(vertexAttribBuffer), vertexAttribBuffer, GL_STATIC_DRAW);
443 
444  // setting up main controls
445  glDisable(GL_DEPTH_TEST);
446  glDisable(GL_CULL_FACE);
447  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
448  glBlendColor(1.0f, 1.0f, 1.0f, 1.0f);
449  switchMode(GraphicPipeline::Mode::RENDERING);
450  GL::GLException::check("initial GPU setup");
451  }
GPU exception.
Definition: bgl.h:56
bool isGlEs
if true, the use OpenGL context is GL ES-compliant
Definition: pipeline.cpp:78
bool isRectangularTextureCoordinates
if true, the texture coordinates is a rectangle
Definition: pipeline.cpp:73
void switchMode(GraphicPipeline::Mode mode)
Definition: pipeline.cpp:804
GLuint hVertexAttribBuffer
buffer used when rendering
Definition: pipeline.cpp:74
VertexAttribBufferElement vertexAttribBuffer[4]
Definition: pipeline.cpp:72
struct GraphicPipeline::Impl::@15 glLimits
GraphicPipeline & front
Definition: pipeline.cpp:68
int glslVersion
GLSL language version to put into shaders code, e.g. 100 for 1.00.
Definition: pipeline.cpp:79
#define BEATMUP_DEBUG_I(...)
Definition: debug.h:33
jlong jint jint jint jint pixelFormat
return(jlong) new Beatmup jlong jstring jint val
Beatmup::SceneRenderer * renderer

◆ ~Impl()

Beatmup::GraphicPipeline::Impl::~Impl ( )
inline

Definition at line 454 of file pipeline.cpp.

454  {
455  glDeleteFramebuffers(1, &hFrameBuffer);
456 
457 #ifdef BEATMUP_OPENGLVERSION_GLES
458  eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
459  if (eglSurface != EGL_NO_SURFACE && eglSurface != eglDefaultSurface)
460  eglDestroySurface(eglDisplay, eglSurface);
461  eglDestroySurface(eglDisplay, eglDefaultSurface);
462  eglDestroyContext(eglDisplay, eglContext);
463  eglTerminate(eglDisplay);
464 #elif BEATMUP_PLATFORM_WINDOWS
465  wglDeleteContext(hglrc);
466  DestroyWindow(hwnd);
467 #else
468  glXDestroyContext(xDisplay, glxContext);
469  glXDestroyPbuffer(xDisplay, glxPbuffer);
470  XCloseDisplay(xDisplay);
471 #endif
472  }

Member Function Documentation

◆ switchDisplay()

void Beatmup::GraphicPipeline::Impl::switchDisplay ( void *  data)
inline

Platform-dependent display switching routine.

Definition at line 478 of file pipeline.cpp.

478  {
479 #ifdef BEATMUP_PLATFORM_WINDOWS
480  throw GL::Unsupported("switchDisplay is not implemented on Windows");
481 #elif BEATMUP_PLATFORM_ANDROID
482  // disconnecting old surface
483  eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
484  if (eglSurface != EGL_NO_SURFACE && eglSurface != eglDefaultSurface)
485  eglDestroySurface(eglDisplay, eglSurface);
486 
487  if (data) {
488  // create a surface to draw to
489  EGLint surfaceAttributes[] = {
490  EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
491  EGL_NONE
492  };
493 
494  eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (ANativeWindow*)data, surfaceAttributes);
495  if (eglSurface == EGL_NO_SURFACE)
496  throw GpuOperationError("EGL: window surface creation failed when switching display", eglGetError());
497 
498  // bind the context to the current thread
499  if (! eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
500  throw GpuOperationError("EGL: switching display", eglGetError());
501 
502  // setting viewport
503  displayResolution.set(ANativeWindow_getWidth((ANativeWindow*)data), ANativeWindow_getHeight((ANativeWindow*)data));
504  glViewport(0, 0, displayResolution.getWidth(), displayResolution.getHeight());
505  }
506  else {
507  eglSurface = eglDefaultSurface;
508  if (! eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
509  throw GpuOperationError("EGL: making current", eglGetError());
510  //fixme: what about display resolution?
511  }
512 #endif
513 
514  glDisable(GL_DEPTH_TEST);
515  glDisable(GL_CULL_FACE);
516  glEnable(GL_BLEND);
517  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
518  glBlendColor(1.0f, 1.0f, 1.0f, 1.0f);
519  }
Exception communicating the use of an unsupported feature on GPU.
Definition: bgl.h:72
unsigned int getWidth() const
void set(unsigned int width, unsigned int height)
unsigned int getHeight() const
ImageResolution displayResolution
width and height of a display obtained when switching
Definition: pipeline.cpp:76

◆ swapBuffers()

void Beatmup::GraphicPipeline::Impl::swapBuffers ( )
inline

Definition at line 522 of file pipeline.cpp.

522  {
523  glFinish();
524 #ifdef BEATMUP_PLATFORM_WINDOWS
525  throw GL::Unsupported("swapBuffers is not implemented on Windows");
526 #elif BEATMUP_OPENGLVERSION_GLES
527  if (! eglSwapBuffers(eglDisplay, eglSurface))
528  throw GpuOperationError("EGL: swapping buffers", eglGetError());
529 #endif
530  }

◆ bindImage()

void Beatmup::GraphicPipeline::Impl::bindImage ( GL::TextureHandler texture,
int  imageUnit,
bool  read,
bool  write 
)
inline

Binds a texture handle to an image unit.

Parameters
[in]textureThe texture handler
[in]imageUnitThe image unit number
[in]readIf true, the image will be read
[in]writeIf true, the image will be modified

Definition at line 540 of file pipeline.cpp.

540  {
541 #ifdef BEATMUP_OPENGLVERSION_GLES20
542  throw GL::Unsupported("Images binding is not supported in GL ES 2.0.");
543 #else
544 
545  texture.prepare(front);
546 
547  // if the following is not set, black images are out when writing with imageStore()
548  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
549  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
550 
551  // binding, actually
552  glBindImageTexture(imageUnit,
553  texture.textureHandle,
554  0, texture.getDepth() > 1 ? GL_TRUE : GL_FALSE, 0,
555  read && write ? GL_READ_WRITE : (write ? GL_WRITE_ONLY : GL_READ_ONLY),
557  );
558  GL::GLException::check("preparing image unit");
559 #endif
560  }
virtual const int getDepth() const =0
Depth of the texture in pixels.
virtual void prepare(GraphicPipeline &gpu)
Prepares (eventually uploads) texture data on GPU.
virtual const TextureFormat getTextureFormat() const =0
Returns the texture format specifying how the shader must interpret the data.
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
const GLuint TEXTUREHANDLER_INTERNALFORMATS[]
Definition: bgl.h:128

◆ bind()

void Beatmup::GraphicPipeline::Impl::bind ( GL::TextureHandler texture,
size_t  unit,
const TextureParam  param 
)
inline

Definition at line 563 of file pipeline.cpp.

563  {
564  glActiveTexture(GL_TEXTURE0 + unit);
565  switch (texture.getTextureFormat()) {
566  case GL::TextureHandler::TextureFormat::Rx8:
567  case GL::TextureHandler::TextureFormat::RGBx8:
568  case GL::TextureHandler::TextureFormat::RGBAx8:
569  texture.prepare(front);
570  if (param & TextureParam::INTERP_LINEAR) {
571  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
572  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
573  }
574  else {
575  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
576  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
577  }
578  break;
579 
580  case GL::TextureHandler::TextureFormat::Rx32f:
581  case GL::TextureHandler::TextureFormat::RGBx32f:
582  case GL::TextureHandler::TextureFormat::RGBAx32f:
583  texture.prepare(front);
584 #ifndef BEATMUP_OPENGLVERSION_GLES
585  if (param & TextureParam::INTERP_LINEAR) {
586  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
587  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
588  }
589  else {
590  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
591  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
592  }
593 #else
594  // GLES only allows nearest interpolation for floating point texture
595  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
596  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
597 #endif
598  break;
599 
600  case GL::TextureHandler::TextureFormat::OES_Ext:
601  texture.prepare(front);
602  break;
603  }
604 
605  if (param & TextureParam::REPEAT) {
606  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
607  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
608  }
609  else {
610  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
611  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
612  }
613 
614  GL::GLException::check("applying texture parameter");
615  }
@ INTERP_LINEAR
bilinear pixel interpolation
@ REPEAT
wrapping the texture by repeating instead of clamping to edge

◆ bindOutput() [1/3]

void Beatmup::GraphicPipeline::Impl::bindOutput ( AbstractBitmap bitmap,
const IntRectangle viewport 
)
inline

Definition at line 618 of file pipeline.cpp.

618  {
619  if (bitmap.isMask())
620  throw GL::GLException("Mask bitmaps can not be used as output");
623  glViewport(viewport.getX1(), viewport.getY1(), viewport.width(), viewport.height());
624  glClear(GL_COLOR_BUFFER_BIT);
625  }
virtual void prepare(GraphicPipeline &gpu)
Prepares (eventually uploads) texture data on GPU.
bool isMask() const
Returns true if the bitmap is a mask, false otherwise.
numeric height() const
Definition: geometry.h:178
numeric width() const
Definition: geometry.h:174
numeric getX1() const
Definition: geometry.h:169
numeric getY1() const
Definition: geometry.h:170
void bindOutput(AbstractBitmap &bitmap, const IntRectangle &viewport)
Definition: pipeline.cpp:618
Beatmup::InternalBitmap * bitmap

◆ bindOutput() [2/3]

void Beatmup::GraphicPipeline::Impl::bindOutput ( GL::TextureHandler textureHandler)
inline

Definition at line 628 of file pipeline.cpp.

628  {
629  textureHandler.prepare(front);
630  bindOutput(textureHandler.textureHandle);
631  glViewport(0, 0, textureHandler.getWidth(), textureHandler.getHeight());
632  }
virtual const int getHeight() const =0
Height of the texture in pixels.
virtual const int getWidth() const =0
Width of the texture in pixels.

◆ bindOutput() [3/3]

void Beatmup::GraphicPipeline::Impl::bindOutput ( GL::handle_t  texture)
inline

Definition at line 635 of file pipeline.cpp.

635  {
636  // setting up a texture
637  glBindFramebuffer(GL_FRAMEBUFFER, hFrameBuffer);
638  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
639 #ifdef BEATMUP_DEBUG
640  GLuint err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
641  if (err != GL_FRAMEBUFFER_COMPLETE)
642  throw GL::GLException("framebuffer incomplete", err);
643 #endif
644  }

◆ unbindOutput()

void Beatmup::GraphicPipeline::Impl::unbindOutput ( )
inline

Definition at line 647 of file pipeline.cpp.

647  {
648  glBindFramebuffer(GL_FRAMEBUFFER, 0);
649  glViewport(0, 0, displayResolution.getWidth(), displayResolution.getHeight());
650  glClear(GL_COLOR_BUFFER_BIT);
651  }

◆ getDisplayResolution()

const ImageResolution& Beatmup::GraphicPipeline::Impl::getDisplayResolution ( ) const
inline

Definition at line 654 of file pipeline.cpp.

654  {
655  return displayResolution;
656  }

◆ pullPixels()

void Beatmup::GraphicPipeline::Impl::pullPixels ( AbstractBitmap bitmap)
inline

Transfers texture data from GPU to CPU.

The bitmap is assumed locked.

Definition at line 661 of file pipeline.cpp.

661  {
662 #ifdef BEATMUP_DEBUG
663  DebugAssertion::check(bitmap.getData(0, 0) != nullptr, "Cannot pull pixels: the bitmap is not locked");
664 #endif
665 
666 #ifdef BEATMUP_OPENGLVERSION_GLES20
667  if (bitmap.isFloat())
668  throw GL::Unsupported("Floating point valued bitmaps are not updatable from GPU memory");
669  // 'cause GLES does not support such data to be transferred from GPU to CPU memory
670 #endif
671 
672  glBindFramebuffer(GL_FRAMEBUFFER, hFrameBuffer);
674  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bitmap.textureHandle, 0);
675 
676  // disable high order alignment
677  glPixelStorei(GL_PACK_ALIGNMENT, 1);
678 
679  bool buffered = false;
680 #ifdef BEATMUP_OPENGLVERSION_GLES20
681  // according to GL ES 2.0 spec, only one format/type pair may be read from GPU memory directly; otherwise we need a buffer
682  if (bitmap.getPixelFormat() != QuadByte) {
683  GLint format, type;
684  glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
685  glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
687  buffered = true;
688  }
689 #endif
690 
691  // copy data with a buffer
692  if (buffered) {
696 
697  {
699  glReadPixels(0, 0, buffer.getWidth(), buffer.getHeight(),
700  GL::BITMAP_PIXELFORMATS[buffer.getPixelFormat()],
701  GL::BITMAP_PIXELTYPES[buffer.getPixelFormat()],
702  buffer.getData(0, 0)
703  );
704  GL::GLException::check("reading pixel data from GPU memory");
705  }
706 
707  // converting to the required format
708  FormatConverter::convert(buffer, bitmap);
709  }
710 
711  // copy data directly
712  else {
713  glReadPixels(0, 0, bitmap.getWidth(), bitmap.getHeight(),
716  bitmap.getData(0, 0)
717  );
718  }
719 
720  GL::GLException::check("reading pixel data from texture");
721 
723  }
Makes a bitmap writable for a specific target device.
Context & getContext() const
bool isFloat() const
Returns true if the bitmap contains floating point values, false otherwise.
bool upToDate[2]
bitmap up-to-date state on CPU and GPU
Bitmap whose memory is managed by the Beatmup engine.
const pixbyte * getData(int x, int y) const
Returns a pointer to given pixel.
const int getHeight() const
Height of the texture in pixels.
const int getWidth() const
Width of the texture in pixels.
const PixelFormat getPixelFormat() const
Pixel format of the bitmap.
const GLuint BITMAP_PIXELTYPES[]
Mapping of bitmap pixel formats to GL pixel types.
Definition: bgl.h:160
const GLuint BITMAP_PIXELFORMATS[]
Mapping of bitmap pixel formats to GL pixel formats.
Definition: bgl.h:80
@ QuadFloat
4 channels of 32 bits per pixel, single precision floating point values,
@ QuadByte
4 channels of 8 bits per pixel (like RGBA), unsigned integer values
JNIEnv jobject jint format

◆ pushPixels()

void Beatmup::GraphicPipeline::Impl::pushPixels ( AbstractBitmap bitmap)
inline

Transfers texture data from CPU to GPU.

The bitmap is assumed locked.

Definition at line 729 of file pipeline.cpp.

729  {
731 
732  // pushing data if any
733  if (bitmap.getTextureFormat() != GL::TextureHandler::TextureFormat::OES_Ext) {
734 #ifdef BEATMUP_DEBUG
735  DebugAssertion::check(bitmap.getData(0, 0) != nullptr, "Cannot push pixels: the bitmap is not locked");
736 #endif
737 
738  // setup alignment
739  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
740 
741  if (bitmap.isMask()) {
742  // masks are stored as horizontally-stretched bitmaps
743  const int textureWidth = bitmap.getWidth() / (8 / bitmap.getBitsPerPixel());
744 
745 #ifdef BEATMUP_OPENGLVERSION_GLES20
746  glTexImage2D(GL_TEXTURE_2D,
747  0, GL_ALPHA,
748  textureWidth, bitmap.getHeight(),
749  0, GL_ALPHA, GL_UNSIGNED_BYTE,
750  bitmap.getData(0, 0));
751 #else
752  glTexSubImage2D(GL_TEXTURE_2D,
753  0, 0, 0, textureWidth, bitmap.getHeight(),
754  GL_RED,
755  GL_UNSIGNED_BYTE,
756  bitmap.getData(0, 0));
757 #endif
758  GL::GLException::check("sending texture data (mask)");
759  }
760 
761  else {
762 #ifdef BEATMUP_OPENGLVERSION_GLES20
763  glTexImage2D(GL_TEXTURE_2D,
764  0,
767  0,
770  bitmap.getData(0, 0));
771 #else
772  glTexSubImage2D(GL_TEXTURE_2D,
773  0, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
776  bitmap.getData(0, 0));
777 #endif
778  GL::GLException::check("sending texture data");
779  }
780  }
781 
783  }
virtual const TextureFormat getTextureFormat() const
Returns the texture format specifying how the shader must interpret the data.
const unsigned char getBitsPerPixel() const
Returns number of bits per pixel stored in each bitmap.
const GLuint BITMAP_INTERNALFORMATS[]
Definition: bgl.h:147

◆ getLimit()

int Beatmup::GraphicPipeline::Impl::getLimit ( GraphicPipeline::Limit  limit) const
inline

Definition at line 786 of file pipeline.cpp.

786  {
787  switch (limit) {
788  case Limit::TEXTURE_IMAGE_UNITS: return glLimits.maxTextureImageUnits;
789  case Limit::FRAGMENT_UNIFORM_VECTORS: return glLimits.maxFragmentUniformVectors;
790  case Limit::LOCAL_GROUPS_TOTAL: return glLimits.maxTotalWorkGroupSize;
791  case Limit::LOCAL_GROUPS_X: return glLimits.maxWorkGroupSize[0];
792  case Limit::LOCAL_GROUPS_Y: return glLimits.maxWorkGroupSize[1];
793  case Limit::LOCAL_GROUPS_Z: return glLimits.maxWorkGroupSize[2];
794  case Limit::SHARED_MEM: return glLimits.maxSharedMemSize;
795  }
796  return 0;
797  }

◆ getSharedMemSize()

int Beatmup::GraphicPipeline::Impl::getSharedMemSize ( ) const
inline

Definition at line 799 of file pipeline.cpp.

799  {
800  return glLimits.maxSharedMemSize;
801  }

◆ switchMode()

void Beatmup::GraphicPipeline::Impl::switchMode ( GraphicPipeline::Mode  mode)
inline

Definition at line 804 of file pipeline.cpp.

804  {
805  if (mode == GraphicPipeline::Mode::RENDERING) {
806  glEnable(GL_BLEND);
807  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
808  } else if (mode == GraphicPipeline::Mode::INFERENCE) {
809  glDisable(GL_BLEND);
810  glClearColor(0, 0, 0, 0);
811  }
812  }
JNIEnv jlong jint mode

◆ setTextureCoordinates() [1/2]

void Beatmup::GraphicPipeline::Impl::setTextureCoordinates ( const Rectangle coords)
inline

Definition at line 815 of file pipeline.cpp.

815  {
816  if (vertexAttribBuffer[0].s != coords.getX1() ||
817  vertexAttribBuffer[1].s != coords.getX2() ||
818  vertexAttribBuffer[0].t != coords.getY1() ||
819  vertexAttribBuffer[2].t != coords.getY2() ||
821  {
822  vertexAttribBuffer[0].s = vertexAttribBuffer[2].s = coords.getX1();
823  vertexAttribBuffer[1].s = vertexAttribBuffer[3].s = coords.getX2();
824  vertexAttribBuffer[0].t = vertexAttribBuffer[1].t = coords.getY1();
825  vertexAttribBuffer[2].t = vertexAttribBuffer[3].t = coords.getY2();
826  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
827  glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexAttribBuffer), vertexAttribBuffer);
829  }
830 #ifdef BEATMUP_DEBUG
831  GL::GLException::check("vertex attributes buffer setup");
832 #endif
833  }
numeric getX2() const
Definition: geometry.h:171
numeric getY2() const
Definition: geometry.h:172
JNIEnv jlong jfloat jfloat s

◆ setTextureCoordinates() [2/2]

void Beatmup::GraphicPipeline::Impl::setTextureCoordinates ( const Point leftTop,
const Point rightTop,
const Point leftBottom,
const Point rightBottom 
)
inline

Definition at line 835 of file pipeline.cpp.

835  {
836  vertexAttribBuffer[0].s = leftTop.x;
837  vertexAttribBuffer[0].t = leftTop.y;
838  vertexAttribBuffer[1].s = rightTop.x;
839  vertexAttribBuffer[1].t = rightTop.y;
840  vertexAttribBuffer[2].s = leftBottom.x;
841  vertexAttribBuffer[2].t = leftBottom.y;
842  vertexAttribBuffer[3].s = rightBottom.x;
843  vertexAttribBuffer[3].t = rightBottom.y;
844  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
845  glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexAttribBuffer), vertexAttribBuffer);
847 #ifdef BEATMUP_DEBUG
848  GL::GLException::check("vertex attributes buffer setup");
849 #endif
850  }

◆ getGlslVersion()

int Beatmup::GraphicPipeline::Impl::getGlslVersion ( ) const
inline

Definition at line 852 of file pipeline.cpp.

852 { return glslVersion; }

◆ isGlEsCompliant()

bool Beatmup::GraphicPipeline::Impl::isGlEsCompliant ( ) const
inline

Definition at line 853 of file pipeline.cpp.

853 { return isGlEs; }

Member Data Documentation

◆ front

GraphicPipeline& Beatmup::GraphicPipeline::Impl::front
private

Definition at line 68 of file pipeline.cpp.

◆ hFrameBuffer

GLuint Beatmup::GraphicPipeline::Impl::hFrameBuffer
private

Definition at line 70 of file pipeline.cpp.

◆ vertexAttribBuffer

VertexAttribBufferElement Beatmup::GraphicPipeline::Impl::vertexAttribBuffer[4]
private

Definition at line 72 of file pipeline.cpp.

◆ isRectangularTextureCoordinates

bool Beatmup::GraphicPipeline::Impl::isRectangularTextureCoordinates
private

if true, the texture coordinates is a rectangle

Definition at line 73 of file pipeline.cpp.

◆ hVertexAttribBuffer

GLuint Beatmup::GraphicPipeline::Impl::hVertexAttribBuffer
private

buffer used when rendering

Definition at line 74 of file pipeline.cpp.

◆ displayResolution

ImageResolution Beatmup::GraphicPipeline::Impl::displayResolution
private

width and height of a display obtained when switching

Definition at line 76 of file pipeline.cpp.

◆ isGlEs

bool Beatmup::GraphicPipeline::Impl::isGlEs
private

if true, the use OpenGL context is GL ES-compliant

Definition at line 78 of file pipeline.cpp.

◆ glslVersion

int Beatmup::GraphicPipeline::Impl::glslVersion
private

GLSL language version to put into shaders code, e.g. 100 for 1.00.

Definition at line 79 of file pipeline.cpp.

◆ xDisplay

Display* Beatmup::GraphicPipeline::Impl::xDisplay
private

Definition at line 99 of file pipeline.cpp.

◆ xWindow

Window Beatmup::GraphicPipeline::Impl::xWindow
private

Definition at line 100 of file pipeline.cpp.

◆ glxContext

GLXContext Beatmup::GraphicPipeline::Impl::glxContext
private

Definition at line 101 of file pipeline.cpp.

◆ glxPbuffer

GLXPbuffer Beatmup::GraphicPipeline::Impl::glxPbuffer
private

Definition at line 102 of file pipeline.cpp.

◆ maxTextureImageUnits

int Beatmup::GraphicPipeline::Impl::maxTextureImageUnits

Definition at line 106 of file pipeline.cpp.

◆ maxFragmentUniformVectors

int Beatmup::GraphicPipeline::Impl::maxFragmentUniformVectors

Definition at line 107 of file pipeline.cpp.

◆ maxWorkGroupCount

int Beatmup::GraphicPipeline::Impl::maxWorkGroupCount[3]

Definition at line 108 of file pipeline.cpp.

◆ maxWorkGroupSize

int Beatmup::GraphicPipeline::Impl::maxWorkGroupSize[3]

Definition at line 109 of file pipeline.cpp.

◆ maxTotalWorkGroupSize

int Beatmup::GraphicPipeline::Impl::maxTotalWorkGroupSize

Definition at line 110 of file pipeline.cpp.

◆ maxSharedMemSize

msize Beatmup::GraphicPipeline::Impl::maxSharedMemSize

Definition at line 111 of file pipeline.cpp.

◆ 

struct { ... } Beatmup::GraphicPipeline::Impl::glLimits

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