Plan for gfx directx: Difference between revisions
Hieran Del8 (talk | contribs) →Graphics: filling out topics |
Hieran Del8 (talk | contribs) m →Engine Controlling Cursor: updated about mouse bug fix |
||
Line 66: | Line 66: | ||
===Engine Controlling Cursor=== | ===Engine Controlling Cursor=== | ||
The engine makes calls to io_setmouse(), which tries to set the position of the cursor on the client area of the ohr window. The engine does not need to know any other information about the screen or client dimensions, just simply requesting the cursor move. | The engine makes calls to io_setmouse(), which tries to set the position of the cursor on the client area of the ohr window. The engine does not need to know any other information about the screen or client dimensions, just simply requesting the cursor move. The bug here was fixed. | ||
===Leaving the Window=== | ===Leaving the Window=== |
Revision as of 19:05, 30 April 2011
This article contains the todo list discussion for the gfx_directx backend. It also presents ideas for hardware accelerated graphics operations.
Input
The input is largely gathered from window messages. Currently, the engine asks for snapshots of current state of each input device. It is the task of the backend to interpret the messages into a block of current state and events. The engine may also attempt to manipulate the position of the mouse cursor within the window. The backend should respect those manipulations unless overridden.
Keyboard
Messages
The WM_KEYDOWN message fires every time a key press occurs. It continues firing if that key is held down. It contains information about the actual key being pressed, including scan code, whether it's an extended key, and the virtual key it represents.
The continuous firing for the same key being held down should not generate new events for the engine, since the engine manages that anyway. The backend ignores continuous firing.
The WM_KEYUP message fires every time a key release occurs. It contains information about the actual key being released, including scan code, whether it's an extended key, and the virtual key it represents. There is a bug with the SHIFT keys. It can be recreated as follows:
- Hold down both SHIFT keys
- Release one SHIFT key
The one SHIFT key that was released did not have a WM_KEYUP message sent to the window because the other SHIFT key is still depressed. When the other SHIFT key releases, the window receives the WM_KEYUP message for that SHIFT key, but not the one that was released first.
The workaround for this case was using GetAsyncKeyState(VK_LSHIFT) and GetAsyncKeyState(VK_RSHIFT) right before copying all the OHR scancode values to the engine's keyboard state buffer. The VK_SHIFT virtual key is manually toggled, as discussed in L/R Keys.
L/R Keys
The Ctrl, Alt, Win, Shift, and NumPad keys all have duplicates. Currently, they are all being checked for left vs. right state. This is done by checking the 0x1000000 bit (extended key bit), or the scan code for Shift keys.
Using this feature, NumLock no longer needs to be enabled to differentiate between the NumPad keys and their duplicate counterparts. The NumPad 5 key is a duplicate of the CLEAR key (VK_CLEAR).
gfx_sdl fails to note when both Ctrl, Alt, Shift, and Enter keys are pressed. With Enter, it updates it's state after the other Enter is released. The other said keys do not update state. gfx_directx should ignore this type of behavior, but for compatibility, it will only fire the generic Ctrl, Alt, and Shift once while either of the L/R keys are depressed until both are released.
The VK_CONTROL(Ctrl), VK_MENU(Alt), and VK_SHIFT(Shift) keys are the generic virtual key codes. They are tested accordingly:
...after evaluating a keypress for a L/R vk code, it's generic being VK_*... if(m_virtualKeys[ VK_* ] == 0x0) { m_virtualKeys[ VK_* ] = 0x80; KB_CREATE_KEYPRESS(m_ohrScans[ c_vk2fb[ VK_* ] ]); }
And then for the key release:
...after evaluating a key release for a L/R vk code, it's generic being VK_*... if(m_virtualKeys[ VK_L* ] == 0x0 && m_virtualKeys[ VK_R* ] == 0x0) { m_virtualKeys[ VK_* ] = 0x0; KB_CREATE_KEYRELEASE(m_ohrScans[ c_vk2fb[ VK_* ] ]); }
Toggle Keys
Toggle keys are reported as actual keyboard state, possible with GetKeyState() right before copying the OHR scancodes to the engine's keyboard state buffer.
Leaving the Window
Keyboard state, aside from toggle keys, should be cleared when the window becomes inactive instead of maintaining its last state. This has been implemented.
System Keys
Some key combinations spawn system messages, such as Alt-Tab, Alt-F4, Alt-Space, etc. An option is available to allow those system key presses to be ignored. By default, though, the option should allow system messages.
Mouse
Messages
The window receives many messages related to the mouse: WM_NCMOUSEMOVE, WM_MOUSEMOVE, WM_NC*BUTTONDOWN, WM_*BUTTONDOWN, WM_NC*BUTTONUP, WM_*BUTTONUP, WM_MOUSEWHEEL, and WM_NCHITTEST. (The '*' wildcard represents L, R, or M, for Left, Right, and Middle mouse buttons.) The NC in the message name refers to the non-client area of the window, such as the window title, close button, borders, etc.
The input currently exhibits a problem in gathering mouse input when the cursor is hidden by the engine, then the user attempts to resize the window. It's discussed in Showing and Hiding the Cursor.
Clipping to the Window
The mouse will clip to the window only when a mouse button is being held down or io_clipcursor() is called from the engine. The mouse should be free-able (which it currently is), as discussed in Toggling Dead/Live Input. Haven't stumbled across any bugs here.
Engine Controlling Cursor
The engine makes calls to io_setmouse(), which tries to set the position of the cursor on the client area of the ohr window. The engine does not need to know any other information about the screen or client dimensions, just simply requesting the cursor move. The bug here was fixed.
Leaving the Window
Input state should be cleared when the window loses focus. This includes dropping the clipped cursor area.
Showing and Hiding the Cursor
The ShowCursor() function is used to show or hide the cursor. There is a bug that is reproduced by:
- Enter maptile editor
- Drag window border to some dimension
- Hover mouse over client area
Input has also fallen to a dead state. This may not be a Showing/Hiding cursor bug, but a Dead/Live input state error.
Toggling Dead/Live Input
The backend should allow the user to override the engine's request for the mouse cursor by disabling input to the engine. This is currently done by using the ScrollLock toggle key. This toggle has no effect in fullscreen mode. Setting the input state to 'dead' allows the cursor to be free of the window (in case io_clipcursor() was called by the engine) and prevents any mouse movement being updated.
It has been discussed to use a different key / key combination for disabling/enabling input. ScrollLock is a good choice because it's a toggle key, and it's unlikely to be used by anybody in game implementations.
The Showing and Hiding the Cursor bug may actually be a bug caused by a toggle in the Dead/Live input state.
Joystick
Joystick input is supported by DirectInput8. Any number of joystick inputs may be attached to the computer. XInput is not currently supported. The discussion here is for configuration menus available in the Options dialog. There are now discussions for planned improvements for joysticks.
Configuration Menus
There are currently no configuration menus. A menu should provide the ability to map buttons/axises to OHR engine input (which I think is 4 buttons and 2 scalars for the x and y axis.) Because it is an extra configuration menu, it may not be supported by the backend, and the window will change dynamically for each input device (that is, in listing available buttons/axises), the configuration menu should exist in a separate menu that can be opened from the Options dialog.
Assigning Joysticks to input slots
Whatever order DirectInput finds the joysticks in, that is the order they are in for input slots. This should be configurable under a separate menu opened from the Options dialog.
Mapping Button presses to Keyboard/Mouse input
As an extension to the Configuration Menus for buttons/axises, it'd be convenient to add the option to perform macro commands for either mouse or keyboard input. But this may be a little too ambitious. (Though it sounds nice, who cares? The mouse and keyboard aren't even set up to manage anything like that.) This item will probably be scrapped before I think about it too much more.
Graphics
This section discusses the graphical operations performed by gfx_directx.
Current
The current graphical help of the backend is simply pushing the precomputed image to the window client area. Essentially, in gfx_directx this is by using a surface lock and writing, then using IDirect3DDevice9::StretchRect() onto the backbuffer surface. But there are many scenarios where the driver could malfunction, the device could be lost, or the window surface area could change. The backend is responsible for appropriately recovering and adapting to these changing settings, remaining transparent to the engine.
Lost/Reset devices
A lost device needs to be reset using IDirect3DDevice9::Reset(). After a device is reset, all the unmanaged resources need to also be reset, which includes the offscreen surface that has the precomputed image copied to it. A need to reset the device occurs anytime a resolution changes, the system is locked, a driver fails and recovers, the system goes to sleep then wakes.
There may be situations in which the device and resources are not appropriately recovering, including the following topic.
Disconnected monitors
Hot-swapping monitors is a situation in which the device will completely fail and become an invalid memory location. DirectX 9 does not provide a mechanism for recovering from a hot-swapped device. This would also be an issue for laptops which close the lid, effectively stopping the display adapter. The IDirect3D9 object can continue functioning, but there needs to be a safe mechanism for recovering from hot-swapped monitors.
Mike Caron sent an email addressing this point a while ago, but I've lost track of which email that was, and have yet to dig through the 2500 messages to solve this issue.
Aspect ratio preservation
The aspect ratio of the precomputed image is intended to be preserved, no matter the dimensions of the window. There is an option to disable this in the Options dialog. There is a bug currently exhibited by disabling ARP (aspect ratio preservation) and re-enabling it. The client area will show residual garbage in the black borders that are supposed to be cleared every presentation with IDirect3DDevice9::Clear(). I do not know why this is failing.
Window resizing
The window resize causes client area calculations to be re-evaluated (like mouse position and clipping rects), and changes the backbuffer dimensions appropriately. By dragging a corner, one can jump to multiples of the native resolution. By grabbing the other borders, non-native resolutions can be attained. Pressing Alt-Enter resizes the window to full screen or back to windowed mode. Haven't experienced any issues here.
Hardware support
The device will be created with either hardware or software vertex processing. More information as to what models are supported will become available, but earlier iterations of the backend have successfully functioned on DirectX 8.1 hardware.
Testing and Debug Messages
Initialization debug messages have just been implemented, but further debug messages are desired. This would require the engine to provide the backend with access to a function to write debug information to a file. Otherwise, the backend could just generate it's own debug output file.
Hardware Accelerated Rendering
This is something not currently exposed to the engine, though could provide greater efficiency and more options in rendering. New interfaces would have to be created to expose these features.
Sprites
Sprites are simply a part of a surface rendered at a time. In DirectX, sprites are drawn in a batch for greater efficiency. Sprites can also undergo transformations, including rotations, translations, and scaling. Technically, they do not need to be rendered flat, but can be rendered skewed or in 3d. They can have a z-order. They can also take advantage of true transparency support. They can be any size, and be placed anywhere within a scene.
Transparent Surfaces
Any surface, including sprites, can contain an alpha value which can be used to blend a source and destination pixel color. There are many ways to blend a source alpha surface with a destination alpha surface (too many ways to discuss right this moment.) The most popular blending equation is:
(srcColor x srcAlpha) + (destColor x (1-srcAlpha))
Surfaces with Z-ordering
Surfaces can be ordered in projective or view space. A surface could potentially move between layers by adjusting it's z-order. The higher the order, the farther in the screen the surface is.
2d/3d Primitives
Besides surfaces, other 2d and 3d geometry could be created and rendered with/without surfaces on them. The implication is that a 3d camera system is also controllable.
Shader effects
There are so many different effects that can be generated with shaders. Perhaps a certain number of pre-compiled shaders could be exposed, and the user could optionally write their own for loading.