- 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:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user