Add controller input and a laser-pointer-driven menu quad
build / build (push) Successful in 2m26s

- xr_input.c/h: an OpenXR action set (aim pose, trigger/select click, a
  menu-toggle button) plus ray/quad hit-testing, and a visible
  laser-pointer line drawn from the controller toward the hit point.
- xr_menu.c/h + MenuOverlay.java: a second composition-layer quad,
  toggled by a controller button, showing an off-screen, never-attached
  Android View tree (one "Keyboard" button so far) driven by synthetic
  touch events computed from the laser ray's hit UV.
- Migrate gl4es from a prebuilt binary baked into the Docker build-image
  to a vendored source snapshot (android/gl4es-src/) compiled from
  source at APK build time via CMake add_subdirectory(), patched through
  a new android/gl4es-patches/ (mirrors the existing engine-patches/
  pattern). This was needed to track down and fix a bug hit while
  building the menu: gl4es's fixed-pipeline emulation (fpe.c) was
  unconditionally substituting its own shader onto the menu's draw call
  (fpe_ReleventState() always sets alphafunc to a nonzero sentinel, so
  its fpe_IsEmpty() check could never see the state as empty), making
  the menu quad show the game's own rendering instead of its own
  content. Fixed by routing the menu's blit through a real
  glBlitFramebuffer() call instead of a shader-based draw, which gl4es's
  fpe.c has nothing to intercept - documented in README.md's new
  "Debugging notes" section.
- Renumber android/engine-patches/ to close the gap left by removing an
  unrelated diagnostic-only patch, and strip investigation-journal
  comments and dead diagnostic code (temporary tracing, env-var probes)
  left over from finding the bug above.
- Restructure README.md into numbered sections, document every
  engine/gl4es patch, add Android Studio dev/testing-cycle instructions,
  and generalize Quest-specific wording to any OpenXR headset. Update
  NOTICE.txt to match (gl4es is now vendored/patched source, not a
  prebuilt binary; add the OpenXR-SDK loader).
