diff --git a/src/Makefile b/src/Makefile index 0f50e18..62b9f96 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,7 +10,8 @@ LIB_MINOR = ${OBJ3DENGINE_LIB_MINOR} SRCS = O3DEngine.m \ O3DGlide3Renderer.m \ - O3DRenderer.m + O3DRenderer.m \ + O3DWinAPIWindow.m INCLUDES := ${SRCS:.m=.h} OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_A} diff --git a/src/O3DGlide3Renderer.h b/src/O3DGlide3Renderer.h index 8df131b..e0cbe90 100644 --- a/src/O3DGlide3Renderer.h +++ b/src/O3DGlide3Renderer.h @@ -19,9 +19,14 @@ OF_ASSUME_NONNULL_BEGIN +@class O3DWinAPIWindow; + @interface O3DGlide3Renderer: OFObject { GrResolution _resolution; +#ifdef OF_WINDOWS + O3DWinAPIWindow *_winAPIWindow; +#endif GrContext_t _context; } @end diff --git a/src/O3DGlide3Renderer.m b/src/O3DGlide3Renderer.m index 32ab4ed..fb6101e 100644 --- a/src/O3DGlide3Renderer.m +++ b/src/O3DGlide3Renderer.m @@ -14,6 +14,7 @@ */ #import "O3DGlide3Renderer.h" +#import "O3DWinAPIWindow.h" static OFSize screenResolutionToSize(GrScreenResolution_t resolution) @@ -214,6 +215,10 @@ floatToScreenRefresh(float refresh) grGlideShutdown(); +#ifdef OF_WINDOWS + [_winAPIWindow release]; +#endif + [super dealloc]; } @@ -269,6 +274,9 @@ floatToScreenRefresh(float refresh) - (void)createWithResolution: (O3DResolution)resolution { + if (_context != 0) + @throw [OFAlreadyOpenException exceptionWithObject: self]; + GrScreenResolution_t screenResolution = sizeToScreenResolution([resolution.firstObject sizeValue]); GrScreenRefresh_t screenRefresh = @@ -278,7 +286,14 @@ floatToScreenRefresh(float refresh) screenRefresh == GR_REFRESH_NONE) @throw [OFInvalidArgumentException exception]; - if ((_context = grSstWinOpen(0, screenRefresh, screenRefresh, + FxU32 hWnd = 0; +#ifdef OF_WINDOWS + _winAPIWindow = [[O3DWinAPIWindow alloc] + initWithSize: [resolution.firstObject sizeValue]]; + hWnd = (FxU32)_winAPIWindow.hWnd; +#endif + + if ((_context = grSstWinOpen(hWnd, screenRefresh, screenRefresh, GR_COLORFORMAT_RGBA, GR_ORIGIN_LOWER_LEFT, 2, 1)) == 0) @throw [OFInitializationFailedException exceptionWithClass: self.class]; diff --git a/src/O3DWinAPIWindow.h b/src/O3DWinAPIWindow.h new file mode 100644 index 0000000..65b24ce --- /dev/null +++ b/src/O3DWinAPIWindow.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of Obj3DEngine. It may be distributed under the terms of + * the Q Public License 1.0, which can be found in the file LICENSE.QPL + * included in the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of + * this file. + */ + +#import + +#ifdef OF_WINDOWS +# include + +@interface O3DWinAPIWindow: OFObject +{ + WNDCLASS _wndClass; + HWND _hWnd; +} + +@property (readonly, nonatomic) HWND hWnd; + +- (instancetype)initWithSize: (OFSize)size; +- (instancetype)init OF_UNAVAILABLE; +@end +#endif diff --git a/src/O3DWinAPIWindow.m b/src/O3DWinAPIWindow.m new file mode 100644 index 0000000..076b65c --- /dev/null +++ b/src/O3DWinAPIWindow.m @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of Obj3DEngine. It may be distributed under the terms of + * the Q Public License 1.0, which can be found in the file LICENSE.QPL + * included in the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of + * this file. + */ + +#import "O3DWinAPIWindow.h" + +#ifdef OF_WINDOWS +# include + +@implementation O3DWinAPIWindow +@synthesize hWnd = _hWnd; + +- (instancetype)initWithSize: (OFSize)size +{ + self = [super init]; + + @try { + _wndClass = (WNDCLASS){ + .lpfnWndProc = (WNDPROC)DefWindowProc, + .hInstance = GetModuleHandle(NULL), + .lpszClassName = "O3DMainWindowClass" + }; + + if (!RegisterClass(&_wndClass)) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + if ((_hWnd = CreateWindowEx(WS_EX_APPWINDOW, + _wndClass.lpszClassName, "O3DMainWindow", WS_OVERLAPPED, + CW_USEDEFAULT, CW_USEDEFAULT, size.width, size.height, + NULL, NULL, _wndClass.hInstance, NULL)) == NULL) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + ShowWindow(_hWnd, SW_NORMAL); + UpdateWindow(_hWnd); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (void)dealloc +{ + if (_hWnd != NULL) + OFEnsure(DestroyWindow(_hWnd)); + + if (_wndClass.lpszClassName != NULL) + OFEnsure(UnregisterClass( + _wndClass.lpszClassName, _wndClass.hInstance)); + + [super dealloc]; +} +@end +#endif diff --git a/tests/TestsAppDelegate.m b/tests/TestsAppDelegate.m index 048055a..87fe929 100644 --- a/tests/TestsAppDelegate.m +++ b/tests/TestsAppDelegate.m @@ -35,7 +35,7 @@ OF_APPLICATION_DELEGATE(TestsAppDelegate) engine.renderer.availableResolutions]; O3DResolution resolution = [OFPair - pairWithFirstObject: [OFValue valueWithSize: OFMakeSize(640, 480)] + pairWithFirstObject: [OFValue valueWithSize: OFMakeSize(800, 600)] secondObject: [OFNumber numberWithFloat: 60]]; [engine.renderer createWithResolution: resolution];