aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/gfx/drivers/dx_driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/gfx/drivers/dx_driver.cpp')
-rw-r--r--engines/sci/gfx/drivers/dx_driver.cpp1179
1 files changed, 0 insertions, 1179 deletions
diff --git a/engines/sci/gfx/drivers/dx_driver.cpp b/engines/sci/gfx/drivers/dx_driver.cpp
deleted file mode 100644
index 899d1fa70c..0000000000
--- a/engines/sci/gfx/drivers/dx_driver.cpp
+++ /dev/null
@@ -1,1179 +0,0 @@
-/***************************************************************************
- dx_driver.cpp Copyright (C) 2008 Alexander R Angas,
- Some portions Copyright (C) 1999 Dmitry Jemerov
-
- This program may be modified and copied freely according to the terms of
- the GNU general public license (GPL), as long as the above copyright
- notice and the licensing information contained herein are preserved.
-
- Please refer to www.gnu.org for licensing details.
-
- This work is provided AS IS, without warranty of any kind, expressed or
- implied, including but not limited to the warranties of merchantibility,
- noninfringement, and fitness for a specific purpose. The author will not
- be held liable for any damage caused by this work or derivatives of it.
-
- By using this source code, you agree to the licensing terms as stated
- above.
-
- Please contact the maintainer for bug reports or inquiries.
-
- Current Maintainer:
-
- Alexander R Angas (Alex) <arangas AT internode dot on dot net>
-
- History:
- 20051106 (AAngas) - Rewrite
- 20060201 (AAngas) - Fixed wrong format for texture priority maps
- 20060205 (AAngas) - Changed pointer to use D3DXSprite
- 20060208 (AAngas) - Fixed pointer alpha blending bug
- 20060307 (AAngas) - Fixed crash on exit
- 20080118 (AAngas) - Fixed pointer scaling and window size
-
- Notes:
- DirectX handles all scaling. All drawing functions assume an unscaled
- resolution.
-
-TODO:
- P1 - Corrupt cursor at different resolutions
- P1 - Lost devices
- P1 - Problems moving and activating window
- P1 - Occasional pause when starting FreeSCI and poor sound resulting (?)
- P1 - Mouse pointer corruption at bottom and why need to scale vertical by 4?
- P2 - Full screen
- P3 - Draw lines as Direct3D vertices
- P3 - Fine line mode
- P3 - Allow user to specify hardware or software vertex processing
- P3 - Fancies
-
-***************************************************************************/
-
-#ifdef HAVE_DIRECTX
-
-#ifndef __cplusplus
-#error NOTE: This file MUST be compiled as C++. In Visual C++, use the /Tp command line option.
-#endif
-
-#include "dx_driver.h"
-
-#define TO_STRING2(x) #x
-#define TO_STRING(x) TO_STRING2(x)
-#if (DIRECT3D_VERSION < 0x0800)
-# error The DirectX 8 SDK (or higher) is required for this driver.
-#elif (DIRECT3D_VERSION > 0x0800)
-# pragma message (" ")
-# pragma message ("*** This driver has been developed against version 8 of the DirectX SDK and may not work against your version " TO_STRING(DIRECT3D_VERSION))
-# pragma message (" ")
-#endif
-
-
-// Stores driver flags
-static int flags = 0;
-
-
-// Windows message processing
-LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
- return DefWindowProc( hWnd, msg, wParam, lParam );
-}
-
-
-///// RENDERING
-
-// Render the scene to screen
-static gfx_return_value_t
-RenderD3D(struct _gfx_driver *drv)
-{
- HRESULT hr;
-
- // Check we haven't lost the device (i.e. window focus)
- if (CheckDevice(drv))
- {
- // Begin scene
- DODX( (dx_state->pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0, 0)), RenderD3D );
- DODX( (dx_state->pDevice->BeginScene()), RenderD3D );
-
- // Set texture
- DODX( (dx_state->pDevice->SetTexture( 0, dx_state->pTexVisuals[PRIMARY_VIS] )), RenderD3D ); // Scene image
-
- // Set texture states for scene
- DODX( (dx_state->pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE )), RenderD3D );
- DODX( (dx_state->pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE )), RenderD3D );
- DODX( (dx_state->pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE )), RenderD3D );
-
- // Set vertices and how to draw
- DODX( (dx_state->pDevice->SetStreamSource(0, dx_state->pVertBuff, sizeof(CUSTOMVERTEX))), RenderD3D );
- DODX( (dx_state->pDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX )), RenderD3D );
- DODX( (dx_state->pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2)), RenderD3D );
-
- // Draw the pointer sprite
- if (dx_state->pTexPointer)
- {
- D3DXVECTOR2 pointerPos((float)drv->pointer_x, (float)drv->pointer_y);
- DODX( (dx_state->pSPointer->Begin()), RenderD3D );
- DODX( (dx_state->pSPointer->Draw(dx_state->pTexPointer, NULL, NULL, NULL, 0.0, &pointerPos, 0xFFFFFFFF)), RenderD3D );
- DODX( (dx_state->pSPointer->End()), RenderD3D );
- }
-
- // Present scene
- DODX( (dx_state->pDevice->EndScene()), RenderD3D );
- DODX( (dx_state->pDevice->Present(NULL, NULL, NULL, NULL)), RenderD3D );
- }
-
- return GFX_OK;
-}
-
-
-// Check device hasn't been lost
-static int
-CheckDevice(struct _gfx_driver *drv)
-{
- HRESULT hr;
- switch ( dx_state->pDevice->TestCooperativeLevel() )
- {
- case D3DERR_DEVICELOST: return false; // Lost window focus
-
- case D3DERR_DEVICENOTRESET: // We're back!
- {
- // Reset with our presentation parameters and reinitialise the scene
- DODX( (dx_state->pDevice->Reset(&dx_state->presParams)), CheckDevice );
- if (hr != D3D_OK)
- return false;
-
- InitScene(drv);
- return true;
- }
-
- default: return true;
- }
-}
-
-
-///// INITIALIZATION
-
-// Create window to draw to
-static gfx_return_value_t
-InitWindow(struct _gfx_driver *drv, UINT width, UINT height)
-{
- DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- DWORD dwStyle = WS_OVERLAPPEDWINDOW;
- RECT clientSize = { 0, 0, width, height };
- sciprintf("Window %d x %d\n", width, height);
-
- // Register the window class
- ZeroMemory( &(dx_state->wc), sizeof(WNDCLASSEX) );
- dx_state->wc.cbSize = sizeof(WNDCLASSEX);
- dx_state->wc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
- dx_state->wc.lpfnWndProc = MsgProc;
- dx_state->wc.hInstance = GetModuleHandle(NULL);
- dx_state->wc.lpszClassName = DX_CLASS_NAME;
- if ( RegisterClassEx( &dx_state->wc ) == 0 )
- {
- sciprintf("InitWindow(): RegisterClassEx failed (%u)\n", GetLastError());
- return GFX_FATAL;
- }
-
- // Get correct size of window to pass to CreateWindow (considering window decorations)
- if ( AdjustWindowRectEx( &clientSize, dwStyle, false, dwExStyle ) == 0 )
- {
- sciprintf("InitWindow(): Window size calculation failed (%u)\n", GetLastError());
- return GFX_FATAL;
- }
-
- // Create the application's window
- dx_state->hWnd = CreateWindowEx(
- dwExStyle,
- DX_CLASS_NAME, DX_APP_NAME,
- dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
- CW_USEDEFAULT, CW_USEDEFAULT,
- clientSize.right - clientSize.left, clientSize.bottom - clientSize.top,
- NULL/*GetDesktopWindow()*/, NULL, dx_state->wc.hInstance, NULL );
-
- if ( dx_state->hWnd == NULL )
- {
- sciprintf("InitWindow(): CreateWindow failed (%u)\n", GetLastError());
- return GFX_FATAL;
- }
-
- // Show the window
- ShowWindow( dx_state->hWnd, SW_SHOWDEFAULT );
- UpdateWindow( dx_state->hWnd );
-
- return GFX_OK;
-}
-
-
-// Initialize Direct3D
-static gfx_return_value_t
-InitD3D(struct _gfx_driver *drv)
-{
- HRESULT hr;
-
- sciprintf("Initializing Direct3D\n");
-
- // Set our colour format
- dx_state->d3dFormat = D3DFMT_A8R8G8B8;
- dx_state->vertexProcessing = D3DCREATE_MIXED_VERTEXPROCESSING;
-
- // Create Direct3D object
- dx_state->pD3d = Direct3DCreate8( D3D_SDK_VERSION );
- if ( FAILED( dx_state->pD3d ) ) {
- sciprintf("InitD3D(): Direct3DCreate8 failed\n");
- return GFX_FATAL;
- }
-
- // Look for adapters
- for ( UINT adapterLoop = 0; adapterLoop < dx_state->pD3d->GetAdapterCount(); adapterLoop++ )
- {
- D3DADAPTER_IDENTIFIER8 adapterId;
- DODX( (dx_state->pD3d->GetAdapterIdentifier(adapterLoop, D3DENUM_NO_WHQL_LEVEL, &adapterId)), InitD3D );
- if ( FAILED( hr ) )
- break;
- if (adapterId.Driver[0] == '\0')
- break;
- sciprintf(" Adapter %u: %s\n", adapterLoop++, adapterId.Description);
- }
- if (dx_state->adapterId == -1)
- dx_state->adapterId = D3DADAPTER_DEFAULT;
-
- // Get device caps
- DODX( (dx_state->pD3d->GetDeviceCaps(dx_state->adapterId, D3DDEVTYPE_HAL, &(dx_state->deviceCaps))), InitD3D );
- if ( FAILED( hr ) ) {
- sciprintf("Sorry, this adapter does not have a 3D accelerated video driver installed.\n");
- return GFX_FATAL;
- }
-
- // Define presentation parameters
- ZeroMemory( &dx_state->presParams, sizeof(D3DPRESENT_PARAMETERS) );
- dx_state->presParams.Windowed = TRUE; // We want windowed by default
- dx_state->presParams.SwapEffect = D3DSWAPEFFECT_DISCARD; // Throw away last frame
- dx_state->presParams.hDeviceWindow = dx_state->hWnd; // Window handle
- dx_state->presParams.BackBufferWidth = 320; // Back buffer dimensions
- dx_state->presParams.BackBufferHeight = 200; //
- dx_state->presParams.BackBufferFormat = dx_state->d3dFormat; // Colour format
-
- // Check if user requested full screen
- if (flags & DX_FLAGS_FULLSCREEN)
- {
- if (dx_state->deviceCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) {
- dx_state->presParams.Windowed = FALSE;
- sciprintf("Full screen mode");
- } else {
- sciprintf("Sorry, DirectX will not render in full screen with your video card\n");
- }
- }
-
- // Get current display mode
- DODX( (dx_state->pD3d->GetAdapterDisplayMode( dx_state->adapterId, &dx_state->displayMode )), InitD3D );
- sciprintf("Chosen adapter %u\n", dx_state->adapterId);
-
- // Turn off Windows mouse pointer
- ShowCursor(FALSE);
-
- return GFX_OK;
-}
-
-
-// Initialize scene
-static gfx_return_value_t
-InitScene(struct _gfx_driver *drv)
-{
- HRESULT hr;
-
- sciprintf("Creating scene\n");
-
- // Describe how scene will be rendered
- DODX((dx_state->pDevice->SetRenderState( D3DRS_AMBIENT, RGB(255,255,255) )), InitScene); // Maximum ambient light
- DODX((dx_state->pDevice->SetRenderState( D3DRS_LIGHTING, FALSE )), InitScene); // Disable lighting features
- DODX((dx_state->pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE )), InitScene); // Don't cull back side of polygons
- DODX((dx_state->pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE )), InitScene); // No depth buffering
-
- return GFX_OK;
-}
-
-
-// For user to set a driver-specific parameter
-static int
-dx_set_param(struct _gfx_driver *drv, char *attribute, char *value)
-{
-/* // Full screen
- if (!strncmp(attribute, "fullscreen", 11)) {
- if (string_truep(value))
- flags |= DX_FLAGS_FULLSCREEN;
- else
- flags &= ~DX_FLAGS_FULLSCREEN;
-
- return GFX_OK;
- }
-*/
- // Adapter ID
- if (!strncmp(attribute, "adapterid", 11)) {
- int aid = D3DADAPTER_DEFAULT;
- dx_state->adapterId = atoi(value);
-
- return GFX_OK;
- }
-
- sciprintf("Unrecognised attempt to set DirectX parameter \"%s\" to \"%s\"\n", attribute, value);
- return GFX_ERROR;
-}
-
-
-// Initialize a specific graphics mode
-static int
-dx_init_specific(struct _gfx_driver *drv,
- int xfact, int yfact, /* horizontal and vertical scaling */
- int bytespp) /* must be value 4 */
-{
- HRESULT hr;
- int red_shift = 8, green_shift = 16, blue_shift = 24, alpha_shift = 32;
- int alpha_mask = 0x00000000, red_mask = 0x00ff0000, green_mask = 0x0000ff00, blue_mask = 0x000000ff;
- gfx_return_value_t d3dret;
-
- // Error checking
- if (xfact < 1 || yfact < 1 || bytespp < 1 || bytespp > 4) {
- sciprintf("Attempt to open window with invalid scale factors (%d,%d) and bpp=%d!\n",
- xfact, yfact, bytespp);
- return GFX_ERROR;
- }
-
- // Prepare memory for gfx_dx_struct_t
- drv->state = (struct gfx_dx_struct_t *) sci_malloc(sizeof(gfx_dx_struct_t));
- ZeroMemory(drv->state, sizeof(gfx_dx_struct_t));
- dx_state->adapterId = -1; // we will set this later
-
- // Set window size factor
- dx_state->xfact = xfact;
- dx_state->yfact = yfact;
- dx_state->bpp = bytespp;
- sciprintf("Window scaling %d x %d @ %d bpp\n", dx_state->xfact, dx_state->yfact, dx_state->bpp << 3);
-
- // Set up Direct3D
- d3dret = InitD3D(drv);
- if (d3dret != GFX_OK)
- return d3dret;
-
- // Create window
- InitWindow(drv, dx_state->xfact * 320, dx_state->yfact * 200);
-
- // Create D3D device
- DODX( (dx_state->pD3d->CreateDevice(dx_state->adapterId, D3DDEVTYPE_HAL, dx_state->hWnd,
- dx_state->vertexProcessing, &dx_state->presParams, &dx_state->pDevice)), dx_init_specific );
-
- // Create the scene
- d3dret = InitScene(drv);
- if (d3dret != GFX_OK)
- return d3dret;
-
- // Define and populate vertex buffers
- DODX((dx_state->pDevice->CreateVertexBuffer( 4 * sizeof(CUSTOMVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX,
- D3DPOOL_MANAGED, &dx_state->pVertBuff )), dx_init_specific);
-
- dx_state->pvData[0].p = D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f);
- dx_state->pvData[1].p = D3DXVECTOR4(320.0f, 0.0f, 0.0f, 1.0f);
- dx_state->pvData[2].p = D3DXVECTOR4( 0.0f, 200.0f, 0.0f, 1.0f);
- dx_state->pvData[3].p = D3DXVECTOR4(320.0f, 200.0f, 0.0f, 1.0f);
- dx_state->pvData[0].colour = dx_state->pvData[1].colour = dx_state->pvData[2].colour = dx_state->pvData[3].colour = 0xffffffff;
- dx_state->pvData[0].t = D3DXVECTOR2(0.0f, 0.0f);
- dx_state->pvData[1].t = D3DXVECTOR2(1.0f, 0.0f);
- dx_state->pvData[2].t = D3DXVECTOR2(0.0f, 1.0f);
- dx_state->pvData[3].t = D3DXVECTOR2(1.0f, 1.0f);
-
- VOID *ptr;
- DODX((dx_state->pVertBuff->Lock(0, 0, (BYTE**)&ptr, 0)), dx_init_specific);
- memcpy(ptr, dx_state->pvData, sizeof(dx_state->pvData));
- DODX((dx_state->pVertBuff->Unlock()), dx_init_specific);
-
- // Create textures
- int i;
- for (i = 0; i < NUM_VISUAL_BUFFERS; i++)
- {
- DODX((dx_state->pDevice->CreateTexture(320, 200,
- 1, 0,
- dx_state->d3dFormat,
- D3DPOOL_MANAGED,
- &dx_state->pTexVisuals[i])), dx_init_specific);
- }
- for (i = 0; i < NUM_PRIORITY_BUFFERS; i++)
- {
- DODX((dx_state->pDevice->CreateTexture(320, 200,
- 1, 0,
- dx_state->d3dFormat,
- D3DPOOL_MANAGED,
- &dx_state->pTexPrioritys[i])), dx_init_specific);
- }
-
- // Create sprite for pointer
- DODX( (D3DXCreateSprite(dx_state->pDevice, &dx_state->pSPointer)), dx_init_specific );
-
- // Allocate priority maps
- for (int i = 0; i < NUM_PRIORITY_BUFFERS; i++)
- {
- dx_state->priority_maps[i] = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320, 200, GFX_RESID_NONE, -i, -777));
- if (!dx_state->priority_maps[i]) {
- GFXERROR("Out of memory: Could not allocate priority maps! (%dx%d)\n", 320, 200);
- return GFX_FATAL;
- }
- dx_state->priority_maps[i]->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX;
- }
-
- // Set up the event queue
- dx_state->queue_first = 0;
- dx_state->queue_last = 0;
- dx_state->queue_size = 256;
- dx_state->event_queue = (sci_event_t *) sci_malloc (dx_state->queue_size * sizeof (sci_event_t));
-
- // Set up graphics mode for primary vis
- drv->mode = gfx_new_mode(1, 1, dx_state->bpp,
- red_mask, green_mask, blue_mask, alpha_mask,
- red_shift, green_shift, blue_shift, alpha_shift,
- (dx_state->bpp == 1) ? 256 : 0, 0);
-
- // Set up graphics mode for pointer
- dx_state->pointerMode = gfx_new_mode(1, 4, dx_state->bpp,
- 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000,
- 24, 16, 8, 0,
- 0, GFX_MODE_FLAG_REVERSE_ALPHA);
-
- return GFX_OK;
-}
-
-
-// Initialize 'most natural' graphics mode
-static int
-dx_init(struct _gfx_driver *drv)
-{
- return dx_init_specific(drv, 2, 2, 4);
-}
-
-
-// Uninitialize the current graphics mode
-static void
-dx_exit(struct _gfx_driver *drv)
-{
- int i;
-
- if(drv->state == NULL)
- return;
-
- for (i = 0; i < NUM_PRIORITY_BUFFERS; i++)
- SAFE_RELEASE( dx_state->pTexPrioritys[i] );
- for (i = 0; i < NUM_VISUAL_BUFFERS; i++)
- SAFE_RELEASE( dx_state->pTexVisuals[i] );
- SAFE_RELEASE( dx_state->pTexPointer );
- SAFE_RELEASE( dx_state->pSPointer );
- SAFE_RELEASE( dx_state->pVertBuff );
- SAFE_RELEASE( dx_state->pDevice );
- SAFE_RELEASE( dx_state->pD3d );
-
- if ( dx_state->pointerMode )
- gfx_free_mode(dx_state->pointerMode);
- if ( drv->mode )
- gfx_free_mode(drv->mode);
-
- if ( dx_state->event_queue )
- sci_free(dx_state->event_queue);
- dx_state->queue_size = 0;
-
- for (i = 0; i < NUM_PRIORITY_BUFFERS; i++)
- gfx_free_pixmap(drv, dx_state->priority_maps[i]);
-
- UnregisterClass( DX_CLASS_NAME, dx_state->wc.hInstance );
- DestroyWindow(dx_state->hWnd);
-
- sci_free(dx_state);
-}
-
-
-///// DRAWING
-
-// Draws a single filled and possibly shaded rectangle to the back buffer
-static int
-dx_draw_filled_rect(struct _gfx_driver *drv, rect_t box,
- gfx_color_t color1, gfx_color_t color2,
- gfx_rectangle_fill_t shade_mode)
-{
- if (color1.mask & GFX_MASK_VISUAL)
- {
- HRESULT hr;
- D3DLOCKED_RECT lockedRect;
-
- // Calculate colour value for line pixel
- UINT lineColor = (color1.alpha << 24) | (color1.visual.r << 16) | (color1.visual.g << 8) | color1.visual.b;
- RECT r = { box.x, box.y, box.x + box.xl, box.y + box.yl };
- RECT lr = r;
-
- // Fix bounds
- if (lr.left == lr.right)
- lr.right++;
- if (lr.top == lr.bottom)
- lr.bottom++;
- if ((UINT)r.right > 320)
- lr.right = r.right = 320;
- if ((UINT)r.bottom > 200)
- lr.bottom = r.bottom = 200;
-
- sciprintf("dx_draw_filled_rect(): %08X %i,%i -> %i,%i\n", lineColor, r.left, r.top, r.right, r.bottom);
-
- DODX( (dx_state->pTexVisuals[BACK_VIS]->LockRect(0, &lockedRect, &lr, 0)), dx_draw_filled_rect );
- UINT *rectPtr = (UINT*)lockedRect.pBits;
-
- // Going along x axis
- for (int y_pixel = r.top; y_pixel < r.bottom; y_pixel++)
- {
- UINT *startLine = rectPtr;
- for (int x_pixel = r.left; x_pixel < r.right; x_pixel++)
- {
- *rectPtr = lineColor;
- rectPtr++;
- }
- rectPtr = startLine;
- rectPtr += 320;
- }
-
- DODX( (dx_state->pTexVisuals[BACK_VIS]->UnlockRect(0)), dx_draw_filled_rect );
- }
-
- if (color1.mask & GFX_MASK_PRIORITY)
- {
- byte *pri;
- pri = dx_state->priority_maps[BACK_PRI]->index_data + box.x + box.y*(320);
- for(int i=0; i<box.yl; i++)
- {
- memset(pri,color1.priority,box.xl);
- pri += 320;
- }
- }
-
- return GFX_OK;
-}
-
-
-// Draws a single line to the back buffer
-static int
-dx_draw_line(struct _gfx_driver *drv,
- point_t start, point_t end,
- gfx_color_t color,
- gfx_line_mode_t line_mode, gfx_line_style_t line_style)
-{
- if (color.mask & GFX_MASK_VISUAL) {
-
- rect_t line_rect = { start.x, start.y, end.x - start.x + 1, end.y - start.y + 1 };
-
- sciprintf("dx_draw_line(): %i,%i -> %i,%i\n", line_rect.x, line_rect.y, line_rect.xl + line_rect.x, line_rect.yl + line_rect.y);
-
- // Make sure priorities are not updated in dx_draw_filled_rect()
- gfx_color_t col = color;
- col.mask = GFX_MASK_VISUAL;
-
- dx_draw_filled_rect(drv, line_rect, col, col, GFX_SHADE_FLAT);
- }
-
- if (color.mask & GFX_MASK_PRIORITY) {
- gfx_draw_line_pixmap_i(dx_state->priority_maps[BACK_PRI], start, end, color.priority);
- }
-
- return GFX_OK;
-}
-
-
-///// PIXMAPS
-
-// Register the pixmap as a texture
-static int
-dx_register_pixmap(struct _gfx_driver *drv, gfx_pixmap_t *pxm)
-{
- HRESULT hr;
-
- int i, xs;
- byte *s, *d;
- D3DLOCKED_RECT lockedRect;
- LPDIRECT3DTEXTURE8 newTex;
- DODX( (dx_state->pDevice->CreateTexture(pxm->xl, pxm->yl, 1, 0, dx_state->d3dFormat, D3DPOOL_MANAGED, &newTex )), dx_register_pixmap );
-
- // Do gfx crossblit
- DODX( (newTex->LockRect(0, &lockedRect, NULL, 0)), dx_register_pixmap );
- s = pxm->data;
- d = (byte *) lockedRect.pBits;
- xs = drv->mode->bytespp * pxm->xl;
-
- for(i = 0; i < pxm->yl; i++)
- {
- memcpy(d, s, xs);
- s += xs;
- d += lockedRect.Pitch;
- }
- DODX( (newTex->UnlockRect(0)), dx_register_pixmap );
-
- pxm->internal.info = newTex;
- pxm->internal.handle = SCI_DX_HANDLE_NORMAL;
-
- return GFX_OK;
-}
-
-
-// Unregister the pixmap
-static int
-dx_unregister_pixmap(struct _gfx_driver *drv, gfx_pixmap_t *pxm)
-{
- SAFE_RELEASE((LPDIRECT3DTEXTURE8) (pxm->internal.info));
- pxm->internal.info = NULL;
-
- return GFX_OK;
-}
-
-
-// Draws part of a pixmap to the static or back buffer
-static int
-dx_draw_pixmap(struct _gfx_driver *drv, gfx_pixmap_t *pxm, int priority,
- rect_t src, rect_t dest, gfx_buffer_t buffer)
-{
- HRESULT hr;
- int bufnr = (buffer == GFX_BUFFER_STATIC) ? 2 : 1;
- int pribufnr = bufnr - 1;
- LPDIRECT3DTEXTURE8 srct, dstt;
- LPDIRECT3DSURFACE8 sbuf, dbuf;
- D3DLOCKED_RECT lockedRect;
- byte *pri_map = NULL;
-
- if (pxm->internal.handle == SCI_DX_HANDLE_GRABBED) {
- // copy from pxm->internal.info to visual[bufnr]
- RECT srcRect = RECT_T_TO_RECT(src);
- POINT dstPoint = { dest.x, dest.y };
-
- srct = (LPDIRECT3DTEXTURE8) (pxm->internal.info);
- dstt = dx_state->pTexVisuals[bufnr];
-
- DODX( (srct->GetSurfaceLevel(0, &sbuf)), dx_draw_pixmap );
- DODX( (dstt->GetSurfaceLevel(0, &dbuf)), dx_draw_pixmap );
- DODX( (dx_state->pDevice->CopyRects(sbuf, &srcRect, 1, dbuf, &dstPoint)), dx_draw_pixmap );
-
- SAFE_RELEASE(sbuf);
- SAFE_RELEASE(dbuf);
-
- return GFX_OK;
- }
-
-
- // Create texture to temporarily hold visuals[bufnr]
- LPDIRECT3DTEXTURE8 temp;
- DODX( (dx_state->pDevice->CreateTexture(pxm->xl, pxm->yl, 1, 0, dx_state->d3dFormat, D3DPOOL_MANAGED, &temp)), dx_draw_pixmap );
- RECT srcRect = RECT_T_TO_RECT(dest);
- RECT destRect = { 0, 0, dest.xl, dest.yl };
- POINT dstPoint = { destRect.left, destRect.top };
-
- // Copy from visuals[bufnr] to temp
- srct = dx_state->pTexVisuals[bufnr];
- dstt = temp;
- DODX( (srct->GetSurfaceLevel(0, &sbuf)), dx_draw_pixmap );
- DODX( (dstt->GetSurfaceLevel(0, &dbuf)), dx_draw_pixmap );
- DODX( (dx_state->pDevice->CopyRects(sbuf, &srcRect, 1, dbuf, &dstPoint)), dx_draw_pixmap );
-
- // Copy from given pixmap to temp
- DODX( (dbuf->LockRect(&lockedRect, &destRect, 0)), dx_draw_pixmap );
- gfx_crossblit_pixmap(drv->mode, pxm, priority, src, dest,
- (byte *) lockedRect.pBits, lockedRect.Pitch,
- dx_state->priority_maps[pribufnr]->index_data,
- dx_state->priority_maps[pribufnr]->index_xl, 1,
- GFX_CROSSBLIT_FLAG_DATA_IS_HOMED);
- DODX( (dbuf->UnlockRect()), dx_draw_pixmap );
-
- SAFE_RELEASE(sbuf);
- SAFE_RELEASE(dbuf);
-
-
- // Copy from temp to visuals[bufnr]
- RECT src2Rect = { 0, 0, dest.xl, dest.yl };
- POINT dst2Point = { dest.x, dest.y };
-
- srct = temp;
- dstt = dx_state->pTexVisuals[bufnr];
- DODX( (srct->GetSurfaceLevel(0, &sbuf)), dx_draw_pixmap );
- DODX( (dstt->GetSurfaceLevel(0, &dbuf)), dx_draw_pixmap );
- DODX( (dx_state->pDevice->CopyRects(sbuf, &src2Rect, 1, dbuf, &dst2Point)), dx_draw_pixmap );
-
- SAFE_RELEASE(sbuf);
- SAFE_RELEASE(dbuf);
- SAFE_RELEASE(temp);
-
- return GFX_OK;
-}
-
-
-// Grabs an image from the visual or priority back buffer
-static int
-dx_grab_pixmap(struct _gfx_driver *drv, rect_t src, gfx_pixmap_t *pxm,
- gfx_map_mask_t map)
-{
- HRESULT hr;
-
- if (src.x < 0 || src.y < 0) {
- GFXERROR("Attempt to grab pixmap from invalid coordinates (%d,%d)\n", src.x, src.y);
- return GFX_ERROR;
- }
-
- if (!pxm->data) {
- GFXERROR("Attempt to grab pixmap to unallocated memory\n");
- return GFX_ERROR;
- }
-
- // Choose map to grab from
- switch (map) {
-
- case GFX_MASK_VISUAL: {
- LPDIRECT3DTEXTURE8 temp;
- LPDIRECT3DSURFACE8 tempSrf, backSrf;
- CONST RECT srcRect = RECT_T_TO_RECT(src);
- CONST POINT dstPoint = { 0, 0 };
-
- pxm->xl = src.xl;
- pxm->yl = src.yl;
-
- DODX( (dx_state->pDevice->CreateTexture(pxm->xl, pxm->yl, 1, 0, dx_state->d3dFormat, D3DPOOL_MANAGED, &temp)), dx_grab_pixmap );
-
- DODX( (dx_state->pTexVisuals[BACK_VIS]->GetSurfaceLevel(0, &backSrf)), dx_grab_pixmap );
- DODX( (temp->GetSurfaceLevel(0, &tempSrf)), dx_grab_pixmap );
- DODX( (dx_state->pDevice->CopyRects(backSrf, &srcRect, 1, tempSrf, &dstPoint)), dx_grab_pixmap );
-
- pxm->internal.info = temp;
- pxm->internal.handle = SCI_DX_HANDLE_GRABBED;
- pxm->flags |= GFX_PIXMAP_FLAG_INSTALLED | GFX_PIXMAP_FLAG_EXTERNAL_PALETTE | GFX_PIXMAP_FLAG_PALETTE_SET;
-
- SAFE_RELEASE(backSrf);
- SAFE_RELEASE(tempSrf);
-
- break;
- }
-
- case GFX_MASK_PRIORITY:
- sciprintf("FIXME: priority map grab not implemented yet!\n");
- break;
-
- default:
- sciprintf("Attempt to grab pixmap from invalid map 0x%02x\n", map);
- return GFX_ERROR;
- }
-
- return GFX_OK;
-}
-
-
-///// BUFFERING
-
-// Updates the front buffer or the back buffers
-static int
-dx_update(struct _gfx_driver *drv, rect_t src, point_t dest, gfx_buffer_t buffer)
-{
- HRESULT hr;
- LPDIRECT3DTEXTURE8 srct, dstt;
- LPDIRECT3DSURFACE8 sbuf, dbuf;
- CONST RECT srcRect = RECT_T_TO_RECT(src);
- CONST POINT dstPoint = { dest.x, dest.y };
-
- switch (buffer) {
-
- case GFX_BUFFER_FRONT:
- srct = dx_state->pTexVisuals[BACK_VIS];
- dstt = dx_state->pTexVisuals[PRIMARY_VIS];
-
- DODX( (srct->GetSurfaceLevel(0, &sbuf)), dx_update );
- DODX( (dstt->GetSurfaceLevel(0, &dbuf)), dx_update );
-
- DODX( (dx_state->pDevice->CopyRects(sbuf, &srcRect, 1, dbuf, &dstPoint)), dx_update );
-
- SAFE_RELEASE(sbuf);
- SAFE_RELEASE(dbuf);
-
- RenderD3D(drv);
- break;
-
- case GFX_BUFFER_BACK:
- if (src.x == dest.x && src.y == dest.y)
- gfx_copy_pixmap_box_i(dx_state->priority_maps[BACK_PRI], dx_state->priority_maps[STATIC_PRI], src);
-
- srct = dx_state->pTexVisuals[STATIC_VIS];
- dstt = dx_state->pTexVisuals[BACK_VIS];
-
- DODX( (srct->GetSurfaceLevel(0, &sbuf)), dx_update );
- DODX( (dstt->GetSurfaceLevel(0, &dbuf)), dx_update );
-
- DODX( (dx_state->pDevice->CopyRects(sbuf, &srcRect, 1, dbuf, &dstPoint)), dx_update );
-
- SAFE_RELEASE(sbuf);
- SAFE_RELEASE(dbuf);
-
- break;
-
- default:
- GFXERROR("Invalid buffer %d in update!\n", buffer);
- return GFX_ERROR;
- }
-
- return GFX_OK;
-}
-
-
-// Sets the contents of the static visual and priority buffers
-static int
-dx_set_static_buffer(struct _gfx_driver *drv, gfx_pixmap_t *pic,
- gfx_pixmap_t *priority)
-{
- if (!pic->internal.info) {
- GFXERROR("Attempt to set static buffer with unregistered pixmap!\n");
- return GFX_ERROR;
- }
-
- HRESULT hr;
- LPDIRECT3DTEXTURE8 pii = (LPDIRECT3DTEXTURE8) (pic->internal.info);
- LPDIRECT3DSURFACE8 pbf;
- LPDIRECT3DTEXTURE8 vis = dx_state->pTexVisuals[STATIC_VIS];
- LPDIRECT3DSURFACE8 vbf;
-
- // Copy from pic to visual[static]
- DODX( (pii->GetSurfaceLevel(0, &pbf)), dx_set_static_buffer );
- DODX( (vis->GetSurfaceLevel(0, &vbf)), dx_set_static_buffer );
- DODX( (dx_state->pDevice->CopyRects(pbf, NULL, 0, vbf, NULL)), dx_set_static_buffer );
-
- SAFE_RELEASE(pbf);
- SAFE_RELEASE(vbf);
-
- // Copy priority map
- gfx_copy_pixmap_box_i(dx_state->priority_maps[STATIC_PRI], priority, gfx_rect(0, 0, 320, 200));
-
- return GFX_OK;
-}
-
-
-///// MOUSE
-
-// Sets a new mouse pointer
-static int
-dx_set_pointer(struct _gfx_driver *drv, gfx_pixmap_t *pointer)
-{
- HRESULT hr;
-
- if (pointer->data == NULL)
- return GFX_OK;
- pointer->yl /= 2; // Scale the pointer to compensate for mode scale
-
- LPDIRECT3DTEXTURE8 pntTex;
- LPDIRECT3DSURFACE8 pntSrf;
-
- // Get pointer dimensions and init
- POINTS pDims = {pointer->xl, pointer->yl};
- dx_state->pointerDims = pDims;
- RECT r = {0, 0, pointer->xl, pointer->yl};
-
- // Recreate pointer data according to the graphics mode we need
- gfx_pixmap_free_data(pointer);
- gfx_xlate_pixmap(pointer, dx_state->pointerMode, GFX_XLATE_FILTER_NONE);
-
- // Create texture and fill with pointer data
- DODX( (dx_state->pDevice->CreateTexture(pointer->xl, pointer->yl, 1, 0, dx_state->d3dFormat, D3DPOOL_MANAGED, &pntTex )), dx_set_pointer );
- DODX( (pntTex->GetSurfaceLevel(0, &pntSrf)), dx_set_pointer );
-
- DODX( (D3DXLoadSurfaceFromMemory(pntSrf, NULL, &r, pointer->data, dx_state->d3dFormat, 256, NULL, &r, D3DX_FILTER_NONE, 0)), dx_set_pointer);
-
- SAFE_RELEASE(pntSrf);
-
- // Assign as current pointer texture
- if (dx_state->pTexPointer)
- SAFE_RELEASE(dx_state->pTexPointer);
- dx_state->pTexPointer = pntTex;
-
- return GFX_OK;
-}
-
-
-// Display mouse pointer
-static int
-show_pointer(struct _gfx_driver *drv, LPARAM pos)
-{
- POINTS mousePos; // mouse coordinates
-
- // Sort out coordinates
- mousePos = MAKEPOINTS(pos);
-
- // Update pos
- drv->pointer_x = mousePos.x;
- drv->pointer_y = mousePos.y;
-
- RenderD3D(drv);
-
- return GFX_OK;
-}
-
-
-///// EVENTS
-
-// Get event from the queue
-static sci_event_t
-get_queue_event(gfx_dx_struct_t *ctx)
-{
- if (ctx->queue_first == ctx->queue_size)
- ctx->queue_first = 0;
-
- if (ctx->queue_first == ctx->queue_last)
- {
- sci_event_t noevent;
- noevent.data = 0;
- noevent.type = SCI_EVT_NONE;
- noevent.buckybits = 0;
- return noevent;
- }
- else
- return ctx->event_queue [ctx->queue_first++];
-}
-
-
-// Add event to the queue
-static void add_queue_event(gfx_dx_struct_t *ctx, int type, int data, short buckybits)
-{
- if ((ctx->queue_last+1) % ctx->queue_size == ctx->queue_first)
- {
- /* Reallocate queue */
- int i, event_count;
- sci_event_t *new_queue;
-
- new_queue = (sci_event_t *) sci_malloc (ctx->queue_size * 2 * sizeof (sci_event_t));
- event_count = (ctx->queue_last - ctx->queue_first) % ctx->queue_size;
- for (i=0; i<event_count; i++)
- new_queue [i] = ctx->event_queue [(ctx->queue_first+i) % ctx->queue_size];
- free (ctx->event_queue);
- ctx->event_queue = new_queue;
- ctx->queue_size *= 2;
- ctx->queue_first = 0;
- ctx->queue_last = event_count;
- }
-
- ctx->event_queue [ctx->queue_last].data = data;
- ctx->event_queue [ctx->queue_last].type = type;
- ctx->event_queue [ctx->queue_last++].buckybits = buckybits;
- if (ctx->queue_last == ctx->queue_size)
- ctx->queue_last=0;
-}
-
-
-// Add keystroke event to queue
-static void add_key_event (gfx_dx_struct_t *ctx, int data)
-{
- short buckybits = 0;
-
- if (GetAsyncKeyState (VK_RSHIFT))
- buckybits |= SCI_EVM_RSHIFT;
- if (GetAsyncKeyState (VK_LSHIFT))
- buckybits |= SCI_EVM_LSHIFT;
- if (GetAsyncKeyState (VK_CONTROL))
- buckybits |= SCI_EVM_CTRL;
- if (GetAsyncKeyState (VK_MENU))
- buckybits |= SCI_EVM_ALT;
- if (GetKeyState (VK_SCROLL) & 1)
- buckybits |= SCI_EVM_SCRLOCK;
- if (GetKeyState (VK_NUMLOCK) & 1)
- buckybits |= SCI_EVM_NUMLOCK;
- if (GetKeyState (VK_CAPITAL) & 1)
- buckybits |= SCI_EVM_CAPSLOCK;
-
- add_queue_event (ctx, SCI_EVT_KEYBOARD, data, buckybits);
-}
-
-
-// Add mouse event to queue
-static void add_mouse_event(gfx_dx_struct_t *ctx, int type, int data, WPARAM wParam)
-{
- short buckybits = 0;
- if (wParam & MK_SHIFT)
- buckybits |= SCI_EVM_LSHIFT | SCI_EVM_RSHIFT;
- if (wParam & MK_CONTROL)
- buckybits |= SCI_EVM_CTRL;
-
- add_queue_event (ctx, type, data, buckybits);
-}
-
-
-// Returns the next event in the event queue for this driver
-static sci_event_t
-dx_get_event(struct _gfx_driver *drv)
-{
- assert(drv->state != NULL);
- return get_queue_event(dx_state);
-}
-
-
-// Sleeps the specified amount of microseconds, or until the mouse moves
-static int
-dx_usleep(struct _gfx_driver *drv, long usecs)
-{
- if (usecs < 1000)
- {
- sleep(0);
- }
- else
- {
- sleep(usecs/1000);
- }
- ProcessMessages(drv);
-
- return GFX_OK;
-}
-
-
-// Process any Windows messages
-static int
-ProcessMessages(struct _gfx_driver *drv)
-{
- MSG msg;
-
- while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
- switch( msg.message )
- {
- case WM_PAINT:
- ValidateRect( dx_state->hWnd, NULL );
- RenderD3D(drv);
- break;
-
- case WM_KEYDOWN:
- switch (msg.wParam)
- {
- MAP_KEY (VK_ESCAPE, SCI_K_ESC);
- MAP_KEY (VK_BACK, SCI_K_BACKSPACE);
- MAP_KEY (VK_RETURN, SCI_K_ENTER);
- MAP_KEY (VK_TAB, SCI_K_TAB);
- MAP_KEY (VK_END, SCI_K_END);
- MAP_KEY (VK_DOWN, SCI_K_DOWN);
- MAP_KEY (VK_NEXT, SCI_K_PGDOWN);
- MAP_KEY (VK_LEFT, SCI_K_LEFT);
- MAP_KEY (VK_RIGHT, SCI_K_RIGHT);
- MAP_KEY (VK_HOME, SCI_K_HOME);
- MAP_KEY (VK_UP, SCI_K_UP);
- MAP_KEY (VK_PRIOR, SCI_K_PGUP);
- MAP_KEY (VK_INSERT, SCI_K_INSERT);
- MAP_KEY (VK_DELETE, SCI_K_DELETE);
- MAP_KEY (VK_DECIMAL, SCI_K_DELETE);
- /* TODO: Glutton no longer had SCI_K etc... declared
- MAP_KEY (VK_ADD, SCI_K_PLUS);
- MAP_KEY (VK_OEM_PLUS, SCI_K_EQUALS);
- MAP_KEY (VK_SUBTRACT, SCI_K_MINUS);
- MAP_KEY (VK_OEM_MINUS, SCI_K_MINUS);
- MAP_KEY (VK_MULTIPLY, SCI_K_MULTIPLY);
- MAP_KEY (VK_DIVIDE, SCI_K_DIVIDE);
- */
- MAP_KEY (VK_OEM_COMMA, ',');
- MAP_KEY (VK_OEM_PERIOD, '.');
- MAP_KEY (VK_OEM_1, ';'); // US keyboards only
- MAP_KEY (VK_OEM_2, '/');
- MAP_KEY (VK_OEM_3, '`');
- MAP_KEY (VK_OEM_4, '[');
- MAP_KEY (VK_OEM_5, '\\');
- MAP_KEY (VK_OEM_6, ']');
- MAP_KEY (VK_OEM_7, '\'');
- MAP_KEY (VK_F1, SCI_K_F1);
- MAP_KEY (VK_F2, SCI_K_F2);
- MAP_KEY (VK_F3, SCI_K_F3);
- MAP_KEY (VK_F4, SCI_K_F4);
- MAP_KEY (VK_F5, SCI_K_F5);
- MAP_KEY (VK_F6, SCI_K_F6);
- MAP_KEY (VK_F7, SCI_K_F7);
- MAP_KEY (VK_F8, SCI_K_F8);
- MAP_KEY (VK_F9, SCI_K_F9);
- MAP_KEY (VK_F10, SCI_K_F10);
-
- case VK_RSHIFT:
- case VK_LSHIFT:
- case VK_CONTROL:
- case VK_MENU:
- case VK_SCROLL:
- case VK_NUMLOCK:
- case VK_CAPITAL:
- break; // ignore
-
- default:
- if (msg.wParam >= 'A' && msg.wParam <= 'Z')
- add_key_event (dx_state, msg.wParam - 'A' + 97);
- else if (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9)
- {
- if (GetKeyState (VK_NUMLOCK) & 1)
- add_key_event (dx_state, msg.wParam - VK_NUMPAD0 + '0');
- else
- switch (msg.wParam)
- {
- MAP_KEY (VK_NUMPAD0, SCI_K_INSERT);
- MAP_KEY (VK_NUMPAD1, SCI_K_END);
- MAP_KEY (VK_NUMPAD2, SCI_K_DOWN);
- MAP_KEY (VK_NUMPAD3, SCI_K_PGDOWN);
- MAP_KEY (VK_NUMPAD4, SCI_K_LEFT);
- MAP_KEY (VK_NUMPAD6, SCI_K_RIGHT);
- MAP_KEY (VK_NUMPAD7, SCI_K_HOME);
- MAP_KEY (VK_NUMPAD8, SCI_K_UP);
- MAP_KEY (VK_NUMPAD9, SCI_K_PGUP);
- }
- }
- else if (msg.wParam == 0xC0) // tilde key - used for invoking console
- add_key_event (dx_state, '`');
- else
- add_key_event (dx_state, msg.wParam);
- break;
- }
- break;
-
- case WM_MOUSEMOVE:
- // Turn off mouse cursor
- ShowCursor(FALSE);
- show_pointer(drv, msg.lParam);
- break;
-
- case WM_MOUSELEAVE:
- // Turn on mouse cursor
- ShowCursor(TRUE);
- break;
-
- case WM_LBUTTONDOWN: add_mouse_event (dx_state, SCI_EVT_MOUSE_PRESS, 1, msg.wParam); break;
- case WM_RBUTTONDOWN: add_mouse_event (dx_state, SCI_EVT_MOUSE_PRESS, 2, msg.wParam); break;
- case WM_MBUTTONDOWN: add_mouse_event (dx_state, SCI_EVT_MOUSE_PRESS, 3, msg.wParam); break;
- case WM_LBUTTONUP: add_mouse_event (dx_state, SCI_EVT_MOUSE_RELEASE, 1, msg.wParam); break;
- case WM_RBUTTONUP: add_mouse_event (dx_state, SCI_EVT_MOUSE_RELEASE, 2, msg.wParam); break;
- case WM_MBUTTONUP: add_mouse_event (dx_state, SCI_EVT_MOUSE_RELEASE, 3, msg.wParam); break;
-
- case WM_DESTROY:
- PostQuitMessage( 0 );
- drv->exit(drv);
- exit(-1);
- break;
-
- }
- }
-
- return 0;
-}
-
-
-extern "C"
-gfx_driver_t gfx_driver_dx = {
- "directx",
- "0.4.2",
- SCI_GFX_DRIVER_MAGIC,
- SCI_GFX_DRIVER_VERSION,
- NULL, /* mode */
- 0, 0, /* mouse pointer position */
- GFX_CAPABILITY_MOUSE_SUPPORT | GFX_CAPABILITY_MOUSE_POINTER | GFX_CAPABILITY_COLOR_MOUSE_POINTER | GFX_CAPABILITY_PIXMAP_REGISTRY | GFX_CAPABILITY_WINDOWED,
- 0,
- dx_set_param,
- dx_init_specific,
- dx_init,
- dx_exit,
- dx_draw_line,
- dx_draw_filled_rect,
- dx_register_pixmap,
- dx_unregister_pixmap,
- dx_draw_pixmap,
- dx_grab_pixmap,
- dx_update,
- dx_set_static_buffer,
- dx_set_pointer,
- NULL,
- dx_get_event,
- dx_usleep,
- NULL
-};
-
-#endif