This commit is contained in:
ml
2026-08-02 06:27:49 +02:00
parent 2300d081c3
commit d2dc58391b
310 changed files with 141458 additions and 226 deletions
+12
View File
@@ -0,0 +1,12 @@
#ifdef DRMFUNC
DRMFUNC(drmModeResPtr,drmModeGetResources,(int fd))
DRMFUNC(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connectorId))
DRMFUNC(void, drmModeFreeConnector,(drmModeConnectorPtr ptr))
DRMFUNC(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id))
DRMFUNC(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
DRMFUNC(int,drmModeRmFB,(int fd, uint32_t bufferId))
DRMFUNC(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id))
DRMFUNC(int,drmModeSetCrtc,(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode))
#endif
+420
View File
@@ -0,0 +1,420 @@
#include "hardext.h"
#include "../gl/loader.h"
#include "../gl/init.h"
#include "../gl/gl4es.h"
#include "glx_gbm.h"
#define SHUT(a) if(!globals4es.nobanner) a
#ifndef NO_GBM
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <gbm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <errno.h>
#ifndef NO_GBM
#ifndef EGL_PLATFORM_GBM_KHR
#define EGL_PLATFORM_GBM_KHR 0x31D7
#endif
#endif
// define static function pointers
// for GBM
#define GBMFUNC(ret, name, args) \
typedef ret (*PFN##name) args; \
static PFN##name gbmdrm_##name = NULL;
#include "gbmfunc.h"
#undef GBMFUNC
// for DRM
#define DRMFUNC(ret, name, args) \
typedef ret (*PFN##name) args; \
static PFN##name gbmdrm_##name = NULL;
#include "drmfunc.h"
#undef DRMFUNC
struct drm_fb {
struct gbm_bo *bo;
uint32_t fb_id;
};
static int drm_fd = -1; // drm handle
static drmModeModeInfo *drm_mode = NULL;
static uint32_t drm_crtc_id = 0;
static uint32_t drm_connector_id = 0;
static struct gbm_device *gbmdev = NULL;
static struct gbm_surface *gbmsurf = NULL;
static struct gbm_bo *gbm_bo = NULL;
static uint32_t fb_id = 0;
// code here from icecream95 https://gitlab.com/icecream95/drmegl-wrapper
static uint32_t find_crtc_for_encoder(const drmModeRes *resources,
const drmModeEncoder *encoder) {
int i;
for (i = 0; i < resources->count_crtcs; i++) {
/* possible_crtcs is a bitmask as described here:
* https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api
*/
const uint32_t crtc_mask = 1 << i;
const uint32_t crtc_id = resources->crtcs[i];
if (encoder->possible_crtcs & crtc_mask) {
return crtc_id;
}
}
/* no match found */
return -1;
}
static uint32_t find_crtc_for_connector(const drmModeRes *resources,
const drmModeConnector *connector) {
int i;
for (i = 0; i < connector->count_encoders; i++) {
const uint32_t encoder_id = connector->encoders[i];
drmModeEncoder *encoder = gbmdrm_drmModeGetEncoder(drm_fd, encoder_id);
if (encoder) {
const uint32_t crtc_id = find_crtc_for_encoder(resources, encoder);
gbmdrm_drmModeFreeEncoder(encoder);
if (crtc_id != 0) {
return crtc_id;
}
}
}
/* no match found */
return -1;
}
static void CancelGBM()
{
if(gbm)
dlclose(gbm);
#define GBMFUNC(ret, name, args) \
gbmdrm_##name = NULL;
#include "gbmfunc.h"
#undef GBMFUNC
if(drm)
dlclose(drm);
#define DRMFUNC(ret, name, args) \
gbmdrm_##name = NULL;
#include "drmfunc.h"
#undef DRMFUNC
gbm = NULL;
globals4es.usegbm = 0;
}
static int init_drm_and_gbm()
{
drmModeRes *resources;
drmModeConnector *connector = NULL;
drmModeEncoder *encoder = NULL;
int i, area;
drm_fd = open(globals4es.drmcard, O_RDWR | O_CLOEXEC);
if (drm_fd < 0) {
return 0;
}
resources = gbmdrm_drmModeGetResources(drm_fd);
if(!resources) {
printf("LIBGL: Error initializing drm resources\n");
return 0;
}
/* find a connected connector: */
for (i = 0; i < resources->count_connectors; i++) {
connector = gbmdrm_drmModeGetConnector(drm_fd, resources->connectors[i]);
if (connector->connection == DRM_MODE_CONNECTED) {
/* it's connected, let's use this! */
break;
}
gbmdrm_drmModeFreeConnector(connector);
connector = NULL;
}
if (!connector) {
/* we could be fancy and listen for hotplug events and wait for
* a connector..
*/
printf("LIBGL: DRM no connected connector!\n");
return 0;
}
/* find prefered mode or the highest resolution mode: */
for (i = 0, area = 0; i < connector->count_modes; i++) {
drmModeModeInfo *current_mode = &connector->modes[i];
if (current_mode->type & DRM_MODE_TYPE_PREFERRED) {
drm_mode = current_mode;
}
int current_area = current_mode->hdisplay * current_mode->vdisplay;
if (current_area > area) {
drm_mode = current_mode;
area = current_area;
}
}
if (!drm_mode) {
printf("LIBGL: DRM could not find mode!\n");
return 0;
}
/* find encoder: */
for (i = 0; i < resources->count_encoders; i++) {
encoder = gbmdrm_drmModeGetEncoder(drm_fd, resources->encoders[i]);
if (encoder->encoder_id == connector->encoder_id)
break;
gbmdrm_drmModeFreeEncoder(encoder);
encoder = NULL;
}
if (encoder) {
drm_crtc_id = encoder->crtc_id;
} else {
uint32_t crtc_id = find_crtc_for_connector(resources, connector);
if (crtc_id == 0) {
printf("LIBGL: DRM no crtc found!\n");
return 0;
}
drm_crtc_id = crtc_id;
}
drm_connector_id = connector->connector_id;
gbmdev = gbmdrm_gbm_create_device(drm_fd);
if(!gbmdev) {
printf("LIBGL: Error initializing gbm device\n");
return 0;
}
gbmsurf = gbmdrm_gbm_surface_create(gbmdev, drm_mode->hdisplay, drm_mode->vdisplay,
GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if(!gbmsurf) {
printf("LIBGL: Error initializing gbm surface\n");
return 0;
}
return 1;
}
static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
{
struct drm_fb *fb = data;
struct gbm_device *gbm = gbmdrm_gbm_bo_get_device(bo);
if (fb->fb_id)
gbmdrm_drmModeRmFB(drm_fd, fb->fb_id);
free(fb);
}
static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo)
{
struct drm_fb *fb = gbmdrm_gbm_bo_get_user_data(bo);
uint32_t width, height, stride, handle;
int ret;
if (fb)
return fb;
fb = calloc(1, sizeof(*fb));
fb->bo = bo;
width = gbmdrm_gbm_bo_get_width(bo);
height = gbmdrm_gbm_bo_get_height(bo);
stride = gbmdrm_gbm_bo_get_stride(bo);
handle = gbmdrm_gbm_bo_get_handle(bo).u32;
ret = gbmdrm_drmModeAddFB(drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id);
if (ret) {
printf("failed to create fb: %s\n", strerror(errno));
free(fb);
return NULL;
}
gbmdrm_gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
return fb;
}
static int OpenGBM()
{
int available = 0;
available = init_drm_and_gbm();
SHUT(printf("LIBGL: GBM on card %s is %s\n", globals4es.drmcard, available?"Available":"Not available"));
return available;
}
void LoadGBMFunctions()
{
static int hasrun = 0;
if(hasrun)
return;
hasrun = 1;
if(!gbm || !drm)
return;
// load functions
#define GBMFUNC(ret, name, args) \
gbmdrm_##name = (PFN##name)dlsym(gbm, #name); \
if(!gbmdrm_##name) { \
printf("LIBGL: libgbm function %s missing, no gbm surface enabled\n", #name); \
CancelGBM(); \
return; \
}
#include "gbmfunc.h"
#undef DRMFUNC
// load functions
#define DRMFUNC(ret, name, args) \
gbmdrm_##name = (PFN##name)dlsym(drm, #name); \
if(!gbmdrm_##name) { \
printf("LIBGL: libdrm function %s missing, no gbm surface enabled\n", #name); \
CancelGBM(); \
return; \
}
#include "drmfunc.h"
#undef DRMFUNC
// Check card
if(!OpenGBM()) {
CancelGBM();
return;
}
// all done
return;
}
void CloseGBMFunctions()
{
if(gbmdev) {
gbmdrm_gbm_device_destroy(gbmdev);
gbmdev = NULL;
}
if (drm_fd >= 0) {
close(drm_fd);
drm_fd = -1;
}
}
void* OpenGBMDisplay(void* display)
{
LOAD_EGL_EXT(eglGetPlatformDisplay);
if(egl_eglGetPlatformDisplay) {
return egl_eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, gbmdev, NULL);
} else {
LOAD_EGL(eglGetDisplay);
return egl_eglGetDisplay((EGLNativeDisplayType)gbmdev);
}
}
void* CreateGBMWindow(int w, int h)
{
void* ret = gbmsurf;
if(!ret)
printf("LIBGL: Warning, cannot create gbm surface %dx%d\n", w, h);
}
void DeleteGBMWindow(void* win)
{
gbmdrm_gbm_surface_destroy((struct gbm_surface*)win);
}
int FindGBMConfig(EGLDisplay eglDisp, EGLConfig *configs, int numFounds)
{
LOAD_EGL(eglGetConfigAttrib);
int idx = 0;
while(idx<numFounds)
{
EGLint gbm_format;
if (egl_eglGetConfigAttrib(eglDisp, configs[idx], EGL_NATIVE_VISUAL_ID, &gbm_format)) {
if (gbm_format == GBM_FORMAT_XRGB8888) {
return idx;
}
}
++idx;
}
printf("LIBGL: Warning, no EGLConfig matching GBM Format found\n");
return 0; // not found...
}
EGLBoolean GBMMakeCurrent(EGLDisplay eglDisp, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
LOAD_EGL(eglMakeCurrent);
LOAD_EGL(eglSwapBuffers);
EGLBoolean res = egl_eglMakeCurrent(eglDisp, draw, read, ctx);
if(ctx==EGL_NO_CONTEXT || draw==NULL) {
// clean up gbm/drm stuff?
return res;
}
egl_eglSwapBuffers(eglDisp, draw);
struct gbm_bo *bo = gbmdrm_gbm_surface_lock_front_buffer(gbmsurf);
if(!bo) {
// probably a PBuffer
//printf("LIBGL: gbm BO is NULL\n");
return EGL_TRUE;
}
struct drm_fb *fb = drm_fb_get_from_bo(bo);
// Is it safe to do this here?
gbmdrm_gbm_surface_release_buffer(gbmsurf, bo);
int r = gbmdrm_drmModeSetCrtc(drm_fd, drm_crtc_id, fb->fb_id, 0, 0,
&drm_connector_id, 1, drm_mode);
if (r) {
printf("LIBGL: GBM failed to set mode: %s\n", strerror(errno));
return EGL_FALSE;
}
return EGL_TRUE;
}
#else // NO_GBM
void LoadGBMFunctions()
{
}
void CloseGBMFunctions()
{
}
void* OpenGBMDisplay(void* display)
{
return NULL;
}
void* CreateGBMWindow(int w, int h)
{
return NULL;
}
void DeleteGBMWindow(void* win)
{
}
#if !defined(NOEGL) && !defined(ANDROID)
int FindGBMConfig(EGLDisplay eglDisp, EGLConfig *configs, int numFounds)
{
return 0;
}
EGLBoolean GBMMakeCurrent(EGLDisplay eglDisp, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
return EGL_FALSE;
}
#endif
#endif // NO_GBM
+28
View File
@@ -0,0 +1,28 @@
#ifdef GBMFUNC
GBMFUNC(int,gbm_device_get_fd,(struct gbm_device *gbm))
GBMFUNC(int,gbm_device_is_format_supported,(struct gbm_device *gbm,
uint32_t format, uint32_t usage))
GBMFUNC(void,gbm_device_destroy,(struct gbm_device *gbm))
GBMFUNC(struct gbm_device *,gbm_create_device,(int fd))
GBMFUNC(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo))
GBMFUNC(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo))
GBMFUNC(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo))
GBMFUNC(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo))
GBMFUNC(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count))
GBMFUNC(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo))
GBMFUNC(void,gbm_bo_set_user_data,(struct gbm_bo *bo, void *data,
void (*destroy_user_data)(struct gbm_bo *, void *)))
GBMFUNC(void *,gbm_bo_get_user_data,(struct gbm_bo *bo))
GBMFUNC(void,gbm_bo_destroy,(struct gbm_bo *bo))
GBMFUNC(struct gbm_bo *,gbm_bo_create,(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t usage))
GBMFUNC(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags))
GBMFUNC(void,gbm_surface_destroy,(struct gbm_surface *surf))
GBMFUNC(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf))
GBMFUNC(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo))
#endif
File diff suppressed because it is too large Load Diff
+316
View File
@@ -0,0 +1,316 @@
#ifndef _GLX_GLX_H_
#define _GLX_GLX_H_
#ifndef NOEGL
#include <EGL/egl.h>
#endif
#include <stdbool.h>
#include <stdlib.h>
#ifndef NOX11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#else
typedef void Display;
typedef int Bool;
#endif
#include <stdio.h>
#include <string.h>
#include "../gl/gl4es.h"
// defines yoinked from Mesa glx.h
#define GLX_VERSION_1_1 1
#define GLX_VERSION_1_2 1
#define GLX_VERSION_1_3 1
#define GLX_VERSION_1_4 1
#define GLX_EXTENSION_NAME "GLX"
/*
* Tokens for glXChooseVisual and glXGetConfig:
*/
#define GLX_USE_GL 1
#define GLX_BUFFER_SIZE 2
#define GLX_LEVEL 3
#define GLX_RGBA 4
#define GLX_DOUBLEBUFFER 5
#define GLX_STEREO 6
#define GLX_AUX_BUFFERS 7
#define GLX_RED_SIZE 8
#define GLX_GREEN_SIZE 9
#define GLX_BLUE_SIZE 10
#define GLX_ALPHA_SIZE 11
#define GLX_DEPTH_SIZE 12
#define GLX_STENCIL_SIZE 13
#define GLX_ACCUM_RED_SIZE 14
#define GLX_ACCUM_GREEN_SIZE 15
#define GLX_ACCUM_BLUE_SIZE 16
#define GLX_ACCUM_ALPHA_SIZE 17
/*
* Error codes returned by glXGetConfig:
*/
#define GLX_BAD_SCREEN 1
#define GLX_BAD_ATTRIBUTE 2
#define GLX_NO_EXTENSION 3
#define GLX_BAD_VISUAL 4
#define GLX_BAD_CONTEXT 5
#define GLX_BAD_VALUE 6
#define GLX_BAD_ENUM 7
/*
* GLX 1.1 and later:
*/
#define GLX_VENDOR 1
#define GLX_VERSION 2
#define GLX_EXTENSIONS 3
/*
* GLX 1.3 and later:
*/
#define GLX_CONFIG_CAVEAT 0x20
#define GLX_DONT_CARE 0xFFFFFFFF
#define GLX_X_VISUAL_TYPE 0x22
#define GLX_TRANSPARENT_TYPE 0x23
#define GLX_TRANSPARENT_INDEX_VALUE 0x24
#define GLX_TRANSPARENT_RED_VALUE 0x25
#define GLX_TRANSPARENT_GREEN_VALUE 0x26
#define GLX_TRANSPARENT_BLUE_VALUE 0x27
#define GLX_TRANSPARENT_ALPHA_VALUE 0x28
#define GLX_WINDOW_BIT 0x00000001
#define GLX_PIXMAP_BIT 0x00000002
#define GLX_PBUFFER_BIT 0x00000004
#define GLX_AUX_BUFFERS_BIT 0x00000010
#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004
#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
#define GLX_DEPTH_BUFFER_BIT 0x00000020
#define GLX_STENCIL_BUFFER_BIT 0x00000040
#define GLX_ACCUM_BUFFER_BIT 0x00000080
#define GLX_NONE 0x8000
#define GLX_SLOW_CONFIG 0x8001
#define GLX_TRUE_COLOR 0x8002
#define GLX_DIRECT_COLOR 0x8003
#define GLX_PSEUDO_COLOR 0x8004
#define GLX_STATIC_COLOR 0x8005
#define GLX_GRAY_SCALE 0x8006
#define GLX_STATIC_GRAY 0x8007
#define GLX_TRANSPARENT_RGB 0x8008
#define GLX_TRANSPARENT_INDEX 0x8009
#define GLX_VISUAL_ID 0x800B
#define GLX_SCREEN 0x800C
#define GLX_NON_CONFORMANT_CONFIG 0x800D
#define GLX_DRAWABLE_TYPE 0x8010
#define GLX_RENDER_TYPE 0x8011
#define GLX_X_RENDERABLE 0x8012
#define GLX_FBCONFIG_ID 0x8013
#define GLX_RGBA_TYPE 0x8014
#define GLX_COLOR_INDEX_TYPE 0x8015
#define GLX_MAX_PBUFFER_WIDTH 0x8016
#define GLX_MAX_PBUFFER_HEIGHT 0x8017
#define GLX_MAX_PBUFFER_PIXELS 0x8018
#define GLX_PRESERVED_CONTENTS 0x801B
#define GLX_LARGEST_PBUFFER 0x801C
#define GLX_WIDTH 0x801D
#define GLX_HEIGHT 0x801E
#define GLX_EVENT_MASK 0x801F
#define GLX_DAMAGED 0x8020
#define GLX_SAVED 0x8021
#define GLX_WINDOW 0x8022
#define GLX_PBUFFER 0x8023
#define GLX_PBUFFER_HEIGHT 0x8040
#define GLX_PBUFFER_WIDTH 0x8041
#define GLX_RGBA_BIT 0x00000001
#define GLX_COLOR_INDEX_BIT 0x00000002
#define GLX_PBUFFER_CLOBBER_MASK 0x08000000
/*
* GLX 1.4 and later:
*/
#define GLX_SAMPLE_BUFFERS 0x186a0 /*100000*/
#define GLX_SAMPLES 0x186a1 /*100001*/
#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
#define GLX_SWAP_INTERVAL_EXT 0x20F1
#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GLX_CONTEXT_FLAGS_ARB 0x2094
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
#ifdef NOX11
typedef int GLXDrawable; // need 64 / 32bits difs.
#else
typedef XID GLXDrawable;
#endif
#ifndef NOX11
struct __GLXContextRec {
Display *display;
GLXDrawable drawable;
unsigned char direct;
int currentWritable;
int currentReadable;
XID xid;
EGLSurface eglSurface;
EGLConfig eglConfigs[64];
int eglConfigsCount;
int eglconfigIdx;
EGLContext eglContext;
int samples;
int samplebuffers;
int depth;
int stencil;
int rbits, gbits, bbits, abits;
int es2only;
int doublebuff;
void* glstate;
struct __GLXContextRec* shared;
int* shared_eglsurface;
void* nativewin;
int contextType; // 0 = Window, 1 = PBuffer, 2 = PixmapBuffer, 3 = Emulated PixmapBuffer (with PBuffer)
};
typedef struct __GLXContextRec *GLXContext;
typedef XID GLXPbuffer;
typedef XID GLXPixmap;
#endif //NOX11
struct __GLXFBConfigRec {
int visualType;
int transparentType;
/* colors are floats scaled to ints */
int transparentRed, transparentGreen, transparentBlue, transparentAlpha;
int transparentIndex;
int visualCaveat;
int associatedVisualId;
int screen;
int drawableType;
int renderType;
int maxPbufferWidth, maxPbufferHeight, maxPbufferPixels;
int optimalPbufferWidth, optimalPbufferHeight; /* for SGIX_pbuffer */
int visualSelectGroup; /* visuals grouped by select priority */
#ifndef NOEGL
EGLConfig id;
#else
int id;
#endif
unsigned char rgbMode;
unsigned char colorIndexMode;
unsigned char doubleBufferMode;
unsigned char stereoMode;
unsigned char haveAccumBuffer;
unsigned char haveDepthBuffer;
unsigned char haveStencilBuffer;
/* The number of bits present in various buffers */
int accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
int depthBits;
int stencilBits;
int indexBits;
int redBits, greenBits, blueBits, alphaBits;
unsigned int redMask, greenMask, blueMask, alphaMask;
unsigned int multiSampleSize; /* Number of samples per pixel (0 if no ms) */
unsigned int nMultiSampleBuffers; /* Number of availble ms buffers */
int maxAuxBuffers;
/* frame buffer level */
int level;
/* color ranges (for SGI_color_range) */
unsigned char extendedRange;
double minRed, maxRed;
double minGreen, maxGreen;
double minBlue, maxBlue;
double minAlpha, maxAlpha;
};
#ifdef NOX11
// Declare stub types
typedef void *XVisualInfo, *GLXContext, *Font, *Window, *Pixmap;
typedef unsigned int GLXPixmap, GLXPbuffer;
#endif
typedef struct __GLXFBConfigRec *GLXFBConfig;
#if !defined(NOX11) || defined(GLX_STUBS)
GLXContext gl4es_glXCreateContext(Display *dpy,
XVisualInfo *visual,
GLXContext shareList,
Bool direct);
GLXContext gl4es_glXCreateContextAttribsARB(Display *display, GLXFBConfig config,
GLXContext share_context, Bool direct,
const int *attrib_list);
void gl4es_glXSwapIntervalEXT(Display *display, int drawable, int interval);
#endif // !defined(NOX11) || defined(GLX_STUBS)
void gl4es_glXSwapInterval(int interval);
// GLX 1.1?
#if !defined(NOX11) || defined(GLX_STUBS)
Bool gl4es_glXIsDirect(Display * display, GLXContext ctx);
Bool gl4es_glXMakeCurrent(Display *display, GLXDrawable drawable, GLXContext context);
Bool gl4es_glXQueryExtension(Display *display, int *errorBase, int *eventBase);
Bool gl4es_glXQueryVersion(Display *display, int *major, int *minor);
const char *gl4es_glXGetClientString(Display *display, int name);
const char *gl4es_glXQueryExtensionsString(Display *display, int screen);
const char *gl4es_glXQueryServerString(Display *display, int screen, int name);
#endif
GLXDrawable gl4es_glXGetCurrentDrawable();
#if !defined(NOX11) || defined(GLX_STUBS)
int gl4es_glXGetConfig(Display *display, XVisualInfo *visual, int attribute, int *value);
void gl4es_glXCopyContext(Display *display, GLXContext src, GLXContext dst, GLuint mask);
void gl4es_glXDestroyContext(Display *display, GLXContext ctx);
void gl4es_glXSwapBuffers(Display *display, GLXDrawable drawable);
void gl4es_glXUseXFont(Font font, int first, int count, int listBase);
#endif // !defined(NOX11) || defined(GLX_STUBS)
void gl4es_glXWaitGL();
void gl4es_glXWaitX();
#if !defined(NOX11) || defined(GLX_STUBS)
XVisualInfo *gl4es_glXChooseVisual(Display *display, int screen, int *attributes);
int gl4es_glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
// GLX 1.2
Display *gl4es_glXGetCurrentDisplay();
// GLX 1.3
GLXContext gl4es_glXGetCurrentContext();
XVisualInfo *gl4es_glXGetVisualFromFBConfig(Display *display, GLXFBConfig config);
GLXFBConfig *gl4es_glXChooseFBConfig(Display *display, int screen, const int *attrib_list, int *count);
GLXFBConfig *gl4es_glXGetFBConfigs(Display *display, int screen, int *count);
int gl4es_glXGetFBConfigAttrib(Display *display, GLXFBConfig config, int attribute, int *value);
int gl4es_glXQueryContext(Display *display, GLXContext ctx, int attribute, int *value);
GLXFBConfig *gl4es_glXChooseFBConfigSGIX(Display *display, int screen, const int *attrib_list, int *count);
Window gl4es_glXCreateWindow(Display *display, GLXFBConfig config, Window win, int *attrib_list);
void gl4es_glXDestroyWindow(Display *display, void *win);
Bool gl4es_glXMakeContextCurrent(Display *display, int drawable, int readable, GLXContext context);
GLXContext gl4es_glXCreateNewContext(Display *display, GLXFBConfig config, int render_type, GLXContext share_list, Bool is_direct);
void gl4es_glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf);
GLXPbuffer gl4es_glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int * attrib_list);
GLXPixmap gl4es_glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list);
void gl4es_glXDestroyPixmap(Display *display, void *pixmap);
GLXPixmap gl4es_glXCreateGLXPixmap(Display *display, XVisualInfo * visual, Pixmap pixmap);
void gl4es_glXDestroyGLXPixmap(Display *display, void *pixmap);
GLXContext gl4es_glXCreateContextAttribs(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
#endif // !defined(NOX11) || defined(GLX_STUBS)
#endif // _GLX_GLX_H
+21
View File
@@ -0,0 +1,21 @@
#ifndef _GLX_GBM_H_
#define _GLX_GBM_H_
#ifndef NOEGL
#include <EGL/egl.h>
#endif
void LoadGBMFunctions();
void CloseGBMFunctions();
void* OpenGBMDisplay(void* display);
void* CreateGBMWindow(int w, int h);
void DeleteGBMWindow(void* win);
#if !defined(NOEGL) && !defined(ANDROID)
int FindGBMConfig(EGLDisplay eglDisp, EGLConfig *configs, int numFounds);
EGLBoolean GBMMakeCurrent(EGLDisplay eglDisp, EGLSurface draw, EGLSurface read, EGLContext ctx);
#endif
#endif // _GLX_GBM_H_
+77
View File
@@ -0,0 +1,77 @@
#include "glx.h"
#include "../gl/init.h"
#include "../gl/logs.h"
#if defined(NOX11) && defined(GLX_STUBS)
//#define WARN_GLX_STUB() LOGD("Warning, stubbed %s\n", __FUNCTION__); return NULL;
#define WARN_GLX_STUB() return NULL;
GLXContext gl4es_glXCreateContext(Display *display, XVisualInfo *visual, GLXContext shareList, Bool isDirect){ WARN_GLX_STUB(); }
GLXContext gl4es_glXCreateContextAttribsARB(Display *display, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list){ WARN_GLX_STUB(); }
void gl4es_glXDestroyContext(Display *display, GLXContext ctx){ WARN_GLX_STUB(); }
Display *gl4es_glXGetCurrentDisplay(){ WARN_GLX_STUB(); }
XVisualInfo *gl4es_glXChooseVisual(Display *display, int screen, int *attributes){ WARN_GLX_STUB(); }
Bool gl4es_glXMakeCurrent(Display *display, GLXDrawable drawable, GLXContext context){ WARN_GLX_STUB(); }
Bool gl4es_glXMakeContextCurrent(Display *display, int drawable, int readable, GLXContext context){ WARN_GLX_STUB(); }
void gl4es_glXSwapBuffers(Display *display, GLXDrawable drawable){ WARN_GLX_STUB(); }
int gl4es_glXGetConfig(Display *display, XVisualInfo *visual, int attribute, int *value){ WARN_GLX_STUB(); }
int gl4es_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value){ WARN_GLX_STUB(); }
GLXContext gl4es_glXGetCurrentContext(){ WARN_GLX_STUB(); }
GLXFBConfig *gl4es_glXChooseFBConfig(Display *display, int screen, const int *attrib_list, int *count){ WARN_GLX_STUB(); }
GLXFBConfig *gl4es_glXChooseFBConfigSGIX(Display *display, int screen, const int *attrib_list, int *count){ WARN_GLX_STUB(); }
GLXFBConfig *gl4es_glXGetFBConfigs(Display *display, int screen, int *count){ WARN_GLX_STUB(); }
int gl4es_glXGetFBConfigAttrib(Display *display, GLXFBConfig config, int attribute, int *value){ WARN_GLX_STUB(); }
XVisualInfo *gl4es_glXGetVisualFromFBConfig(Display *display, GLXFBConfig config){ WARN_GLX_STUB(); }
GLXContext gl4es_glXCreateNewContext(Display *display, GLXFBConfig config, int render_type, GLXContext share_list, Bool is_direct){ WARN_GLX_STUB(); }
void gl4es_glXSwapIntervalEXT(Display *display, int drawable, int interval){ WARN_GLX_STUB(); }
void gl4es_glXCopyContext(Display *display, GLXContext src, GLXContext dst, GLuint mask){ WARN_GLX_STUB(); }
Window gl4es_glXCreateWindow(Display *display, GLXFBConfig config, Window win, int *attrib_list){ WARN_GLX_STUB(); }
void gl4es_glXDestroyWindow(Display *display, void *win){ WARN_GLX_STUB(); }
GLXDrawable gl4es_glXGetCurrentDrawable(){ WARN_GLX_STUB(); }
Bool gl4es_glXIsDirect(Display * display, GLXContext ctx){ WARN_GLX_STUB(); }
void gl4es_glXUseXFont(Font font, int first, int count, int listBase){ WARN_GLX_STUB(); }
int gl4es_glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value){ WARN_GLX_STUB(); }
void gl4es_glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf){ WARN_GLX_STUB(); }
GLXPbuffer gl4es_glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int * attrib_list){ WARN_GLX_STUB(); }
GLXPixmap gl4es_glXCreateGLXPixmap(Display *display, XVisualInfo * visual, Pixmap pixmap){ WARN_GLX_STUB(); }
GLXPixmap gl4es_glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list){ WARN_GLX_STUB(); }
void gl4es_glXDestroyGLXPixmap(Display *display, void *pixmap){ WARN_GLX_STUB(); }
void gl4es_glXDestroyPixmap(Display *display, void *pixmap){ WARN_GLX_STUB(); }
GLXContext gl4es_glXCreateContextAttribs(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list){ WARN_GLX_STUB(); }
void gl4es_glXSwapIntervalMESA(int interval){ WARN_GLX_STUB(); }
void gl4es_glXSwapIntervalSGI(int interval){ WARN_GLX_STUB(); }
AliasExport(GLXContext,glXCreateContext,,(Display *display, XVisualInfo *visual, GLXContext shareList, Bool isDirect));
AliasExport(GLXContext,glXCreateContextAttribs,ARB,(Display *display, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list));
AliasExport(void,glXDestroyContext,,(Display *display, GLXContext ctx));
AliasExport(Display*,glXGetCurrentDisplay,,());
AliasExport(XVisualInfo*,glXChooseVisual,,(Display *display, int screen, int *attributes));
AliasExport(Bool,glXMakeCurrent,,(Display *display, GLXDrawable drawable, GLXContext context));
AliasExport(Bool,glXMakeContextCurrent,,(Display *display, int drawable, int readable, GLXContext context));
AliasExport(void,glXSwapBuffers,,(Display *display, GLXDrawable drawable));
AliasExport(int,glXGetConfig,,(Display *display, XVisualInfo *visual, int attribute, int *value));
AliasExport(int,glXQueryContext,,( Display *dpy, GLXContext ctx, int attribute, int *value));
AliasExport(GLXContext,glXGetCurrentContext,,());
AliasExport(GLXFBConfig*,glXChooseFBConfig,,(Display *display, int screen, const int *attrib_list, int *count));
AliasExport(GLXFBConfig*,glXChooseFBConfig,SGIX,(Display *display, int screen, const int *attrib_list, int *count));
AliasExport(GLXFBConfig*,glXGetFBConfigs,,(Display *display, int screen, int *count));
AliasExport(int,glXGetFBConfigAttrib,,(Display *display, GLXFBConfig config, int attribute, int *value));
AliasExport(XVisualInfo*,glXGetVisualFromFBConfig,,(Display *display, GLXFBConfig config));
AliasExport(GLXContext,glXCreateNewContext,,(Display *display, GLXFBConfig config, int render_type, GLXContext share_list, Bool is_direct));
AliasExport(void,glXSwapIntervalEXT,,(Display *display, int drawable, int interval));
AliasExport(void,glXCopyContext,,(Display *display, GLXContext src, GLXContext dst, GLuint mask));
AliasExport(Window,glXCreateWindow,,(Display *display, GLXFBConfig config, Window win, int *attrib_list));
AliasExport(void,glXDestroyWindow,,(Display *display, void *win));
AliasExport(GLXDrawable,glXGetCurrentDrawable,,());
AliasExport(Bool,glXIsDirect,,(Display * display, GLXContext ctx));
AliasExport(void,glXUseXFont,,(Font font, int first, int count, int listBase));
AliasExport(int,glXQueryDrawable,,(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value));
AliasExport(void,glXDestroyPbuffer,,(Display * dpy, GLXPbuffer pbuf));
AliasExport(GLXPbuffer,glXCreatePbuffer,,(Display * dpy, GLXFBConfig config, const int * attrib_list));
AliasExport(GLXPixmap,glXCreateGLXPixmap,,(Display *display, XVisualInfo * visual, Pixmap pixmap));
AliasExport(GLXPixmap,glXCreatePixmap,,(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list));
AliasExport(void,glXDestroyGLXPixmap,,(Display *display, void *pixmap));
AliasExport(void,glXDestroyPixmap,,(Display *display, void *pixmap));
AliasExport(GLXContext,glXCreateContextAttribs,,(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list));
#endif
+470
View File
@@ -0,0 +1,470 @@
#include "hardext.h"
#include "../gl/debug.h"
#include "../gl/gl4es.h"
#include "../gl/init.h"
#include "../gl/logs.h"
#include "../gl/loader.h"
#ifndef ANDROID
#include "rpi.h"
#endif
#include "glx_gbm.h"
#ifndef EGL_PLATFORM_GBM_KHR
#define EGL_PLATFORM_GBM_KHR 0x31D7
#endif
static int tested = 0;
hardext_t hardext = {0};
static int testGLSL(const char* version, int uniformLoc) {
// check if glsl 120 shaders are supported... by compiling one !
LOAD_GLES2(glCreateShader);
LOAD_GLES2(glShaderSource);
LOAD_GLES2(glCompileShader);
LOAD_GLES2(glGetShaderiv);
LOAD_GLES2(glDeleteShader);
LOAD_GLES(glGetError);
GLuint shad = gles_glCreateShader(GL_VERTEX_SHADER);
const char* shadTest[4] = {
version,
"#extension require GL_IMG_uniform_buffer_object"
"\n"
"layout(location = 0) in vec4 vecPos;\n",
uniformLoc?"layout(location = 0) uniform mat4 matMVP;\n":"uniform mat4 matMVP;\n",
"void main() {\n"
" gl_Position = matMVP * vecPos;\n"
"}\n"
};
gles_glShaderSource(shad, 4, shadTest, NULL);
gles_glCompileShader(shad);
GLint compiled;
gles_glGetShaderiv(shad, GL_COMPILE_STATUS, &compiled);
/*
if(!compiled) {
LOAD_GLES2(glGetShaderInfoLog)
char buff[500];
gles_glGetShaderInfoLog(shad, 500, NULL, buff);
printf("LIBGL: \"%s\" failed, message:\n%s\n", version, buff);
}
*/
gles_glDeleteShader(shad);
gles_glGetError(); // reset GL Error
return compiled;
}
static int testTextureCubeLod() {
LOAD_GLES2(glCreateShader);
LOAD_GLES2(glShaderSource);
LOAD_GLES2(glCompileShader);
LOAD_GLES2(glGetShaderiv);
LOAD_GLES2(glDeleteShader);
LOAD_GLES(glGetError);
GLuint shad = gles_glCreateShader(GL_FRAGMENT_SHADER);
const char* shadTest[3] = {
"#version 100",
"\n"
"#extension GL_EXT_shader_texture_lod : enable\n"
"uniform samplerCube samCube;\n"
"varying mediump vec3 coordCube;\n",
"void main() {\n"
" gl_FragColor = textureCubeLod(samCube, coordCube, 0.0);\n"
"}\n"
};
gles_glShaderSource(shad, 3, shadTest, NULL);
gles_glCompileShader(shad);
GLint compiled;
gles_glGetShaderiv(shad, GL_COMPILE_STATUS, &compiled);
gles_glDeleteShader(shad);
gles_glGetError(); // reset GL Error
return compiled;
}
EXPORT
void GetHardwareExtensions(int notest)
{
if(tested) return;
// put some default values
hardext.maxtex = 2;
hardext.maxsize = 2048;
hardext.maxlights = 8;
hardext.maxplanes = 6;
hardext.maxdrawbuffers = 1;
hardext.esversion = globals4es.es;
if(notest)
{
#ifndef AMIGAOS4
SHUT_LOGD("Hardware test disabled, nothing activated...\n");
#endif
if(hardext.esversion==2) {
hardext.maxteximage = 4;
hardext.maxvarying = 8;
hardext.maxtex = 8;
hardext.maxvattrib = 16;
#ifdef AMIGAOS4
hardext.npot = 3;
#else
hardext.npot = 1;
#endif
hardext.fbo = 1;
hardext.blendcolor = 1;
hardext.blendsub = 1;
hardext.blendfunc = 1;
hardext.blendeq = 1;
hardext.mirrored = 1;
hardext.pointsprite = 1;
hardext.pointsize = 1;
hardext.cubemap = 1;
hardext.maxdrawbuffers = 1;
#ifdef AMIGAOS4
hardext.glsl300es = 1;
#endif
}
return;
}
#if defined(BCMHOST) && !defined(ANDROID)
rpi_init();
#endif
#ifdef NOEGL
SHUT_LOGD("Hardware test on current Context...\n");
#else
// used EGL & GLES functions
LOAD_EGL(eglBindAPI);
LOAD_EGL(eglInitialize);
LOAD_EGL(eglGetDisplay);
LOAD_EGL(eglCreatePbufferSurface);
LOAD_EGL(eglDestroySurface);
LOAD_EGL(eglDestroyContext);
LOAD_EGL(eglMakeCurrent);
LOAD_EGL(eglChooseConfig);
LOAD_EGL(eglCreateContext);
LOAD_EGL(eglQueryString);
LOAD_EGL(eglTerminate);
EGLDisplay eglDisplay;
EGLSurface eglSurface;
EGLContext eglContext;
SHUT_LOGD("Using GLES %s backend\n", (hardext.esversion==1)?"1.1":"2.0");
// Create a PBuffer first...
EGLint egl_context_attrib_es2[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLint egl_context_attrib[] = {
EGL_NONE
};
//let's create a PBuffer attributes
EGLint egl_attribs[10]; // should be enough
int i = 0;
egl_attribs[i++] = EGL_WIDTH;
egl_attribs[i++] = 32;
egl_attribs[i++] = EGL_HEIGHT;
egl_attribs[i++] = 32;
egl_attribs[i++] = EGL_NONE;
EGLint configAttribs[] = {
#ifdef PANDORA
// on the Pandora, there don't seem to exist a 8888 PBuffer config for GLES2.
EGL_RED_SIZE, (hardext.esversion==1)?8:5,
EGL_GREEN_SIZE, (hardext.esversion==1)?8:6,
EGL_BLUE_SIZE, (hardext.esversion==1)?8:5,
EGL_ALPHA_SIZE, (hardext.esversion==1)?8:0,
#else
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
#endif
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, (hardext.esversion==1)?EGL_OPENGL_ES_BIT:EGL_OPENGL_ES2_BIT,
EGL_NONE
};
int configsFound;
static EGLConfig pbufConfigs[1];
#ifndef NO_GBM
if (globals4es.usegbm) {
LoadGBMFunctions();
eglDisplay = OpenGBMDisplay(EGL_DEFAULT_DISPLAY);
}
else
#endif
eglDisplay = egl_eglGetDisplay(EGL_DEFAULT_DISPLAY);
egl_eglBindAPI(EGL_OPENGL_ES_API);
if (egl_eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) {
LOGE("Error while gathering supported extension (eglInitialize: %s), default to none\n", PrintEGLError(0));
egl_eglTerminate(eglDisplay);
return;
}
egl_eglChooseConfig(eglDisplay, configAttribs, pbufConfigs, 1, &configsFound);
#ifndef NO_GBM
const char* eglExts = egl_eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if(eglExts && strstr(eglExts, "EGL_KHR_platform_gbm ")) {
SHUT_LOGD("GBM Surfaces supported%s\n", globals4es.usegbm?" and used":"");
hardext.gbm = 1;
}
#endif
#ifndef PANDORA
if(!configsFound) {
// try without alpha channel
configAttribs[4*2-1] = 0;
egl_eglChooseConfig(eglDisplay, configAttribs, pbufConfigs, 1, &configsFound);
if(configsFound) {
SHUT_LOGD("No alpha channel in PBuffer context, disabling EGL Alpha channel...\n");
hardext.eglnoalpha = 1;
}
}
#endif
if(!configsFound) {
SHUT_LOGE("Error while gathering supported extension (eglChooseConfig: %s), default to none\n", PrintEGLError(0));
egl_eglTerminate(eglDisplay);
return;
}
eglContext = egl_eglCreateContext(eglDisplay, pbufConfigs[0], EGL_NO_CONTEXT, (hardext.esversion==1)?egl_context_attrib:egl_context_attrib_es2);
if(!eglContext) {
SHUT_LOGE("Error while gathering supported extension (eglCreateContext: %s), default to none\n", PrintEGLError(0));
return;
}
eglSurface = egl_eglCreatePbufferSurface(eglDisplay, pbufConfigs[0], egl_attribs);
if(!eglSurface) {
SHUT_LOGE("Error while gathering supported extension (eglCreatePBufferSurface: %s), default to none\n", PrintEGLError(0));
egl_eglDestroyContext(eglDisplay, eglContext);
egl_eglTerminate(eglDisplay);
return;
}
egl_eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
#endif
tested = 1;
LOAD_GLES(glGetString);
LOAD_GLES(glGetIntegerv);
LOAD_GLES(glGetError);
// Now get extensions
const char *Exts = (const char *) gles_glGetString(GL_EXTENSIONS);
// Parse them!
#define S(A, B, C) if(strstr(Exts, A)) { hardext.B = 1; SHUT_LOGD("Extension %s detected%s",A, C?" and used\n":"\n"); }
if(hardext.esversion>1) hardext.npot = 1;
if(strstr(Exts, "GL_APPLE_texture_2D_limited_npot ")) hardext.npot = 1;
if(strstr(Exts, "GL_IMG_texture_npot ")) hardext.npot = 1; // it should enable mipmap (so hardext.npot=2), but mipmap (so level > 0) needs to be POT-sized?!!
if(strstr(Exts, "GL_ARB_texture_non_power_of_two ") || strstr(Exts, "GL_OES_texture_npot ")) hardext.npot = 3;
if(hardext.npot>0) {
SHUT_LOGD("Hardware %s NPOT detected and used\n", hardext.npot==3?"Full":(hardext.npot==2?"Limited+Mipmap":"Limited"));
}
S("GL_EXT_blend_minmax ", blendminmax, 1);
if (hardext.esversion>2) {
SHUT_LOGD("Extension GL_EXT_draw_buffers is in core ES3, and so used\n");
hardext.drawbuffers = 1;
} else {
S("GL_EXT_draw_buffers ", drawbuffers, 1);
}
/*if(hardext.blendcolor==0) {
// try by just loading the function
LOAD_GLES_OR_OES(glBlendColor);
if(gles_glBlendColor != NULL) {
hardext.blendcolor = 1;
SHUT_LOGD("Extension glBlendColor found and used\n");
}
}*/ // I don't think this is correct
if(hardext.esversion<2) {
S("GL_OES_framebuffer_object ", fbo, 1);
S("GL_OES_point_sprite ", pointsprite, 1);
S("GL_OES_point_size_array ", pointsize, 0);
S("GL_OES_texture_cube_map ", cubemap, 1);
S("GL_EXT_blend_color ", blendcolor, 1);
S("GL_OES_blend_subtract ", blendsub, 1);
S("GL_OES_blend_func_separate ", blendfunc, 1);
S("GL_OES_blend_equation_separate ", blendeq, 1);
S("GL_OES_texture_mirrored_repeat ", mirrored, 1);
} else {
hardext.fbo = 1;
SHUT_LOGD("FBO are in core, and so used\n");
hardext.pointsprite = 1;
SHUT_LOGD("PointSprite are in core, and so used\n");
hardext.pointsize = 1;
SHUT_LOGD("CubeMap are in core, and so used\n");
hardext.cubemap = 1;
SHUT_LOGD("BlendColor is in core, and so used\n");
hardext.blendcolor = 1;
SHUT_LOGD("Blend Subtract is in core, and so used\n");
hardext.blendsub = 1;
SHUT_LOGD("Blend Function and Equation Separation is in core, and so used\n");
hardext.blendfunc = 1;
hardext.blendeq = 1;
SHUT_LOGD("Texture Mirrored Repeat is in core, and so used\n");
hardext.mirrored = 1;
}
S("GL_OES_mapbuffer ", mapbuffer, 0);
S("GL_OES_element_index_uint ", elementuint, 1);
S("GL_OES_packed_depth_stencil ", depthstencil, 1);
S("GL_OES_depth24 ", depth24, 1);
S("GL_OES_rgb8_rgba8 ", rgba8, 1);
S("GL_EXT_multi_draw_arrays ", multidraw, 0);
if(!globals4es.nobgra) {
S("GL_EXT_texture_format_BGRA8888 ", bgra8888, 1);
}
if(!globals4es.nodepthtex) {
S("GL_OES_depth_texture ", depthtex, 1);
S("GL_OES_texture_stencil8 ", stenciltex, 1);
}
S("GL_OES_draw_texture ", drawtex, 1);
S("GL_EXT_texture_rg ", rgtex, 1);
if(globals4es.floattex) {
S("GL_OES_texture_float ", floattex, 1);
S("GL_OES_texture_half_float ", halffloattex, 1);
S("GL_EXT_color_buffer_float ", floatfbo, 1);
S("GL_EXT_color_buffer_half_float ", halffloatfbo, 1);
}
S("GL_AOS4_texture_format_RGB332", rgb332, 0);
S("GL_AOS4_texture_format_RGB332REV", rgb332rev, 0);
S("GL_AOS4_texture_format_RGBA1555REV", rgba1555rev, 1);
S("GL_AOS4_texture_format_RGBA8888", rgba8888, 1);
S("GL_AOS4_texture_format_RGBA8888REV", rgba8888rev, 1);
if (hardext.esversion>1) {
if(!globals4es.nohighp) {
S("GL_OES_fragment_precision_high ", highp, 1);
if(!hardext.highp) {
// check if highp is supported anyway
LOAD_GLES2(glGetShaderPrecisionFormat);
if(gles_glGetShaderPrecisionFormat) {
GLint range[2] = {0};
GLint precision=0;
gles_glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
if(!(range[0]==0 && range[1]==0 && precision==0)) {
hardext.highp = 2; // no need to declare #entension here
SHUT_LOGD("high precision float in fragment shader available and used\n");
}
}
}
}
if(!globals4es.noshaderlod)
S("GL_EXT_shader_texture_lod", shaderlod, 1);
if(hardext.shaderlod) {
// test is textureCubeLod need EXT or not (seems to be a bug in some PVR driver)
if(testTextureCubeLod()) {
hardext.cubelod = 1;
SHUT_LOGD("textureCubeLod in fragment doesn't need trailing EXT\n");
}
}
S("GL_EXT_frag_depth ", fragdepth, 1);
gles_glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &hardext.maxvattrib);
SHUT_LOGD("Max vertex attrib: %d\n", hardext.maxvattrib);
S("GL_OES_standard_derivatives ", derivatives, 1);
S("GL_ARM_shader_framebuffer_fetch", shader_fbfetch, 1);
S("GL_OES_get_program ", prgbinary, 1);
if(!hardext.prgbinary) {
S("GL_OES_get_program_binary ", prgbinary, 1);
}
if(hardext.prgbinary) {
gles_glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &hardext.prgbin_n);
SHUT_LOGD("Number of supported Program Binary Format: %d\n", hardext.prgbin_n);
}
}
// Now get some max stuffs
gles_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &hardext.maxsize);
SHUT_LOGD("Max texture size: %d\n", hardext.maxsize);
gles_glGetIntegerv((hardext.esversion==1)?GL_MAX_TEXTURE_UNITS:GL_MAX_TEXTURE_IMAGE_UNITS, &hardext.maxtex);
if (hardext.esversion==1) {
gles_glGetIntegerv(GL_MAX_LIGHTS, &hardext.maxlights);
gles_glGetIntegerv(GL_MAX_CLIP_PLANES, &hardext.maxplanes);
hardext.maxteximage=hardext.maxtex;
} else {
// simulated stuff using the FPE
hardext.maxlights = 8;
hardext.maxplanes = 6;
gles_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &hardext.maxteximage);
gles_glGetIntegerv(GL_MAX_VARYING_VECTORS, &hardext.maxvarying);
SHUT_LOGD("Max Varying Vector: %d\n", hardext.maxvarying);
if(hardext.maxvattrib<16 && hardext.maxtex>4)
hardext.maxtex = 4; // with less then 16 vertexattrib, more then 4 textures seems unreasonnable
}
int hardmaxtex = hardext.maxtex;
if(hardext.maxtex>MAX_TEX) hardext.maxtex=MAX_TEX; // caping, as there are some fixed-sized array...
if(hardext.maxteximage>MAX_TEX) hardext.maxteximage=MAX_TEX;
if(hardext.maxlights>MAX_LIGHT) hardext.maxlights=MAX_LIGHT; // caping lights too
if(hardext.maxplanes>MAX_CLIP_PLANES) hardext.maxplanes=MAX_CLIP_PLANES; // caping planes, even 6 should be the max supported anyway
SHUT_LOGD("Texture Units: %d/%d (hardware: %d), Max lights: %d, Max planes: %d\n", hardext.maxtex, hardext.maxteximage, hardmaxtex, hardext.maxlights, hardext.maxplanes);
S("GL_EXT_texture_filter_anisotropic ", aniso, 1);
if(hardext.aniso) {
gles_glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &hardext.aniso);
if(gles_glGetError()!=GL_NO_ERROR)
hardext.aniso = 0;
if(hardext.aniso)
SHUT_LOGD("Max Anisotropic filtering: %d\n", hardext.aniso);
}
if(hardext.drawbuffers) {
gles_glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT,&hardext.maxcolorattach);
gles_glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &hardext.maxdrawbuffers);
}
if(hardext.maxcolorattach<1)
hardext.maxcolorattach = 1;
if(hardext.maxcolorattach>MAX_DRAW_BUFFERS)
hardext.maxcolorattach=MAX_DRAW_BUFFERS;
if(hardext.maxdrawbuffers<1)
hardext.maxdrawbuffers = 1;
if(hardext.maxdrawbuffers>MAX_DRAW_BUFFERS)
hardext.maxdrawbuffers=MAX_DRAW_BUFFERS;
SHUT_LOGD("Max Color Attachments: %d / Draw buffers: %d\n", hardext.maxdrawbuffers, hardext.maxcolorattach);
// get GLES driver signatures...
const char *vendor = (const char *) gles_glGetString(GL_VENDOR);
SHUT_LOGD("Hardware vendor is %s\n", vendor);
if(strstr(vendor, "ARM"))
hardext.vendor = VEND_ARM;
else if(strstr(vendor, "Imagination Technologies"))
hardext.vendor = VEND_IMGTEC;
if(hardext.esversion>1) {
if(testGLSL("#version 120", 1))
hardext.glsl120 = 1;
if(testGLSL("#version 300 es", 0))
hardext.glsl300es = 1;
if(testGLSL("#version 310 es", 1))
hardext.glsl310es = 1;
}
if(hardext.glsl120) {
SHUT_LOGD("GLSL 120 supported and used\n");
}
if(hardext.glsl300es) {
SHUT_LOGD("GLSL 300 es supported%s\n", (hardext.glsl120||hardext.glsl310es)?"":" and used");
}
if(hardext.glsl310es) {
SHUT_LOGD("GLSL 310 es supported%s\n", hardext.glsl120?"":" and used");
}
#ifndef NOEGL
if(strstr(egl_eglQueryString(eglDisplay, EGL_EXTENSIONS), "EGL_KHR_gl_colorspace")) {
SHUT_LOGD("sRGB surface supported\n");
hardext.srgb = 1;
}
if(strstr(egl_eglQueryString(eglDisplay, EGL_EXTENSIONS), "EGL_KHR_image_pixmap")) {
SHUT_LOGD("EGLImage from Pixmap supported\n");
hardext.khr_pixmap = 1;
}
if(strstr(egl_eglQueryString(eglDisplay, EGL_EXTENSIONS), "EGL_KHR_gl_texture_2D_image")) {
SHUT_LOGD("EGLImage to Texture2D supported\n");
hardext.khr_texture_2d = 1;
}
if(strstr(egl_eglQueryString(eglDisplay, EGL_EXTENSIONS), "EGL_KHR_gl_renderbuffer_image")) {
SHUT_LOGD("EGLImage to RenderBuffer supported\n");
hardext.khr_renderbuffer = 1;
}
// End, cleanup
egl_eglMakeCurrent(eglDisplay, 0, 0, EGL_NO_CONTEXT);
egl_eglDestroySurface(eglDisplay, eglSurface);
egl_eglDestroyContext(eglDisplay, eglContext);
egl_eglTerminate(eglDisplay);
#endif
}
+80
View File
@@ -0,0 +1,80 @@
#ifndef _GLX_HARDEXT_H_
#define _GLX_HARDEXT_H_
#include "../gl/attributes.h"
#define VEND_IMGTEC 0x0100
#define VEND_ARM 0x0200
#define MAX_PRGBIN 10
typedef struct _hardext {
int npot; // 0 = no npot capability, 1 = limited npot, 2 = full npot
int maxtex; // maximum number of texture
int maxlights; // maximum number of light
int maxsize; // maximum texture size
int maxplanes; // maximum clip planes
int blendsub; // GL_OES_blend_subtract
int blendfunc; // GL_OES_blend_func_separate
int blendeq; // GL_OES_blend_equation_separate
int blendminmax; // GL_EXT_blend_minmax
int blendcolor; // GL_EXT_blend_color
int pointsprite; // GL_OES_point_sprite
int pointsize; // GL_OES_point_size_array
int elementuint; // GL_OES_element_index_uint
int fbo; // GL_OES_framebuffer_object
int depthstencil; // GL_OES_packed_depth_stencil
int depth24; // GL_OES_depth24
int rgba8; // GL_OES_rgb8_rgba8
int multidraw; // GL_EXT_multi_draw_arrays
int bgra8888; // GL_EXT_texture_format_BGRA8888
int depthtex; // GL_OES_depth_texture
int stenciltex; // GL_OES_texture_stencil8
int cubemap; // GL_OES_texture_cube_map
int drawtex; // GL_OES_draw_texture
int rgtex; // GL_EXT_texture_rg
int floattex; // GL_OES_texture_float
int halffloattex; // GL_OES_texture_half_float
int floatfbo; // GL_EXT_color_buffer_float
int halffloatfbo; // GL_EXT_color_buffer_half_float
int rgb332; // GL_AOS4_texture_format_RGB332
int rgb332rev; // GL_AOS4_texture_format_RGB332REV
int rgba1555rev; // GL_AOS4_texture_format_RGBA1555REV
int rgba8888; // GL_AOS4_texture_format_RGBA8888
int rgba8888rev; // GL_AOS4_texture_format_RGBA8888REV
int mirrored; // GL_OES_texture_mirrored_repeat
int aniso; // Max ANISOTROPIC filter available (0 if not)
int srgb; // EGL_KHR_gl_colorspace
int mapbuffer; // GL_OES_mapbuffer
int drawbuffers; // GL_EXT_draw_buffers
// es2 stuffs
int esversion; // 1 is ES1.1 backend, 2 is ES2
int maxvattrib; // GL_MAX_VERTEX_ATTRIBS (or 0 if not using es2)
int maxteximage; // GL_MAX_TEXTURE_IMAGE_UNITS for es2
int maxvarying; // GL_MAX_VARYING_VECTORS for es2
int maxcolorattach; // GL_MAX_COLOR_ATTACHMENTS_EXT or 1 if GL_EXT_draw_buffers not supported
int maxdrawbuffers; // GL_MAX_DRAW_BUFFERS_EXT or 1 if GL_EXT_draw_buffers not supported
int highp; // GL_OES_fragment_precision_high
int fragdepth; // GL_EXT_frag_depth
int derivatives; // GL_OES_standard_derivatives
int shaderlod; // GL_EXT_shader_texture_lod
int cubelod; // textureCubeLod doesn't need "EXT" even with GL_EXT_shader_texture_lod
int gbm; // EGL_KHR_platform_gbm
int khr_pixmap; // EGL_KHR_image_pixmap
int khr_texture_2d; // EGL_KHR_gl_texture_2D_image
int khr_renderbuffer; // EGL_KHR_gl_renderbuffer_image
int vendor; // which vendor (to apply workaround)
int eglnoalpha; // EGL surface doesn't seems to have any alpha channel (auto detect)
int prgbinary; // GL_OES_get_program extension
int prgbin_n; // number of program binary format support
int shader_fbfetch; // GL_ARM_shader_framebuffer_fetch
int glsl120; // does version 120 glsl shader are supported ?
int glsl300es; // does version 300es glsl shader are supported ?
int glsl310es; // does version 300es glsl shader are supported ?
} hardext_t;
EXPORT extern hardext_t hardext;
EXPORT void GetHardwareExtensions(int test);
#endif
+80
View File
@@ -0,0 +1,80 @@
#include "../gl/attributes.h"
#include "../gl/init.h"
#include "../gl/logs.h"
#define STUB_FCT glXStub
#include "../gl/gl_lookup.h"
#include "glx.h"
#include "hardext.h"
void glXStub(void *x, ...) {
return;
}
void *gl4es_glXGetProcAddress(const char *name) __attribute__((visibility("default")));
void *gl4es_glXGetProcAddress(const char *name) {
#if !defined(NOX11) || defined(GLX_STUBS)
// glX calls
_EX(glXChooseVisual);
_EX(glXCopyContext);
_EX(glXCreateContext);
_EX(glXCreateNewContext);
_EX(glXCreateContextAttribsARB);
_EX(glXDestroyContext);
_EX(glXGetConfig);
_EX(glXGetCurrentDisplay);
_EX(glXGetCurrentDrawable);
_EX(glXIsDirect);
_EX(glXMakeCurrent);
_EX(glXMakeContextCurrent);
_EX(glXQueryExtensionsString);
_EX(glXQueryServerString);
_EX(glXSwapBuffers);
_EX(glXSwapIntervalEXT);
#endif
MAP("glXSwapIntervalMESA", gl4es_glXSwapInterval);
MAP("glXSwapIntervalSGI", gl4es_glXSwapInterval);
#if !defined(NOX11) || defined(GLX_STUBS)
_EX(glXUseXFont);
_EX(glXWaitGL);
_EX(glXWaitX);
_EX(glXGetCurrentContext);
_EX(glXQueryExtension);
_EX(glXQueryDrawable);
_EX(glXQueryVersion);
_EX(glXGetClientString);
_EX(glXGetFBConfigs);
_EX(glXChooseFBConfig);
MAP("glXChooseFBConfigSGIX", gl4es_glXChooseFBConfig);
_EX(glXGetFBConfigAttrib);
_EX(glXQueryContext);
_EX(glXGetVisualFromFBConfig);
_EX(glXCreateWindow);
_EX(glXDestroyWindow);
_EX(glXCreatePbuffer);
_EX(glXDestroyPbuffer);
_EX(glXCreatePixmap);
_EX(glXDestroyPixmap);
_EX(glXCreateGLXPixmap);
_EX(glXDestroyGLXPixmap);
STUB(glXGetCurrentReadDrawable);
STUB(glXGetSelectedEvent);
STUB(glXSelectEvent);
_EX(glXCreateContextAttribs);
_ARB(glXCreateContextAttribs);
#endif
_EX(glXGetProcAddress);
_ARB(glXGetProcAddress);
return gl4es_GetProcAddress(name);
}
#ifdef AMIGAOS4
//AliasExport(void*,aglGetProcAddress,,(const char* name));
#else
AliasExport(void*,glXGetProcAddress,,(const char* name));
AliasExport(void*,glXGetProcAddress,ARB,(const char* name));
#endif
+126
View File
@@ -0,0 +1,126 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <dlfcn.h>
#include "rpi.h"
// Code specific to RPI
// everything is dynamicaly linked, so this can be saffely compiled everywhere
extern void* bcm_host;
extern void* vcos;
extern void (*bcm_host_init)();
extern void (*bcm_host_deinit)();
typedef uint32_t DISPMANX_DISPLAY_HANDLE_T;
typedef uint32_t DISPMANX_UPDATE_HANDLE_T;
typedef uint32_t DISPMANX_ELEMENT_HANDLE_T;
typedef uint32_t DISPMANX_RESOURCE_HANDLE_T;
typedef uint32_t DISPMANX_PROTECTION_T;
typedef uint32_t DISPMANX_FLAGS_ALPHA_T;
typedef struct tag_VC_RECT_T {
int32_t x;
int32_t y;
int32_t width;
int32_t height;
} VC_RECT_T;
typedef struct {
DISPMANX_ELEMENT_HANDLE_T element;
int width;
int height;
} EGL_DISPMANX_WINDOW_T;
typedef struct {
DISPMANX_FLAGS_ALPHA_T flags;
uint32_t opacity;
DISPMANX_RESOURCE_HANDLE_T mask;
} VC_DISPMANX_ALPHA_T;
int32_t (*graphics_get_display_size)(const uint16_t, uint32_t *, uint32_t*);
DISPMANX_DISPLAY_HANDLE_T (*vc_dispmanx_display_open)(uint32_t);
DISPMANX_UPDATE_HANDLE_T (*vc_dispmanx_update_start)(int32_t);
DISPMANX_ELEMENT_HANDLE_T (*vc_dispmanx_element_add)(
DISPMANX_UPDATE_HANDLE_T, DISPMANX_DISPLAY_HANDLE_T, int32_t,
VC_RECT_T *, DISPMANX_RESOURCE_HANDLE_T,
VC_RECT_T *, DISPMANX_PROTECTION_T,
/*VC_DISPMANX_ALPHA_T*/void*, /*DISPMANX_CLAMP_T*/void*,
/*DISPMANX_TRANSFORM_T*/ int32_t);
int (*vc_dispmanx_update_submit_sync)(DISPMANX_RESOURCE_HANDLE_T);
int (*vc_dispmanx_element_remove)(DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element);
static DISPMANX_UPDATE_HANDLE_T dispman_update;
static DISPMANX_DISPLAY_HANDLE_T dispman_display;
static VC_RECT_T dst_rect;
static VC_RECT_T src_rect;
static int rpi_inited = 0;
void rpi_init() {
if(!bcm_host || rpi_inited)
return;
rpi_inited++;
bcm_host_init = dlsym(bcm_host, "bcm_host_init");
bcm_host_deinit = dlsym(bcm_host, "bcm_host_deinit");
if(!bcm_host_init || !bcm_host_deinit) {
printf("LIBGL: Warning, bcm_host function missing (init=%p, deinit=%p)\n", bcm_host_init, bcm_host_deinit);
return;
}
bcm_host_init();
#define GO(A) A=dlsym(bcm_host, #A); if(A==NULL) A=dlsym(vcos, #A); if(A==NULL) printf("LIBGL: Warning, " #A " is null")
GO(graphics_get_display_size);
GO(vc_dispmanx_display_open);
GO(vc_dispmanx_update_start);
GO(vc_dispmanx_element_add);
GO(vc_dispmanx_update_submit_sync);
GO(vc_dispmanx_element_remove);
#undef GO
}
void rpi_fini() {
if(!bcm_host || !rpi_inited)
return;
--rpi_inited;
if(!bcm_host_init || !bcm_host_deinit)
return;
bcm_host_deinit();
}
void* create_rpi_window(int w, int h) {
EGL_DISPMANX_WINDOW_T *nativewindow = (EGL_DISPMANX_WINDOW_T*)calloc(1, sizeof(EGL_DISPMANX_WINDOW_T));
if(!bcm_host) return NULL;
// create a simple RPI nativewindow of size w*h, on output 0 (i.e. LCD)...
// code heavily inspired from Allegro 5.2
uint32_t screenwidth, screenheight;
graphics_get_display_size(/*LCD*/ 0, &screenwidth, & screenheight);
if(w==0) w=screenwidth;
if(h==0) h=screenheight;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
VC_RECT_T dst_rect, src_rect;
dst_rect.x = 0; dst_rect.y = 0;
dst_rect.width = screenwidth;
dst_rect.height = screenheight;
src_rect.x = 0; src_rect.y = 0;
src_rect.width = w << 16;
src_rect.height = h << 16;
dispman_display = vc_dispmanx_display_open(/*LCD*/ 0);
dispman_update = vc_dispmanx_update_start(0);
VC_DISPMANX_ALPHA_T alpha = { /*DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS*/ 1, 255, 0 };
dispman_element = vc_dispmanx_element_add(
dispman_update,dispman_display, 0, &dst_rect,
0, &src_rect, /*DISPMANX_PROTECTION_NONE*/ 0, &alpha, 0,
/*DISPMAN_NO_ROTATE*/ 0);
nativewindow->element = dispman_element;
nativewindow->width = w;
nativewindow->height = h;
vc_dispmanx_update_submit_sync(dispman_update);
return nativewindow;
}
void delete_rpi_window(void* win) {
EGL_DISPMANX_WINDOW_T* nativewindow = (EGL_DISPMANX_WINDOW_T*)win;
vc_dispmanx_element_remove(dispman_update, nativewindow->element);
vc_dispmanx_update_submit_sync(dispman_update);
free(win);
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef _GLX_RPI_H_
#define _GLX_RPI_H_
// Code specific to RPI
void rpi_init();
void rpi_fini();
void* create_rpi_window(int w, int h);
void delete_rpi_window(void* win);
#endif // _GLX_RPI_H_
+295
View File
@@ -0,0 +1,295 @@
/*
Helper fonctions for Streaming textures
*/
#ifdef TEXSTREAM
#include <bc_cat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "streaming.h"
#include "../gl/loader.h"
#include "../gl/gles.h"
PFNGLTEXBINDSTREAMIMGPROC *glTexBindStreamIMG = NULL;
PFNGLGETTEXSTREAMDEVICEATTRIBUTEIVIMGPROC *glGetTexAttrIMG = NULL;
PFNGLGETTEXSTREAMDEVICENAMEIMGPROC *glGetTexDeviceIMG = NULL;
//extern void* eglGetProcAddress(const char*);
int gl_streaming = 0;
int gl_streaming_initialized = 0;
int bc_cat[10];
int tex_free[10];
const GLubyte * bcdev[10];
int bcdev_w, bcdev_h, bcdev_n;
int bcdev_fmt;
unsigned long buf_paddr[10]; // physical address
char *buf_vaddr[10]; // virtual address
void Streaming_Initialize() {
LOAD_EGL(eglGetProcAddress);
if (gl_streaming_initialized)
return;
// get the extension functions
gl_streaming_initialized = 1;
glTexBindStreamIMG =(PFNGLTEXBINDSTREAMIMGPROC*)egl_eglGetProcAddress("glTexBindStreamIMG");
glGetTexAttrIMG = (PFNGLGETTEXSTREAMDEVICEATTRIBUTEIVIMGPROC*)egl_eglGetProcAddress("glGetTexStreamDeviceAttributeivIMG");
glGetTexDeviceIMG = (PFNGLGETTEXSTREAMDEVICENAMEIMGPROC*)egl_eglGetProcAddress("glGetTexStreamDeviceNameIMG");
if (!glTexBindStreamIMG || !glGetTexAttrIMG || !glGetTexDeviceIMG) {
gl_streaming = 0;
return;
}
gl_streaming = 1;
// initialise the bc_cat ids
for (int i=0; i<10; i++) {
bc_cat[i] = -1;
tex_free[i] = 1;
}
}
int open_bccat(int i) {
if (bc_cat[i]>-1)
return bc_cat[i];
char buff[]="/dev/bccat0";
buff[strlen(buff)-1]='0'+i;
bc_cat[i] = open(buff, O_RDWR|O_NDELAY);
return bc_cat[i];
}
void close_bccat(int i) {
if (bc_cat[i]==-1)
return;
close(bc_cat[i]);
bc_cat[i]=-1;
return;
}
int alloc_buff(int buff, int width, int height) {
if (!gl_streaming_initialized)
Streaming_Initialize;
if (!gl_streaming)
return 0;
if ((buff<0) || (buff>9))
return 0;
if (!tex_free[buff])
return 0;
if (open_bccat(buff)<0)
return 0;
BCIO_package ioctl_var;
bc_buf_params_t buf_param;
buf_param.count = 1; // only 1 buffer?
buf_param.width = width;
buf_param.height = height;
buf_param.fourcc = BC_PIX_FMT_RGB565; // only RGB565 here (other choices are only some YUV formats)
buf_param.type = BC_MEMORY_MMAP;
if (ioctl(bc_cat[buff], BCIOREQ_BUFFERS, &buf_param) != 0) {
printf("LIBGL: BCIOREQ_BUFFERS failed\n");
return 0;
}
if (ioctl(bc_cat[buff], BCIOGET_BUFFERCOUNT, &ioctl_var) != 0) {
printf("LIBGL: BCIOREQ_BUFFERCOUNT failed\n");
return 0;
}
if (ioctl_var.output == 0) {
printf("LIBGL: Streaming, no texture buffer available\n");
return 0;
}
const char *bcdev = glGetTexDeviceIMG(buff);
if (!bcdev) {
printf("LIBGL: problem with getting the GL_IMG_texture_stream device\n");
return 0;
} else {
bcdev_w = width;
bcdev_h = height;
bcdev_n = 1;
glGetTexAttrIMG(buff, GL_TEXTURE_STREAM_DEVICE_NUM_BUFFERS_IMG, &bcdev_n);
glGetTexAttrIMG(buff, GL_TEXTURE_STREAM_DEVICE_WIDTH_IMG, &bcdev_w);
glGetTexAttrIMG(buff, GL_TEXTURE_STREAM_DEVICE_HEIGHT_IMG, &bcdev_h);
glGetTexAttrIMG(buff, GL_TEXTURE_STREAM_DEVICE_FORMAT_IMG, &bcdev_fmt);
printf("LIBGL: Streaming device = %s num: %d, width: %d, height: %d, format: 0x%x\n",
bcdev, bcdev_n, bcdev_w, bcdev_h, bcdev_fmt);
if (bcdev_w!=width) {
printf("LIBGL: Streaming not activate, buffer width != asked width\n");
return 0;
}
}
/* LOAD_GLES(glTexParameterf);
gles_glTexParameterf(GL_TEXTURE_STREAM_IMG, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gles_glTexParameterf(GL_TEXTURE_STREAM_IMG, GL_TEXTURE_MAG_FILTER, GL_LINEAR);*/
ioctl_var.input = 0;
if (ioctl(bc_cat[buff], BCIOGET_BUFFERPHYADDR, &ioctl_var) != 0) {
printf("LIBGL: BCIOGET_BUFFERADDR failed\n");
return 0;
} else {
buf_paddr[buff] = ioctl_var.output;
buf_vaddr[buff] = (char *)mmap(NULL, width*height*2,
PROT_READ | PROT_WRITE, MAP_SHARED,
bc_cat[buff], buf_paddr[buff]);
if (buf_vaddr[buff] == MAP_FAILED) {
printf("LIBGL: mmap failed\n");
return 0;
}
}
// All done!
tex_free[buff] = 0;
return 1;
}
int free_buff(int buff) {
if (!gl_streaming)
return 0;
if ((buff<0) || (buff>9))
return 0;
close_bccat(buff);
tex_free[buff] = 1;
return 1;
}
/*
Streaming Cache functions
*/
int streaming_inited = 0;
typedef struct {
int active;
unsigned int last; // to get the age of last update
unsigned int texID; // ID of texture
} glstreaming_t;
glstreaming_t stream_cache[10];
unsigned int frame_number;
// Function to start the Streaming texture Cache
int InitStreamingCache() {
//printf("InitStreamingCache\n");
if (streaming_inited)
return gl_streaming;
Streaming_Initialize();
for (int i=0; i<10; i++) {
stream_cache[i].active = 0;
stream_cache[i].last = 0;
stream_cache[i].texID = 0;
}
frame_number = 0;
streaming_inited = 1;
return gl_streaming;
}
// Function to get a Streaming buffer address
void* GetStreamingBuffer(int buff) {
//printf("GetStreamingBuffer(%i)\n", buff);
if (!gl_streaming)
return NULL;
if ((buff<0) || (buff>9))
return NULL;
if (tex_free[buff])
return NULL;
stream_cache[buff].last = frame_number;
return buf_vaddr[buff];
}
// Function to add a new texture of size Width*Height, with fake Texture ID "ID". Return the ID or -1 if failed.
int AddStreamed(int width, int height, unsigned int ID) {
//printf("AddStreamed(%i, %i, %u)\n", width, height, ID);
if (!gl_streaming)
return -1;
static int i =0;
int j=0;
while (j<10) {
int k = (i+j)%10;
if (tex_free[k]) {
if (alloc_buff(k, width, height)) {
stream_cache[k].active = 1;
stream_cache[k].last = frame_number;
stream_cache[k].texID = ID;
i = (i+j+1)%10;
return k;
} else {
return -1; // Probably useless to try again and again
}
}
j++;
}
return -1;
}
// Function to free a streamed texture ID
void FreeStreamed(int ID) {
//printf("FreeStreamed(%i)", ID);
if (!gl_streaming)
return;
if ((ID<0) || (ID>9))
return;
if (tex_free[ID])
return;
if (!stream_cache[ID].active)
return;
free_buff(ID);
stream_cache[ID].active = 0;
stream_cache[ID].texID = 0;
}
// Function to find a StreamingID with a TextureID. G-1 if not found
int FindTexID(unsigned int ID) {
//printf("FindTexID(%u)\n", ID);
if (!gl_streaming)
return -1;
int i =0;
while (i<10) {
if (stream_cache[i].texID==ID)
return i;
i++;
}
return -1;
}
// Function to apply Min& Mag filter to Streaming texture
void ApplyFilterID(int ID, GLenum min_filter, GLenum mag_filter) {
//printf("ApplyFilterID(%i, 0x%04X, 0x%04X)\n", ID, min_filter, mag_filter);
if (!gl_streaming)
return;
if ((ID<0) || (ID>9))
return;
if (tex_free[ID])
return;
if (!stream_cache[ID].active)
return;
gl4es_glTexParameterf(GL_TEXTURE_STREAM_IMG, GL_TEXTURE_MIN_FILTER, min_filter);
gl4es_glTexParameterf(GL_TEXTURE_STREAM_IMG, GL_TEXTURE_MAG_FILTER, mag_filter);
}
// Function to activate the Steaming texture ID on current tex...
void ActivateStreaming(int ID) {
//printf("ActivateStreaming(%i)\n", ID);
LOAD_GLES(glEnable);
if (!gl_streaming)
return;
if ((ID<0) || (ID>9))
return;
if (tex_free[ID])
return;
if (!stream_cache[ID].active)
return;
// gles_glEnable(GL_TEXTURE_STREAM_IMG);
glTexBindStreamIMG(ID, 0);
}
// Function to deactivate the Streaming texture on current tex...
void DeactivateStreaming() {
//printf("DeactivateStreaming()\n");
LOAD_GLES(glDisable);
if (!gl_streaming)
return;
// gles_glDisable(GL_TEXTURE_STREAM_IMG);
}
#endif //TEXSTREAM
+46
View File
@@ -0,0 +1,46 @@
#ifndef _GLX_STREAMING_H_
#define _GLX_STREAMING_H_
#ifdef TEXSTREAM
#include "../gl/gl4es.h"
#ifndef GL_APIENTRYP
#define GL_APIENTRYP
#endif
#ifndef GL_IMG_texture_stream
#define GL_TEXTURE_STREAM_IMG 0x8C0D
#define GL_TEXTURE_NUM_STREAM_DEVICES_IMG 0x8C0E
#define GL_TEXTURE_STREAM_DEVICE_WIDTH_IMG 0x8C0F
#define GL_TEXTURE_STREAM_DEVICE_HEIGHT_IMG 0x8EA0
#define GL_TEXTURE_STREAM_DEVICE_FORMAT_IMG 0x8EA1
#define GL_TEXTURE_STREAM_DEVICE_NUM_BUFFERS_IMG 0x8EA2
typedef void (GL_APIENTRYP PFNGLTEXBINDSTREAMIMGPROC) (GLint device, GLint deviceoffset);
typedef const GLubyte *(GL_APIENTRYP PFNGLGETTEXSTREAMDEVICENAMEIMGPROC) (GLenum target);
typedef void (GL_APIENTRYP PFNGLGETTEXSTREAMDEVICEATTRIBUTEIVIMGPROC) (GLenum target, GLenum pname, GLint *params);
#define GL_IMG_texture_stream 1
#endif
extern PFNGLTEXBINDSTREAMIMGPROC *glTexBindStreamIMG;
extern PFNGLGETTEXSTREAMDEVICEATTRIBUTEIVIMGPROC *glGetTexAttrIMG;
extern PFNGLGETTEXSTREAMDEVICENAMEIMGPROC *glGetTexDeviceIMG;
extern int gl_stream; //0 if no streaming not 0 if streaming available
// Function to start the Streaming texture Cache. Return 0 if failed, non-0 if OK.
int InitStreamingCache();
// Function to get a Streaming buffer address
void* GetStreamingBuffer(int buff);
// Function to add a new texture of size Width*Height, with fake Texture ID "ID". Return the StreamingID or -1 if failed.
int AddStreamed(int width, int height, unsigned int ID);
// Function to free a streamed texture ID
void FreeStreamed(int ID);
// Function to find a StreamingID with a TextureID. G-1 if not found
int FindTexID(unsigned int ID);
// Function to apply Min& Mag filter to Streaming texture
void ApplyFilterID(int ID, GLenum min_filter, GLenum mag_filter);
// Function to activate the Steaming texture ID on current tex...
void ActivateStreaming(int ID);
// Function to deactivate the Streaming texture on current tex...
void DeactivateStreaming();
#endif // TEXSTREAM
#endif // _GLX_STREAMING_H_
+91
View File
@@ -0,0 +1,91 @@
#include "utils.h"
/*
* Generate OpenGL-compatible bitmap.
* From Mesa-9.0.1
*/
#ifndef NOX11
void
fill_bitmap(Display * dpy, Window win, GC gc,
unsigned int width, unsigned int height,
int x0, int y0, unsigned int c, GLubyte * bitmap)
{
XImage *image;
unsigned int x, y;
Pixmap pixmap;
XChar2b char2b;
pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
XSetForeground(dpy, gc, 0);
XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
XSetForeground(dpy, gc, 1);
char2b.byte1 = (c >> 8) & 0xff;
char2b.byte2 = (c & 0xff);
XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
if (image) {
/* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
for (y = 0; y < height; y++)
for (x = 0; x < 8 * width; x++)
if (XGetPixel(image, x, y))
bitmap[width * (height - y - 1) + x / 8] |=
(1 << (7 - (x % 8)));
XDestroyImage(image);
}
XFreePixmap(dpy, pixmap);
}
/*
* determine if a given glyph is valid and return the
* corresponding XCharStruct.
* From MesaGL-9.0.1
*/
XCharStruct *
isvalid(XFontStruct * fs, int which)
{
unsigned int rows, pages;
int byte1 = 0, byte2 = 0;
int i, valid = 1;
rows = fs->max_byte1 - fs->min_byte1 + 1;
pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
if (rows == 1) {
/* "linear" fonts */
if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
valid = 0;
}
else {
/* "matrix" fonts */
byte2 = which & 0xff;
byte1 = which >> 8;
if ((fs->min_char_or_byte2 > byte2) ||
(fs->max_char_or_byte2 < byte2) ||
(fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
valid = 0;
}
if (valid) {
if (fs->per_char) {
if (rows == 1) {
/* "linear" fonts */
return (fs->per_char + (which - fs->min_char_or_byte2));
}
else {
/* "matrix" fonts */
i = ((byte1 - fs->min_byte1) * pages) +
(byte2 - fs->min_char_or_byte2);
return (fs->per_char + i);
}
}
else {
return (&fs->min_bounds);
}
}
return (NULL);
}
#endif //NOX11
+21
View File
@@ -0,0 +1,21 @@
#ifndef _GLX_UTILS_H_
#define _GLX_UTILS_H_
#ifndef NOX11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif // NOX11
#include <stdio.h>
#include <string.h>
#include "../gl/gl4es.h"
#ifndef NOX11
void
fill_bitmap(Display * dpy, Window win, GC gc,
unsigned int width, unsigned int height,
int x0, int y0, unsigned int c, GLubyte * bitmap);
XCharStruct *
isvalid(XFontStruct * fs, int which);
#endif // NOX11
#endif // _GLX_UTILS_H_