DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/output/direct3d/direct3d.h
00001 /*
00002  *  Direct3D rendering code by gulikoza
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #ifndef __DIRECT3D_H_
00020 #define __DIRECT3D_H_
00021 
00022 #include <d3d9.h>
00023 #include <d3dx9math.h>
00024 #include "dosbox.h"
00025 #include "hq2x_d3d.h"
00026 
00027 #define LOG_D3D 0               // Set this to 1 to enable D3D debug messages
00028 #define D3D_THREAD 1            // Set this to 1 to thread Direct3D
00029 
00030 #if LOG_D3D
00031 #include <io.h>
00032 #include <fcntl.h>
00033 #include <stdio.h>
00034 #endif
00035 
00036 #if D3D_THREAD
00037 #include "SDL_thread.h"
00038 #endif
00039 
00040 #define SAFE_RELEASE(p)         { if(p) { (p)->Release(); (p)=NULL; } }
00041 
00042 #if defined (_MSC_VER)                                          /* MS Visual C++ */
00043 #define strcasecmp(a,b) stricmp(a,b)
00044 #endif
00045 
00046 // Vertex format
00047 #define D3DFVF_TLVERTEX D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1
00048 
00049 #if C_D3DSHADERS
00050 #include "ScalingEffect.h"
00051 #else
00052 #define D3DXMATRIX D3DMATRIX
00053 #define D3DXVECTOR3 vec3f
00054 #define D3DXVECTOR2 vec2f
00055 #define D3DXMatrixOrthoOffCenterLH MatrixOrthoOffCenterLH
00056 #define D3DXMatrixTranslation MatrixTranslation
00057 #define D3DXMatrixScaling MatrixScaling
00058 
00059 struct vec3f {
00060     float x, y, z;
00061     vec3f() { }
00062     vec3f(float vx, float vy, float vz)
00063     : x(vx), y(vy), z(vz) { }
00064 };
00065 
00066 struct vec2f {
00067     float x, y;
00068     vec2f() { }
00069     vec2f(float vx, float vy)
00070     : x(vx), y(vy) { }
00071 };
00072 
00073 #endif
00074 
00075 class CDirect3D {
00076 private:
00077 
00078     // globals
00079     HMODULE                     mhmodDX9 = NULL;
00080     IDirect3D9*                 pD3D9 = NULL;
00081     IDirect3DDevice9*           pD3DDevice9 = NULL;
00082 
00083     D3DPRESENT_PARAMETERS       d3dpp = {};                     // Present parameters
00084     D3DLOCKED_RECT              d3dlr = {};                     // Texture lock rectangle
00085 
00086     HWND hwnd = NULL;                                           // DOSBox window
00087     DWORD dwX = 0, dwY = 0;                                     // X,Y position
00088     DWORD dwWidth, dwHeight;                            // DOSBox framebuffer size
00089     DWORD dwScaledWidth = 0, dwScaledHeight = 0;                // D3D backbuffer size
00090     const Bit16u* changedLines = NULL;
00091 
00092         int                                     backbuffer_clear_countdown = 0;
00093 
00094     // display modes
00095     D3DDISPLAYMODE*             modes;
00096     unsigned int                iMode = 0;
00097     DWORD                       dwNumModes = 0;
00098 
00099     bool                        deviceLost;
00100 
00101     // vertex stuff
00102     IDirect3DVertexBuffer9*     vertexBuffer;           // VertexBuffer
00103 
00104     // Custom vertex
00105     struct TLVERTEX {
00106         D3DXVECTOR3 position;       // vertex position
00107         D3DCOLOR    diffuse;
00108         D3DXVECTOR2 texcoord;       // texture coords
00109     };
00110 
00111     // Projection matrices
00112     D3DXMATRIX                  m_matProj;
00113     D3DXMATRIX                  m_matWorld;
00114     D3DXMATRIX                  m_matView;
00115 
00116 #if C_D3DSHADERS
00117     D3DXMATRIX                  m_matPreProj;
00118     D3DXMATRIX                  m_matPreView;
00119     D3DXMATRIX                  m_matPreWorld;
00120 
00121     // Pixel shader
00122     std::string         pshader;
00123     ScalingEffect*              psEffect;
00124     LPDIRECT3DTEXTURE9          lpWorkTexture1;
00125     LPDIRECT3DTEXTURE9          lpWorkTexture2;
00126     LPDIRECT3DVOLUMETEXTURE9    lpHq2xLookupTexture;
00127 #if LOG_D3D
00128     LPDIRECT3DTEXTURE9          lpDebugTexture;
00129 #endif
00130 #endif
00131     LPDIRECT3DTEXTURE9          lpTexture;              // D3D texture
00132     bool                        psEnabled;
00133     bool                        preProcess;
00134 
00135     // function declarations
00136     HRESULT InitD3D(void);
00137 
00138     HRESULT RestoreDeviceObjects(void);
00139     HRESULT InvalidateDeviceObjects(void);
00140     HRESULT CreateDisplayTexture(void);
00141     HRESULT CreateVertex(void);
00142 #if !(C_D3DSHADERS)
00143     D3DXMATRIX* MatrixOrthoOffCenterLH(D3DXMATRIX*, float, float, float, float, float, float);
00144     D3DXMATRIX* MatrixScaling(D3DXMATRIX*, float, float, float);
00145     D3DXMATRIX* MatrixTranslation(D3DXMATRIX*, float, float, float);
00146 #endif
00147 
00148     void SetupSceneScaled(void);
00149     bool D3DSwapBuffers(void);
00150 
00151 #if D3D_THREAD
00152     // Thread entry point must be static
00153     static int EntryPoint(void * pthis) { CDirect3D * pt = (CDirect3D *)pthis; return pt->Start(); }
00154     HRESULT Wait(bool unlock = true);
00155     int Start(void);
00156 
00157     SDL_Thread *thread;
00158     CRITICAL_SECTION cs;
00159     SDL_semaphore *thread_sem, *thread_ack;
00160 
00161     volatile enum D3D_state { D3D_IDLE = 0, D3D_LOADPS, D3D_LOCK, D3D_UNLOCK } thread_command;
00162     volatile bool thread_run, wait;
00163     volatile HRESULT thread_hr = 0;
00164 #if LOG_D3D
00165     void EnterLOGCriticalSection(LPCRITICAL_SECTION lpCriticalSection, int);
00166 #endif
00167 #endif
00168 
00169     HRESULT LoadPixelShader(void);
00170     HRESULT Resize3DEnvironment(void);
00171     HRESULT LockTexture(void);
00172     bool UnlockTexture(void);
00173     void DestroyD3D(void);
00174 
00175 public:
00176 
00177     // texture stuff
00178     DWORD       dwTexHeight = 0, dwTexWidth = 0;
00179 
00180     bool        square = false, pow2 = false, dynamic = false, bpp16;           // Texture limitations
00181     Bit8s       aspect, autofit = 0;
00182 
00183     // Pixel shader status
00184     bool        psActive;
00185 
00186     // function declarations
00187     HRESULT InitializeDX(HWND, bool);
00188     HRESULT LoadPixelShader(const char*, double, double, bool forced=false);
00189     HRESULT Resize3DEnvironment(Bitu, Bitu, Bitu, Bitu, Bitu, Bitu, Bitu, Bitu, bool fullscreen=false);
00190     bool LockTexture(Bit8u * & pixels,Bitu & pitch);
00191     bool UnlockTexture(const Bit16u *changed);
00192 
00193     CDirect3D(Bit32u width = 640, Bit32u height = 400):dwWidth(width),dwHeight(height) {
00194         mhmodDX9 = NULL;
00195         pD3D9 = NULL;
00196         pD3DDevice9 = NULL;
00197         modes = NULL;
00198         vertexBuffer = NULL;
00199 
00200         deviceLost = false;
00201 
00202         bpp16 = false;
00203         aspect = 0;
00204         lpTexture = NULL;
00205 
00206         psEnabled = false;
00207         psActive = false;
00208         preProcess = false;
00209 
00210 #if C_D3DSHADERS
00211         lpWorkTexture1 = NULL;
00212         lpWorkTexture2 = NULL;
00213         lpHq2xLookupTexture = NULL;
00214 #if LOG_D3D
00215         lpDebugTexture = NULL;
00216 #endif
00217     pshader.clear();
00218         psEffect = NULL;
00219 #endif
00220 
00221 #if D3D_THREAD
00222         thread = NULL;
00223         wait = false;
00224         thread_run = false;
00225         thread_command = D3D_IDLE;
00226 
00227         InitializeCriticalSection(&cs);
00228         thread_sem = SDL_CreateSemaphore(0);
00229         thread_ack = SDL_CreateSemaphore(0);
00230 #endif
00231 
00232     }
00233 
00234     void UpdateRectFromSDLSurface(int x,int y,int w,int h);
00235     void UpdateRectToSDLSurface(int x,int y,int w,int h);
00236 
00237     bool getForceUpdate(void) {
00238 #if C_D3DSHADERS
00239         if (psEffect) return psEffect->getForceUpdate();
00240 #endif
00241         return false;
00242     }
00243 
00244     ~CDirect3D() {
00245 #if LOG_D3D
00246         LOG_MSG("D3D:Shutting down Direct3D");
00247 #endif
00248         DestroyD3D();
00249 
00250 #if D3D_THREAD
00251         DeleteCriticalSection(&cs);
00252         SDL_DestroySemaphore(thread_sem);
00253         SDL_DestroySemaphore(thread_ack);
00254 #endif
00255 
00256         // Unload d3d9.dll
00257         if (mhmodDX9) {
00258             FreeLibrary(mhmodDX9);
00259             mhmodDX9 = NULL;
00260         }
00261     }
00262 };
00263 
00264 #endif // __DIRECT3D_H_