Beatmup
pipeline.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 "pipeline.h"
20 #include "../bitmap/converter.h"
21 #include "../bitmap/internal_bitmap.h"
22 #include "../debug.h"
23 #include "program.h"
24 
25 #include <algorithm>
26 #include <map>
27 #include <vector>
28 #include <deque>
29 #include <mutex>
30 #include <string>
31 
32 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
33 #include <cstdlib>
34 #include "drm.hpp"
35 #endif
36 
37 #include "bgl.h"
38 
39 
40 using namespace Beatmup;
41 
42 namespace Beatmup {
43  /**
44  \internal
45  Exception reporting issues occurred during initial GPU setup
46  */
48  public:
49  GpuOperationError(const char* info) : Exception(info) {}
50  GpuOperationError(const char* info, int code) : Exception("%s (error %x)", info, code) {}
51  };
52 }
53 
54 
55 /**
56  \internal
57  Graphic pipeline private implementation
58 */
60 private:
61  /**
62  Vertex attribute buffer entry: vertex coordinates (x,y) and texture coordinates (s,t)
63  */
64  typedef struct {
65  GLfloat x, y, s, t;
67 
69 
70  GLuint hFrameBuffer;
71 
73  bool isRectangularTextureCoordinates; //!< if `true`, the texture coordinates is a rectangle
74  GLuint hVertexAttribBuffer; //!< buffer used when rendering
75 
76  ImageResolution displayResolution; //!< width and height of a display obtained when switching
77 
78  bool isGlEs; //!< if `true`, the use OpenGL context is GL ES-compliant
79  int glslVersion; //!< GLSL language version to put into shaders code, e.g. 100 for 1.00
80 
81 #ifdef BEATMUP_OPENGLVERSION_GLES
82  EGLDisplay eglDisplay;
83  EGLSurface
84  eglSurface, //!< currently used surface
85  eglDefaultSurface; //!< default internally managed surface
86  EGLContext eglContext;
87  EGLConfig eglConfig;
88 #ifdef BEATMUP_GLES_ALLOW_DRM_FALLBACK
89  DRM::Device drmDevice;
90  DRM::ModeConnector drmConnector;
91  DRM::ModeCrtc drmCrtc;
92  DRM::GBMDevice gbmDevice;
93  DRM::GBMSurface gbmSurface;
94 #endif
95 #elif BEATMUP_PLATFORM_WINDOWS
96  HWND hwnd;
97  HGLRC hglrc;
98 #else
99  Display* xDisplay;
100  Window xWindow;
101  GLXContext glxContext;
102  GLXPbuffer glxPbuffer;
103 #endif
104 
105  struct {
113 
114 public:
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);
450  GL::GLException::check("initial GPU setup");
451  }
452 
453 
454  ~Impl() {
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  }
473 
474 
475  /**
476  Platform-dependent display switching routine
477  */
478  void switchDisplay(void* data) {
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  }
520 
521 
522  void swapBuffers() {
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  }
531 
532 
533  /**
534  Binds a texture handle to an image unit
535  \param[in] texture The texture handler
536  \param[in] imageUnit The image unit number
537  \param[in] read If `true`, the image will be read
538  \param[in] write If `true`, the image will be modified
539  */
540  void bindImage(GL::TextureHandler& texture, int imageUnit, bool read, bool write) {
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  }
561 
562 
563  void bind(GL::TextureHandler& texture, size_t unit, const TextureParam param) {
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  }
616 
617 
618  void bindOutput(AbstractBitmap& bitmap, const IntRectangle& viewport) {
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  }
626 
627 
628  void bindOutput(GL::TextureHandler& textureHandler) {
629  textureHandler.prepare(front);
630  bindOutput(textureHandler.textureHandle);
631  glViewport(0, 0, textureHandler.getWidth(), textureHandler.getHeight());
632  }
633 
634 
635  void bindOutput(GL::handle_t texture) {
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  }
645 
646 
647  void unbindOutput() {
648  glBindFramebuffer(GL_FRAMEBUFFER, 0);
649  glViewport(0, 0, displayResolution.getWidth(), displayResolution.getHeight());
650  glClear(GL_COLOR_BUFFER_BIT);
651  }
652 
653 
655  return displayResolution;
656  }
657 
658  /**
659  Transfers texture data from GPU to CPU. The bitmap is assumed locked.
660  */
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(),
702  buffer.getData(0, 0)
703  );
704  GL::GLException::check("reading pixel data from GPU memory");
705  }
706 
707  // converting to the required format
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  }
724 
725 
726  /**
727  Transfers texture data from CPU to GPU. The bitmap is assumed locked.
728  */
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  }
784 
785 
786  int getLimit(GraphicPipeline::Limit limit) const {
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  }
798 
799  int getSharedMemSize() const {
800  return glLimits.maxSharedMemSize;
801  }
802 
803 
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  }
813 
814 
815  void setTextureCoordinates(const Rectangle& coords) {
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  }
834 
835  void setTextureCoordinates(const Point& leftTop, const Point& rightTop, const Point& leftBottom, const Point& rightBottom) {
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  }
851 
852  int getGlslVersion() const { return glslVersion; }
853  bool isGlEsCompliant() const { return isGlEs; }
854 };
855 
856 
857 
859  BEATMUP_DEBUG_I("GRAPHIC PIPELINE INITIALIZATION");
860  impl = new Impl(*this);
862 }
863 
864 
866  delete renderingPrograms;
867  delete impl;
868 }
869 
870 
872  impl->switchDisplay(data);
873 }
874 
875 
877  impl->swapBuffers();
878 }
879 
880 
881 void GraphicPipeline::bind(GL::TextureHandler& texture, size_t texUnit, const TextureParam param) {
882  impl->bind(texture, texUnit, param);
883 }
884 
885 
886 void GraphicPipeline::bind(GL::TextureHandler& texture, size_t imageUnit, bool read, bool write) {
887  impl->bindImage(texture, imageUnit, read, write);
888 }
889 
890 
893 }
894 
895 
897  impl->bindOutput(bitmap, viewport);
898 }
899 
900 
902  impl->bindOutput(textureHandler);
903 }
904 
905 
907  impl->bindOutput(texture);
908 }
909 
910 
912  impl->unbindOutput();
913 }
914 
915 
917  return impl->getDisplayResolution();
918 }
919 
920 
923 }
924 
925 
928 }
929 
930 
932  glFinish();
933 }
934 
935 
937  return impl->getLimit(limit);
938 }
939 
940 
942  impl->switchMode(mode);
943 }
944 
945 
947  return (const char*)glGetString(GL_VENDOR);
948 }
949 
950 
952  return (const char*)glGetString(GL_RENDERER);
953 }
954 
955 
957  return impl->getGlslVersion();
958 }
959 
960 
962  return impl->isGlEsCompliant();
963 }
964 
965 
967  impl->setTextureCoordinates(coords);
968 }
969 
970 
971 void GraphicPipeline::setTextureCoordinates(const Point& leftTop, const Point& rightTop, const Point& leftBottom, const Point& rightBottom) {
972  impl->setTextureCoordinates(leftTop, rightTop, leftBottom, rightBottom);
973 }
974 
975 
977  /* Common OpenGL texture sampling model, likely:
978  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <- texture pixels (`size` in number).
979  | * * * * * * * * * | <- sampling point locations (`area`).
980  | | There are exactly `sampling` points.
981  |_____________________________________________________| <- texture coordinates to give to
982  the shaders to get the texture
983  sampled in the starred locations.
984  */
985 
986  // compute offsets of texture coordinates with respect to the sampling positions
987  const float
988  dx = sampling.x > 1 ? 0.5f * area.width() / (sampling.x - 1) : 0.0f,
989  dy = sampling.y > 1 ? 0.5f * area.height() / (sampling.y - 1) : 0.0f;
990 
991  // compute texture coordinates: x + 0.5 is the target sampling position, dx is the offset
992  return Beatmup::Rectangle(
993  (area.a.x + 0.5f - dx) / size.x,
994  (area.a.y + 0.5f - dy) / size.y,
995  (area.b.x + 0.5f + dx) / size.x,
996  (area.b.y + 0.5f + dy) / size.y
997  );
998 }
Makes a bitmap writable for a specific target device.
A very basic class for any image.
virtual const TextureFormat getTextureFormat() const
Returns the texture format specifying how the shader must interpret the data.
Context & getContext() const
const ImageResolution getSize() const
Returns the bitmap resolution within ImageResolution object.
virtual void prepare(GraphicPipeline &gpu)
Prepares (eventually uploads) texture data on GPU.
const unsigned char getBitsPerPixel() const
Returns number of bits per pixel stored in each bitmap.
bool isMask() const
Returns true if the bitmap is a mask, false otherwise.
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
numeric height() const
Definition: geometry.h:178
CustomPoint< numeric > b
Definition: geometry.h:131
numeric getX2() const
Definition: geometry.h:171
numeric width() const
Definition: geometry.h:174
CustomPoint< numeric > a
Definition: geometry.h:131
numeric getY2() const
Definition: geometry.h:172
numeric getX1() const
Definition: geometry.h:169
numeric getY1() const
Definition: geometry.h:170
struct gbm_device * getPointer()
Definition: drm.hpp:220
struct gbm_surface * getPointer()
Definition: drm.hpp:260
Base class for all exceptions.
Definition: exception.h:37
static void convert(AbstractBitmap &input, AbstractBitmap &output)
Definition: converter.cpp:209
GPU exception.
Definition: bgl.h:56
static void check(const std::string &info)
Definition: bgl.h:62
Handles a collection of common rendering programs of predefined types and shared operations among the...
virtual const int getDepth() const =0
Depth of the texture in pixels.
virtual const int getHeight() const =0
Height 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.
virtual const int getWidth() const =0
Width of the texture in pixels.
Exception communicating the use of an unsupported feature on GPU.
Definition: bgl.h:72
GpuOperationError(const char *info)
Definition: pipeline.cpp:49
GpuOperationError(const char *info, int code)
Definition: pipeline.cpp:50
Internal low-level GPU control API.
Definition: pipeline.h:33
static Rectangle getTextureCoordinates(const Rectangle &area, const IntPoint &size, const IntPoint &sampling)
Computes floating-point texture coordinates for pixel-accurate sampling: a texture gets sampled exact...
Definition: pipeline.cpp:976
void switchMode(Mode mode)
Switches GPU mode.
Definition: pipeline.cpp:941
const char * getGpuRendererString() const
Definition: pipeline.cpp:951
const ImageResolution & getDisplayResolution() const
Definition: pipeline.cpp:916
int getLimit(Limit limit) const
Definition: pipeline.cpp:936
void pullPixels(AbstractBitmap &bitmap)
Transfers bitmap pixels from GPU to CPU.
Definition: pipeline.cpp:921
int getGlslVersion() const
Returns GLSL language version supported by the GPU context being used.
Definition: pipeline.cpp:956
const char * getGpuVendorString() const
Definition: pipeline.cpp:946
void pushPixels(AbstractBitmap &bitmap)
Transfers bitmap pixels from CPU to GPU.
Definition: pipeline.cpp:926
void bindOutput(AbstractBitmap &bitmap)
Binds a bitmap to the pipeline output.
Definition: pipeline.cpp:891
Mode
Graphic pipeline working mode setting some common OpenGL switches.
Definition: pipeline.h:47
@ RENDERING
Textures are images to be blended together to produce another image.
@ INFERENCE
Textures are feature maps computed in fragment shaders.
void setTextureCoordinates(const Rectangle &coords)
Specifies texture coordinates for the next rendering pass.
Definition: pipeline.cpp:966
void switchDisplay(void *data)
Definition: pipeline.cpp:871
Limit
GPU characteristics.
Definition: pipeline.h:55
@ TEXTURE_IMAGE_UNITS
maximum number of texture units per fragment shader
@ FRAGMENT_UNIFORM_VECTORS
maximum number of 4-dimensional uniform vectors per fragment shader
static const int ATTRIB_TEXTURE_COORD
texture coordinate attribute index in the VBO
Definition: pipeline.h:67
GL::RenderingPrograms * renderingPrograms
Definition: pipeline.h:39
void flush()
Waits until all operations submitted to GPU are finished.
Definition: pipeline.cpp:931
void bind(GL::TextureHandler &texture, size_t texUnit, const TextureParam param)
Definition: pipeline.cpp:881
void unbindOutput()
Unbinds a bitmap from output and switches to screen.
Definition: pipeline.cpp:911
static const int ATTRIB_VERTEX_COORD
vertex coordinate attribute index in the VBO
Definition: pipeline.h:66
bool isGlEsCompliant() const
Returns true if the GPU context is OpenGL ES-compliant.
Definition: pipeline.cpp:961
Represents image size in pixels.
unsigned int getWidth() const
void set(unsigned int width, unsigned int height)
IntRectangle halfOpenedRectangle() const
unsigned int getHeight() const
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.
void bindOutput(GL::handle_t texture)
Definition: pipeline.cpp:635
void bindImage(GL::TextureHandler &texture, int imageUnit, bool read, bool write)
Binds a texture handle to an image unit.
Definition: pipeline.cpp:540
void bindOutput(GL::TextureHandler &textureHandler)
Definition: pipeline.cpp:628
bool isGlEs
if true, the use OpenGL context is GL ES-compliant
Definition: pipeline.cpp:78
Impl(GraphicPipeline &front)
Definition: pipeline.cpp:115
void bind(GL::TextureHandler &texture, size_t unit, const TextureParam param)
Definition: pipeline.cpp:563
int getLimit(GraphicPipeline::Limit limit) const
Definition: pipeline.cpp:786
bool isRectangularTextureCoordinates
if true, the texture coordinates is a rectangle
Definition: pipeline.cpp:73
void pullPixels(AbstractBitmap &bitmap)
Transfers texture data from GPU to CPU.
Definition: pipeline.cpp:661
void switchMode(GraphicPipeline::Mode mode)
Definition: pipeline.cpp:804
void setTextureCoordinates(const Rectangle &coords)
Definition: pipeline.cpp:815
void setTextureCoordinates(const Point &leftTop, const Point &rightTop, const Point &leftBottom, const Point &rightBottom)
Definition: pipeline.cpp:835
GLuint hVertexAttribBuffer
buffer used when rendering
Definition: pipeline.cpp:74
VertexAttribBufferElement vertexAttribBuffer[4]
Definition: pipeline.cpp:72
ImageResolution displayResolution
width and height of a display obtained when switching
Definition: pipeline.cpp:76
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
void pushPixels(AbstractBitmap &bitmap)
Transfers texture data from CPU to GPU.
Definition: pipeline.cpp:729
const ImageResolution & getDisplayResolution() const
Definition: pipeline.cpp:654
void bindOutput(AbstractBitmap &bitmap, const IntRectangle &viewport)
Definition: pipeline.cpp:618
void switchDisplay(void *data)
Platform-dependent display switching routine.
Definition: pipeline.cpp:478
#define BEATMUP_DEBUG_I(...)
Definition: debug.h:33
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
const GLuint BITMAP_INTERNALFORMATS[]
Definition: bgl.h:147
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
unsigned int handle_t
A reference to a GPU resource.
Definition: basic_types.h:61
uint32_t msize
memory size
Definition: basic_types.h:30
@ 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
CustomRectangle< float > Rectangle
Definition: geometry.h:627
TextureParam
Parameters of binding a texture to a texture unit on GPU.
@ INTERP_LINEAR
bilinear pixel interpolation
@ REPEAT
wrapping the texture by repeating instead of clamping to edge
Vertex attribute buffer entry: vertex coordinates (x,y) and texture coordinates (s,...
Definition: pipeline.cpp:64
JNIEnv jobject jint format
jlong jint jint jint jint pixelFormat
jobject jlong jint jint y
jobject jlong jint x
return(jlong) new Beatmup jlong jstring jint val
Beatmup::InternalBitmap * bitmap
JNIEnv jlong jint mode
jlong jobject size
JNIEnv jlong jfloat jfloat s
Beatmup::SceneRenderer * renderer