diff options
Diffstat (limited to 'src/native')
-rwxr-xr-x | src/native/jogl/EGLDrawableFactory.c | 319 | ||||
-rwxr-xr-x | src/native/jogl/Mixer.cpp | 199 |
2 files changed, 518 insertions, 0 deletions
diff --git a/src/native/jogl/EGLDrawableFactory.c b/src/native/jogl/EGLDrawableFactory.c new file mode 100755 index 000000000..41e0f67e1 --- /dev/null +++ b/src/native/jogl/EGLDrawableFactory.c @@ -0,0 +1,319 @@ +#include <EGL/egl.h> +#include <KD/kd.h> +#include <KD/NV_extwindowprops.h> +#include "com_sun_opengl_impl_egl_EGLDrawableFactory.h" + +// FIXME: move the glViewport call up to Java +#include <GLES/gl.h> + +static EGLDisplay display = NULL; +static EGLSurface surface = NULL; +static EGLContext context = NULL; +static EGLConfig config = NULL; +static KDWindow* window = NULL; +static EGLNativeWindowType nativewin = NULL; +static EGLint lastWidth = 0; +static EGLint lastHeight = 0; + +// FIXME: need to move this up to Java to conditionalize between ES 1 and ES 2 +//static KDint nv_egl_renderable_flags = EGL_OPENGL_ES2_BIT; +static KDint nv_egl_renderable_flags = EGL_OPENGL_ES_BIT; +static KDint nv_egl_surface_flags = EGL_WINDOW_BIT; +static KDust jogPressUST = 0; + +typedef struct +{ + KDint index; + KDboolean wasPressed; + KDust pressTime; +} DeviceButtonState; +#define NVM_BTNS_MAX 5 +typedef enum +{ + NVM_BTN_JOGDIAL, + NVM_BTN_WIDGET, + NVM_BTN_BACK, + NVM_BTN_CAMHALF, + NVM_BTN_CAMFULL, +}; +DeviceButtonState conButtons[NVM_BTNS_MAX] = +{ + {KD_INPUT_JOGDIAL_SELECT, 0, 0}, + {KD_INPUT_BUTTONS_0+0, 0, 0}, + {KD_INPUT_BUTTONS_0+1, 0, 0}, + {KD_INPUT_BUTTONS_0+2, 0, 0}, + {KD_INPUT_BUTTONS_0+3, 0, 0}, +}; + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_initEGL + (JNIEnv *env, jobject unused) +{ + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (display == EGL_NO_DISPLAY) { + kdLogMessage("Error - EGL get display failed\n"); + return JNI_FALSE; + } + if (!eglInitialize(display, 0, 0)) { + kdLogMessage("Error - EGL init failed\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_chooseConfig + (JNIEnv *env, jobject unused) +{ + #define MAX_CONFIGS 64 + EGLConfig confs[MAX_CONFIGS]; + EGLint numConfigs; + EGLint fbAttrs[] = + { +/* + // FIXME + // OpenGL ES 2 settings + EGL_RENDERABLE_TYPE, nv_egl_renderable_flags, + EGL_DEPTH_SIZE, 16, + EGL_SURFACE_TYPE, nv_egl_surface_flags, + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_NONE +*/ + +/* + // FIXME + // OpenGL ES 1 settings + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, EGL_DONT_CARE, + EGL_DEPTH_SIZE, 1, + EGL_STENCIL_SIZE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_NONE +*/ + + // FIXME + // OpenGL ES 1 settings + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_DEPTH_SIZE, 16, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_NONE + }; + + if (!(eglChooseConfig(display, fbAttrs, confs, MAX_CONFIGS, &numConfigs) && numConfigs)) { + kdLogMessage("Error - EGL choose config failed\n"); + return JNI_FALSE; + } + /* Use the first */ + config = confs[0]; + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_checkDisplay + (JNIEnv *env, jobject unused) +{ + if (display == NULL) { + kdLogMessage("Error - EGL get display returned null\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_checkConfig + (JNIEnv *env, jobject unused) +{ + if (config == NULL) { + kdLogMessage("Error - EGL choose config returned null\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_createWindow + (JNIEnv *env, jobject unused) +{ + window = kdCreateWindow(display, config, KD_NULL); + if (!window) { + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT void JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_setWindowVisible + (JNIEnv *env, jobject unused) +{ + KDboolean visible = KD_TRUE; + kdSetWindowPropertybv(window, + KD_WINDOWPROPERTY_VISIBILITY, &visible); +} + +JNIEXPORT void JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_setWindowFullscreen + (JNIEnv *env, jobject unused) +{ + KDboolean fullscreen = KD_TRUE; + kdSetWindowPropertybv(window, + KD_WINDOWPROPERTY_FULLSCREEN_NV, &fullscreen); +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_realizeWindow + (JNIEnv *env, jobject unused) +{ + if (kdRealizeWindow(window, &nativewin) != 0) { + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_createSurface + (JNIEnv *env, jobject unused) +{ + surface = eglCreateWindowSurface(display, + config, nativewin, 0); + if (!surface) + { + kdLogMessage("Error - EGL create window surface failed\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_createContext + (JNIEnv *env, jobject unused) +{ + /*a + static EGLint contextAttrs[] = + { + // FIXME + // OpenGL ES 2 settings + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + */ + + const EGLint contextAttrs[] = + { + // FIXME + // OpenGL ES 1 settings + EGL_CONTEXT_CLIENT_VERSION, 1, + EGL_NONE + }; + + context = eglCreateContext(display, + config, 0, contextAttrs); + if (!context) + { + kdLogMessage("Error - EGL create context failed\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_makeCurrent + (JNIEnv *env, jobject unused) +{ + if (!eglMakeCurrent(display, surface, surface, context)) + { + kdLogMessage("Error - EGL make current failed\n"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +JNIEXPORT void JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_updateWindowSize + (JNIEnv *env, jobject unused) +{ + EGLint drawWidth; + EGLint drawHeight; + + eglQuerySurface(display, surface, EGL_WIDTH, &drawWidth); + eglQuerySurface(display, surface, EGL_HEIGHT, &drawHeight); + if ((lastWidth != drawWidth) || (lastHeight != drawHeight)) + { + glViewport(0, 0, drawWidth, drawHeight); + lastWidth = drawWidth; + lastHeight = drawHeight; + } +} + +JNIEXPORT void JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_swapBuffers0 + (JNIEnv *env, jobject unused) +{ + eglSwapBuffers(display, surface); +} + +JNIEXPORT jboolean JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_shouldExit + (JNIEnv *env, jobject unused) +{ + const KDEvent* ev = NULL; + do { + ev = kdWaitEvent(0); + if (ev != 0) { + switch (ev->type) { + case KD_EVENT_WINDOW_CLOSE: + case KD_EVENT_QUIT: + return JNI_TRUE; + default: + break; + /* + case KD_EVENT_INPUT: + { + if (!s_runningInLauncher) + { + int btn; + for (btn=0; btn<NVM_BTNS_MAX; btn++) + { + if (InputDown(ev, conButtons[btn].index)) + { + if (!conButtons[btn].wasPressed) + { + conButtons[btn].pressTime = ev->timestamp; + conButtons[btn].wasPressed = KD_TRUE; + } + } + else + { + conButtons[btn].wasPressed = KD_FALSE; + } + } + } + break; + } + */ + } + } + } while (ev != 0); + return JNI_FALSE; +} + +JNIEXPORT void JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_shutdown + (JNIEnv *env, jobject unused) +{ + if (context) { + eglMakeCurrent(display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(display, context); + context = EGL_NO_CONTEXT; + } + if (surface) { + eglDestroySurface(display, surface); + surface = EGL_NO_SURFACE; + } + kdDestroyWindow(window); + if (display) { + eglTerminate(display); + display = EGL_NO_DISPLAY; + } +} + +JNIEXPORT jint JNICALL Java_com_sun_opengl_impl_egl_EGLDrawableFactory_getDirectBufferAddress + (JNIEnv *env, jobject unused, jobject buffer) +{ + return (jint) (*env)->GetDirectBufferAddress(env, buffer); +} diff --git a/src/native/jogl/Mixer.cpp b/src/native/jogl/Mixer.cpp new file mode 100755 index 000000000..8843c00ec --- /dev/null +++ b/src/native/jogl/Mixer.cpp @@ -0,0 +1,199 @@ +#include <windows.h> +#include <stdlib.h> +#include <mmsystem.h> +#include <mmreg.h> +#include "com_sun_javafx_audio_windows_waveout_Mixer.h" + +static HANDLE event = NULL; +static HWAVEOUT output = NULL; +// We use only two buffers to keep latency down +#define NUM_BUFFERS 2 +//#define NUM_BUFFERS 4 +// This is about 20 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (20 ms / 1000 ms) * (2 bytes / sample) * (2 channels) +//#define BUFFER_SIZE 3528 + +// This is about 50 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (50 ms / 1000 ms) * (2 bytes / sample) * (1 channel) +//#define BUFFER_SIZE 4410 + +// This is about 200 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (200 ms / 1000 ms) * (2 bytes / sample) * (1 channel) +//#define BUFFER_SIZE 17640 + +// This is about 200 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (200 ms / 1000 ms) * (2 bytes / sample) * (2 channel) +//#define BUFFER_SIZE 35280 + +// This is about 1000 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (1000 ms / 1000 ms) * (2 bytes / sample) * (1 channel) +//#define BUFFER_SIZE 88200 + +// This is about 50 ms of data for WAVE_FORMAT_PCM: +// (44100 samples / sec) * (50 ms / 1000 ms) * (2 bytes / sample) * (2 channels) +//#define BUFFER_SIZE 8820 + +// This is about 50 ms of data for WAVE_FORMAT_IEEE_FLOAT: +// (44100 samples / sec) * (50 ms / 1000 ms) * (4 bytes / sample) * (2 channels) +//#define BUFFER_SIZE 17640 + +// This is about 200 ms of data for WAVE_FORMAT_PCM: +// (11025 samples / sec) * (200 ms / 1000 ms) * (2 bytes / sample) * (2 channel) +#define BUFFER_SIZE 8820 + +//#define BUFFER_SIZE 8192 +static WAVEHDR** buffers = NULL; + +void CALLBACK playbackCallback(HWAVEOUT output, + UINT msg, + DWORD_PTR userData, + DWORD_PTR param1, + DWORD_PTR param2) +{ + if (msg == WOM_DONE) { + WAVEHDR* hdr = (WAVEHDR*) param1; + hdr->dwFlags |= WHDR_DONE; + SetEvent(event); + } +} + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_initializeWaveOut + (JNIEnv *env, jclass unused, jlong eventObject) +{ + event = (HANDLE) eventObject; + + // Note the hard requirements on the RawSoundConverter's output format + WAVEFORMATEX format; + format.wFormatTag = WAVE_FORMAT_PCM; + // format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + format.nChannels = 2; + // format.nChannels = 1; + // format.nSamplesPerSec = 44100; + format.nSamplesPerSec = 11025; + format.wBitsPerSample = 16; + // format.wBitsPerSample = 32; + format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; + format.nAvgBytesPerSec = format.nBlockAlign * format.nSamplesPerSec; + format.cbSize = 0; + MMRESULT res = waveOutOpen(&output, + WAVE_MAPPER, + &format, + /* NULL, */ (DWORD_PTR) &playbackCallback, + NULL, // No user data right now + /* CALLBACK_NULL */ CALLBACK_FUNCTION); + if (res != MMSYSERR_NOERROR) { + return JNI_FALSE; + } + + buffers = (WAVEHDR**) calloc(NUM_BUFFERS, sizeof(WAVEHDR)); + for (int i = 0; i < NUM_BUFFERS; i++) { + char* data = (char*) calloc(BUFFER_SIZE, 1); + WAVEHDR* hdr = (WAVEHDR*) calloc(1, sizeof(WAVEHDR)); + hdr->lpData = data; + hdr->dwBufferLength = BUFFER_SIZE; + hdr->dwFlags |= WHDR_DONE; + buffers[i] = hdr; + } + + return JNI_TRUE; +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_shutdownWaveOut + (JNIEnv *env, jclass unused) +{ + // writeString("Pausing\n"); + waveOutPause(output); + // writeString("Resetting\n"); + waveOutReset(output); + // writeString("Closing output\n"); + waveOutClose(output); +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_getNextMixerBuffer + (JNIEnv *env, jclass unused) +{ + WAVEHDR* hdr = NULL; + for (int i = 0; i < NUM_BUFFERS; i++) { + if (buffers[i] != NULL && ((buffers[i]->dwFlags & WHDR_DONE) != 0)) { + hdr = buffers[i]; + hdr->dwFlags &= ~WHDR_DONE; + break; + } + } + return (jlong) hdr; +} + +JNIEXPORT jobject JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_getMixerBufferData + (JNIEnv *env, jclass unused, jlong mixerBuffer) +{ + WAVEHDR* hdr = (WAVEHDR*) mixerBuffer; + return env->NewDirectByteBuffer(hdr->lpData, hdr->dwBufferLength); +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_getMixerBufferDataAddress + (JNIEnv *env, jclass unused, jlong mixerBuffer) +{ + WAVEHDR* hdr = (WAVEHDR*) mixerBuffer; + return (jlong) hdr->lpData; +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_getMixerBufferDataCapacity + (JNIEnv *env, jclass unused, jlong mixerBuffer) +{ + WAVEHDR* hdr = (WAVEHDR*) mixerBuffer; + return (jint) hdr->dwBufferLength; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_prepareMixerBuffer + (JNIEnv *env, jclass unused, jlong mixerBuffer) +{ + MMRESULT res = waveOutPrepareHeader(output, + (WAVEHDR*) mixerBuffer, + sizeof(WAVEHDR)); + if (res == MMSYSERR_NOERROR) { + return JNI_TRUE; + } + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_writeMixerBuffer + (JNIEnv *env, jclass unused, jlong mixerBuffer) +{ + MMRESULT res = waveOutWrite(output, + (WAVEHDR*) mixerBuffer, + sizeof(WAVEHDR)); + if (res == MMSYSERR_NOERROR) { + waveOutRestart(output); + + return JNI_TRUE; + } + return JNI_FALSE; +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_CreateEvent + (JNIEnv *env, jclass unused) +{ + return (jlong) CreateEvent(NULL, FALSE, TRUE, NULL); +} + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_WaitForSingleObject + (JNIEnv *env, jclass unused, jlong eventObject) +{ + DWORD res = WaitForSingleObject((HANDLE) eventObject, INFINITE); + if (res == WAIT_OBJECT_0) { + return JNI_TRUE; + } + return JNI_FALSE; +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_SetEvent + (JNIEnv *env, jclass unused, jlong eventObject) +{ + SetEvent((HANDLE) eventObject); +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_audio_windows_waveout_Mixer_CloseHandle + (JNIEnv *env, jclass unused, jlong eventObject) +{ + CloseHandle((HANDLE) eventObject); +} |