lwjgl/src/native/win32/org_lwjgl_opengl_Display.c

855 lines
26 KiB
C
Raw Normal View History

2003-08-04 06:09:40 -04:00
/*
2004-06-12 16:28:34 -04:00
* Copyright (c) 2002-2004 LWJGL Project
2003-08-04 06:09:40 -04:00
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
2004-06-12 16:28:34 -04:00
* * Neither the name of 'LWJGL' nor the names of
2003-08-04 06:09:40 -04:00
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* $Id$
*
2004-07-03 06:16:28 -04:00
* Base Win32 display
2003-08-04 06:09:40 -04:00
*
* @author cix_foo <cix_foo@users.sourceforge.net>
* @version $Revision$
*/
#define _PRIVATE_WINDOW_H_
#include "Window.h"
2004-09-22 11:06:27 -04:00
#include <windowsx.h>
2004-07-03 10:39:29 -04:00
#include "extgl_wgl.h"
2003-10-11 12:29:40 -04:00
#include "common_tools.h"
2004-07-03 10:39:29 -04:00
#include "extgl_wgl.h"
2004-07-03 06:16:28 -04:00
#include "display.h"
2004-11-02 08:15:59 -05:00
#include "org_lwjgl_opengl_Win32Display.h"
#include <malloc.h>
2003-08-04 06:09:40 -04:00
2004-09-15 13:07:06 -04:00
static bool oneShotInitialised = false; // Registers the LWJGL window class
2004-09-15 13:07:06 -04:00
static HWND display_hwnd = NULL; // Handle to the window
static HDC display_hdc = NULL; // Device context
static HGLRC display_hglrc = NULL; // OpenGL context
static bool isFullScreen = false; // Whether we're fullscreen or not
static bool isMinimized = false; // Whether we're minimized or not
static bool isFocused = false; // whether we're focused or not
static bool isDirty = false; // Whether we're dirty or not
2004-09-15 13:07:06 -04:00
static bool isUndecorated = false; // Whether we're undecorated or not
extern HINSTANCE dll_handle; // Handle to the LWJGL dll
RECT clientSize; // client size rect used when creating and positioning window
2003-08-04 06:09:40 -04:00
static bool closerequested;
2004-07-03 06:16:28 -04:00
static int pixel_format_index;
2003-08-04 06:09:40 -04:00
#define WINDOWCLASSNAME "LWJGL"
bool applyPixelFormat(HDC hdc, int iPixelFormat) {
2004-02-15 14:24:03 -05:00
PIXELFORMATDESCRIPTOR desc;
if (DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &desc) == 0) {
return false;
}
// make that the pixel format of the device context
if (SetPixelFormat(hdc, iPixelFormat, &desc) == FALSE) {
return false;
}
return true;
}
HWND getCurrentHWND() {
return display_hwnd;
}
2004-07-24 17:19:08 -04:00
HGLRC getCurrentContext() {
return display_hglrc;
}
static int findPixelFormatARBFromBPP(JNIEnv *env, HDC hdc, jobject pixel_format, jobject pixelFormatCaps, int bpp, bool window, bool pbuffer, bool double_buffer) {
jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format);
int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I"));
int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I"));
int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I"));
int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I"));
int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I"));
int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I"));
int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I"));
jboolean stereo = (*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z"));
2004-02-15 14:24:03 -05:00
int iPixelFormat;
unsigned int num_formats_returned;
2004-07-03 06:16:28 -04:00
attrib_list_t attrib_list;
GLuint *pixelFormatCaps_ptr;
jlong pixelFormatCapsSize;
BOOL result;
jlong i;
2004-07-03 06:16:28 -04:00
initAttribList(&attrib_list);
if (window) {
putAttrib(&attrib_list, WGL_DRAW_TO_WINDOW_ARB); putAttrib(&attrib_list, TRUE);
2004-07-24 17:19:08 -04:00
}
if (pbuffer) {
2004-07-03 06:16:28 -04:00
putAttrib(&attrib_list, WGL_DRAW_TO_PBUFFER_ARB); putAttrib(&attrib_list, TRUE);
}
putAttrib(&attrib_list, WGL_ACCELERATION_ARB); putAttrib(&attrib_list, WGL_FULL_ACCELERATION_ARB);
putAttrib(&attrib_list, WGL_PIXEL_TYPE_ARB); putAttrib(&attrib_list, WGL_TYPE_RGBA_ARB);
2004-07-07 04:06:57 -04:00
putAttrib(&attrib_list, WGL_DOUBLE_BUFFER_ARB); putAttrib(&attrib_list, double_buffer ? TRUE : FALSE);
2004-07-03 06:16:28 -04:00
putAttrib(&attrib_list, WGL_SUPPORT_OPENGL_ARB); putAttrib(&attrib_list, TRUE);
putAttrib(&attrib_list, WGL_COLOR_BITS_ARB); putAttrib(&attrib_list, bpp);
putAttrib(&attrib_list, WGL_ALPHA_BITS_ARB); putAttrib(&attrib_list, alpha);
putAttrib(&attrib_list, WGL_DEPTH_BITS_ARB); putAttrib(&attrib_list, depth);
putAttrib(&attrib_list, WGL_STENCIL_BITS_ARB); putAttrib(&attrib_list, stencil);
if (samples > 0 && extension_flags.WGL_ARB_multisample) {
2004-07-03 06:16:28 -04:00
putAttrib(&attrib_list, WGL_SAMPLE_BUFFERS_ARB); putAttrib(&attrib_list, 1);
putAttrib(&attrib_list, WGL_SAMPLES_ARB); putAttrib(&attrib_list, samples);
}
putAttrib(&attrib_list, WGL_ACCUM_BITS_ARB); putAttrib(&attrib_list, accum_bpp);
putAttrib(&attrib_list, WGL_ACCUM_ALPHA_BITS_ARB); putAttrib(&attrib_list, accum_alpha);
putAttrib(&attrib_list, WGL_STEREO_ARB); putAttrib(&attrib_list, stereo ? TRUE : FALSE);
putAttrib(&attrib_list, WGL_AUX_BUFFERS_ARB); putAttrib(&attrib_list, num_aux_buffers);
if ( pixelFormatCaps != NULL ) {
if ( !extension_flags.WGL_ARB_render_texture ) {
2004-07-03 06:16:28 -04:00
return -1;
}
pixelFormatCaps_ptr = (GLuint *)(*env)->GetDirectBufferAddress(env, pixelFormatCaps);
pixelFormatCapsSize = (*env)->GetDirectBufferCapacity(env, pixelFormatCaps);
2004-07-03 06:16:28 -04:00
for (i = 0; i < pixelFormatCapsSize; i++)
2004-07-03 06:16:28 -04:00
putAttrib(&attrib_list, pixelFormatCaps_ptr[i]);
2004-02-15 14:24:03 -05:00
}
2004-07-03 06:16:28 -04:00
putAttrib(&attrib_list, 0); putAttrib(&attrib_list, 0);
result = wglChoosePixelFormatARB(hdc, attrib_list.attribs, NULL, 1, &iPixelFormat, &num_formats_returned);
2004-02-15 14:24:03 -05:00
if (result == FALSE || num_formats_returned < 1) {
return -1;
}
return iPixelFormat;
}
2004-07-24 17:19:08 -04:00
int findPixelFormatARB(JNIEnv *env, HDC hdc, jobject pixel_format, jobject pixelFormatCaps, bool use_hdc_bpp, bool window, bool pbuffer, bool double_buffer) {
2004-07-03 06:16:28 -04:00
int bpp;
int iPixelFormat;
jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format);
2004-07-03 06:16:28 -04:00
if (use_hdc_bpp) {
bpp = GetDeviceCaps(hdc, BITSPIXEL);
iPixelFormat = findPixelFormatARBFromBPP(env, hdc, pixel_format, pixelFormatCaps, bpp, window, pbuffer, double_buffer);
2004-07-03 06:16:28 -04:00
if (iPixelFormat == -1)
bpp = 16;
else
return iPixelFormat;
} else
bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "bpp", "I"));
2004-07-24 17:19:08 -04:00
return findPixelFormatARBFromBPP(env, hdc, pixel_format, pixelFormatCaps, bpp, window, pbuffer, double_buffer);
2004-07-03 06:16:28 -04:00
}
2003-08-04 06:09:40 -04:00
/*
* Find an appropriate pixel format
*/
static int findPixelFormatFromBPP(JNIEnv *env, HDC hdc, jobject pixel_format, int bpp)
2003-08-04 06:09:40 -04:00
{
jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format);
int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I"));
int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I"));
int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I"));
int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I"));
int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I"));
int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I"));
int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I"));
jboolean stereo = (*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z"));
2004-02-15 14:24:03 -05:00
unsigned int flags = PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
(stereo ? PFD_STEREO : 0);
PIXELFORMATDESCRIPTOR desc;
int iPixelFormat;
PIXELFORMATDESCRIPTOR pfd = {
2003-08-04 06:09:40 -04:00
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
flags, // RGBA type
PFD_TYPE_RGBA,
(BYTE)bpp,
0, 0, 0, 0, 0, 0, // color bits ignored
(BYTE)alpha,
0, // shift bit ignored
2004-07-03 06:16:28 -04:00
accum_bpp + accum_alpha, // no accumulation buffer
2003-08-04 06:09:40 -04:00
0, 0, 0, 0, // accum bits ignored
(BYTE)depth,
(BYTE)stencil,
2004-07-03 06:16:28 -04:00
num_aux_buffers,
2003-08-04 06:09:40 -04:00
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
// get the best available match of pixel format for the device context
iPixelFormat = ChoosePixelFormat(hdc, &pfd);
2003-08-04 06:09:40 -04:00
if (iPixelFormat == 0) {
printfDebugJava(env, "Failed to choose pixel format");
2003-08-04 06:09:40 -04:00
return -1;
}
if (DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &desc) == 0) {
printfDebugJava(env, "Could not describe pixel format");
2003-08-04 06:09:40 -04:00
return -1;
}
if (desc.cColorBits < bpp) {
printfDebugJava(env, "Insufficient color precision");
2003-08-04 06:09:40 -04:00
return -1;
}
if (desc.cAlphaBits < alpha) {
printfDebugJava(env, "Insufficient alpha precision");
2003-08-04 06:09:40 -04:00
return -1;
}
if (desc.cStencilBits < stencil) {
printfDebugJava(env, "Insufficient stencil precision");
2003-08-04 06:09:40 -04:00
return -1;
}
if (desc.cDepthBits < depth) {
printfDebugJava(env, "Insufficient depth buffer precision");
2003-08-04 06:09:40 -04:00
return -1;
}
if ((desc.dwFlags & PFD_GENERIC_FORMAT) != 0 || (desc.dwFlags & PFD_GENERIC_ACCELERATED) != 0) {
jboolean allowSoftwareOpenGL = getBooleanProperty(env, "org.lwjgl.opengl.Display.allowSoftwareOpenGL");
2004-07-03 06:16:28 -04:00
// secondary check for software override
if(!allowSoftwareOpenGL) {
printfDebugJava(env, "Pixel format not accelerated");
2004-07-03 06:16:28 -04:00
return -1;
}
2003-08-04 06:09:40 -04:00
}
if ((desc.dwFlags & flags) != flags) {
printfDebugJava(env, "Capabilities not supported");
2003-08-04 06:09:40 -04:00
return -1;
}
return iPixelFormat;
}
int findPixelFormat(JNIEnv *env, HDC hdc, jobject pixel_format) {
int bpp = GetDeviceCaps(hdc, BITSPIXEL);
int iPixelFormat;
iPixelFormat = findPixelFormatFromBPP(env, hdc, pixel_format, bpp);
2004-07-03 12:38:02 -04:00
if (iPixelFormat == -1) {
return findPixelFormatFromBPP(env, hdc, pixel_format, 16);
2004-07-03 12:38:02 -04:00
} else
return iPixelFormat;
}
2003-08-04 06:09:40 -04:00
/*
* Close the window
*/
2005-01-29 05:17:56 -05:00
void closeWindow(HWND *hwnd, HDC *hdc)
2003-08-04 06:09:40 -04:00
{
// Release device context
2005-01-29 05:17:56 -05:00
if (*hdc != NULL && *hwnd != NULL) {
2003-12-20 17:03:25 -05:00
printfDebug("Releasing DC\n");
2005-01-29 05:17:56 -05:00
ReleaseDC(*hwnd, *hdc);
*hdc = NULL;
2003-08-04 06:09:40 -04:00
}
// Close the window
2005-01-29 05:17:56 -05:00
if (*hwnd != NULL) {
ShowWindow(*hwnd, SW_HIDE);
2003-12-20 17:03:25 -05:00
printfDebug("Destroy window\n");
2005-01-29 05:17:56 -05:00
DestroyWindow(*hwnd);
*hwnd = NULL;
2003-08-04 06:09:40 -04:00
}
}
/*
* Called when the application is alt-tabbed to or from
*/
static void appActivate(bool active)
{
static bool inAppActivate = false;
if (inAppActivate) {
return;
}
inAppActivate = true;
2005-02-02 09:51:43 -05:00
isFocused = active;
2003-08-04 06:09:40 -04:00
if (active) {
if (isFullScreen) {
restoreDisplayMode();
}
ShowWindow(display_hwnd, SW_RESTORE);
SetForegroundWindow(display_hwnd);
2005-02-02 09:51:43 -05:00
SetFocus(display_hwnd);
/*
* Calling wglMakeCurrent() (redundantly) seems to help some gfx cards
* restore from minimized to fullscreen.
*/
if (wglGetCurrentContext() == display_hglrc)
wglMakeCurrent(display_hdc, display_hglrc);
2003-08-04 06:09:40 -04:00
} else if (isFullScreen) {
ShowWindow(display_hwnd, SW_SHOWMINNOACTIVE);
resetDisplayMode(NULL);
2003-08-04 06:09:40 -04:00
}
inAppActivate = false;
2003-08-04 06:09:40 -04:00
}
/*
* WindowProc for the GL window.
*/
LRESULT CALLBACK lwjglWindowProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
2005-02-02 09:51:43 -05:00
int xPos;
int yPos;
int dwheel;
2003-08-04 06:09:40 -04:00
switch (msg) {
// disable screen saver and monitor power down messages which wreak havoc
case WM_SYSCOMMAND:
{
switch (wParam) {
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0L;
break;
case SC_CLOSE:
closerequested = true;
//don't continue processing this command since this
//would shutdown the window, which the application might not want to
return 0L;
}
}
break;
case WM_ACTIVATE:
switch (wParam) {
case WA_ACTIVE:
case WA_CLICKACTIVE:
appActivate(true);
break;
case WA_INACTIVE:
appActivate(false);
break;
}
return 0L;
2005-02-02 08:16:50 -05:00
case WM_SIZE:
switch (wParam) {
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
isMinimized = false;
break;
case SIZE_MINIMIZED:
isMinimized = true;
break;
}
2005-02-02 09:51:43 -05:00
break;
2004-09-22 11:06:27 -04:00
case WM_MOUSEMOVE:
{
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
2004-09-22 11:06:27 -04:00
handleMouseMoved(xPos, yPos);
return 0;
}
case WM_MOUSEWHEEL:
{
dwheel = GET_WHEEL_DELTA_WPARAM(wParam);
2004-09-22 11:06:27 -04:00
handleMouseScrolled(dwheel);
return 0;
}
case WM_LBUTTONDOWN:
{
handleMouseButton(0, 1);
return 0;
}
case WM_LBUTTONUP:
{
handleMouseButton(0, 0);
return 0;
}
case WM_RBUTTONDOWN:
{
handleMouseButton(1, 1);
return 0;
}
case WM_RBUTTONUP:
{
handleMouseButton(1, 0);
return 0;
}
case WM_MBUTTONDOWN:
{
handleMouseButton(2, 1);
return 0;
}
case WM_MBUTTONUP:
{
handleMouseButton(2, 0);
return 0;
}
2003-08-04 06:09:40 -04:00
break;
case WM_QUIT:
{
closerequested = true;
return 0L;
}
case WM_PAINT:
{
isDirty = true;
2003-08-04 06:09:40 -04:00
}
}
2003-08-04 06:09:40 -04:00
// default action
return DefWindowProc(hWnd, msg, wParam, lParam);
}
/*
* Register the LWJGL window class.
* Returns true for success, or false for failure
*/
static bool registerWindow()
{
WNDCLASS windowClass;
2003-08-04 06:09:40 -04:00
if (!oneShotInitialised) {
windowClass.style = CS_OWNDC;
2003-08-04 06:09:40 -04:00
windowClass.lpfnWndProc = lwjglWindowProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = dll_handle;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
2003-08-04 06:09:40 -04:00
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = WINDOWCLASSNAME;
if (RegisterClass(&windowClass) == 0) {
2003-12-20 17:03:25 -05:00
printfDebug("Failed to register window class\n");
2003-08-04 06:09:40 -04:00
return false;
}
2003-12-20 17:03:25 -05:00
printfDebug("Window registered\n");
2003-08-04 06:09:40 -04:00
oneShotInitialised = true;
}
return true;
}
/*
* Handle native Win32 messages
*/
2004-09-22 11:06:27 -04:00
void handleMessages(void)
2003-08-04 06:09:40 -04:00
{
/*
* Now's our chance to deal with Windows messages that are
* otherwise just piling up and causing everything not to
* work properly
*/
MSG msg;
while (PeekMessage(
&msg, // message information
display_hwnd, // handle to window
2003-08-04 06:09:40 -04:00
0, // first message
0, // last message
PM_REMOVE // removal options
))
{
DispatchMessage(&msg);
};
}
/*
* Create a window with the specified title, position, size, and
* fullscreen attribute. The window will have DirectInput associated
* with it.
*
* Returns true for success, or false for failure
*/
2004-09-15 13:07:06 -04:00
HWND createWindow(int x, int y, int width, int height, bool fullscreen, bool undecorated)
2003-08-04 06:09:40 -04:00
{
int exstyle, windowflags;
HWND new_hwnd;
// 1. Register window class if necessary
if (!registerWindow()) {
return NULL;
}
2003-08-04 06:09:40 -04:00
if (fullscreen) {
exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST;
2003-11-17 02:45:14 -05:00
windowflags = WS_POPUP;
2004-04-03 18:01:39 -05:00
} else if (undecorated) {
exstyle = WS_EX_APPWINDOW;
windowflags = WS_POPUP;
2003-08-04 06:09:40 -04:00
} else {
exstyle = WS_EX_APPWINDOW;
2003-11-17 02:45:14 -05:00
windowflags = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU;
2003-08-04 06:09:40 -04:00
}
// If we're not a fullscreen window, adjust the height to account for the
2004-04-03 18:01:39 -05:00
// height of the title bar (unless undecorated)
2003-08-04 06:09:40 -04:00
clientSize.bottom = height;
clientSize.left = 0;
clientSize.right = width;
clientSize.top = 0;
AdjustWindowRectEx(
&clientSize, // client-rectangle structure
windowflags, // window styles
FALSE, // menu-present option
exstyle // extended window style
);
// Create the window now, using that class:
new_hwnd = CreateWindowEx (
2003-08-04 06:09:40 -04:00
exstyle,
WINDOWCLASSNAME,
2004-07-03 06:16:28 -04:00
"",
2003-08-04 06:09:40 -04:00
windowflags,
2004-09-15 13:07:06 -04:00
x, y, clientSize.right - clientSize.left, clientSize.bottom - clientSize.top,
2003-08-04 06:09:40 -04:00
NULL,
NULL,
dll_handle,
NULL);
return new_hwnd;
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_Window
* Method: nSetTitle
* Signature: ()V
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_setTitle
(JNIEnv * env, jobject self, jstring title_obj)
2003-08-04 06:09:40 -04:00
{
char * title = GetStringNativeChars(env, title_obj);
SetWindowText(display_hwnd, title);
free(title);
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_Window
2003-08-17 14:40:58 -04:00
* Method: update
2003-08-04 06:09:40 -04:00
* Signature: ()V
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_update
(JNIEnv * env, jobject self)
2003-08-04 06:09:40 -04:00
{
2004-09-22 11:06:27 -04:00
handleMessages();
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_Window
* Method: swapBuffers
* Signature: ()V
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_swapBuffers
(JNIEnv * env, jobject self)
2003-08-04 06:09:40 -04:00
{
isDirty = false;
SwapBuffers(display_hdc);
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_opengl_Window
* Method: nIsDirty
* Signature: ()Z
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Win32Display_isDirty
(JNIEnv *env, jobject self) {
bool result = isDirty;
isDirty = false;
return result ? JNI_TRUE : JNI_FALSE;
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_opengl_Window
* Method: nIsVisible
2003-08-04 06:09:40 -04:00
* Signature: ()Z
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Win32Display_isVisible
(JNIEnv *env, jobject self) {
return isMinimized ? JNI_FALSE : JNI_TRUE;
2003-08-04 06:09:40 -04:00
}
/*
* Class: org_lwjgl_opengl_Window
* Method: nIsCloseRequested
* Signature: ()Z
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Win32Display_isCloseRequested
(JNIEnv *env, jobject self) {
2003-08-04 06:09:40 -04:00
bool saved = closerequested;
closerequested = false;
return saved;
}
/*
* Class: org_lwjgl_opengl_Window
* Method: nIsActive
2003-08-04 06:09:40 -04:00
* Signature: ()Z
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Win32Display_isActive
(JNIEnv *env, jobject self) {
return isFocused;
2003-08-04 06:09:40 -04:00
}
2003-10-20 10:17:47 -04:00
/*
* Class: org_lwjgl_opengl_Window
* Method: nSetVSyncEnabled
* Signature: (Z)Z
*/
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_setVSyncEnabled
(JNIEnv * env, jobject self, jboolean sync)
2003-10-20 10:17:47 -04:00
{
if (extension_flags.WGL_EXT_swap_control) {
2003-10-20 10:17:47 -04:00
if (sync == JNI_TRUE) {
wglSwapIntervalEXT(1);
} else {
wglSwapIntervalEXT(0);
}
}
}
2004-02-18 12:48:26 -05:00
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_makeCurrent
(JNIEnv *env, jobject self)
2004-02-18 12:48:26 -05:00
{
BOOL result = wglMakeCurrent(display_hdc, display_hglrc);
if (!result)
throwException(env, "Could not make display context current");
2004-02-18 12:48:26 -05:00
}
2004-04-03 18:01:39 -05:00
2004-11-02 08:15:59 -05:00
JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_Win32Display_getAvailableDisplayModes(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
return getAvailableDisplayModes(env);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_createWindow(JNIEnv *env, jobject self, jobject mode, jboolean fullscreen, jint x, jint y) {
jclass cls_displayMode = (*env)->GetObjectClass(env, mode);
jfieldID fid_width = (*env)->GetFieldID(env, cls_displayMode, "width", "I");
jfieldID fid_height = (*env)->GetFieldID(env, cls_displayMode, "height", "I");
int width = (*env)->GetIntField(env, mode, fid_width);
int height = (*env)->GetIntField(env, mode, fid_height);
BOOL result;
2004-07-03 06:16:28 -04:00
closerequested = false;
isMinimized = false;
isFocused = false;
2004-07-03 06:16:28 -04:00
isDirty = true;
isFullScreen = fullscreen == JNI_TRUE;
isUndecorated = getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated");
2004-09-15 13:07:06 -04:00
display_hwnd = createWindow(x, y, width, height, isFullScreen, isUndecorated);
if (display_hwnd == NULL) {
throwException(env, "Failed to create the window.");
2004-07-03 06:16:28 -04:00
return;
}
display_hdc = GetDC(display_hwnd);
if (!applyPixelFormat(display_hdc, pixel_format_index)) {
2005-01-29 05:17:56 -05:00
closeWindow(&display_hwnd, &display_hdc);
throwException(env, "Could not apply pixel format to window");
2004-07-03 06:16:28 -04:00
return;
}
ShowWindow(display_hwnd, SW_SHOWDEFAULT);
UpdateWindow(display_hwnd);
SetForegroundWindow(display_hwnd);
SetFocus(display_hwnd);
2004-07-03 06:16:28 -04:00
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_destroyWindow(JNIEnv *env, jobject self) {
2005-01-29 05:17:56 -05:00
closeWindow(&display_hwnd, &display_hdc);
2004-07-03 06:16:28 -04:00
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_switchDisplayMode(JNIEnv *env, jobject self, jobject mode) {
2004-07-03 06:16:28 -04:00
switchDisplayMode(env, mode);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_resetDisplayMode(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
resetDisplayMode(env);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_Win32Display_getGammaRampLength(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
return getGammaRampLength();
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_setGammaRamp(JNIEnv *env, jobject self, jobject gamma_buffer) {
2004-07-03 06:16:28 -04:00
setGammaRamp(env, gamma_buffer);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT jstring JNICALL Java_org_lwjgl_opengl_Win32Display_getAdapter(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
return getAdapter(env);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT jstring JNICALL Java_org_lwjgl_opengl_Win32Display_getVersion(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
return getVersion(env);
}
2004-11-02 08:15:59 -05:00
JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_Win32Display_init(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
return initDisplay(env);
}
2005-02-16 08:31:47 -05:00
bool createARBContextAndPixelFormat(JNIEnv *env, HDC hdc, jobject pixel_format, int *pixel_format_index_return, HGLRC *context_return) {
int pixel_format_index;
HWND arb_hwnd;
HDC arb_hdc;
HGLRC arb_context;
// Some crazy strangeness here so we can use ARB_pixel_format to specify the number
// of multisamples we want. If the extension is present we'll delete the existing
// rendering context and start over, using the ARB extension instead to pick the context.
if (!extension_flags.WGL_ARB_pixel_format)
return false;
pixel_format_index = findPixelFormatARB(env, hdc, pixel_format, NULL, true, true, true, true);
2005-01-31 17:33:27 -05:00
if (pixel_format_index == -1) {
pixel_format_index = findPixelFormatARB(env, hdc, pixel_format, NULL, true, true, false, true);
2005-01-31 17:33:27 -05:00
if ( pixel_format_index == -1)
return false;
}
arb_hwnd = createWindow(0, 0, 1, 1, false, false);
2005-01-31 17:33:27 -05:00
if (arb_hwnd == NULL)
return false;
arb_hdc = GetDC(arb_hwnd);
2005-01-31 17:33:27 -05:00
if (!applyPixelFormat(arb_hdc, pixel_format_index)) {
2005-01-29 05:17:56 -05:00
closeWindow(&arb_hwnd, &arb_hdc);
return false;
}
arb_context = wglCreateContext(arb_hdc);
2005-01-31 17:33:27 -05:00
if (arb_context == NULL) {
closeWindow(&arb_hwnd, &arb_hdc);
2005-01-15 10:45:54 -05:00
return false;
2005-01-31 17:33:27 -05:00
}
if (!wglMakeCurrent(arb_hdc, arb_context)) {
2005-01-15 10:45:54 -05:00
wglDeleteContext(arb_context);
2005-01-31 17:33:27 -05:00
closeWindow(&arb_hwnd, &arb_hdc);
2005-01-15 10:45:54 -05:00
return false;
}
2005-01-15 10:45:54 -05:00
extgl_InitWGL(env);
2005-01-31 17:33:27 -05:00
wglMakeCurrent(NULL, NULL);
closeWindow(&arb_hwnd, &arb_hdc);
*pixel_format_index_return = pixel_format_index;
*context_return = arb_context;
return true;
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_createContext(JNIEnv *env, jobject self, jobject pixel_format) {
HWND dummy_hwnd;
HDC dummy_hdc;
BOOL result;
jclass cls_pixel_format;
int samples;
int pixel_format_index_arb;
HGLRC context_arb;
bool arb_success;
dummy_hwnd = createWindow(0, 0, 1, 1, false, false);
if (dummy_hwnd == NULL) {
throwException(env, "Failed to create the window.");
2004-07-03 06:16:28 -04:00
return;
}
dummy_hdc = GetDC(dummy_hwnd);
pixel_format_index = findPixelFormat(env, dummy_hdc, pixel_format);
2004-07-03 12:38:02 -04:00
if (pixel_format_index == -1) {
return;
}
if (!applyPixelFormat(dummy_hdc, pixel_format_index)) {
2005-01-29 05:17:56 -05:00
closeWindow(&dummy_hwnd, &dummy_hdc);
throwException(env, "Could not apply pixel format to window");
2004-07-03 06:16:28 -04:00
return;
}
display_hglrc = wglCreateContext(dummy_hdc);
if (display_hglrc == NULL) {
2005-01-29 05:17:56 -05:00
closeWindow(&dummy_hwnd, &dummy_hdc);
2004-07-03 06:16:28 -04:00
throwException(env, "Failed to create OpenGL rendering context");
return;
}
result = wglMakeCurrent(dummy_hdc, display_hglrc);
2004-07-03 12:07:00 -04:00
if (!result) {
throwException(env, "Could not bind context to dummy window");
wglDeleteContext(display_hglrc);
2005-01-29 05:17:56 -05:00
closeWindow(&dummy_hwnd, &dummy_hdc);
2004-07-03 12:07:00 -04:00
return;
}
extgl_InitWGL(env);
cls_pixel_format = (*env)->GetObjectClass(env, pixel_format);
samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I"));
if (samples > 0) {
arb_success = createARBContextAndPixelFormat(env, dummy_hdc, pixel_format, &pixel_format_index_arb, &context_arb);
2005-01-29 05:17:56 -05:00
closeWindow(&dummy_hwnd, &dummy_hdc);
2004-07-24 17:19:08 -04:00
wglDeleteContext(display_hglrc);
if (!arb_success) {
throwException(env, "Samples > 0 but could not find a suitable ARB pixel format");
return;
}
display_hglrc = context_arb;
pixel_format_index = pixel_format_index_arb;
} else
2005-01-29 05:17:56 -05:00
closeWindow(&dummy_hwnd, &dummy_hdc);
2004-07-03 06:16:28 -04:00
}
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_destroyContext(JNIEnv *env, jobject self) {
2004-07-03 06:16:28 -04:00
wglMakeCurrent(NULL, NULL);
// Delete the rendering context
if (display_hglrc != NULL) {
2004-07-03 06:16:28 -04:00
printfDebug("Deleting GL context\n");
wglDeleteContext(display_hglrc);
display_hglrc = NULL;
2004-07-03 06:16:28 -04:00
}
}
2004-09-15 13:07:06 -04:00
2004-11-02 08:15:59 -05:00
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Win32Display_reshape(JNIEnv *env, jobject self, jint x, jint y, jint width, jint height) {
int exstyle, windowflags;
2004-09-15 13:07:06 -04:00
if (isFullScreen) {
return;
}
if (isFullScreen) {
exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST;
windowflags = WS_POPUP;
} else if (getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated")) {
exstyle = WS_EX_APPWINDOW;
windowflags = WS_POPUP;
} else {
exstyle = WS_EX_APPWINDOW;
windowflags = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU;
}
// If we're not a fullscreen window, adjust the height to account for the
// height of the title bar:
clientSize.bottom = height;
clientSize.left = 0;
clientSize.right = width;
clientSize.top = 0;
AdjustWindowRectEx(
&clientSize, // client-rectangle structure
windowflags, // window styles
FALSE, // menu-present option
exstyle // extended window style
);
SetWindowPos(display_hwnd, HWND_TOP, x, y, clientSize.right - clientSize.left, clientSize.bottom - clientSize.top, SWP_NOZORDER);
}