PCem
view src/win-d3d-fs.cc @ 169:b184d3ebfd41
Updated version number to v9.
Updated documentation for next release.
| author | TomW |
|---|---|
| date | Sat Oct 04 19:39:09 2014 +0100 |
| parents | face56551501 |
| children |
line source
1 #include <stdint.h>
2 #define BITMAP WINDOWS_BITMAP
3 #include <d3d9.h>
4 #undef BITMAP
5 #include "resources.h"
6 #include "video.h"
7 #include "win-d3d-fs.h"
8 #include "win.h"
10 extern "C" void fatal(const char *format, ...);
11 extern "C" void pclog(const char *format, ...);
13 extern "C" void device_force_redraw();
15 static void d3d_fs_init_objects();
16 static void d3d_fs_close_objects();
17 static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h);
18 static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h);
20 static LPDIRECT3D9 d3d = NULL;
21 static LPDIRECT3DDEVICE9 d3ddev = NULL;
22 static LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
23 static LPDIRECT3DTEXTURE9 d3dTexture = NULL;
24 static D3DPRESENT_PARAMETERS d3dpp;
26 static HWND d3d_hwnd;
27 static HWND d3d_device_window;
29 static int d3d_fs_w, d3d_fs_h;
31 struct CUSTOMVERTEX
32 {
33 FLOAT x, y, z, rhw; // from the D3DFVF_XYZRHW flag
34 FLOAT tu, tv;
35 };
37 static PALETTE cgapal=
38 {
39 {0,0,0},{0,42,0},{42,0,0},{42,21,0},
40 {0,0,0},{0,42,42},{42,0,42},{42,42,42},
41 {0,0,0},{21,63,21},{63,21,21},{63,63,21},
42 {0,0,0},{21,63,63},{63,21,63},{63,63,63},
44 {0,0,0},{0,0,42},{0,42,0},{0,42,42},
45 {42,0,0},{42,0,42},{42,21,00},{42,42,42},
46 {21,21,21},{21,21,63},{21,63,21},{21,63,63},
47 {63,21,21},{63,21,63},{63,63,21},{63,63,63},
49 {0,0,0},{0,21,0},{0,0,42},{0,42,42},
50 {42,0,21},{21,10,21},{42,0,42},{42,0,63},
51 {21,21,21},{21,63,21},{42,21,42},{21,63,63},
52 {63,0,0},{42,42,0},{63,21,42},{41,41,41},
54 {0,0,0},{0,42,42},{42,0,0},{42,42,42},
55 {0,0,0},{0,42,42},{42,0,0},{42,42,42},
56 {0,0,0},{0,63,63},{63,0,0},{63,63,63},
57 {0,0,0},{0,63,63},{63,0,0},{63,63,63},
58 };
60 static uint32_t pal_lookup[256];
62 static CUSTOMVERTEX d3d_verts[] =
63 {
64 { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f},
65 {2048.0f, 2048.0f, 1.0f, 1.0f, 1.0f, 1.0f},
66 { 0.0f, 2048.0f, 1.0f, 1.0f, 0.0f, 1.0f},
68 { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f},
69 {2048.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f},
70 {2048.0f, 2048.0f, 1.0f, 1.0f, 1.0f, 1.0f},
71 };
73 void d3d_fs_init(HWND h)
74 {
75 int c;
76 HRESULT hr;
78 d3d_fs_w = GetSystemMetrics(SM_CXSCREEN);
79 d3d_fs_h = GetSystemMetrics(SM_CYSCREEN);
81 for (c = 0; c < 256; c++)
82 pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2);
84 d3d_hwnd = h;
86 d3d_device_window = CreateWindowEx (
87 0,
88 szSubClassName,
89 "PCem v9",
90 WS_POPUP,
91 CW_USEDEFAULT,
92 CW_USEDEFAULT,
93 640,
94 480,
95 HWND_DESKTOP,
96 NULL,
97 NULL,
98 NULL
99 );
101 d3d = Direct3DCreate9(D3D_SDK_VERSION);
103 memset(&d3dpp, 0, sizeof(d3dpp));
105 d3dpp.Flags = 0;
106 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
107 d3dpp.hDeviceWindow = d3d_device_window;
108 d3dpp.BackBufferCount = 1;
109 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
110 d3dpp.MultiSampleQuality = 0;
111 d3dpp.EnableAutoDepthStencil = false;
112 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
113 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
114 d3dpp.Windowed = false;
115 d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
116 d3dpp.BackBufferWidth = d3d_fs_w;
117 d3dpp.BackBufferHeight = d3d_fs_h;
119 hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, h, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
121 d3d_fs_init_objects();
123 video_blit_memtoscreen = d3d_fs_blit_memtoscreen;
124 video_blit_memtoscreen_8 = d3d_fs_blit_memtoscreen_8;
125 }
127 static void d3d_fs_close_objects()
128 {
129 if (d3dTexture)
130 {
131 d3dTexture->Release();
132 d3dTexture = NULL;
133 }
134 if (v_buffer)
135 {
136 v_buffer->Release();
137 v_buffer = NULL;
138 }
139 }
141 static void d3d_fs_init_objects()
142 {
143 HRESULT hr;
144 D3DLOCKED_RECT dr;
145 int y;
146 RECT r;
148 hr = d3ddev->CreateVertexBuffer(6*sizeof(CUSTOMVERTEX),
149 0,
150 D3DFVF_XYZRHW | D3DFVF_TEX1,
151 D3DPOOL_MANAGED,
152 &v_buffer,
153 NULL);
155 d3ddev->CreateTexture(2048, 2048, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &d3dTexture, NULL);
157 r.top = r.left = 0;
158 r.bottom = r.right = 2047;
160 if (FAILED(d3dTexture->LockRect(0, &dr, &r, 0)))
161 fatal("LockRect failed\n");
163 for (y = 0; y < 2048; y++)
164 {
165 uint32_t *p = (uint32_t *)(dr.pBits + (y * dr.Pitch));
166 memset(p, 0, 2048 * 4);
167 }
169 d3dTexture->UnlockRect(0);
171 d3ddev->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
172 d3ddev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
173 d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
175 d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
176 d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
177 }
179 /*void d3d_resize(int x, int y)
180 {
181 HRESULT hr;
183 d3dpp.BackBufferWidth = x;
184 d3dpp.BackBufferHeight = y;
186 d3d_reset();
187 }*/
189 void d3d_fs_reset()
190 {
191 HRESULT hr;
193 memset(&d3dpp, 0, sizeof(d3dpp));
195 d3dpp.Flags = 0;
196 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
197 d3dpp.hDeviceWindow = d3d_device_window;
198 d3dpp.BackBufferCount = 1;
199 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
200 d3dpp.MultiSampleQuality = 0;
201 d3dpp.EnableAutoDepthStencil = false;
202 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
203 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
204 d3dpp.Windowed = false;
205 d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
206 d3dpp.BackBufferWidth = d3d_fs_w;
207 d3dpp.BackBufferHeight = d3d_fs_h;
209 hr = d3ddev->Reset(&d3dpp);
211 if (hr == D3DERR_DEVICELOST)
212 return;
214 d3ddev->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
215 d3ddev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
216 d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
218 d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
219 d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
221 device_force_redraw();
222 }
224 void d3d_fs_close()
225 {
226 if (d3dTexture)
227 {
228 d3dTexture->Release();
229 d3dTexture = NULL;
230 }
231 if (v_buffer)
232 {
233 v_buffer->Release();
234 v_buffer = NULL;
235 }
236 if (d3ddev)
237 {
238 d3ddev->Release();
239 d3ddev = NULL;
240 }
241 if (d3d)
242 {
243 d3d->Release();
244 d3d = NULL;
245 }
246 DestroyWindow(d3d_device_window);
247 }
249 static void d3d_fs_size(RECT window_rect, double *l, double *t, double *r, double *b, int w, int h)
250 {
251 int ratio_w, ratio_h;
252 switch (video_fullscreen_scale)
253 {
254 case FULLSCR_SCALE_FULL:
255 *l = -0.5;
256 *t = -0.5;
257 *r = (window_rect.right - window_rect.left) - 0.5;
258 *b = (window_rect.bottom - window_rect.top) - 0.5;
259 break;
260 case FULLSCR_SCALE_43:
261 *t = -0.5;
262 *b = (window_rect.bottom - window_rect.top) - 0.5;
263 *l = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)) - 0.5;
264 *r = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * 4) / (3 * 2)) - 0.5;
265 if (*l < -0.5)
266 {
267 *l = -0.5;
268 *r = (window_rect.right - window_rect.left) - 0.5;
269 *t = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * 3) / (4 * 2)) - 0.5;
270 *b = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * 3) / (4 * 2)) - 0.5;
271 }
272 break;
273 case FULLSCR_SCALE_SQ:
274 *t = -0.5;
275 *b = (window_rect.bottom - window_rect.top) - 0.5;
276 *l = ((window_rect.right - window_rect.left) / 2) - (((window_rect.bottom - window_rect.top) * w) / (h * 2)) - 0.5;
277 *r = ((window_rect.right - window_rect.left) / 2) + (((window_rect.bottom - window_rect.top) * w) / (h * 2)) - 0.5;
278 if (*l < -0.5)
279 {
280 *l = -0.5;
281 *r = (window_rect.right - window_rect.left) - 0.5;
282 *t = ((window_rect.bottom - window_rect.top) / 2) - (((window_rect.right - window_rect.left) * h) / (w * 2)) - 0.5;
283 *b = ((window_rect.bottom - window_rect.top) / 2) + (((window_rect.right - window_rect.left) * h) / (w * 2)) - 0.5;
284 }
285 break;
286 case FULLSCR_SCALE_INT:
287 ratio_w = (window_rect.right - window_rect.left) / w;
288 ratio_h = (window_rect.bottom - window_rect.top) / h;
289 if (ratio_h < ratio_w)
290 ratio_w = ratio_h;
291 *l = ((window_rect.right - window_rect.left) / 2) - ((w * ratio_w) / 2) - 0.5;
292 *r = ((window_rect.right - window_rect.left) / 2) + ((w * ratio_w) / 2) - 0.5;
293 *t = ((window_rect.bottom - window_rect.top) / 2) - ((h * ratio_w) / 2) - 0.5;
294 *b = ((window_rect.bottom - window_rect.top) / 2) + ((h * ratio_w) / 2) - 0.5;
295 break;
296 }
297 }
299 static void d3d_fs_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
300 {
301 HRESULT hr = D3D_OK;
302 VOID* pVoid;
303 D3DLOCKED_RECT dr;
304 RECT window_rect;
305 uint32_t *p, *src;
306 int yy;
307 double l, t, r, b;
309 d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0;
310 d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0;
311 d3d_verts[1].tu = d3d_verts[4].tu = d3d_verts[5].tu = (float)w / 2048.0;
312 d3d_verts[1].tv = d3d_verts[2].tv = d3d_verts[5].tv = (float)h / 2048.0;
314 GetClientRect(d3d_device_window, &window_rect);
315 d3d_fs_size(window_rect, &l, &t, &r, &b, w, h);
317 d3d_verts[0].x = l;
318 d3d_verts[0].y = t;
319 d3d_verts[1].x = r;
320 d3d_verts[1].y = b;
321 d3d_verts[2].x = l;
322 d3d_verts[2].y = b;
323 d3d_verts[3].x = l;
324 d3d_verts[3].y = t;
325 d3d_verts[4].x = r;
326 d3d_verts[4].y = t;
327 d3d_verts[5].x = r;
328 d3d_verts[5].y = b;
330 if (hr == D3D_OK)
331 hr = v_buffer->Lock(0, 0, (void**)&pVoid, 0);
332 if (hr == D3D_OK)
333 memcpy(pVoid, d3d_verts, sizeof(d3d_verts));
334 if (hr == D3D_OK)
335 hr = v_buffer->Unlock();
337 if (hr == D3D_OK && !(y1 == 0 && y2 == 0))
338 {
339 RECT lock_rect;
341 lock_rect.top = y1;
342 lock_rect.left = 0;
343 lock_rect.bottom = y2;
344 lock_rect.right = 2047;
346 if (FAILED(d3dTexture->LockRect(0, &dr, &lock_rect, 0)))
347 fatal("LockRect failed\n");
349 for (yy = y1; yy < y2; yy++)
350 memcpy(dr.pBits + ((yy - y1) * dr.Pitch), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4);
352 d3dTexture->UnlockRect(0);
353 }
355 if (hr == D3D_OK)
356 hr = d3ddev->BeginScene();
358 if (hr == D3D_OK)
359 {
360 if (hr == D3D_OK)
361 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
363 if (hr == D3D_OK)
364 hr = d3ddev->SetTexture(0, d3dTexture);
366 if (hr == D3D_OK)
367 hr = d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
369 if (hr == D3D_OK)
370 hr = d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
372 if (hr == D3D_OK)
373 hr = d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
375 if (hr == D3D_OK)
376 hr = d3ddev->SetTexture(0, NULL);
378 if (hr == D3D_OK)
379 hr = d3ddev->EndScene();
380 }
382 if (hr == D3D_OK)
383 hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL);
385 if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL)
386 PostMessage(ghwnd, WM_RESETD3D, 0, 0);
387 }
389 static void d3d_fs_blit_memtoscreen_8(int x, int y, int w, int h)
390 {
391 HRESULT hr = D3D_OK;
392 VOID* pVoid;
393 D3DLOCKED_RECT dr;
394 RECT window_rect;
395 uint32_t *p, *src;
396 int xx, yy;
397 double l, t, r, b;
399 d3d_verts[0].tu = d3d_verts[2].tu = d3d_verts[3].tu = 0;
400 d3d_verts[0].tv = d3d_verts[3].tv = d3d_verts[4].tv = 0;
401 d3d_verts[1].tu = d3d_verts[4].tu = d3d_verts[5].tu = (float)w / 2048.0;
402 d3d_verts[1].tv = d3d_verts[2].tv = d3d_verts[5].tv = (float)h / 2048.0;
404 GetClientRect(d3d_device_window, &window_rect);
405 d3d_fs_size(window_rect, &l, &t, &r, &b, w, h);
407 d3d_verts[0].x = l;
408 d3d_verts[0].y = t;
409 d3d_verts[1].x = r;
410 d3d_verts[1].y = b;
411 d3d_verts[2].x = l;
412 d3d_verts[2].y = b;
413 d3d_verts[3].x = l;
414 d3d_verts[3].y = t;
415 d3d_verts[4].x = r;
416 d3d_verts[4].y = t;
417 d3d_verts[5].x = r;
418 d3d_verts[5].y = b;
420 if (hr == D3D_OK)
421 hr = v_buffer->Lock(0, 0, (void**)&pVoid, 0);
422 if (hr == D3D_OK)
423 memcpy(pVoid, d3d_verts, sizeof(d3d_verts));
424 if (hr == D3D_OK)
425 hr = v_buffer->Unlock();
427 if (hr == D3D_OK)
428 {
429 RECT lock_rect;
431 lock_rect.top = 0;
432 lock_rect.left = 0;
433 lock_rect.bottom = 2047;
434 lock_rect.right = 2047;
436 if (FAILED(d3dTexture->LockRect(0, &dr, &lock_rect, 0)))
437 fatal("LockRect failed\n");
439 for (yy = 0; yy < h; yy++)
440 {
441 uint32_t *p = (uint32_t *)(dr.pBits + (yy * dr.Pitch));
442 if ((y + yy) >= 0 && (y + yy) < buffer->h)
443 {
444 for (xx = 0; xx < w; xx++)
445 p[xx] = pal_lookup[buffer->line[y + yy][x + xx]];
446 }
447 }
449 d3dTexture->UnlockRect(0);
450 }
452 if (hr == D3D_OK)
453 hr = d3ddev->BeginScene();
455 if (hr == D3D_OK)
456 {
457 if (hr == D3D_OK)
458 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);
460 if (hr == D3D_OK)
461 hr = d3ddev->SetTexture(0, d3dTexture);
463 if (hr == D3D_OK)
464 hr = d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
466 if (hr == D3D_OK)
467 hr = d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
469 if (hr == D3D_OK)
470 hr = d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
472 if (hr == D3D_OK)
473 hr = d3ddev->SetTexture(0, NULL);
475 if (hr == D3D_OK)
476 hr = d3ddev->EndScene();
477 }
479 if (hr == D3D_OK)
480 hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL);
482 if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL)
483 PostMessage(ghwnd, WM_RESETD3D, 0, 0);
484 }
