Guest User

drawd3d.c

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

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×