Advertisement
Guest User

ddrawd3d.c - Koopah's D3D Patch/Vivosku .162 edit

a guest
Jun 18th, 2015
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 93.47 KB | None | 0 0
  1. // license:BSD-3-Clause
  2. // copyright-holders:Aaron Giles
  3. //============================================================
  4. //
  5. // drawd3d.c - Win32 Direct3D implementation
  6. //
  7. //============================================================
  8.  
  9. // Useful info:
  10. // Windows XP/2003 shipped with DirectX 8.1
  11. // Windows 2000 shipped with DirectX 7a
  12. // Windows 98SE shipped with DirectX 6.1a
  13. // Windows 98 shipped with DirectX 5
  14. // Windows NT shipped with DirectX 3.0a
  15. // Windows 95 shipped with DirectX 2
  16.  
  17. // standard windows headers
  18. #define WIN32_LEAN_AND_MEAN
  19. #include <windows.h>
  20. #include <tchar.h>
  21. #include <mmsystem.h>
  22. #include <d3d9.h>
  23. #include <d3dx9.h>
  24. #include <math.h>
  25. #undef interface
  26.  
  27. // MAME headers
  28. #include "emu.h"
  29. #include "render.h"
  30. #include "ui/ui.h"
  31. #include "rendutil.h"
  32. #include "options.h"
  33. #include "emuopts.h"
  34. #include "aviio.h"
  35. #include "png.h"
  36.  
  37. // MAMEOS headers
  38. #include "modules/render/d3d/d3dintf.h"
  39. #include "winmain.h"
  40. #include "window.h"
  41. #include "config.h"
  42. #include "strconv.h"
  43. #include "modules/render/d3d/d3dcomm.h"
  44. #include "drawd3d.h"
  45.  
  46.  
  47.  
  48. //============================================================
  49. // DEBUGGING
  50. //============================================================
  51.  
  52. extern void mtlog_add(const char *event);
  53.  
  54.  
  55.  
  56. //============================================================
  57. // CONSTANTS
  58. //============================================================
  59.  
  60. #define ENABLE_BORDER_PIX (1)
  61.  
  62. enum
  63. {
  64. TEXTURE_TYPE_PLAIN,
  65. TEXTURE_TYPE_DYNAMIC,
  66. TEXTURE_TYPE_SURFACE
  67. };
  68.  
  69.  
  70.  
  71. //============================================================
  72. // MACROS
  73. //============================================================
  74.  
  75. #define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0)
  76.  
  77.  
  78.  
  79. //============================================================
  80. // GLOBALS
  81. //============================================================
  82.  
  83. static const line_aa_step line_aa_1step[] =
  84. {
  85. { 0.00f, 0.00f, 1.00f },
  86. { 0 }
  87. };
  88.  
  89. static const line_aa_step line_aa_4step[] =
  90. {
  91. { -0.25f, 0.00f, 0.25f },
  92. { 0.25f, 0.00f, 0.25f },
  93. { 0.00f, -0.25f, 0.25f },
  94. { 0.00f, 0.25f, 0.25f },
  95. { 0 }
  96. };
  97.  
  98. //============================================================
  99. // INLINES
  100. //============================================================
  101.  
  102. INLINE BOOL GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscreen)
  103. {
  104. static HMENU last_menu;
  105. static RECT last_rect;
  106. static RECT cached_rect;
  107. HMENU menu = GetMenu(hWnd);
  108. BOOL result = GetClientRect(hWnd, pRect);
  109.  
  110. if (!fullscreen || !menu)
  111. return result;
  112.  
  113. // to avoid flicker use cache if we can use
  114. if (last_menu != menu || memcmp(&last_rect, pRect, sizeof *pRect) != 0)
  115. {
  116. last_menu = menu;
  117. last_rect = *pRect;
  118.  
  119. SetMenu(hWnd, NULL);
  120. result = GetClientRect(hWnd, &cached_rect);
  121. SetMenu(hWnd, menu);
  122. }
  123.  
  124. *pRect = cached_rect;
  125. return result;
  126. }
  127.  
  128.  
  129. INLINE UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr)
  130. {
  131. /* original equations:
  132.  
  133. C = Y - 16
  134. D = Cb - 128
  135. E = Cr - 128
  136.  
  137. R = clip(( 298 * C + 409 * E + 128) >> 8)
  138. G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
  139. B = clip(( 298 * C + 516 * D + 128) >> 8)
  140.  
  141. R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8)
  142. G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8)
  143. B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8)
  144.  
  145. R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8)
  146. G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
  147. B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8)
  148.  
  149. R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8)
  150. G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
  151. B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8)
  152. */
  153. int r, g, b, common;
  154.  
  155. common = 298 * y - 298 * 16;
  156. r = (common + 409 * cr - 409 * 128 + 128) >> 8;
  157. g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8;
  158. b = (common + 516 * cb - 516 * 128 + 128) >> 8;
  159.  
  160. if (r < 0) r = 0;
  161. else if (r > 255) r = 255;
  162. if (g < 0) g = 0;
  163. else if (g > 255) g = 255;
  164. if (b < 0) b = 0;
  165. else if (b > 255) b = 255;
  166.  
  167. return rgb_t(0xff, r, g, b);
  168. }
  169.  
  170. //============================================================
  171. // drawd3d_init
  172. //============================================================
  173.  
  174. static d3d::base * d3dintf; // FIX ME
  175.  
  176. //============================================================
  177. // PROTOTYPES
  178. //============================================================
  179.  
  180. // core functions
  181. static void drawd3d_exit(void);
  182.  
  183.  
  184. //============================================================
  185. // drawd3d_window_init
  186. //============================================================
  187.  
  188. int d3d::renderer::create()
  189. {
  190. if (!initialize())
  191. {
  192. destroy();
  193. osd_printf_error("Unable to initialize Direct3D.\n");
  194. return 1;
  195. }
  196.  
  197. else
  198. {
  199. // set max update rate and bounds
  200. d3d::renderer::get_primitives();
  201. }
  202. return 0;
  203. }
  204.  
  205. //============================================================
  206. // drawd3d_exit
  207. //============================================================
  208.  
  209. static void drawd3d_exit(void)
  210. {
  211. if (d3dintf != NULL)
  212. (*d3dintf->d3d.release)(d3dintf);
  213. }
  214.  
  215. void d3d::renderer::toggle_fsfx()
  216. {
  217. set_restarting(true);
  218. }
  219.  
  220. void d3d::renderer::record()
  221. {
  222. get_shaders()->window_record();
  223. }
  224.  
  225. void d3d::renderer::save()
  226. {
  227. get_shaders()->window_save();
  228. }
  229.  
  230.  
  231.  
  232. //============================================================
  233. // drawd3d_window_destroy
  234. //============================================================
  235.  
  236. void d3d::renderer::destroy()
  237. {
  238. if (get_shaders() != NULL && get_shaders()->recording())
  239. get_shaders()->window_record();
  240.  
  241. }
  242.  
  243.  
  244.  
  245. //============================================================
  246. // drawd3d_window_get_primitives
  247. //============================================================
  248.  
  249. render_primitive_list *d3d::renderer::get_primitives()
  250. {
  251. RECT client;
  252.  
  253. GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen());
  254. if (rect_width(&client) > 0 && rect_height(&client) > 0)
  255. {
  256. window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect());
  257. window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh());
  258. }
  259. return &window().target()->get_primitives();
  260. }
  261.  
  262. //============================================================
  263. // drawnone_create
  264. //============================================================
  265.  
  266. static osd_renderer *drawd3d_create(osd_window *window)
  267. {
  268. return global_alloc(d3d::renderer(window));
  269. }
  270.  
  271. int drawd3d_init(running_machine &machine, osd_draw_callbacks *callbacks)
  272. {
  273. d3dintf = NULL;
  274.  
  275. // Use Direct3D9
  276. d3dintf = d3d::drawd3d9_init();
  277.  
  278. // if we failed, note the error
  279. if (d3dintf == NULL)
  280. {
  281. osd_printf_error("Unable to initialize Direct3D.\n");
  282. return 1;
  283. }
  284.  
  285. // fill in the callbacks
  286. memset(callbacks, 0, sizeof(*callbacks));
  287. callbacks->exit = drawd3d_exit;
  288. callbacks->create = drawd3d_create;
  289. return 0;
  290. }
  291.  
  292. //============================================================
  293. // drawd3d_window_draw
  294. //============================================================
  295.  
  296. int d3d::renderer::draw(const int update)
  297. {
  298. int check = pre_window_draw_check();
  299. if (check >= 0)
  300. return check;
  301.  
  302. begin_frame();
  303. process_primitives();
  304. end_frame();
  305.  
  306. return 0;
  307. }
  308.  
  309. namespace d3d
  310. {
  311. void renderer::set_texture(texture_info *texture)
  312. {
  313. if (texture != m_last_texture)
  314. {
  315. m_last_texture = texture;
  316. m_last_texture_flags = (texture == NULL ? 0 : texture->get_flags());
  317. HRESULT result = (*d3dintf->device.set_texture)(m_device, 0, (texture == NULL) ? get_default_texture()->get_finaltex() : texture->get_finaltex());
  318. m_shaders->set_texture(texture);
  319. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result);
  320. }
  321. }
  322.  
  323.  
  324. void renderer::set_filter(int filter)
  325. {
  326. if (filter != m_last_filter)
  327. {
  328. m_last_filter = filter;
  329. HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
  330. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  331. result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
  332. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  333. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
  334. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  335. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
  336. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  337. }
  338. }
  339.  
  340.  
  341. void renderer::set_wrap(D3DTEXTUREADDRESS wrap)
  342. {
  343. if (wrap != m_last_wrap)
  344. {
  345. m_last_wrap = wrap;
  346. HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap);
  347. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  348. result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap);
  349. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  350. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap);
  351. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  352. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap);
  353. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  354. }
  355. }
  356.  
  357.  
  358. void renderer::set_modmode(DWORD modmode)
  359. {
  360. if (modmode != m_last_modmode)
  361. {
  362. m_last_modmode = modmode;
  363. HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, modmode);
  364. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  365. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, modmode);
  366. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result);
  367. }
  368. }
  369.  
  370.  
  371. void renderer::set_blendmode(int blendmode)
  372. {
  373. int blendenable;
  374. int blendop;
  375. int blendsrc;
  376. int blenddst;
  377.  
  378. // choose the parameters
  379. switch (blendmode)
  380. {
  381. default:
  382. case BLENDMODE_NONE: blendenable = FALSE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break;
  383. case BLENDMODE_ALPHA: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break;
  384. case BLENDMODE_RGB_MULTIPLY: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_DESTCOLOR; blenddst = D3DBLEND_ZERO; break;
  385. case BLENDMODE_ADD: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_ONE; break;
  386. }
  387.  
  388. // adjust the bits that changed
  389. if (blendenable != m_last_blendenable)
  390. {
  391. m_last_blendenable = blendenable;
  392. HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHABLENDENABLE, blendenable);
  393. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result);
  394. }
  395.  
  396. if (blendop != m_last_blendop)
  397. {
  398. m_last_blendop = blendop;
  399. HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_BLENDOP, blendop);
  400. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result);
  401. }
  402.  
  403. if (blendsrc != m_last_blendsrc)
  404. {
  405. m_last_blendsrc = blendsrc;
  406. HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SRCBLEND, blendsrc);
  407. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result);
  408. }
  409.  
  410. if (blenddst != m_last_blenddst)
  411. {
  412. m_last_blenddst = blenddst;
  413. HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DESTBLEND, blenddst);
  414. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result);
  415. }
  416. }
  417.  
  418.  
  419. void renderer::reset_render_states()
  420. {
  421. // this ensures subsequent calls to the above setters will force-update the data
  422. m_last_texture = (texture_info *)~0;
  423. m_last_filter = -1;
  424. m_last_blendenable = -1;
  425. m_last_blendop = -1;
  426. m_last_blendsrc = -1;
  427. m_last_blenddst = -1;
  428. m_last_wrap = (D3DTEXTUREADDRESS)-1;
  429. }
  430.  
  431.  
  432.  
  433. texture_manager::texture_manager(renderer *d3d)
  434. {
  435. m_renderer = d3d;
  436.  
  437. m_texlist = NULL;
  438. m_vector_texture = NULL;
  439. m_default_texture = NULL;
  440.  
  441. // check for dynamic texture support
  442. DWORD tempcaps;
  443. HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps);
  444. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  445. m_dynamic_supported = ((tempcaps & D3DCAPS2_DYNAMICTEXTURES) != 0);
  446. if (m_dynamic_supported) osd_printf_verbose("Direct3D: Using dynamic textures\n");
  447.  
  448. // check for stretchrect support
  449. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_STRETCH_RECT_FILTER, &tempcaps);
  450. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  451. m_stretch_supported = ((tempcaps & D3DPTFILTERCAPS_MAGFPOINT) != 0);
  452. if (m_stretch_supported && video_config.prescale > 1) osd_printf_verbose("Direct3D: Using StretchRect for prescaling\n");
  453.  
  454. // get texture caps
  455. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_TEXTURE_CAPS, &m_texture_caps);
  456. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  457. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_ASPECT, &m_texture_max_aspect);
  458. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  459. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_WIDTH, &m_texture_max_width);
  460. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  461. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_HEIGHT, &m_texture_max_height);
  462. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  463.  
  464. // pick a YUV texture format
  465. m_yuv_format = D3DFMT_UYVY;
  466. result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY);
  467. if (result != D3D_OK)
  468. {
  469. m_yuv_format = D3DFMT_YUY2;
  470. result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2);
  471. if (result != D3D_OK)
  472. m_yuv_format = D3DFMT_A8R8G8B8;
  473. }
  474. osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB");
  475.  
  476. // set the max texture size
  477. d3d->window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height);
  478. osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height);
  479. }
  480.  
  481. texture_manager::~texture_manager()
  482. {
  483. }
  484.  
  485. void texture_manager::create_resources()
  486. {
  487. // experimental: load a PNG to use for vector rendering; it is treated
  488. // as a brightness map
  489. emu_file file(m_renderer->window().machine().options().art_path(), OPEN_FLAG_READ);
  490. render_load_png(m_vector_bitmap, file, NULL, "vector.png");
  491. if (m_vector_bitmap.valid())
  492. {
  493. m_vector_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff));
  494. render_load_png(m_vector_bitmap, file, NULL, "vector.png", true);
  495. }
  496.  
  497. m_default_bitmap.allocate(8, 8);
  498. m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff));
  499.  
  500. if (m_default_bitmap.valid())
  501. {
  502. render_texinfo texture;
  503.  
  504. // fake in the basic data so it looks like it came from render.c
  505. texture.base = m_default_bitmap.raw_pixptr(0);
  506. texture.rowpixels = m_default_bitmap.rowpixels();
  507. texture.width = m_default_bitmap.width();
  508. texture.height = m_default_bitmap.height();
  509. texture.palette = NULL;
  510. texture.seqid = 0;
  511.  
  512. // now create it
  513. m_default_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)));
  514. }
  515.  
  516. // experimental: if we have a vector bitmap, create a texture for it
  517. if (m_vector_bitmap.valid())
  518. {
  519. render_texinfo texture;
  520.  
  521. // fake in the basic data so it looks like it came from render.c
  522. texture.base = &m_vector_bitmap.pix32(0);
  523. texture.rowpixels = m_vector_bitmap.rowpixels();
  524. texture.width = m_vector_bitmap.width();
  525. texture.height = m_vector_bitmap.height();
  526. texture.palette = NULL;
  527. texture.seqid = 0;
  528.  
  529. // now create it
  530. m_vector_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)));
  531. }
  532. }
  533.  
  534. void texture_manager::delete_resources()
  535. {
  536. // is part of m_texlist and will be free'd there
  537. //global_free(m_default_texture);
  538. m_default_texture = NULL;
  539.  
  540. //global_free(m_vector_texture);
  541. m_vector_texture = NULL;
  542.  
  543. // free all textures
  544. while (m_texlist != NULL)
  545. {
  546. texture_info *tex = m_texlist;
  547. m_texlist = tex->get_next();
  548. global_free(tex);
  549. }
  550. }
  551.  
  552. UINT32 texture_manager::texture_compute_hash(const render_texinfo *texture, UINT32 flags)
  553. {
  554. return (FPTR)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK));
  555. }
  556.  
  557. texture_info *texture_manager::find_texinfo(const render_texinfo *texinfo, UINT32 flags)
  558. {
  559. UINT32 hash = texture_compute_hash(texinfo, flags);
  560. texture_info *texture;
  561.  
  562. // find a match
  563. for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next())
  564. {
  565. UINT32 test_screen = (UINT32)texture->get_texinfo().osddata >> 1;
  566. UINT32 test_page = (UINT32)texture->get_texinfo().osddata & 1;
  567. UINT32 prim_screen = (UINT32)texinfo->osddata >> 1;
  568. UINT32 prim_page = (UINT32)texinfo->osddata & 1;
  569. if (test_screen != prim_screen || test_page != prim_page)
  570. {
  571. continue;
  572. }
  573.  
  574. if (texture->get_hash() == hash &&
  575. texture->get_texinfo().base == texinfo->base &&
  576. texture->get_texinfo().width == texinfo->width &&
  577. texture->get_texinfo().height == texinfo->height &&
  578. ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0)
  579. {
  580. // Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache
  581. if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0)
  582. {
  583. if (m_renderer->get_shaders()->find_render_target(texture) != NULL)
  584. {
  585. return texture;
  586. }
  587. }
  588. else
  589. {
  590. return texture;
  591. }
  592. }
  593. }
  594.  
  595. // Nothing found, check if we need to unregister something with HLSL
  596. if (m_renderer->get_shaders()->enabled())
  597. {
  598. if (texinfo->width == 0 || texinfo->height == 0)
  599. {
  600. return NULL;
  601. }
  602.  
  603. UINT32 prim_screen = texinfo->osddata >> 1;
  604. UINT32 prim_page = texinfo->osddata & 1;
  605.  
  606. for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next())
  607. {
  608. UINT32 test_screen = texture->get_texinfo().osddata >> 1;
  609. UINT32 test_page = texture->get_texinfo().osddata & 1;
  610. if (test_screen != prim_screen || test_page != prim_page)
  611. {
  612. continue;
  613. }
  614.  
  615. // Clear out our old texture reference
  616. if (texture->get_hash() == hash &&
  617. texture->get_texinfo().base == texinfo->base &&
  618. ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 &&
  619. (texture->get_texinfo().width != texinfo->width ||
  620. texture->get_texinfo().height != texinfo->height))
  621. {
  622. m_renderer->get_shaders()->remove_render_target(texture);
  623. }
  624. }
  625. }
  626.  
  627. return NULL;
  628. }
  629.  
  630. renderer::renderer(osd_window *window)
  631. : osd_renderer(window, FLAG_NONE)
  632. {
  633. m_device = NULL;
  634. m_restarting = false;
  635. m_shaders = NULL;
  636. m_numverts = 0;
  637. m_numpolys = 0;
  638. m_vertexbuf = NULL;
  639. m_lockedbuf = NULL;
  640. m_vectorbatch = NULL;
  641. m_last_texture = NULL;
  642. m_hlsl_buf = NULL;
  643. m_texture_manager = NULL;
  644. }
  645.  
  646. int renderer::initialize()
  647. {
  648. // configure the adapter for the mode we want
  649. if (config_adapter_mode())
  650. return false;
  651.  
  652. // create the device immediately for the full screen case (defer for window mode)
  653. if (window().fullscreen() && device_create(window().m_focus_hwnd))
  654. return false;
  655.  
  656. return true;
  657. }
  658.  
  659. int renderer::pre_window_draw_check()
  660. {
  661. // if we're in the middle of resizing, leave things alone
  662. if (window().m_resize_state == RESIZE_STATE_RESIZING)
  663. return 0;
  664.  
  665. // if we're restarting the renderer, leave things alone
  666. if (m_restarting)
  667. {
  668. m_shaders->toggle();
  669.  
  670. // free all existing resources and re-create
  671. device_delete_resources();
  672. device_create_resources();
  673.  
  674. m_restarting = false;
  675. }
  676.  
  677. // if we have a device, check the cooperative level
  678. if (m_device != NULL)
  679. {
  680. if (device_test_cooperative())
  681. {
  682. return 1;
  683. }
  684. }
  685.  
  686. // in window mode, we need to track the window size
  687. if (!window().fullscreen() || m_device == NULL)
  688. {
  689. // if the size changes, skip this update since the render target will be out of date
  690. if (update_window_size())
  691. return 0;
  692.  
  693. // if we have no device, after updating the size, return an error so GDI can try
  694. if (m_device == NULL)
  695. return 1;
  696. }
  697.  
  698. return -1;
  699. }
  700.  
  701. void texture_manager::update_textures()
  702. {
  703. for (render_primitive *prim = m_renderer->window().m_primlist->first(); prim != NULL; prim = prim->next())
  704. {
  705. if (prim->texture.base != NULL)
  706. {
  707. texture_info *texture = find_texinfo(&prim->texture, prim->flags);
  708. if (texture == NULL)
  709. {
  710. // if there isn't one, create a new texture
  711. global_alloc(texture_info(this, &prim->texture, m_renderer->window().prescale(), prim->flags));
  712. }
  713. else
  714. {
  715. // if there is one, but with a different seqid, copy the data
  716. if (texture->get_texinfo().seqid != prim->texture.seqid)
  717. {
  718. texture->set_data(&prim->texture, prim->flags);
  719. texture->get_texinfo().seqid = prim->texture.seqid;
  720. }
  721. }
  722. }
  723. else if(m_renderer->get_shaders()->vector_enabled() && PRIMFLAG_GET_VECTORBUF(prim->flags))
  724. {
  725. if (!m_renderer->get_shaders()->get_vector_target())
  726. {
  727. m_renderer->get_shaders()->create_vector_target(prim);
  728. }
  729. }
  730. }
  731. }
  732.  
  733. void renderer::begin_frame()
  734. {
  735. HRESULT result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
  736. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result);
  737.  
  738. m_shaders->begin_frame();
  739.  
  740. window().m_primlist->acquire_lock();
  741.  
  742. // first update any textures
  743. m_texture_manager->update_textures();
  744.  
  745. // begin the scene
  746. mtlog_add("drawd3d_window_draw: begin_scene");
  747. result = (*d3dintf->device.begin_scene)(m_device);
  748. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result);
  749.  
  750. m_lockedbuf = NULL;
  751.  
  752. if(m_shaders->enabled())
  753. {
  754. m_hlsl_buf = (void*)mesh_alloc(6);
  755. m_shaders->init_fsfx_quad(m_hlsl_buf);
  756. }
  757.  
  758. m_line_count = 0;
  759.  
  760. // loop over primitives
  761. for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next())
  762. if (prim->type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim->flags))
  763. m_line_count++;
  764. }
  765.  
  766. void renderer::process_primitives()
  767. {
  768. // Rotating index for vector time offsets
  769. for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next())
  770. {
  771. switch (prim->type)
  772. {
  773. case render_primitive::LINE:
  774. if (PRIMFLAG_GET_VECTOR(prim->flags))
  775. {
  776. if (m_line_count > 0)
  777. batch_vectors();
  778. else
  779. continue;
  780. }
  781. else
  782. {
  783. draw_line(prim);
  784. }
  785. break;
  786.  
  787. case render_primitive::QUAD:
  788. draw_quad(prim);
  789. break;
  790.  
  791. default:
  792. throw emu_fatalerror("Unexpected render_primitive type");
  793. }
  794. }
  795. }
  796.  
  797. void renderer::end_frame()
  798. {
  799. window().m_primlist->release_lock();
  800.  
  801. // flush any pending polygons
  802. primitive_flush_pending();
  803.  
  804. m_shaders->end_frame();
  805.  
  806. // finish the scene
  807. HRESULT result = (*d3dintf->device.end_scene)(m_device);
  808. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result);
  809.  
  810. // present the current buffers
  811. result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0);
  812. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device present call\n", (int)result);
  813. }
  814.  
  815. //============================================================
  816. // device_create
  817. //============================================================
  818.  
  819. int renderer::device_create(HWND device_hwnd)
  820. {
  821. // if a device exists, free it
  822. if (m_device != NULL)
  823. device_delete();
  824.  
  825. // verify the caps
  826. int verify = device_verify_caps();
  827. if (verify == 2)
  828. {
  829. osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n");
  830. return 1;
  831. }
  832. if (verify == 1)
  833. osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n");
  834.  
  835. // verify texture formats
  836. HRESULT result = (*d3dintf->d3d.check_device_format)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
  837. if (result != D3D_OK)
  838. {
  839. osd_printf_error("Error: A8R8G8B8 format textures not supported\n");
  840. return 1;
  841. }
  842.  
  843. m_texture_manager = global_alloc(texture_manager(this));
  844.  
  845. try_again:
  846. // try for XRGB first
  847. m_screen_format = D3DFMT_X8R8G8B8;
  848. result = (*d3dintf->d3d.check_device_format)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format);
  849. if (result != D3D_OK)
  850. {
  851. // if not, try for ARGB
  852. m_screen_format = D3DFMT_A8R8G8B8;
  853. result = (*d3dintf->d3d.check_device_format)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format);
  854. if (result != D3D_OK && m_texture_manager->is_dynamic_supported())
  855. {
  856. m_texture_manager->set_dynamic_supported(FALSE);
  857. goto try_again;
  858. }
  859. if (result != D3D_OK)
  860. {
  861. osd_printf_error("Error: unable to configure a screen texture format\n");
  862. return 1;
  863. }
  864. }
  865.  
  866. // initialize the D3D presentation parameters
  867. memset(&m_presentation, 0, sizeof(m_presentation));
  868. m_presentation.BackBufferWidth = m_width;
  869. m_presentation.BackBufferHeight = m_height;
  870. m_presentation.BackBufferFormat = m_pixformat;
  871. m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1;
  872. m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
  873. m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
  874. m_presentation.hDeviceWindow = window().m_hwnd;
  875. m_presentation.Windowed = !window().fullscreen() || window().win_has_menu();
  876. m_presentation.EnableAutoDepthStencil = FALSE;
  877. m_presentation.AutoDepthStencilFormat = D3DFMT_D16;
  878. m_presentation.Flags = 0;
  879. m_presentation.FullScreen_RefreshRateInHz = m_refresh;
  880. m_presentation.PresentationInterval = ((video_config.triplebuf && window().fullscreen()) ||
  881. video_config.waitvsync || video_config.syncrefresh) ?
  882. D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
  883.  
  884. // create the D3D device
  885. result = (*d3dintf->d3d.create_device)(d3dintf, m_adapter, D3DDEVTYPE_HAL, device_hwnd,
  886. D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device);
  887. if (result != D3D_OK)
  888. {
  889. // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if
  890. // we exceed a threshold
  891. if (result == D3DERR_DEVICELOST)
  892. {
  893. m_create_error_count++;
  894. if (m_create_error_count < 10)
  895. {
  896. return 0;
  897. }
  898. }
  899.  
  900. // fatal error if we just can't do it
  901. osd_printf_error("Unable to create the Direct3D device (%08X)\n", (UINT32)result);
  902. return 1;
  903. }
  904. m_create_error_count = 0;
  905. osd_printf_verbose("Direct3D: Device created at %dx%d\n", m_width, m_height);
  906.  
  907. // set the gamma if we need to
  908. if (window().fullscreen())
  909. {
  910. // only set the gamma if it's not 1.0f
  911. windows_options &options = downcast<windows_options &>(window().machine().options());
  912. float brightness = options.full_screen_brightness();
  913. float contrast = options.full_screen_contrast();
  914. float gamma = options.full_screen_gamma();
  915. if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f)
  916. {
  917. // warn if we can't do it
  918. if (!m_gamma_supported)
  919. {
  920. osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n");
  921. }
  922. else
  923. {
  924. // create a standard ramp and set it
  925. D3DGAMMARAMP ramp;
  926. for (int i = 0; i < 256; i++)
  927. {
  928. ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8;
  929. }
  930. (*d3dintf->device.set_gamma_ramp)(m_device, 0, &ramp);
  931. }
  932. }
  933. }
  934.  
  935. int ret = m_shaders->create_resources(false);
  936. if (ret != 0)
  937. return ret;
  938.  
  939. return device_create_resources();
  940. }
  941.  
  942.  
  943.  
  944. //============================================================
  945. // device_create_resources
  946. //============================================================
  947.  
  948. int renderer::device_create_resources()
  949. {
  950. // allocate a vertex buffer to use
  951. HRESULT result = (*d3dintf->device.create_vertex_buffer)(m_device,
  952. sizeof(vertex) * VERTEX_BUFFER_SIZE,
  953. D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY,
  954. VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW),
  955. D3DPOOL_DEFAULT, &m_vertexbuf);
  956. if (result != D3D_OK)
  957. {
  958. osd_printf_error("Error creating vertex buffer (%08X)\n", (UINT32)result);
  959. return 1;
  960. }
  961.  
  962. // set the vertex format
  963. result = (*d3dintf->device.set_vertex_format)(m_device, (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() &&
  964. d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW)));
  965. if (result != D3D_OK)
  966. {
  967. osd_printf_error("Error setting vertex format (%08X)\n", (UINT32)result);
  968. return 1;
  969. }
  970.  
  971. // set the fixed render state
  972. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZENABLE, D3DZB_FALSE);
  973. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FILLMODE, D3DFILL_SOLID);
  974. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SHADEMODE, D3DSHADE_FLAT);
  975. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZWRITEENABLE, FALSE);
  976. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHATESTENABLE, TRUE);
  977. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LASTPIXEL, TRUE);
  978. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CULLMODE, D3DCULL_NONE);
  979. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZFUNC, D3DCMP_LESS);
  980. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAREF, 0);
  981. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
  982. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DITHERENABLE, FALSE);
  983. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FOGENABLE, FALSE);
  984. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SPECULARENABLE, FALSE);
  985. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_STENCILENABLE, FALSE);
  986. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_WRAP0, FALSE);
  987. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CLIPPING, TRUE);
  988. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LIGHTING, FALSE);
  989. result = (*d3dintf->device.set_render_state)(m_device, D3DRS_COLORVERTEX, TRUE);
  990.  
  991. result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  992. result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  993. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
  994. result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  995.  
  996. // reset the local states to force updates
  997. reset_render_states();
  998.  
  999. // clear the buffer
  1000. result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0);
  1001. result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0);
  1002.  
  1003. m_texture_manager->create_resources();
  1004.  
  1005. return 0;
  1006. }
  1007.  
  1008.  
  1009.  
  1010. //============================================================
  1011. // device_delete
  1012. //============================================================
  1013.  
  1014. renderer::~renderer()
  1015. {
  1016. device_delete();
  1017. }
  1018.  
  1019. void renderer::device_delete()
  1020. {
  1021. if (m_shaders != NULL)
  1022. {
  1023. // free our effects
  1024. m_shaders->delete_resources(false);
  1025.  
  1026. // delete the HLSL interface
  1027. global_free(m_shaders);
  1028. }
  1029.  
  1030. // free our base resources
  1031. device_delete_resources();
  1032.  
  1033. if (m_texture_manager != NULL)
  1034. {
  1035. global_free(m_texture_manager);
  1036. }
  1037. m_texture_manager = NULL;
  1038.  
  1039. // free the device itself
  1040. if (m_device != NULL)
  1041. {
  1042. (*d3dintf->device.reset)(m_device, &m_presentation);
  1043. (*d3dintf->device.release)(m_device);
  1044. }
  1045. m_device = NULL;
  1046. }
  1047.  
  1048. //============================================================
  1049. // device_delete_resources
  1050. //============================================================
  1051.  
  1052. void renderer::device_delete_resources()
  1053. {
  1054. if (m_texture_manager != NULL)
  1055. m_texture_manager->delete_resources();
  1056. // free the vertex buffer
  1057. if (m_vertexbuf != NULL)
  1058. (*d3dintf->vertexbuf.release)(m_vertexbuf);
  1059. m_vertexbuf = NULL;
  1060. }
  1061.  
  1062.  
  1063.  
  1064. //============================================================
  1065. // device_verify_caps
  1066. //============================================================
  1067.  
  1068. int renderer::device_verify_caps()
  1069. {
  1070. int retval = 0;
  1071.  
  1072. m_shaders = global_alloc_clear(shaders);
  1073. // FIXME: Dynamic cast
  1074. m_shaders->init(d3dintf, &window().machine(), this);
  1075.  
  1076. DWORD tempcaps;
  1077. HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_MAX_PS30_INSN_SLOTS, &tempcaps);
  1078. if (result != D3D_OK) osd_printf_verbose("Direct3D Error %08X during get_caps_dword call\n", (int)result);
  1079. if (tempcaps < 512)
  1080. {
  1081. osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n");
  1082. d3dintf->post_fx_available = false;
  1083. }
  1084.  
  1085. // verify presentation capabilities
  1086. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_PRESENTATION_INTERVALS, &tempcaps);
  1087. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  1088. if (!(tempcaps & D3DPRESENT_INTERVAL_IMMEDIATE))
  1089. {
  1090. osd_printf_verbose("Direct3D: Error - Device does not support immediate presentations\n");
  1091. retval = 2;
  1092. }
  1093. if (!(tempcaps & D3DPRESENT_INTERVAL_ONE))
  1094. {
  1095. osd_printf_verbose("Direct3D: Error - Device does not support per-refresh presentations\n");
  1096. retval = 2;
  1097. }
  1098.  
  1099. // verify device capabilities
  1100. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_DEV_CAPS, &tempcaps);
  1101. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  1102. if (!(tempcaps & D3DDEVCAPS_CANRENDERAFTERFLIP))
  1103. {
  1104. osd_printf_verbose("Direct3D: Warning - Device does not support queued rendering after a page flip\n");
  1105. retval = 1;
  1106. }
  1107. if (!(tempcaps & D3DDEVCAPS_HWRASTERIZATION))
  1108. {
  1109. osd_printf_verbose("Direct3D: Warning - Device does not support hardware rasterization\n");
  1110. retval = 1;
  1111. }
  1112.  
  1113. // verify texture operation capabilities
  1114. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_TEXTURE_OP_CAPS, &tempcaps);
  1115. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  1116. if (!(tempcaps & D3DTEXOPCAPS_MODULATE))
  1117. {
  1118. osd_printf_verbose("Direct3D: Warning - Device does not support texture modulation\n");
  1119. retval = 1;
  1120. }
  1121.  
  1122. // set a simpler flag to indicate mod2x and mod4x texture modes
  1123. m_mod2x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE2X) != 0);
  1124. m_mod4x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE4X) != 0);
  1125.  
  1126. result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps);
  1127. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result);
  1128. m_gamma_supported = ((tempcaps & D3DCAPS2_FULLSCREENGAMMA) != 0);
  1129.  
  1130. return retval;
  1131. }
  1132.  
  1133.  
  1134.  
  1135. //============================================================
  1136. // device_test_cooperative
  1137. //============================================================
  1138.  
  1139. int renderer::device_test_cooperative()
  1140. {
  1141. // check our current status; if we lost the device, punt to GDI
  1142. HRESULT result = (*d3dintf->device.test_cooperative_level)(m_device);
  1143. if (result == D3DERR_DEVICELOST)
  1144. return 1;
  1145.  
  1146. // if we're able to reset ourselves, try it
  1147. if (result == D3DERR_DEVICENOTRESET)
  1148. {
  1149. osd_printf_verbose("Direct3D: resetting device\n");
  1150.  
  1151. // free all existing resources and call reset on the device
  1152. //device_delete();
  1153. device_delete_resources();
  1154. m_shaders->delete_resources(true);
  1155. result = (*d3dintf->device.reset)(m_device, &m_presentation);
  1156.  
  1157. // if it didn't work, punt to GDI
  1158. if (result != D3D_OK)
  1159. {
  1160. osd_printf_error("Unable to reset, result %08x\n", (UINT32)result);
  1161. return 1;
  1162. }
  1163.  
  1164. // try to create the resources again; if that didn't work, delete the whole thing
  1165. if (device_create_resources())
  1166. {
  1167. osd_printf_verbose("Direct3D: failed to recreate resources for device; failing permanently\n");
  1168. device_delete();
  1169. return 1;
  1170. }
  1171.  
  1172. if (m_shaders->create_resources(true))
  1173. {
  1174. osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n");
  1175. device_delete();
  1176. return 1;
  1177. }
  1178. }
  1179. return 0;
  1180. }
  1181.  
  1182.  
  1183.  
  1184. //============================================================
  1185. // config_adapter_mode
  1186. //============================================================
  1187.  
  1188. int renderer::config_adapter_mode()
  1189. {
  1190. adapter_identifier identifier;
  1191.  
  1192. // choose the monitor number
  1193. m_adapter = get_adapter_for_monitor();
  1194.  
  1195. // get the identifier
  1196. HRESULT result = (*d3dintf->d3d.get_adapter_identifier)(d3dintf, m_adapter, 0, &identifier);
  1197. if (result != D3D_OK)
  1198. {
  1199. osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter);
  1200. return 1;
  1201. }
  1202. osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, identifier.Description);
  1203.  
  1204. // get the current display mode
  1205. result = (*d3dintf->d3d.get_adapter_display_mode)(d3dintf, m_adapter, &m_origmode);
  1206. if (result != D3D_OK)
  1207. {
  1208. osd_printf_error("Error getting mode for adapter #%d\n", m_adapter);
  1209. return 1;
  1210. }
  1211.  
  1212. // choose a resolution: window mode case
  1213. if (!window().fullscreen() || !video_config.switchres || window().win_has_menu())
  1214. {
  1215. RECT client;
  1216.  
  1217. // bounds are from the window client rect
  1218. GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen());
  1219. m_width = client.right - client.left;
  1220. m_height = client.bottom - client.top;
  1221.  
  1222. // pix format is from the current mode
  1223. m_pixformat = m_origmode.Format;
  1224. m_refresh = 0;
  1225.  
  1226. // make sure it's a pixel format we can get behind
  1227. if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8)
  1228. {
  1229. osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename());
  1230. return 1;
  1231. }
  1232. }
  1233.  
  1234. // choose a resolution: full screen mode case
  1235. else
  1236. {
  1237. // default to the current mode exactly
  1238. m_width = m_origmode.Width;
  1239. m_height = m_origmode.Height;
  1240. m_pixformat = m_origmode.Format;
  1241. m_refresh = m_origmode.RefreshRate;
  1242.  
  1243. // if we're allowed to switch resolutions, override with something better
  1244. if (video_config.switchres)
  1245. pick_best_mode();
  1246. }
  1247.  
  1248. // see if we can handle the device type
  1249. result = (*d3dintf->d3d.check_device_type)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen());
  1250. if (result != D3D_OK)
  1251. {
  1252. osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename());
  1253. return 1;
  1254. }
  1255. return 0;
  1256. }
  1257.  
  1258.  
  1259.  
  1260. //============================================================
  1261. // get_adapter_for_monitor
  1262. //============================================================
  1263.  
  1264. int renderer::get_adapter_for_monitor()
  1265. {
  1266. int maxadapter = (*d3dintf->d3d.get_adapter_count)(d3dintf);
  1267.  
  1268. // iterate over adapters until we error or find a match
  1269. for (int adapternum = 0; adapternum < maxadapter; adapternum++)
  1270. {
  1271. // get the monitor for this adapter
  1272. HMONITOR curmonitor = (*d3dintf->d3d.get_adapter_monitor)(d3dintf, adapternum);
  1273.  
  1274. // if we match the proposed monitor, this is it
  1275. if (curmonitor == *((HMONITOR *)window().monitor()->oshandle()))
  1276. {
  1277. return adapternum;
  1278. }
  1279. }
  1280.  
  1281. // default to the default
  1282. return D3DADAPTER_DEFAULT;
  1283. }
  1284.  
  1285.  
  1286.  
  1287. //============================================================
  1288. // pick_best_mode
  1289. //============================================================
  1290.  
  1291. void renderer::pick_best_mode()
  1292. {
  1293. double target_refresh = 60.0;
  1294. INT32 minwidth, minheight;
  1295. float best_score = 0.0f;
  1296.  
  1297. // determine the refresh rate of the primary screen
  1298. const screen_device *primary_screen = window().machine().config().first_screen();
  1299. if (primary_screen != NULL)
  1300. {
  1301. target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds());
  1302. }
  1303.  
  1304. // determine the minimum width/height for the selected target
  1305. // note: technically we should not be calling this from an alternate window
  1306. // thread; however, it is only done during init time, and the init code on
  1307. // the main thread is waiting for us to finish, so it is safe to do so here
  1308. window().target()->compute_minimum_size(minwidth, minheight);
  1309.  
  1310. // use those as the target for now
  1311. INT32 target_width = minwidth;
  1312. INT32 target_height = minheight;
  1313.  
  1314. // determine the maximum number of modes
  1315. int maxmodes = (*d3dintf->d3d.get_adapter_mode_count)(d3dintf, m_adapter, D3DFMT_X8R8G8B8);
  1316.  
  1317. // enumerate all the video modes and find the best match
  1318. osd_printf_verbose("Direct3D: Selecting video mode...\n");
  1319. for (int modenum = 0; modenum < maxmodes; modenum++)
  1320. {
  1321. // check this mode
  1322. D3DDISPLAYMODE mode;
  1323. HRESULT result = (*d3dintf->d3d.enum_adapter_modes)(d3dintf, m_adapter, D3DFMT_X8R8G8B8, modenum, &mode);
  1324. if (result != D3D_OK)
  1325. break;
  1326.  
  1327. // skip non-32 bit modes
  1328. if (mode.Format != D3DFMT_X8R8G8B8)
  1329. continue;
  1330.  
  1331. // compute initial score based on difference between target and current
  1332. float size_score = 1.0f / (1.0f + fabs((float)(mode.Width - target_width)) + fabs((float)(mode.Height - target_height)));
  1333.  
  1334. // if the mode is too small, give a big penalty
  1335. if (mode.Width < minwidth || mode.Height < minheight)
  1336. size_score *= 0.01f;
  1337.  
  1338. // if mode is smaller than we'd like, it only scores up to 0.1
  1339. if (mode.Width < target_width || mode.Height < target_height)
  1340. size_score *= 0.1f;
  1341.  
  1342. // if we're looking for a particular mode, that's a winner
  1343. if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height)
  1344. size_score = 2.0f;
  1345.  
  1346. // compute refresh score
  1347. float refresh_score = 1.0f / (1.0f + fabs((double)mode.RefreshRate - target_refresh));
  1348.  
  1349. // if refresh is smaller than we'd like, it only scores up to 0.1
  1350. if ((double)mode.RefreshRate < target_refresh)
  1351. refresh_score *= 0.1f;
  1352.  
  1353. // if we're looking for a particular refresh, make sure it matches
  1354. if (mode.RefreshRate == window().m_win_config.refresh)
  1355. refresh_score = 2.0f;
  1356.  
  1357. // weight size and refresh equally
  1358. float final_score = size_score + refresh_score;
  1359.  
  1360. // best so far?
  1361. osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", mode.Width, mode.Height, mode.RefreshRate, final_score * 1000.0f);
  1362. if (final_score > best_score)
  1363. {
  1364. best_score = final_score;
  1365. m_width = mode.Width;
  1366. m_height = mode.Height;
  1367. m_pixformat = mode.Format;
  1368. m_refresh = mode.RefreshRate;
  1369. }
  1370. }
  1371. osd_printf_verbose("Direct3D: Mode selected = %4dx%4d@%3dHz\n", m_width, m_height, m_refresh);
  1372. }
  1373.  
  1374.  
  1375.  
  1376. //============================================================
  1377. // update_window_size
  1378. //============================================================
  1379.  
  1380. int renderer::update_window_size()
  1381. {
  1382. // get the current window bounds
  1383. RECT client;
  1384. GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen());
  1385.  
  1386. // if we have a device and matching width/height, nothing to do
  1387. if (m_device != NULL && rect_width(&client) == m_width && rect_height(&client) == m_height)
  1388. {
  1389. // clear out any pending resizing if the area didn't change
  1390. if (window().m_resize_state == RESIZE_STATE_PENDING)
  1391. window().m_resize_state = RESIZE_STATE_NORMAL;
  1392. return FALSE;
  1393. }
  1394.  
  1395. // if we're in the middle of resizing, leave it alone as well
  1396. if (window().m_resize_state == RESIZE_STATE_RESIZING)
  1397. return FALSE;
  1398.  
  1399. // set the new bounds and create the device again
  1400. m_width = rect_width(&client);
  1401. m_height = rect_height(&client);
  1402. if (device_create(window().m_focus_hwnd))
  1403. return FALSE;
  1404.  
  1405. // reset the resize state to normal, and indicate we made a change
  1406. window().m_resize_state = RESIZE_STATE_NORMAL;
  1407. return TRUE;
  1408. }
  1409.  
  1410. //============================================================
  1411. // batch_vectors
  1412. //============================================================
  1413.  
  1414. void renderer::batch_vectors()
  1415. {
  1416. windows_options &options = downcast<windows_options &>(window().machine().options());
  1417.  
  1418. int vector_size = (options.antialias() ? 24 : 6);
  1419. m_vectorbatch = mesh_alloc(m_line_count * vector_size);
  1420. m_batchindex = 0;
  1421.  
  1422. static int start_index = 0;
  1423. int line_index = 0;
  1424. float period = options.screen_vector_time_period();
  1425. UINT32 cached_flags = 0;
  1426. for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next())
  1427. {
  1428. switch (prim->type)
  1429. {
  1430. case render_primitive::LINE:
  1431. if (PRIMFLAG_GET_VECTOR(prim->flags))
  1432. {
  1433. if (period == 0.0f || m_line_count == 0)
  1434. {
  1435. batch_vector(prim, 1.0f);
  1436. }
  1437. else
  1438. {
  1439. batch_vector(prim, (float)(start_index + line_index) / ((float)m_line_count * period));
  1440. line_index++;
  1441. }
  1442. cached_flags = prim->flags;
  1443. }
  1444. break;
  1445.  
  1446. default:
  1447. // Skip
  1448. break;
  1449. }
  1450. }
  1451.  
  1452. // now add a polygon entry
  1453. m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, m_line_count * (options.antialias() ? 8 : 2), vector_size * m_line_count, cached_flags,
  1454. m_texture_manager->get_vector_texture(), D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f);
  1455. m_numpolys++;
  1456.  
  1457. start_index += (int)((float)line_index * period);
  1458. if (m_line_count > 0)
  1459. {
  1460. start_index %= m_line_count;
  1461. }
  1462.  
  1463. m_line_count = 0;
  1464. }
  1465.  
  1466. void renderer::batch_vector(const render_primitive *prim, float line_time)
  1467. {
  1468. // compute the effective width based on the direction of the line
  1469. float effwidth = prim->width;
  1470. if (effwidth < 0.5f)
  1471. {
  1472. effwidth = 0.5f;
  1473. }
  1474.  
  1475. // determine the bounds of a quad to draw this line
  1476. render_bounds b0, b1;
  1477. render_line_to_quad(&prim->bounds, effwidth, &b0, &b1);
  1478.  
  1479. // iterate over AA steps
  1480. for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step;
  1481. step->weight != 0; step++)
  1482. {
  1483. // get a pointer to the vertex buffer
  1484. if (m_vectorbatch == NULL)
  1485. return;
  1486.  
  1487. m_vectorbatch[m_batchindex + 0].x = b0.x0 + step->xoffs;
  1488. m_vectorbatch[m_batchindex + 0].y = b0.y0 + step->yoffs;
  1489. m_vectorbatch[m_batchindex + 1].x = b0.x1 + step->xoffs;
  1490. m_vectorbatch[m_batchindex + 1].y = b0.y1 + step->yoffs;
  1491. m_vectorbatch[m_batchindex + 2].x = b1.x0 + step->xoffs;
  1492. m_vectorbatch[m_batchindex + 2].y = b1.y0 + step->yoffs;
  1493.  
  1494. m_vectorbatch[m_batchindex + 3].x = b0.x1 + step->xoffs;
  1495. m_vectorbatch[m_batchindex + 3].y = b0.y1 + step->yoffs;
  1496. m_vectorbatch[m_batchindex + 4].x = b1.x0 + step->xoffs;
  1497. m_vectorbatch[m_batchindex + 4].y = b1.y0 + step->yoffs;
  1498. m_vectorbatch[m_batchindex + 5].x = b1.x1 + step->xoffs;
  1499. m_vectorbatch[m_batchindex + 5].y = b1.y1 + step->yoffs;
  1500.  
  1501. float dx = b1.x1 - b0.x1;
  1502. float dy = b1.y1 - b0.y1;
  1503. float line_length = sqrtf(dx * dx + dy * dy);
  1504.  
  1505. // determine the color of the line
  1506. INT32 r = (INT32)(prim->color.r * step->weight * 255.0f);
  1507. INT32 g = (INT32)(prim->color.g * step->weight * 255.0f);
  1508. INT32 b = (INT32)(prim->color.b * step->weight * 255.0f);
  1509. INT32 a = (INT32)(prim->color.a * 255.0f);
  1510. if (r > 255 || g > 255 || b > 255)
  1511. {
  1512. if (r > 2*255 || g > 2*255 || b > 2*255)
  1513. {
  1514. r >>= 2; g >>= 2; b >>= 2;
  1515. }
  1516. else
  1517. {
  1518. r >>= 1; g >>= 1; b >>= 1;
  1519. }
  1520. }
  1521. if (r > 255) r = 255;
  1522. if (g > 255) g = 255;
  1523. if (b > 255) b = 255;
  1524. if (a > 255) a = 255;
  1525. DWORD color = D3DCOLOR_ARGB(a, r, g, b);
  1526.  
  1527. vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart());
  1528. vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop());
  1529.  
  1530. m_vectorbatch[m_batchindex + 0].u0 = start.c.x;
  1531. m_vectorbatch[m_batchindex + 0].v0 = start.c.y;
  1532. m_vectorbatch[m_batchindex + 1].u0 = start.c.x;
  1533. m_vectorbatch[m_batchindex + 1].v0 = stop.c.y;
  1534. m_vectorbatch[m_batchindex + 2].u0 = stop.c.x;
  1535. m_vectorbatch[m_batchindex + 2].v0 = start.c.y;
  1536.  
  1537. m_vectorbatch[m_batchindex + 3].u0 = start.c.x;
  1538. m_vectorbatch[m_batchindex + 3].v0 = stop.c.y;
  1539. m_vectorbatch[m_batchindex + 4].u0 = stop.c.x;
  1540. m_vectorbatch[m_batchindex + 4].v0 = start.c.y;
  1541. m_vectorbatch[m_batchindex + 5].u0 = stop.c.x;
  1542. m_vectorbatch[m_batchindex + 5].v0 = stop.c.y;
  1543.  
  1544. m_vectorbatch[m_batchindex + 0].u1 = line_length;
  1545. m_vectorbatch[m_batchindex + 1].u1 = line_length;
  1546. m_vectorbatch[m_batchindex + 2].u1 = line_length;
  1547. m_vectorbatch[m_batchindex + 3].u1 = line_length;
  1548. m_vectorbatch[m_batchindex + 4].u1 = line_length;
  1549. m_vectorbatch[m_batchindex + 5].u1 = line_length;
  1550.  
  1551. // set the color, Z parameters to standard values
  1552. for (int i = 0; i < 6; i++)
  1553. {
  1554. m_vectorbatch[m_batchindex + i].z = 0.0f;
  1555. m_vectorbatch[m_batchindex + i].rhw = 1.0f;
  1556. m_vectorbatch[m_batchindex + i].color = color;
  1557. }
  1558.  
  1559. m_batchindex += 6;
  1560. }
  1561. }
  1562.  
  1563. //============================================================
  1564. // draw_line
  1565. //============================================================
  1566.  
  1567. void renderer::draw_line(const render_primitive *prim)
  1568. {
  1569. // compute the effective width based on the direction of the line
  1570. float effwidth = prim->width;
  1571. if (effwidth < 0.5f)
  1572. {
  1573. effwidth = 0.5f;
  1574. }
  1575.  
  1576. // determine the bounds of a quad to draw this line
  1577. render_bounds b0, b1;
  1578. render_line_to_quad(&prim->bounds, effwidth, &b0, &b1);
  1579.  
  1580. // iterate over AA steps
  1581. for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step;
  1582. step->weight != 0; step++)
  1583. {
  1584. // get a pointer to the vertex buffer
  1585. vertex *vertex = mesh_alloc(4);
  1586. if (vertex == NULL)
  1587. return;
  1588.  
  1589. // rotate the unit vector by 135 degrees and add to point 0
  1590. vertex[0].x = b0.x0 + step->xoffs;
  1591. vertex[0].y = b0.y0 + step->yoffs;
  1592.  
  1593. // rotate the unit vector by -135 degrees and add to point 0
  1594. vertex[1].x = b0.x1 + step->xoffs;
  1595. vertex[1].y = b0.y1 + step->yoffs;
  1596.  
  1597. // rotate the unit vector by 45 degrees and add to point 1
  1598. vertex[2].x = b1.x0 + step->xoffs;
  1599. vertex[2].y = b1.y0 + step->yoffs;
  1600.  
  1601. // rotate the unit vector by -45 degrees and add to point 1
  1602. vertex[3].x = b1.x1 + step->xoffs;
  1603. vertex[3].y = b1.y1 + step->yoffs;
  1604.  
  1605. // determine the color of the line
  1606. INT32 r = (INT32)(prim->color.r * step->weight * 255.0f);
  1607. INT32 g = (INT32)(prim->color.g * step->weight * 255.0f);
  1608. INT32 b = (INT32)(prim->color.b * step->weight * 255.0f);
  1609. INT32 a = (INT32)(prim->color.a * 255.0f);
  1610. if (r > 255) r = 255;
  1611. if (g > 255) g = 255;
  1612. if (b > 255) b = 255;
  1613. if (a > 255) a = 255;
  1614. DWORD color = D3DCOLOR_ARGB(a, r, g, b);
  1615.  
  1616. vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart());
  1617. vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop());
  1618.  
  1619. vertex[0].u0 = start.c.x;
  1620. vertex[0].v0 = start.c.y;
  1621.  
  1622. vertex[2].u0 = stop.c.x;
  1623. vertex[2].v0 = start.c.y;
  1624.  
  1625. vertex[1].u0 = start.c.x;
  1626. vertex[1].v0 = stop.c.y;
  1627.  
  1628. vertex[3].u0 = stop.c.x;
  1629. vertex[3].v0 = stop.c.y;
  1630.  
  1631. // set the color, Z parameters to standard values
  1632. for (int i = 0; i < 4; i++)
  1633. {
  1634. vertex[i].z = 0.0f;
  1635. vertex[i].rhw = 1.0f;
  1636. vertex[i].color = color;
  1637. }
  1638.  
  1639. // now add a polygon entry
  1640. m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, get_vector_texture(),
  1641. D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f);
  1642. m_numpolys++;
  1643. }
  1644. }
  1645.  
  1646.  
  1647.  
  1648. //============================================================
  1649. // draw_quad
  1650. //============================================================
  1651.  
  1652. void renderer::draw_quad(const render_primitive *prim)
  1653. {
  1654. texture_info *texture = m_texture_manager->find_texinfo(&prim->texture, prim->flags);
  1655.  
  1656. if (texture == NULL)
  1657. {
  1658. texture = get_default_texture();
  1659. }
  1660.  
  1661. // get a pointer to the vertex buffer
  1662. vertex *vertex = mesh_alloc(4);
  1663. if (vertex == NULL)
  1664. return;
  1665.  
  1666. // fill in the vertexes clockwise
  1667. vertex[0].x = prim->bounds.x0;
  1668. vertex[0].y = prim->bounds.y0;
  1669. vertex[1].x = prim->bounds.x1;
  1670. vertex[1].y = prim->bounds.y0;
  1671. vertex[2].x = prim->bounds.x0;
  1672. vertex[2].y = prim->bounds.y1;
  1673. vertex[3].x = prim->bounds.x1;
  1674. vertex[3].y = prim->bounds.y1;
  1675. float width = prim->bounds.x1 - prim->bounds.x0;
  1676. float height = prim->bounds.y1 - prim->bounds.y0;
  1677.  
  1678. // set the texture coordinates
  1679. if(texture != NULL)
  1680. {
  1681. vec2f& start = texture->get_uvstart();
  1682. vec2f& stop = texture->get_uvstop();
  1683. vec2f delta = stop - start;
  1684. vertex[0].u0 = start.c.x + delta.c.x * prim->texcoords.tl.u;
  1685. vertex[0].v0 = start.c.y + delta.c.y * prim->texcoords.tl.v;
  1686. vertex[1].u0 = start.c.x + delta.c.x * prim->texcoords.tr.u;
  1687. vertex[1].v0 = start.c.y + delta.c.y * prim->texcoords.tr.v;
  1688. vertex[2].u0 = start.c.x + delta.c.x * prim->texcoords.bl.u;
  1689. vertex[2].v0 = start.c.y + delta.c.y * prim->texcoords.bl.v;
  1690. vertex[3].u0 = start.c.x + delta.c.x * prim->texcoords.br.u;
  1691. vertex[3].v0 = start.c.y + delta.c.y * prim->texcoords.br.v;
  1692. }
  1693.  
  1694. // determine the color, allowing for over modulation
  1695. INT32 r = (INT32)(prim->color.r * 255.0f);
  1696. INT32 g = (INT32)(prim->color.g * 255.0f);
  1697. INT32 b = (INT32)(prim->color.b * 255.0f);
  1698. INT32 a = (INT32)(prim->color.a * 255.0f);
  1699. DWORD modmode = D3DTOP_MODULATE;
  1700. if (texture != NULL)
  1701. {
  1702. if (m_mod2x_supported && (r > 255 || g > 255 || b > 255))
  1703. {
  1704. if (m_mod4x_supported && (r > 2*255 || g > 2*255 || b > 2*255))
  1705. {
  1706. r >>= 2; g >>= 2; b >>= 2;
  1707. modmode = D3DTOP_MODULATE4X;
  1708. }
  1709. else
  1710. {
  1711. r >>= 1; g >>= 1; b >>= 1;
  1712. modmode = D3DTOP_MODULATE2X;
  1713. }
  1714. }
  1715. }
  1716. if (r > 255) r = 255;
  1717. if (g > 255) g = 255;
  1718. if (b > 255) b = 255;
  1719. if (a > 255) a = 255;
  1720. DWORD color = D3DCOLOR_ARGB(a, r, g, b);
  1721.  
  1722. // adjust half pixel X/Y offset, set the color, Z parameters to standard values
  1723. for (int i = 0; i < 4; i++)
  1724. {
  1725. vertex[i].x -= 0.5f;
  1726. vertex[i].y -= 0.5f;
  1727. vertex[i].z = 0.0f;
  1728. vertex[i].rhw = 1.0f;
  1729. vertex[i].color = color;
  1730. }
  1731.  
  1732. // now add a polygon entry
  1733. m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, texture, modmode, width, height);
  1734. m_numpolys++;
  1735. }
  1736.  
  1737. void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts,
  1738. UINT32 flags, texture_info *texture, UINT32 modmode,
  1739. float line_time, float line_length,
  1740. float prim_width, float prim_height)
  1741. {
  1742. init(type, count, numverts, flags, texture, modmode, prim_width, prim_height);
  1743. m_line_time = line_time;
  1744. m_line_length = line_length;
  1745. }
  1746.  
  1747. void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts,
  1748. UINT32 flags, texture_info *texture, UINT32 modmode,
  1749. float prim_width, float prim_height)
  1750. {
  1751. m_type = type;
  1752. m_count = count;
  1753. m_numverts = numverts;
  1754. m_flags = flags;
  1755. m_texture = texture;
  1756. m_modmode = modmode;
  1757. m_prim_width = prim_width;
  1758. m_prim_height = prim_height;
  1759. }
  1760.  
  1761. //============================================================
  1762. // primitive_alloc
  1763. //============================================================
  1764.  
  1765. vertex *renderer::mesh_alloc(int numverts)
  1766. {
  1767. HRESULT result;
  1768.  
  1769. // if we're going to overflow, flush
  1770. if (m_lockedbuf != NULL && m_numverts + numverts >= VERTEX_BUFFER_SIZE)
  1771. {
  1772. primitive_flush_pending();
  1773.  
  1774. if(m_shaders->enabled())
  1775. {
  1776. m_hlsl_buf = (void*)mesh_alloc(6);
  1777. m_shaders->init_fsfx_quad(m_hlsl_buf);
  1778. }
  1779. }
  1780.  
  1781. // if we don't have a lock, grab it now
  1782. if (m_lockedbuf == NULL)
  1783. {
  1784. result = (*d3dintf->vertexbuf.lock)(m_vertexbuf, 0, 0, (VOID **)&m_lockedbuf, D3DLOCK_DISCARD);
  1785. if (result != D3D_OK)
  1786. return NULL;
  1787. }
  1788.  
  1789. // if we already have the lock and enough room, just return a pointer
  1790. if (m_lockedbuf != NULL && m_numverts + numverts < VERTEX_BUFFER_SIZE)
  1791. {
  1792. int oldverts = m_numverts;
  1793. m_numverts += numverts;
  1794. return &m_lockedbuf[oldverts];
  1795. }
  1796. return NULL;
  1797. }
  1798.  
  1799.  
  1800.  
  1801. //============================================================
  1802. // primitive_flush_pending
  1803. //============================================================
  1804.  
  1805. void renderer::primitive_flush_pending()
  1806. {
  1807. // ignore if we're not locked
  1808. if (m_lockedbuf == NULL)
  1809. {
  1810. return;
  1811. }
  1812.  
  1813. // unlock the buffer
  1814. HRESULT result = (*d3dintf->vertexbuf.unlock)(m_vertexbuf);
  1815. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result);
  1816. m_lockedbuf = NULL;
  1817.  
  1818. // set the stream
  1819. result = (*d3dintf->device.set_stream_source)(m_device, 0, m_vertexbuf, sizeof(vertex));
  1820. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result);
  1821.  
  1822. m_shaders->begin_draw();
  1823.  
  1824. int vertnum = 0;
  1825. if (m_shaders->enabled())
  1826. {
  1827. vertnum = 6;
  1828. }
  1829.  
  1830. // now do the polys
  1831. for (int polynum = 0; polynum < m_numpolys; polynum++)
  1832. {
  1833. UINT32 flags = m_poly[polynum].get_flags();
  1834. texture_info *texture = m_poly[polynum].get_texture();
  1835. int newfilter;
  1836.  
  1837. // set the texture if different
  1838. set_texture(texture);
  1839.  
  1840. // set filtering if different
  1841. if (texture != NULL)
  1842. {
  1843. newfilter = FALSE;
  1844. if (PRIMFLAG_GET_SCREENTEX(flags))
  1845. newfilter = video_config.filter;
  1846. set_filter(newfilter);
  1847. set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
  1848. set_modmode(m_poly[polynum].get_modmode());
  1849.  
  1850. m_shaders->init_effect_info(&m_poly[polynum]);
  1851. }
  1852.  
  1853. // set the blendmode if different
  1854. set_blendmode(PRIMFLAG_GET_BLENDMODE(flags));
  1855.  
  1856. if (vertnum + m_poly[polynum].get_vertcount() > m_numverts)
  1857. {
  1858. osd_printf_error("Error: vertnum (%d) plus poly vertex count (%d) > %d\n", vertnum, m_poly[polynum].get_vertcount(), m_numverts);
  1859. fflush(stdout);
  1860. }
  1861.  
  1862. assert(vertnum + m_poly[polynum].get_vertcount() <= m_numverts);
  1863.  
  1864. if(m_shaders->enabled() && d3dintf->post_fx_available)
  1865. {
  1866. m_shaders->render_quad(&m_poly[polynum], vertnum);
  1867. }
  1868. else
  1869. {
  1870. // add the primitives
  1871. result = (*d3dintf->device.draw_primitive)(m_device, m_poly[polynum].get_type(), vertnum,
  1872. m_poly[polynum].get_count());
  1873. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
  1874. }
  1875.  
  1876. vertnum += m_poly[polynum].get_vertcount();
  1877. }
  1878.  
  1879. m_shaders->end_draw();
  1880.  
  1881. // reset the vertex count
  1882. m_numverts = 0;
  1883. m_numpolys = 0;
  1884. }
  1885.  
  1886. //============================================================
  1887. // texture_info destructor
  1888. //============================================================
  1889.  
  1890. texture_info::~texture_info()
  1891. {
  1892. if (m_d3dfinaltex != NULL)
  1893. {
  1894. if (m_d3dtex == m_d3dfinaltex)
  1895. {
  1896. m_d3dtex = NULL;
  1897. }
  1898. (*d3dintf->texture.release)(m_d3dfinaltex);
  1899. m_d3dfinaltex = NULL;
  1900. }
  1901. if (m_d3dtex != NULL)
  1902. {
  1903. (*d3dintf->texture.release)(m_d3dtex);
  1904. m_d3dtex = NULL;
  1905. }
  1906. if (m_d3dsurface != NULL)
  1907. {
  1908. (*d3dintf->surface.release)(m_d3dsurface);
  1909. m_d3dsurface = NULL;
  1910. }
  1911. }
  1912.  
  1913. //============================================================
  1914. // texture_info constructor
  1915. //============================================================
  1916.  
  1917. texture_info::texture_info(texture_manager *manager, const render_texinfo* texsource, int prescale, UINT32 flags)
  1918. {
  1919. HRESULT result;
  1920.  
  1921. // fill in the core data
  1922. m_texture_manager = manager;
  1923. m_renderer = m_texture_manager->get_d3d();
  1924. m_hash = m_texture_manager->texture_compute_hash(texsource, flags);
  1925. m_flags = flags;
  1926. m_texinfo = *texsource;
  1927. m_xprescale = prescale;
  1928. m_yprescale = prescale;
  1929.  
  1930. m_d3dtex = NULL;
  1931. m_d3dsurface = NULL;
  1932. m_d3dfinaltex = NULL;
  1933.  
  1934. // compute the size
  1935. compute_size(texsource->width, texsource->height);
  1936.  
  1937. // non-screen textures are easy
  1938. if (!PRIMFLAG_GET_SCREENTEX(flags))
  1939. {
  1940. assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16);
  1941. DWORD usage = m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0;
  1942. D3DPOOL pool = m_texture_manager->is_dynamic_supported() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
  1943. result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, D3DFMT_A8R8G8B8, pool, &m_d3dtex);
  1944. if (result != D3D_OK)
  1945. goto error;
  1946. m_d3dfinaltex = m_d3dtex;
  1947. m_type = TEXTURE_TYPE_PLAIN;
  1948. }
  1949.  
  1950. // screen textures are allocated differently
  1951. else
  1952. {
  1953. D3DFORMAT format;
  1954. DWORD usage = m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0;
  1955. D3DPOOL pool = m_texture_manager->is_dynamic_supported() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
  1956. int maxdim = MAX(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight);
  1957.  
  1958. // pick the format
  1959. if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16)
  1960. {
  1961. format = m_texture_manager->get_yuv_format();
  1962. }
  1963. else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32 || PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_PALETTEA16)
  1964. {
  1965. format = D3DFMT_A8R8G8B8;
  1966. }
  1967. else
  1968. {
  1969. format = m_renderer->get_screen_format();
  1970. }
  1971.  
  1972. // don't prescale above screen size
  1973. while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim)
  1974. {
  1975. m_xprescale--;
  1976. }
  1977. while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width())
  1978. {
  1979. m_xprescale--;
  1980. }
  1981. while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim)
  1982. {
  1983. m_yprescale--;
  1984. }
  1985. while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height())
  1986. {
  1987. m_yprescale--;
  1988. }
  1989.  
  1990. int prescale = m_renderer->window().prescale();
  1991. if (m_xprescale != prescale || m_yprescale != prescale)
  1992. {
  1993. osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale);
  1994. }
  1995.  
  1996. // loop until we allocate something or error
  1997. for (int attempt = 0; attempt < 2; attempt++)
  1998. {
  1999. // second attempt is always 1:1
  2000. if (attempt == 1)
  2001. {
  2002. m_xprescale = m_yprescale = 1;
  2003. }
  2004.  
  2005. // screen textures with no prescaling are pretty easy
  2006. if (m_xprescale == 1 && m_yprescale == 1)
  2007. {
  2008. result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex);
  2009. if (result == D3D_OK)
  2010. {
  2011. m_d3dfinaltex = m_d3dtex;
  2012. m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
  2013. if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this))
  2014. {
  2015. goto error;
  2016. }
  2017.  
  2018. break;
  2019. }
  2020. }
  2021.  
  2022. // screen textures with prescaling require two allocations
  2023. else
  2024. {
  2025. // use an offscreen plain surface for stretching if supported
  2026. // (won't work for YUY textures)
  2027. if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16)
  2028. {
  2029. result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface);
  2030. if (result != D3D_OK)
  2031. {
  2032. continue;
  2033. }
  2034. m_type = TEXTURE_TYPE_SURFACE;
  2035. }
  2036.  
  2037. // otherwise, we allocate a dynamic texture for the source
  2038. else
  2039. {
  2040. result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex);
  2041. if (result != D3D_OK)
  2042. {
  2043. continue;
  2044. }
  2045. m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN;
  2046. }
  2047.  
  2048. // for the target surface, we allocate a render target texture
  2049. int scwidth = m_rawdims.c.x * m_xprescale;
  2050. int scheight = m_rawdims.c.y * m_yprescale;
  2051.  
  2052. // target surfaces typically cannot be YCbCr, so we always pick RGB in that case
  2053. D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8;
  2054. result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex);
  2055. if (result == D3D_OK)
  2056. {
  2057. if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this))
  2058. {
  2059. goto error;
  2060. }
  2061. break;
  2062. }
  2063. (*d3dintf->texture.release)(m_d3dtex);
  2064. m_d3dtex = NULL;
  2065. }
  2066. }
  2067. }
  2068.  
  2069. // copy the data to the texture
  2070. set_data(texsource, flags);
  2071.  
  2072. //texsource->osdhandle = (void*)this;
  2073. // add us to the texture list
  2074. if(m_texture_manager->get_texlist() != NULL)
  2075. m_texture_manager->get_texlist()->m_prev = this;
  2076. m_prev = NULL;
  2077. m_next = m_texture_manager->get_texlist();
  2078. m_texture_manager->set_texlist(this);
  2079. return;
  2080.  
  2081. error:
  2082. d3dintf->post_fx_available = false;
  2083. osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n");
  2084. if (m_d3dsurface != NULL)
  2085. (*d3dintf->surface.release)(m_d3dsurface);
  2086. if (m_d3dtex != NULL)
  2087. (*d3dintf->texture.release)(m_d3dtex);
  2088. }
  2089.  
  2090.  
  2091.  
  2092. //============================================================
  2093. // texture_info::compute_size_subroutine
  2094. //============================================================
  2095.  
  2096. void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height)
  2097. {
  2098. int finalheight = texheight;
  2099. int finalwidth = texwidth;
  2100.  
  2101. // round width/height up to nearest power of 2 if we need to
  2102. if (!(m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
  2103. {
  2104. // first the width
  2105. if (finalwidth & (finalwidth - 1))
  2106. {
  2107. finalwidth |= finalwidth >> 1;
  2108. finalwidth |= finalwidth >> 2;
  2109. finalwidth |= finalwidth >> 4;
  2110. finalwidth |= finalwidth >> 8;
  2111. finalwidth++;
  2112. }
  2113.  
  2114. // then the height
  2115. if (finalheight & (finalheight - 1))
  2116. {
  2117. finalheight |= finalheight >> 1;
  2118. finalheight |= finalheight >> 2;
  2119. finalheight |= finalheight >> 4;
  2120. finalheight |= finalheight >> 8;
  2121. finalheight++;
  2122. }
  2123. }
  2124.  
  2125. // round up to square if we need to
  2126. if (m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY)
  2127. {
  2128. if (finalwidth < finalheight)
  2129. finalwidth = finalheight;
  2130. else
  2131. finalheight = finalwidth;
  2132. }
  2133.  
  2134. // adjust the aspect ratio if we need to
  2135. while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect())
  2136. {
  2137. finalwidth *= 2;
  2138. }
  2139. while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect())
  2140. {
  2141. finalheight *= 2;
  2142. }
  2143.  
  2144. *p_width = finalwidth;
  2145. *p_height = finalheight;
  2146. }
  2147.  
  2148. //============================================================
  2149. // texture_info::compute_size
  2150. //============================================================
  2151.  
  2152. void texture_info::compute_size(int texwidth, int texheight)
  2153. {
  2154. int finalheight = texheight;
  2155. int finalwidth = texwidth;
  2156.  
  2157. m_xborderpix = 0;
  2158. m_yborderpix = 0;
  2159.  
  2160. // if we're not wrapping, add a 1-2 pixel border on all sides
  2161. if (ENABLE_BORDER_PIX && !(m_flags & PRIMFLAG_TEXWRAP_MASK))
  2162. {
  2163. // note we need 2 pixels in X for YUY textures
  2164. m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1;
  2165. m_yborderpix = 1;
  2166. }
  2167.  
  2168. // compute final texture size
  2169. finalwidth += 2 * m_xborderpix;
  2170. finalheight += 2 * m_yborderpix;
  2171.  
  2172. compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight);
  2173.  
  2174. // if we added pixels for the border, and that just barely pushed us over, take it back
  2175. if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height())
  2176. {
  2177. finalheight = texheight;
  2178. finalwidth = texwidth;
  2179.  
  2180. m_xborderpix = 0;
  2181. m_yborderpix = 0;
  2182.  
  2183. compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight);
  2184. }
  2185.  
  2186. // if we're above the max width/height, do what?
  2187. if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height())
  2188. {
  2189. static int printed = FALSE;
  2190. if (!printed) osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth, finalheight, (int)m_texture_manager->get_max_texture_width(), (int)m_texture_manager->get_max_texture_height());
  2191. printed = TRUE;
  2192. }
  2193.  
  2194. // compute the U/V scale factors
  2195. m_start.c.x = (float)m_xborderpix / (float)finalwidth;
  2196. m_start.c.y = (float)m_yborderpix / (float)finalheight;
  2197. m_stop.c.x = (float)(texwidth + m_xborderpix) / (float)finalwidth;
  2198. m_stop.c.y = (float)(texheight + m_yborderpix) / (float)finalheight;
  2199.  
  2200. // set the final values
  2201. m_rawdims.c.x = finalwidth;
  2202. m_rawdims.c.y = finalheight;
  2203. }
  2204.  
  2205.  
  2206.  
  2207. //============================================================
  2208. // copyline_palette16
  2209. //============================================================
  2210.  
  2211. INLINE void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix)
  2212. {
  2213. int x;
  2214.  
  2215. assert(xborderpix == 0 || xborderpix == 1);
  2216. if (xborderpix)
  2217. *dst++ = 0xff000000 | palette[*src];
  2218. for (x = 0; x < width; x++)
  2219. *dst++ = 0xff000000 | palette[*src++];
  2220. if (xborderpix)
  2221. *dst++ = 0xff000000 | palette[*--src];
  2222. }
  2223.  
  2224.  
  2225.  
  2226. //============================================================
  2227. // copyline_palettea16
  2228. //============================================================
  2229.  
  2230. INLINE void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix)
  2231. {
  2232. int x;
  2233.  
  2234. assert(xborderpix == 0 || xborderpix == 1);
  2235. if (xborderpix)
  2236. *dst++ = palette[*src];
  2237. for (x = 0; x < width; x++)
  2238. *dst++ = palette[*src++];
  2239. if (xborderpix)
  2240. *dst++ = palette[*--src];
  2241. }
  2242.  
  2243.  
  2244.  
  2245. //============================================================
  2246. // copyline_rgb32
  2247. //============================================================
  2248.  
  2249. INLINE void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix)
  2250. {
  2251. int x;
  2252.  
  2253. assert(xborderpix == 0 || xborderpix == 1);
  2254.  
  2255. // palette (really RGB map) case
  2256. if (palette != NULL)
  2257. {
  2258. if (xborderpix)
  2259. {
  2260. rgb_t srcpix = *src;
  2261. *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2262. }
  2263. for (x = 0; x < width; x++)
  2264. {
  2265. rgb_t srcpix = *src++;
  2266. *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2267. }
  2268. if (xborderpix)
  2269. {
  2270. rgb_t srcpix = *--src;
  2271. *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2272. }
  2273. }
  2274.  
  2275. // direct case
  2276. else
  2277. {
  2278. if (xborderpix)
  2279. *dst++ = 0xff000000 | *src;
  2280. for (x = 0; x < width; x++)
  2281. *dst++ = 0xff000000 | *src++;
  2282. if (xborderpix)
  2283. *dst++ = 0xff000000 | *--src;
  2284. }
  2285. }
  2286.  
  2287.  
  2288.  
  2289. //============================================================
  2290. // copyline_argb32
  2291. //============================================================
  2292.  
  2293. INLINE void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix)
  2294. {
  2295. int x;
  2296.  
  2297. assert(xborderpix == 0 || xborderpix == 1);
  2298.  
  2299. // palette (really RGB map) case
  2300. if (palette != NULL)
  2301. {
  2302. if (xborderpix)
  2303. {
  2304. rgb_t srcpix = *src;
  2305. *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2306. }
  2307. for (x = 0; x < width; x++)
  2308. {
  2309. rgb_t srcpix = *src++;
  2310. *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2311. }
  2312. if (xborderpix)
  2313. {
  2314. rgb_t srcpix = *--src;
  2315. *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
  2316. }
  2317. }
  2318.  
  2319. // direct case
  2320. else
  2321. {
  2322. if (xborderpix)
  2323. *dst++ = *src;
  2324. for (x = 0; x < width; x++)
  2325. *dst++ = *src++;
  2326. if (xborderpix)
  2327. *dst++ = *--src;
  2328. }
  2329. }
  2330.  
  2331.  
  2332.  
  2333. //============================================================
  2334. // copyline_yuy16_to_yuy2
  2335. //============================================================
  2336.  
  2337. INLINE void copyline_yuy16_to_yuy2(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix)
  2338. {
  2339. int x;
  2340.  
  2341. assert(xborderpix == 0 || xborderpix == 2);
  2342. assert(width % 2 == 0);
  2343.  
  2344. // palette (really RGB map) case
  2345. if (palette != NULL)
  2346. {
  2347. if (xborderpix)
  2348. {
  2349. UINT16 srcpix0 = *src++;
  2350. UINT16 srcpix1 = *src--;
  2351. *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8);
  2352. *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix1 << 8);
  2353. }
  2354. for (x = 0; x < width; x += 2)
  2355. {
  2356. UINT16 srcpix0 = *src++;
  2357. UINT16 srcpix1 = *src++;
  2358. *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8);
  2359. *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8);
  2360. }
  2361. if (xborderpix)
  2362. {
  2363. UINT16 srcpix1 = *--src;
  2364. UINT16 srcpix0 = *--src;
  2365. *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix0 << 8);
  2366. *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8);
  2367. }
  2368. }
  2369.  
  2370. // direct case
  2371. else
  2372. {
  2373. if (xborderpix)
  2374. {
  2375. UINT16 srcpix0 = *src++;
  2376. UINT16 srcpix1 = *src--;
  2377. *dst++ = (srcpix0 >> 8) | (srcpix0 << 8);
  2378. *dst++ = (srcpix0 >> 8) | (srcpix1 << 8);
  2379. }
  2380. for (x = 0; x < width; x += 2)
  2381. {
  2382. UINT16 srcpix0 = *src++;
  2383. UINT16 srcpix1 = *src++;
  2384. *dst++ = (srcpix0 >> 8) | (srcpix0 << 8);
  2385. *dst++ = (srcpix1 >> 8) | (srcpix1 << 8);
  2386. }
  2387. if (xborderpix)
  2388. {
  2389. UINT16 srcpix1 = *--src;
  2390. UINT16 srcpix0 = *--src;
  2391. *dst++ = (srcpix1 >> 8) | (srcpix0 << 8);
  2392. *dst++ = (srcpix1 >> 8) | (srcpix1 << 8);
  2393. }
  2394. }
  2395. }
  2396.  
  2397.  
  2398.  
  2399. //============================================================
  2400. // copyline_yuy16_to_uyvy
  2401. //============================================================
  2402.  
  2403. INLINE void copyline_yuy16_to_uyvy(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix)
  2404. {
  2405. int x;
  2406.  
  2407. assert(xborderpix == 0 || xborderpix == 2);
  2408. assert(width % 2 == 0);
  2409.  
  2410. // palette (really RGB map) case
  2411. if (palette != NULL)
  2412. {
  2413. if (xborderpix)
  2414. {
  2415. UINT16 srcpix0 = *src++;
  2416. UINT16 srcpix1 = *src--;
  2417. *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff);
  2418. *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix1 & 0xff);
  2419. }
  2420. for (x = 0; x < width; x += 2)
  2421. {
  2422. UINT16 srcpix0 = *src++;
  2423. UINT16 srcpix1 = *src++;
  2424. *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff);
  2425. *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff);
  2426. }
  2427. if (xborderpix)
  2428. {
  2429. UINT16 srcpix1 = *--src;
  2430. UINT16 srcpix0 = *--src;
  2431. *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix0 & 0xff);
  2432. *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff);
  2433. }
  2434. }
  2435.  
  2436. // direct case
  2437. else
  2438. {
  2439. if (xborderpix)
  2440. {
  2441. UINT16 srcpix0 = src[0];
  2442. UINT16 srcpix1 = src[1];
  2443. *dst++ = srcpix0;
  2444. *dst++ = (srcpix0 & 0xff00) | (srcpix1 & 0x00ff);
  2445. }
  2446. for (x = 0; x < width; x += 2)
  2447. {
  2448. *dst++ = *src++;
  2449. *dst++ = *src++;
  2450. }
  2451. if (xborderpix)
  2452. {
  2453. UINT16 srcpix1 = *--src;
  2454. UINT16 srcpix0 = *--src;
  2455. *dst++ = (srcpix1 & 0xff00) | (srcpix0 & 0x00ff);
  2456. *dst++ = srcpix1;
  2457. }
  2458. }
  2459. }
  2460.  
  2461.  
  2462.  
  2463. //============================================================
  2464. // copyline_yuy16_to_argb
  2465. //============================================================
  2466.  
  2467. INLINE void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix)
  2468. {
  2469. int x;
  2470.  
  2471. assert(xborderpix == 0 || xborderpix == 2);
  2472. assert(width % 2 == 0);
  2473.  
  2474. // palette (really RGB map) case
  2475. if (palette != NULL)
  2476. {
  2477. if (xborderpix)
  2478. {
  2479. UINT16 srcpix0 = src[0];
  2480. UINT16 srcpix1 = src[1];
  2481. UINT8 cb = srcpix0 & 0xff;
  2482. UINT8 cr = srcpix1 & 0xff;
  2483. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
  2484. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
  2485. }
  2486. for (x = 0; x < width / 2; x++)
  2487. {
  2488. UINT16 srcpix0 = *src++;
  2489. UINT16 srcpix1 = *src++;
  2490. UINT8 cb = srcpix0 & 0xff;
  2491. UINT8 cr = srcpix1 & 0xff;
  2492. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
  2493. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
  2494. }
  2495. if (xborderpix)
  2496. {
  2497. UINT16 srcpix1 = *--src;
  2498. UINT16 srcpix0 = *--src;
  2499. UINT8 cb = srcpix0 & 0xff;
  2500. UINT8 cr = srcpix1 & 0xff;
  2501. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
  2502. *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
  2503. }
  2504. }
  2505.  
  2506. // direct case
  2507. else
  2508. {
  2509. if (xborderpix)
  2510. {
  2511. UINT16 srcpix0 = src[0];
  2512. UINT16 srcpix1 = src[1];
  2513. UINT8 cb = srcpix0 & 0xff;
  2514. UINT8 cr = srcpix1 & 0xff;
  2515. *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr);
  2516. *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr);
  2517. }
  2518. for (x = 0; x < width; x += 2)
  2519. {
  2520. UINT16 srcpix0 = *src++;
  2521. UINT16 srcpix1 = *src++;
  2522. UINT8 cb = srcpix0 & 0xff;
  2523. UINT8 cr = srcpix1 & 0xff;
  2524. *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr);
  2525. *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr);
  2526. }
  2527. if (xborderpix)
  2528. {
  2529. UINT16 srcpix1 = *--src;
  2530. UINT16 srcpix0 = *--src;
  2531. UINT8 cb = srcpix0 & 0xff;
  2532. UINT8 cr = srcpix1 & 0xff;
  2533. *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr);
  2534. *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr);
  2535. }
  2536. }
  2537. }
  2538.  
  2539.  
  2540.  
  2541. //============================================================
  2542. // texture_set_data
  2543. //============================================================
  2544.  
  2545. void texture_info::set_data(const render_texinfo *texsource, UINT32 flags)
  2546. {
  2547. D3DLOCKED_RECT rect;
  2548. HRESULT result;
  2549.  
  2550. // lock the texture
  2551. switch (m_type)
  2552. {
  2553. default:
  2554. case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, 0); break;
  2555. case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, D3DLOCK_DISCARD); break;
  2556. case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.lock_rect)(m_d3dsurface, &rect, NULL, D3DLOCK_DISCARD); break;
  2557. }
  2558. if (result != D3D_OK)
  2559. {
  2560. return;
  2561. }
  2562.  
  2563. // loop over Y
  2564. int miny = 0 - m_yborderpix;
  2565. int maxy = texsource->height + m_yborderpix;
  2566. for (int dsty = miny; dsty < maxy; dsty++)
  2567. {
  2568. int srcy = (dsty < 0) ? 0 : (dsty >= texsource->height) ? texsource->height - 1 : dsty;
  2569. void *dst = (BYTE *)rect.pBits + (dsty + m_yborderpix) * rect.Pitch;
  2570.  
  2571. // switch off of the format and
  2572. switch (PRIMFLAG_GET_TEXFORMAT(flags))
  2573. {
  2574. case TEXFORMAT_PALETTE16:
  2575. copyline_palette16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2576. break;
  2577.  
  2578. case TEXFORMAT_PALETTEA16:
  2579. copyline_palettea16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2580. break;
  2581.  
  2582. case TEXFORMAT_RGB32:
  2583. copyline_rgb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2584. break;
  2585.  
  2586. case TEXFORMAT_ARGB32:
  2587. copyline_argb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2588. break;
  2589.  
  2590. case TEXFORMAT_YUY16:
  2591. if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2)
  2592. copyline_yuy16_to_yuy2((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2593. else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY)
  2594. copyline_yuy16_to_uyvy((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2595. else
  2596. copyline_yuy16_to_argb((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix);
  2597. break;
  2598.  
  2599. default:
  2600. osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags));
  2601. break;
  2602. }
  2603. }
  2604.  
  2605. // unlock
  2606. switch (m_type)
  2607. {
  2608. default:
  2609. case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break;
  2610. case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break;
  2611. case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.unlock_rect)(m_d3dsurface); break;
  2612. }
  2613. if (result != D3D_OK)
  2614. {
  2615. osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result);
  2616. }
  2617.  
  2618. // prescale
  2619. prescale();
  2620. }
  2621.  
  2622.  
  2623.  
  2624. //============================================================
  2625. // texture_info::prescale
  2626. //============================================================
  2627.  
  2628. void texture_info::prescale()
  2629. {
  2630. surface *scale_surface;
  2631. HRESULT result;
  2632. int i;
  2633.  
  2634. // if we don't need to, just skip it
  2635. if (m_d3dtex == m_d3dfinaltex)
  2636. return;
  2637.  
  2638. // for all cases, we need to get the surface of the render target
  2639. result = (*d3dintf->texture.get_surface_level)(m_d3dfinaltex, 0, &scale_surface);
  2640. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture get_surface_level call\n", (int)result);
  2641.  
  2642. // if we have an offscreen plain surface, we can just StretchRect to it
  2643. if (m_type == TEXTURE_TYPE_SURFACE)
  2644. {
  2645. assert(m_d3dsurface != NULL);
  2646.  
  2647. // set the source bounds
  2648. RECT source;
  2649. source.left = source.top = 0;
  2650. source.right = m_texinfo.width + 2 * m_xborderpix;
  2651. source.bottom = m_texinfo.height + 2 * m_yborderpix;
  2652.  
  2653. // set the target bounds
  2654. RECT dest;
  2655. dest = source;
  2656. dest.right *= m_xprescale;
  2657. dest.bottom *= m_yprescale;
  2658.  
  2659. // do the stretchrect
  2660. result = (*d3dintf->device.stretch_rect)(m_renderer->get_device(), m_d3dsurface, &source, scale_surface, &dest, D3DTEXF_POINT);
  2661. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device stretct_rect call\n", (int)result);
  2662. }
  2663.  
  2664. // if we are using a texture render target, we need to do more preparations
  2665. else
  2666. {
  2667. surface *backbuffer;
  2668.  
  2669. assert(m_d3dtex != NULL);
  2670.  
  2671. // first remember the original render target and set the new one
  2672. result = (*d3dintf->device.get_render_target)(m_renderer->get_device(), 0, &backbuffer);
  2673. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result);
  2674. result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, scale_surface);
  2675. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 1\n", (int)result);
  2676. m_renderer->reset_render_states();
  2677.  
  2678. // start the scene
  2679. result = (*d3dintf->device.begin_scene)(m_renderer->get_device());
  2680. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result);
  2681.  
  2682. // configure the rendering pipeline
  2683. m_renderer->set_filter(FALSE);
  2684. m_renderer->set_blendmode(BLENDMODE_NONE);
  2685. result = (*d3dintf->device.set_texture)(m_renderer->get_device(), 0, m_d3dtex);
  2686. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result);
  2687.  
  2688. // lock the vertex buffer
  2689. result = (*d3dintf->vertexbuf.lock)(m_renderer->get_vertex_buffer(), 0, 0, m_renderer->get_locked_buffer_ptr(), D3DLOCK_DISCARD);
  2690. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer lock call\n", (int)result);
  2691.  
  2692. // configure the X/Y coordinates on the target surface
  2693. vertex *lockedbuf = m_renderer->get_locked_buffer();
  2694. lockedbuf[0].x = -0.5f;
  2695. lockedbuf[0].y = -0.5f;
  2696. lockedbuf[1].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f;
  2697. lockedbuf[1].y = -0.5f;
  2698. lockedbuf[2].x = -0.5f;
  2699. lockedbuf[2].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f;
  2700. lockedbuf[3].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f;
  2701. lockedbuf[3].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f;
  2702.  
  2703. // configure the U/V coordintes on the source texture
  2704. lockedbuf[0].u0 = 0.0f;
  2705. lockedbuf[0].v0 = 0.0f;
  2706. lockedbuf[1].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x;
  2707. lockedbuf[1].v0 = 0.0f;
  2708. lockedbuf[2].u0 = 0.0f;
  2709. lockedbuf[2].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y;
  2710. lockedbuf[3].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x;
  2711. lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y;
  2712.  
  2713. // reset the remaining vertex parameters
  2714. for (i = 0; i < 4; i++)
  2715. {
  2716. lockedbuf[i].z = 0.0f;
  2717. lockedbuf[i].rhw = 1.0f;
  2718. lockedbuf[i].color = D3DCOLOR_ARGB(0xff,0xff,0xff,0xff);
  2719. }
  2720.  
  2721. // unlock the vertex buffer
  2722. result = (*d3dintf->vertexbuf.unlock)(m_renderer->get_vertex_buffer());
  2723. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result);
  2724. m_renderer->set_locked_buffer(NULL);
  2725.  
  2726. // set the stream and draw the triangle strip
  2727. result = (*d3dintf->device.set_stream_source)(m_renderer->get_device(), 0, m_renderer->get_vertex_buffer(), sizeof(vertex));
  2728. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result);
  2729. result = (*d3dintf->device.draw_primitive)(m_renderer->get_device(), D3DPT_TRIANGLESTRIP, 0, 2);
  2730. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result);
  2731.  
  2732. // end the scene
  2733. result = (*d3dintf->device.end_scene)(m_renderer->get_device());
  2734. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result);
  2735.  
  2736. // reset the render target and release our reference to the backbuffer
  2737. result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, backbuffer);
  2738. if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 2\n", (int)result);
  2739. (*d3dintf->surface.release)(backbuffer);
  2740. m_renderer->reset_render_states();
  2741. }
  2742.  
  2743. // release our reference to the target surface
  2744. (*d3dintf->surface.release)(scale_surface);
  2745. }
  2746.  
  2747.  
  2748. //============================================================
  2749. // cache_target::~cache_target
  2750. //============================================================
  2751.  
  2752. cache_target::~cache_target()
  2753. {
  2754. for (int index = 0; index < 11; index++)
  2755. {
  2756. if (bloom_texture[index] != NULL)
  2757. {
  2758. (*d3dintf->texture.release)(bloom_texture[index]);
  2759. bloom_texture[index] = NULL;
  2760. }
  2761. if (bloom_target[index] != NULL)
  2762. {
  2763. (*d3dintf->surface.release)(bloom_target[index]);
  2764. bloom_target[index] = NULL;
  2765. }
  2766. }
  2767.  
  2768. if (last_texture != NULL)
  2769. {
  2770. (*d3dintf->texture.release)(last_texture);
  2771. last_texture = NULL;
  2772. }
  2773. if (last_target != NULL)
  2774. {
  2775. (*d3dintf->surface.release)(last_target);
  2776. last_target = NULL;
  2777. }
  2778. }
  2779.  
  2780.  
  2781. //============================================================
  2782. // cache_target::init - initializes a target cache
  2783. //============================================================
  2784.  
  2785. bool cache_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y)
  2786. {
  2787. int bloom_size = (width < height) ? width : height;
  2788. int bloom_index = 0;
  2789. int bloom_width = width;
  2790. int bloom_height = height;
  2791. for (; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1)
  2792. {
  2793. bloom_width >>= 1;
  2794. bloom_height >>= 1;
  2795. HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), bloom_width, bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]);
  2796. if (result != D3D_OK)
  2797. {
  2798. return false;
  2799. }
  2800. (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]);
  2801. bloom_index++;
  2802. }
  2803.  
  2804. HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture);
  2805. if (result != D3D_OK)
  2806. return false;
  2807. (*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target);
  2808.  
  2809. target_width = width * prescale_x;
  2810. target_height = height * prescale_y;
  2811.  
  2812. return true;
  2813. }
  2814.  
  2815. //============================================================
  2816. // render_target::~render_target
  2817. //============================================================
  2818.  
  2819. render_target::~render_target()
  2820. {
  2821. for (int index = 0; index < 11; index++)
  2822. {
  2823. if (bloom_texture[index] != NULL)
  2824. {
  2825. (*d3dintf->texture.release)(bloom_texture[index]);
  2826. bloom_texture[index] = NULL;
  2827. }
  2828. if (bloom_target[index] != NULL)
  2829. {
  2830. (*d3dintf->surface.release)(bloom_target[index]);
  2831. bloom_target[index] = NULL;
  2832. }
  2833. }
  2834.  
  2835. for (int index = 0; index < 5; index++)
  2836. {
  2837. if (render_texture[index] != NULL)
  2838. {
  2839. (*d3dintf->texture.release)(render_texture[index]);
  2840. render_texture[index] = NULL;
  2841. }
  2842. if (target[index] != NULL)
  2843. {
  2844. (*d3dintf->surface.release)(target[index]);
  2845. target[index] = NULL;
  2846. }
  2847. }
  2848.  
  2849. if (prescaletexture != NULL)
  2850. {
  2851. (*d3dintf->texture.release)(prescaletexture);
  2852. prescaletexture = NULL;
  2853. }
  2854. if (prescaletarget != NULL)
  2855. {
  2856. (*d3dintf->surface.release)(prescaletarget);
  2857. prescaletarget = NULL;
  2858. }
  2859.  
  2860. if (smalltexture != NULL)
  2861. {
  2862. (*d3dintf->texture.release)(smalltexture);
  2863. smalltexture = NULL;
  2864. }
  2865. if (smalltarget != NULL)
  2866. {
  2867. (*d3dintf->surface.release)(smalltarget);
  2868. smalltarget = NULL;
  2869. }
  2870. }
  2871.  
  2872.  
  2873. //============================================================
  2874. // render_target::init - initializes a render target
  2875. //============================================================
  2876.  
  2877. bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y)
  2878. {
  2879. D3DFORMAT format = D3DFMT_A8R8G8B8;
  2880.  
  2881. HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[0]);
  2882. if (result != D3D_OK)
  2883. return false;
  2884. (*d3dintf->texture.get_surface_level)(render_texture[0], 0, &target[0]);
  2885.  
  2886. result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[1]);
  2887. if (result != D3D_OK)
  2888. return false;
  2889. (*d3dintf->texture.get_surface_level)(render_texture[1], 0, &target[1]);
  2890.  
  2891. result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[2]);
  2892. if (result != D3D_OK)
  2893. return false;
  2894. (*d3dintf->texture.get_surface_level)(render_texture[2], 0, &target[2]);
  2895.  
  2896. result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[3]);
  2897. if (result != D3D_OK)
  2898. return false;
  2899. (*d3dintf->texture.get_surface_level)(render_texture[3], 0, &target[3]);
  2900.  
  2901. result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[4]);
  2902. if (result != D3D_OK)
  2903. return false;
  2904. (*d3dintf->texture.get_surface_level)(render_texture[4], 0, &target[4]);
  2905.  
  2906. result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &smalltexture);
  2907. if (result != D3D_OK)
  2908. return false;
  2909. (*d3dintf->texture.get_surface_level)(smalltexture, 0, &smalltarget);
  2910.  
  2911. result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &prescaletexture);
  2912. if (result != D3D_OK)
  2913. return false;
  2914. (*d3dintf->texture.get_surface_level)(prescaletexture, 0, &prescaletarget);
  2915.  
  2916. float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
  2917. int bloom_index = 0;
  2918. float bloom_width = d3d->get_width();
  2919. float bloom_height = d3d->get_height();
  2920. for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
  2921. {
  2922. bloom_width *= 0.5f;
  2923. bloom_height *= 0.5f;
  2924. result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)bloom_width, (int)bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]);
  2925. if (result != D3D_OK)
  2926. return false;
  2927. (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]);
  2928. bloom_index++;
  2929. }
  2930.  
  2931. this->width = width;
  2932. this->height = height;
  2933.  
  2934. target_width = width * prescale_x;
  2935. target_height = height * prescale_y;
  2936.  
  2937. return true;
  2938. }
  2939.  
  2940. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement