trunk/3rdparty/bgfx/examples/common/imgui/fs_imgui_latlong.bin.h
| r244651 | r244652 | |
| 1 | | static const uint8_t fs_imgui_latlong_glsl[649] = |
| 1 | static const uint8_t fs_imgui_latlong_glsl[646] = |
| 2 | 2 | { |
| 3 | 3 | 0x46, 0x53, 0x48, 0x03, 0x6f, 0x1e, 0x3e, 0x3c, 0x02, 0x00, 0x11, 0x75, 0x5f, 0x69, 0x6d, 0x61, // FSH.o.><...u_ima |
| 4 | 4 | 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x07, 0x01, 0x00, 0x00, // geLodEnabled.... |
| 5 | 5 | 0x01, 0x00, 0x0a, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x01, 0x00, // ...s_texColor... |
| 6 | | 0x00, 0x01, 0x00, 0x51, 0x02, 0x00, 0x00, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, // ...Q...varying h |
| 6 | 0x00, 0x01, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, // ...N...varying h |
| 7 | 7 | 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, // ighp vec2 v_texc |
| 8 | 8 | 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x68, // oord0;.uniform h |
| 9 | 9 | 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x75, 0x5f, 0x69, 0x6d, 0x61, 0x67, // ighp vec4 u_imag |
| r244651 | r244652 | |
| 21 | 21 | 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x28, 0x76, 0x5f, // tmpvar_3 = (v_ |
| 22 | 22 | 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x33, 0x2e, // texcoord0.y * 3. |
| 23 | 23 | 0x31, 0x34, 0x31, 0x35, 0x39, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, // 14159);. result |
| 24 | | 0x5f, 0x31, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x28, 0x2d, 0x28, 0x73, 0x69, 0x6e, 0x28, 0x74, 0x6d, // _1.x = (-(sin(tm |
| 25 | | 0x70, 0x76, 0x61, 0x72, 0x5f, 0x33, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x6e, 0x28, 0x74, // pvar_3)) * sin(t |
| 26 | | 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x73, // mpvar_2));. res |
| 27 | | 0x75, 0x6c, 0x74, 0x5f, 0x31, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x73, 0x28, 0x74, 0x6d, // ult_1.y = cos(tm |
| 28 | | 0x70, 0x76, 0x61, 0x72, 0x5f, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, // pvar_3);. resul |
| 29 | | 0x74, 0x5f, 0x31, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x2d, 0x28, 0x73, 0x69, 0x6e, 0x28, 0x74, // t_1.z = (-(sin(t |
| 30 | | 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x33, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x63, 0x6f, 0x73, 0x28, // mpvar_3)) * cos( |
| 31 | | 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, // tmpvar_2));. lo |
| 32 | | 0x77, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, // wp vec4 tmpvar_4 |
| 33 | | 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, 0x2e, 0x78, 0x79, 0x7a, // ;. tmpvar_4.xyz |
| 34 | | 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x75, 0x62, 0x65, 0x4c, 0x6f, // = textureCubeLo |
| 35 | | 0x64, 0x20, 0x20, 0x20, 0x20, 0x28, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, // d (s_texColor |
| 36 | | 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x31, 0x2c, 0x20, 0x75, 0x5f, 0x69, 0x6d, // , result_1, u_im |
| 37 | | 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x29, // ageLodEnabled.x) |
| 38 | | 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, // .xyz;. tmpvar_4 |
| 39 | | 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x28, 0x30, 0x2e, 0x32, 0x20, 0x2b, 0x20, 0x28, 0x30, 0x2e, 0x38, // .w = (0.2 + (0.8 |
| 40 | | 0x20, 0x2a, 0x20, 0x75, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, // * u_imageLodEna |
| 41 | | 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, // bled.y));. gl_F |
| 42 | | 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, // ragColor = tmpva |
| 43 | | 0x72, 0x5f, 0x34, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // r_4;.}... |
| 24 | 0x5f, 0x31, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x28, 0x73, 0x69, 0x6e, 0x28, 0x74, 0x6d, 0x70, 0x76, // _1.x = (sin(tmpv |
| 25 | 0x61, 0x72, 0x5f, 0x33, 0x29, 0x20, 0x2a, 0x20, 0x63, 0x6f, 0x73, 0x28, 0x74, 0x6d, 0x70, 0x76, // ar_3) * cos(tmpv |
| 26 | 0x61, 0x72, 0x5f, 0x32, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, // ar_2));. result |
| 27 | 0x5f, 0x31, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x73, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, // _1.y = cos(tmpva |
| 28 | 0x72, 0x5f, 0x33, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x31, // r_3);. result_1 |
| 29 | 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x2d, 0x28, 0x73, 0x69, 0x6e, 0x28, 0x74, 0x6d, 0x70, 0x76, // .z = (-(sin(tmpv |
| 30 | 0x61, 0x72, 0x5f, 0x33, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x73, 0x69, 0x6e, 0x28, 0x74, 0x6d, 0x70, // ar_3)) * sin(tmp |
| 31 | 0x76, 0x61, 0x72, 0x5f, 0x32, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, // var_2));. lowp |
| 32 | 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, 0x3b, 0x0a, 0x20, // vec4 tmpvar_4;. |
| 33 | 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, // tmpvar_4.xyz = |
| 34 | 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x75, 0x62, 0x65, 0x4c, 0x6f, 0x64, 0x20, 0x20, // textureCubeLod |
| 35 | 0x20, 0x20, 0x28, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x72, // (s_texColor, r |
| 36 | 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x31, 0x2c, 0x20, 0x75, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, // esult_1, u_image |
| 37 | 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x29, 0x2e, 0x78, 0x79, // LodEnabled.x).xy |
| 38 | 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, 0x2e, 0x77, 0x20, // z;. tmpvar_4.w |
| 39 | 0x3d, 0x20, 0x28, 0x30, 0x2e, 0x32, 0x20, 0x2b, 0x20, 0x28, 0x30, 0x2e, 0x38, 0x20, 0x2a, 0x20, // = (0.2 + (0.8 * |
| 40 | 0x75, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, // u_imageLodEnable |
| 41 | 0x64, 0x2e, 0x79, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, // d.y));. gl_Frag |
| 42 | 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x34, // Color = tmpvar_4 |
| 43 | 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // ;.}... |
| 44 | 44 | }; |
| 45 | | static const uint8_t fs_imgui_latlong_dx9[537] = |
| 45 | static const uint8_t fs_imgui_latlong_dx9[553] = |
| 46 | 46 | { |
| 47 | 47 | 0x46, 0x53, 0x48, 0x03, 0x6f, 0x1e, 0x3e, 0x3c, 0x01, 0x00, 0x11, 0x75, 0x5f, 0x69, 0x6d, 0x61, // FSH.o.><...u_ima |
| 48 | 48 | 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x15, 0x01, 0x00, 0x00, // geLodEnabled.... |
| 49 | | 0x01, 0x00, 0xf4, 0x01, 0x00, 0x03, 0xff, 0xff, 0xfe, 0xff, 0x30, 0x00, 0x43, 0x54, 0x41, 0x42, // ..........0.CTAB |
| 49 | 0x01, 0x00, 0x04, 0x02, 0x00, 0x03, 0xff, 0xff, 0xfe, 0xff, 0x30, 0x00, 0x43, 0x54, 0x41, 0x42, // ..........0.CTAB |
| 50 | 50 | 0x1c, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, // ................ |
| 51 | 51 | 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, // ............D... |
| 52 | 52 | 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........P....... |
| r244651 | r244652 | |
| 71 | 71 | 0x01, 0x00, 0x00, 0xa0, 0x13, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x80, // ................ |
| 72 | 72 | 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x55, 0xa0, // ..............U. |
| 73 | 73 | 0x01, 0x00, 0xaa, 0xa0, 0x25, 0x00, 0x00, 0x02, 0x02, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x80, // ....%........... |
| 74 | | 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x80, 0x01, 0x00, 0xc5, 0x80, 0x02, 0x00, 0x55, 0x81, // ..............U. |
| 74 | 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x55, 0x80, // ..............U. |
| 75 | 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x80, 0x01, 0x00, 0x55, 0x80, 0x02, 0x00, 0x55, 0x81, // ..........U...U. |
| 75 | 76 | 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x80, 0x02, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x02, // ................ |
| 76 | 77 | 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0xa0, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, // ........_....... |
| 77 | 78 | 0x00, 0x00, 0xe4, 0x80, 0x00, 0x08, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x07, 0x80, // ................ |
| r244651 | r244652 | |
| 83 | 84 | { |
| 84 | 85 | 0x46, 0x53, 0x48, 0x03, 0x6f, 0x1e, 0x3e, 0x3c, 0x01, 0x00, 0x11, 0x75, 0x5f, 0x69, 0x6d, 0x61, // FSH.o.><...u_ima |
| 85 | 86 | 0x67, 0x65, 0x4c, 0x6f, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x15, 0x00, 0x30, 0x0a, // geLodEnabled..0. |
| 86 | | 0x01, 0x00, 0x30, 0x02, 0x44, 0x58, 0x42, 0x43, 0xbb, 0x3e, 0xd7, 0x3a, 0x63, 0xc9, 0x70, 0x0b, // ..0.DXBC.>.:c.p. |
| 87 | | 0xa5, 0x2c, 0x7d, 0xb2, 0x3c, 0x0c, 0x75, 0x44, 0x01, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, // .,}.<.uD....0... |
| 87 | 0x01, 0x00, 0x30, 0x02, 0x44, 0x58, 0x42, 0x43, 0x89, 0x11, 0x25, 0xa6, 0xf5, 0x66, 0x12, 0x3f, // ..0.DXBC..%..f.? |
| 88 | 0xc0, 0x1f, 0x67, 0x9b, 0x6e, 0x4e, 0xac, 0x03, 0x01, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, // ..g.nN......0... |
| 88 | 89 | 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, // ....,........... |
| 89 | 90 | 0x49, 0x53, 0x47, 0x4e, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ISGNP........... |
| 90 | 91 | 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // 8............... |
| r244651 | r244652 | |
| 100 | 101 | 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x30, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, // .`......X0...p.. |
| 101 | 102 | 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, // ....UU..b...2... |
| 102 | 103 | 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....e.... ...... |
| 103 | | 0x68, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x0a, 0x32, 0x00, 0x10, 0x00, // h.......8...2... |
| 104 | | 0x00, 0x00, 0x00, 0x00, 0x16, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, // .............@.. |
| 105 | | 0xdb, 0x0f, 0x49, 0x40, 0xdb, 0x0f, 0xc9, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ..I@...@........ |
| 106 | | 0x4d, 0x00, 0x00, 0x06, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, // M...B........... |
| 107 | | 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x07, 0x82, 0x00, 0x10, 0x00, // ........M....... |
| 108 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, // ............A... |
| 104 | 0x68, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x0a, 0x32, 0x00, 0x10, 0x00, // h.......8...2... |
| 105 | 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, // ....F........@.. |
| 106 | 0xdb, 0x0f, 0xc9, 0x40, 0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ...@..I@........ |
| 107 | 0x4d, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, // M...B........... |
| 108 | 0x1a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x06, // ....A.......M... |
| 109 | 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x16, 0x05, 0x10, 0x00, // 2............... |
| 109 | 110 | 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x06, 0x00, 0xd0, 0x00, 0x00, 0x62, 0x00, 0x10, 0x00, // ....M.......b... |
| 110 | | 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, // ............8... |
| 111 | | 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........*....... |
| 112 | | 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x82, 0x00, 0x10, 0x00, // :.......8....... |
| 113 | | 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, // ....:.......*... |
| 114 | | 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0c, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....H........... |
| 115 | | 0x46, 0x03, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // F.......F~...... |
| 111 | 0x02, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, // ............8... |
| 112 | 0x82, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........*....... |
| 113 | 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, // ........8....... |
| 114 | 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, // ................ |
| 115 | 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0c, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....H........... |
| 116 | 0x86, 0x03, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........F~...... |
| 116 | 117 | 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // .`........ ..... |
| 117 | 118 | 0xa3, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....6...r ...... |
| 118 | 119 | 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x82, 0x20, 0x10, 0x00, // F.......2.... .. |
trunk/3rdparty/genie/src/host/scripts.c
| r244651 | r244652 | |
| 69 | 69 | "m)\ntbl[item] = item\nend\nend\nend\nreturn tbl\nend\nlocal function removevalues(tbl, removes)\nfor i=#tbl,1,-1 do\n for _, pattern in ipairs(removes) do\n if pattern == tbl[i] then\n table.remove(tbl, i)\n break\n end\n end\n end\nend\nlocal function mergeobject(dest, src)\nif not src then \nreturn \nend\nfor fieldname, value in pairs(src) do\nif not nocopy[fieldname] then\nlocal field = premake.fields[fieldname]\nif field then\nif type(value) == \"table\" then\ndest[fieldname] = mergefield(field.kind, dest[fieldname], value)\nif src.removes then\nremoves = src.removes[fieldname]\nif removes then\nremovevalues(dest[fieldname], removes)\nend\nend\nelse\ndest[fieldname] = value\nend\nelse\ndest[fieldname] = value\nend\nend\nend\nend\nlocal function merge(dest, obj, basis, terms, cfgname, pltname)\nlocal key = cfgname or \"\"\npltname = pltname or \"Native\"\nif pltname ~= \"Native\" then\nkey = key .. pltname\nend" |
| 70 | 70 | "\nterms.config = (cfgname or \"\"):lower()\nterms.platform = pltname:lower()\nlocal cfg = {}\nmergeobject(cfg, basis[key])\nadjustpaths(obj.location, cfg)\nmergeobject(cfg, obj)\nif (cfg.kind) then \nterms['kind']=cfg.kind:lower()\nend\nfor _, blk in ipairs(obj.blocks) do\nif (premake.iskeywordsmatch(blk.keywords, terms))then\nmergeobject(cfg, blk)\nif (cfg.kind and not cfg.terms.kind) then \ncfg.terms['kind'] = cfg.kind:lower()\nterms['kind'] = cfg.kind:lower()\nend\nend\nend\ncfg.name = cfgname\ncfg.platform = pltname\nfor k,v in pairs(terms) do\ncfg.terms[k] =v\nend\ndest[key] = cfg\nend\nlocal function collapse(obj, basis)\nlocal result = {}\nbasis = basis or {}\nlocal sln = obj.solution or obj\nlocal terms = premake.getactiveterms()\nmerge(result, obj, basis, terms)--this adjusts terms\nfor _, cfgname in ipairs(sln.configurations) do\nlocal terms_local = {}\nfor k,v in pairs(terms)do terms_local[k]=v end\nmerge(result, obj, basis, terms_local, cfgname, \"Native\")--terms cam also be adjusted here\nf" |
| 71 | 71 | "or _, pltname in ipairs(sln.platforms or {}) do\nif pltname ~= \"Native\" then\nmerge(result, obj, basis,terms_local, cfgname, pltname)--terms also here\nend\nend\nend\nreturn result\nend\nlocal function builduniquedirs()\nlocal num_variations = 4\nlocal cfg_dirs = {}\nlocal hit_counts = {}\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nfor _, cfg in pairs(prj.__configs) do\nlocal dirs = { }\ndirs[1] = path.getabsolute(path.join(cfg.location, cfg.objdir or cfg.project.objdir or \"obj\"))\ndirs[2] = path.join(dirs[1], iif(cfg.platform == \"Native\", \"\", cfg.platform))\ndirs[3] = path.join(dirs[2], cfg.name)\ndirs[4] = path.join(dirs[3], cfg.project.name)\ncfg_dirs[cfg] = dirs\nlocal start = iif(cfg.name, 2, 1)\nfor v = start, num_variations do\nlocal d = dirs[v]\nhit_counts[d] = (hit_counts[d] or 0) + 1\nend\nend\nend\nend\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nfor _, cfg in pairs(prj.__configs) do\nlocal dir\nlocal start = iif(cfg.name, " |
| 72 | | "2, 1)\nfor v = start, num_variations do\ndir = cfg_dirs[cfg][v]\nif hit_counts[dir] == 1 then break end\nend\nif (cfg.flags.SingleOutputDir) then\ncfg.objectsdir = cfg.objdir or cfg.project.objdir or \"obj\"\nelse\ncfg.objectsdir = path.getrelative(cfg.location, dir)\nend\nend\nend\nend\nend\nlocal function buildtargets()\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nfor _, cfg in pairs(prj.__configs) do\nlocal pathstyle = premake.getpathstyle(cfg)\nlocal namestyle = premake.getnamestyle(cfg)\ncfg.buildtarget = premake.gettarget(cfg, \"build\", pathstyle, namestyle, cfg.system)\ncfg.linktarget = premake.gettarget(cfg, \"link\", pathstyle, namestyle, cfg.system)\nif pathstyle == \"windows\" then\ncfg.objectsdir = path.translate(cfg.objectsdir, \"\\\\\")\nend\nend\nend\nend\nend\n local function getCfgKind(cfg)\n if(cfg.kind) then\n return cfg.kind;\n end\n \n if(cfg.project.__configs[\"\"] and cfg.project.__configs[\"\"].kind) then\n return cfg.project.__configs[\"\"].k" |
| 73 | | "ind;\n end\n \n return nil\n end\n \n local function getprojrec(dstArray, foundList, cfg, cfgname, searchField, bLinkage)\n if(not cfg) then return end\n \n local foundUsePrjs = {};\n for _, useName in ipairs(cfg[searchField]) do\n local testName = useName:lower();\n if((not foundList[testName])) then\n local theProj = nil;\n local theUseProj = nil;\n for _, prj in ipairs(cfg.project.solution.projects) do\n if (prj.name:lower() == testName) then\n if(prj.usage) then\n theUseProj = prj;\n else\n theProj = prj;\n end\n end\n end\n \n --Must connect to a usage project.\n if(theUseProj) then\n foundList[testName] = true;\n local prjEntry = {\n name = testName,\n proj = theProj,\n usageProj = theUseProj,\n bLinkageOnly = bLinkage,\n };\n dstArray[testName] = prjEntry;\n table.insert(foundUsePrjs, theUseProj);\n end\n end\n end\n \n for _, usePrj in ipairs(foundUsePrjs) do\n --Links can only recurse through static libraries.\n if((searchField ~= \"links\") or\n (getCfgKind(" |
| 74 | | "usePrj.__configs[cfgname]) == \"StaticLib\")) then\n getprojrec(dstArray, foundList, usePrj.__configs[cfgname],\n cfgname, searchField, bLinkage);\n end\n end\n end\n \n --\n -- This function will recursively get all projects that the given configuration has in its \"uses\"\n -- field. The return values are a list of tables. Each table in that list contains the following:\n --name = The lowercase name of the project.\n --proj = The project. Can be nil if it is usage-only.\n --usageProj = The usage project. Can't be nil, as using a project that has no\n -- usage project is not put into the list.\n --bLinkageOnly = If this is true, then only the linkage information should be copied.\n -- The recursion will only look at the \"uses\" field on *usage* projects.\n -- This function will also add projects to the list that are mentioned in the \"links\"\n -- field of usage projects. These will only copy linker information, but they will recurse.\n -- through other \"links\" fields.\n --\n local func" |
| 75 | | "tion getprojectsconnections(cfg, cfgname)\n local dstArray = {};\n local foundList = {};\n foundList[cfg.project.name:lower()] = true;\n \n --First, follow the uses recursively.\n getprojrec(dstArray, foundList, cfg, cfgname, \"uses\", false);\n \n --Next, go through all of the usage projects and recursively get their links.\n --But only if they're not already there. Get the links as linkage-only.\n local linkArray = {};\n for prjName, prjEntry in pairs(dstArray) do\n getprojrec(linkArray, foundList, prjEntry.usageProj.__configs[cfgname], cfgname, \n \"links\", true);\n end\n \n --Copy from linkArray into dstArray.\n for prjName, prjEntry in pairs(linkArray) do\n dstArray[prjName] = prjEntry;\n end\n \n return dstArray;\n end\n \n \n local function isnameofproj(cfg, strName)\n local sln = cfg.project.solution;\n local strTest = strName:lower();\n for prjIx, prj in ipairs(sln.projects) do\n if (prj.name:lower() == strTest) then\n return true;\n end\n end\n \n return false;\n e" |
| 76 | | "nd\n --\n -- Copies the field from dstCfg to srcCfg.\n --\n local function copydependentfield(srcCfg, dstCfg, strSrcField)\n local srcField = premake.fields[strSrcField];\n local strDstField = strSrcField;\n \n if type(srcCfg[strSrcField]) == \"table\" then\n --handle paths.\n if (srcField.kind == \"dirlist\" or srcField.kind == \"filelist\") and\n (not keeprelative[strSrcField]) then\n for i,p in ipairs(srcCfg[strSrcField]) do\n table.insert(dstCfg[strDstField],\n path.rebase(p, srcCfg.project.location, dstCfg.project.location))\n end\n else\n if(strSrcField == \"links\") then\n for i,p in ipairs(srcCfg[strSrcField]) do\n if(not isnameofproj(dstCfg, p)) then\n table.insert(dstCfg[strDstField], p)\n else\n printf(\"Failed to copy '%s' from proj '%s'.\",\n p, srcCfg.project.name);\n end\n end\n else\n for i,p in ipairs(srcCfg[strSrcField]) do\n table.insert(dstCfg[strDstField], p)\n end\n end\n end\n else\n if(srcField.kind == \"path\" and (not keeprelative[strSrcField])) then\n" |
| 77 | | " dstCfg[strDstField] = path.rebase(srcCfg[strSrcField],\n prj.location, dstCfg.project.location);\n else\n dstCfg[strDstField] = srcCfg[strSrcField];\n end\n end\n end\n \n --\n -- This function will take the list of project entries and apply their usage project data\n -- to the given configuration. It will copy compiling information for the projects that are\n -- not listed as linkage-only. It will copy the linking information for projects only if\n -- the source project is not a static library. It won't copy linking information\n -- if the project is in this solution; instead it will add that project to the configuration's\n -- links field, expecting that Premake will handle the rest.\n --\n local function copyusagedata(cfg, cfgname, linkToProjs)\n local myPrj = cfg.project;\n local bIsStaticLib = (getCfgKind(cfg) == \"StaticLib\");\n \n for prjName, prjEntry in pairs(linkToProjs) do\n local srcPrj = prjEntry.usageProj;\n local srcCfg = srcPrj.__configs[cfgname];\n \n for name, field" |
| 78 | | " in pairs(premake.fields) do\n if(srcCfg[name]) then\n if(field.usagecopy) then\n if(not prjEntry.bLinkageOnly) then\n copydependentfield(srcCfg, cfg, name)\n end\n elseif(field.linkagecopy) then\n --Copy the linkage data if we're building a non-static thing\n --and this is a pure usage project. If it's not pure-usage, then\n --we will simply put the project's name in the links field later.\n if((not bIsStaticLib) and (not prjEntry.proj)) then\n copydependentfield(srcCfg, cfg, name)\n end\n end\n end\n end\n \n if((not bIsStaticLib) and prjEntry.proj) then\n table.insert(cfg.links, prjEntry.proj.name);\n end\n end\n end\nfunction premake.bake.buildconfigs()\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nprj.location = prj.location or sln.location or prj.basedir\nadjustpaths(prj.location, prj)\nfor _, blk in ipairs(prj.blocks) do\nadjustpaths(prj.location, blk)\nend\nend\nsln.location = sln.location or sln.basedir\nend\nfor sln in premake.solution.each() do\n" |
| 79 | | "local basis = collapse(sln)\nfor _, prj in ipairs(sln.projects) do\nprj.__configs = collapse(prj, basis)\nfor _, cfg in pairs(prj.__configs) do\nbake.postprocess(prj, cfg)\nend\nend\nend\nfor sln in premake.solution.each() do\nfor prjIx, prj in ipairs(sln.projects) do\nif(not prj.usage) then\nfor cfgname, cfg in pairs(prj.__configs) do\nlocal usesPrjs = getprojectsconnections(cfg, cfgname);\ncopyusagedata(cfg, cfgname, usesPrjs)\nend\nend\nend\nend\nfor sln in premake.solution.each() do\nlocal removeList = {};\nfor index, prj in ipairs(sln.projects) do\nif(prj.usage) then\ntable.insert(removeList, 1, index); --Add in reverse order.\nend\nend\nfor _, index in ipairs(removeList) do\ntable.remove(sln.projects, index);\nend\nend\nbuilduniquedirs()\nbuildtargets(cfg)\nend\nfunction premake.bake.postprocess(prj, cfg)\ncfg.project = prj\ncfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true)\ncfg.longname = premake.getconfigname(cfg.name, cfg.platform)\ncfg.location = cfg.location or cfg.basedir\nloca" |
| 80 | | "l platform = premake.platforms[cfg.platform]\nif platform.iscrosscompiler then\ncfg.system = cfg.platform\nelse\ncfg.system = os.get()\nend\nif cfg.kind == \"SharedLib\" and platform.nosharedlibs then\ncfg.kind = \"StaticLib\"\nend\nlocal files = { }\nfor _, fname in ipairs(cfg.files) do\nlocal excluded = false\nfor _, exclude in ipairs(cfg.excludes) do\nexcluded = (fname == exclude)\nif (excluded) then break end\nend\nif (not excluded) then\ntable.insert(files, fname)\nend\nend\ncfg.files = files\nfor name, field in pairs(premake.fields) do\nif field.isflags then\nlocal values = cfg[name]\nfor _, flag in ipairs(values) do values[flag] = true end\nend\nend\ncfg.__fileconfigs = { }\nfor _, fname in ipairs(cfg.files) do\ncfg.terms.required = fname:lower()\nlocal fcfg = {}\nfor _, blk in ipairs(cfg.project.blocks) do\nif (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then\nmergeobject(fcfg, blk)\nend\nend\nfcfg.name = fname\ncfg.__fileconfigs[fname] = fcfg\ntable.insert(cfg.__fileconfigs, fcfg)\nend\nend\n", |
| 72 | "2, 1)\nfor v = start, num_variations do\ndir = cfg_dirs[cfg][v]\nif hit_counts[dir] == 1 then break end\nend\ncfg.objectsdir = path.getrelative(cfg.location, dir)\nend\nend\nend\nend\nlocal function buildtargets()\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nfor _, cfg in pairs(prj.__configs) do\nlocal pathstyle = premake.getpathstyle(cfg)\nlocal namestyle = premake.getnamestyle(cfg)\ncfg.buildtarget = premake.gettarget(cfg, \"build\", pathstyle, namestyle, cfg.system)\ncfg.linktarget = premake.gettarget(cfg, \"link\", pathstyle, namestyle, cfg.system)\nif pathstyle == \"windows\" then\ncfg.objectsdir = path.translate(cfg.objectsdir, \"\\\\\")\nend\nend\nend\nend\nend\n local function getCfgKind(cfg)\n if(cfg.kind) then\n return cfg.kind;\n end\n \n if(cfg.project.__configs[\"\"] and cfg.project.__configs[\"\"].kind) then\n return cfg.project.__configs[\"\"].kind;\n end\n \n return nil\n end\n \n local function getprojrec(dstArray, foundList, cfg, cfgname, searc" |
| 73 | "hField, bLinkage)\n if(not cfg) then return end\n \n local foundUsePrjs = {};\n for _, useName in ipairs(cfg[searchField]) do\n local testName = useName:lower();\n if((not foundList[testName])) then\n local theProj = nil;\n local theUseProj = nil;\n for _, prj in ipairs(cfg.project.solution.projects) do\n if (prj.name:lower() == testName) then\n if(prj.usage) then\n theUseProj = prj;\n else\n theProj = prj;\n end\n end\n end\n \n --Must connect to a usage project.\n if(theUseProj) then\n foundList[testName] = true;\n local prjEntry = {\n name = testName,\n proj = theProj,\n usageProj = theUseProj,\n bLinkageOnly = bLinkage,\n };\n dstArray[testName] = prjEntry;\n table.insert(foundUsePrjs, theUseProj);\n end\n end\n end\n \n for _, usePrj in ipairs(foundUsePrjs) do\n --Links can only recurse through static libraries.\n if((searchField ~= \"links\") or\n (getCfgKind(usePrj.__configs[cfgname]) == \"StaticLib\")) then\n getprojrec(dstArray, foundList, usePrj.__configs[cfgname" |
| 74 | "],\n cfgname, searchField, bLinkage);\n end\n end\n end\n \n --\n -- This function will recursively get all projects that the given configuration has in its \"uses\"\n -- field. The return values are a list of tables. Each table in that list contains the following:\n --name = The lowercase name of the project.\n --proj = The project. Can be nil if it is usage-only.\n --usageProj = The usage project. Can't be nil, as using a project that has no\n -- usage project is not put into the list.\n --bLinkageOnly = If this is true, then only the linkage information should be copied.\n -- The recursion will only look at the \"uses\" field on *usage* projects.\n -- This function will also add projects to the list that are mentioned in the \"links\"\n -- field of usage projects. These will only copy linker information, but they will recurse.\n -- through other \"links\" fields.\n --\n local function getprojectsconnections(cfg, cfgname)\n local dstArray = {};\n local foundList = {};\n foundList[cfg.pr" |
| 75 | "oject.name:lower()] = true;\n \n --First, follow the uses recursively.\n getprojrec(dstArray, foundList, cfg, cfgname, \"uses\", false);\n \n --Next, go through all of the usage projects and recursively get their links.\n --But only if they're not already there. Get the links as linkage-only.\n local linkArray = {};\n for prjName, prjEntry in pairs(dstArray) do\n getprojrec(linkArray, foundList, prjEntry.usageProj.__configs[cfgname], cfgname, \n \"links\", true);\n end\n \n --Copy from linkArray into dstArray.\n for prjName, prjEntry in pairs(linkArray) do\n dstArray[prjName] = prjEntry;\n end\n \n return dstArray;\n end\n \n \n local function isnameofproj(cfg, strName)\n local sln = cfg.project.solution;\n local strTest = strName:lower();\n for prjIx, prj in ipairs(sln.projects) do\n if (prj.name:lower() == strTest) then\n return true;\n end\n end\n \n return false;\n end\n --\n -- Copies the field from dstCfg to srcCfg.\n --\n local function copydependentfield(srcCfg, dstC" |
| 76 | "fg, strSrcField)\n local srcField = premake.fields[strSrcField];\n local strDstField = strSrcField;\n \n if type(srcCfg[strSrcField]) == \"table\" then\n --handle paths.\n if (srcField.kind == \"dirlist\" or srcField.kind == \"filelist\") and\n (not keeprelative[strSrcField]) then\n for i,p in ipairs(srcCfg[strSrcField]) do\n table.insert(dstCfg[strDstField],\n path.rebase(p, srcCfg.project.location, dstCfg.project.location))\n end\n else\n if(strSrcField == \"links\") then\n for i,p in ipairs(srcCfg[strSrcField]) do\n if(not isnameofproj(dstCfg, p)) then\n table.insert(dstCfg[strDstField], p)\n else\n printf(\"Failed to copy '%s' from proj '%s'.\",\n p, srcCfg.project.name);\n end\n end\n else\n for i,p in ipairs(srcCfg[strSrcField]) do\n table.insert(dstCfg[strDstField], p)\n end\n end\n end\n else\n if(srcField.kind == \"path\" and (not keeprelative[strSrcField])) then\n dstCfg[strDstField] = path.rebase(srcCfg[strSrcField],\n prj.location, dstCfg.project.location);\n else\n " |
| 77 | " dstCfg[strDstField] = srcCfg[strSrcField];\n end\n end\n end\n \n --\n -- This function will take the list of project entries and apply their usage project data\n -- to the given configuration. It will copy compiling information for the projects that are\n -- not listed as linkage-only. It will copy the linking information for projects only if\n -- the source project is not a static library. It won't copy linking information\n -- if the project is in this solution; instead it will add that project to the configuration's\n -- links field, expecting that Premake will handle the rest.\n --\n local function copyusagedata(cfg, cfgname, linkToProjs)\n local myPrj = cfg.project;\n local bIsStaticLib = (getCfgKind(cfg) == \"StaticLib\");\n \n for prjName, prjEntry in pairs(linkToProjs) do\n local srcPrj = prjEntry.usageProj;\n local srcCfg = srcPrj.__configs[cfgname];\n \n for name, field in pairs(premake.fields) do\n if(srcCfg[name]) then\n if(field.usagecopy) then\n if(not prjEntry.bLinkageO" |
| 78 | "nly) then\n copydependentfield(srcCfg, cfg, name)\n end\n elseif(field.linkagecopy) then\n --Copy the linkage data if we're building a non-static thing\n --and this is a pure usage project. If it's not pure-usage, then\n --we will simply put the project's name in the links field later.\n if((not bIsStaticLib) and (not prjEntry.proj)) then\n copydependentfield(srcCfg, cfg, name)\n end\n end\n end\n end\n \n if((not bIsStaticLib) and prjEntry.proj) then\n table.insert(cfg.links, prjEntry.proj.name);\n end\n end\n end\nfunction premake.bake.buildconfigs()\nfor sln in premake.solution.each() do\nfor _, prj in ipairs(sln.projects) do\nprj.location = prj.location or sln.location or prj.basedir\nadjustpaths(prj.location, prj)\nfor _, blk in ipairs(prj.blocks) do\nadjustpaths(prj.location, blk)\nend\nend\nsln.location = sln.location or sln.basedir\nend\nfor sln in premake.solution.each() do\nlocal basis = collapse(sln)\nfor _, prj in ipairs(sln.projects) do\nprj.__configs = collapse(prj, basis)\nfor " |
| 79 | "_, cfg in pairs(prj.__configs) do\nbake.postprocess(prj, cfg)\nend\nend\nend\nfor sln in premake.solution.each() do\nfor prjIx, prj in ipairs(sln.projects) do\nif(not prj.usage) then\nfor cfgname, cfg in pairs(prj.__configs) do\nlocal usesPrjs = getprojectsconnections(cfg, cfgname);\ncopyusagedata(cfg, cfgname, usesPrjs)\nend\nend\nend\nend\nfor sln in premake.solution.each() do\nlocal removeList = {};\nfor index, prj in ipairs(sln.projects) do\nif(prj.usage) then\ntable.insert(removeList, 1, index); --Add in reverse order.\nend\nend\nfor _, index in ipairs(removeList) do\ntable.remove(sln.projects, index);\nend\nend\nbuilduniquedirs()\nbuildtargets(cfg)\nend\nfunction premake.bake.postprocess(prj, cfg)\ncfg.project = prj\ncfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true)\ncfg.longname = premake.getconfigname(cfg.name, cfg.platform)\ncfg.location = cfg.location or cfg.basedir\nlocal platform = premake.platforms[cfg.platform]\nif platform.iscrosscompiler then\ncfg.system = cfg.platform\nels" |
| 80 | "e\ncfg.system = os.get()\nend\nif cfg.kind == \"SharedLib\" and platform.nosharedlibs then\ncfg.kind = \"StaticLib\"\nend\nlocal files = { }\nfor _, fname in ipairs(cfg.files) do\nlocal excluded = false\nfor _, exclude in ipairs(cfg.excludes) do\nexcluded = (fname == exclude)\nif (excluded) then break end\nend\nif (not excluded) then\ntable.insert(files, fname)\nend\nend\ncfg.files = files\nfor name, field in pairs(premake.fields) do\nif field.isflags then\nlocal values = cfg[name]\nfor _, flag in ipairs(values) do values[flag] = true end\nend\nend\ncfg.__fileconfigs = { }\nfor _, fname in ipairs(cfg.files) do\ncfg.terms.required = fname:lower()\nlocal fcfg = {}\nfor _, blk in ipairs(cfg.project.blocks) do\nif (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then\nmergeobject(fcfg, blk)\nend\nend\nfcfg.name = fname\ncfg.__fileconfigs[fname] = fcfg\ntable.insert(cfg.__fileconfigs, fcfg)\nend\nend\n", |
| 81 | 81 | |
| 82 | 82 | /* base/api.lua */ |
| 83 | | "premake.fields =\n{\narchivesplit_size =\n{\nkind = \"string\",\nscope = \"config\",\n},\nbasedir =\n{\nkind = \"path\",\nscope = \"container\",\n},\nbuildaction =\n{\nkind = \"string\",\nscope = \"config\",\nallowed = {\n\"Compile\",\n\"Copy\",\n\"Embed\",\n\"None\"\n}\n},\nbuildoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nbuildoptions_c =\n{\nkind = \"list\",\nscope = \"config\",\n},\nbuildoptions_cpp =\n{\nkind = \"list\",\nscope = \"config\",\n},\nconfigurations =\n{\nkind = \"list\",\nscope = \"solution\",\n},\ndebugargs =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndebugdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\ndebugenvs =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndefines =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndeploymentoptions =\n{\nkind = \"list\",\nscope = \"config\",\nusagecopy = true,\n},\nexcludes =\n{\nkind = \"filelist\",\nscope = \"config\",\n},\nfiles =\n{\nkind = \"filelist\",\nscope = \"config\",\n},\nflags =\n{\nkind = \"list\",\nscope = " |
| 84 | | "\"config\",\nisflags = true,\nusagecopy = true,\nallowed = function(value)\nlocal allowed_flags = {\nATL = 1,\nDebugEnvsDontMerge = 1,\nDebugEnvsInherit = 1,\nEnableMinimalRebuild = 1,\nEnableSSE = 1,\nEnableSSE2 = 1,\nExtraWarnings = 1,\nFatalWarnings = 1,\nFloatFast = 1,\nFloatStrict = 1,\nManaged = 1,\nMFC = 1,\nNativeWChar = 1,\nNo64BitChecks = 1,\nNoEditAndContinue = 1,\nNoExceptions = 1,\nNoFramePointer = 1,\nNoImportLib = 1,\nNoIncrementalLink = 1,\nNoManifest = 1,\nNoMultiProcessorCompilation = 1,\nNoNativeWChar = 1,\nNoPCH = 1,\nNoRTTI = 1,\nSingleOutputDir = 1,\nOptimize = 1,\nOptimizeSize = 1,\nOptimizeSpeed = 1,\nSEH = 1,\nStaticATL = 1,\nStaticRuntime = 1,\nSymbols = 1,\nUnicode = 1,\nUnsafe = 1,\nUnsignedChar = 1,\nWinMain = 1,\n}\nlocal englishToAmericanSpelling =\n{\noptimise = 'optimize',\noptimisesize = 'optimizesize',\noptimisespeed = 'optimizespeed',\n}\nlocal lowervalue = value:lower()\nlowervalue = englishToAmericanSpelling[lowervalue] or lowervalue\nfor v, _ in pairs(allowed_flags) do\ni" |
| 85 | | "f v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid flag\"\nend,\n},\nframework =\n{\nkind = \"string\",\nscope = \"container\",\nallowed = {\n\"1.0\",\n\"1.1\",\n\"2.0\",\n\"3.0\",\n\"3.5\",\n\"4.0\",\n\"4.5\",\n}\n},\nforcedincludes = \n{\nkind = \"absolutefilelist\",\nscope = \"config\",\n},\nimagepath =\n{\nkind = \"path\",\nscope = \"config\",\n},\nimageoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nimplibdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\nimplibextension =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibname =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibprefix =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibsuffix =\n{\nkind = \"string\",\nscope = \"config\",\n},\nincludedirs =\n{\nkind = \"dirlist\",\nscope = \"config\",\nusagecopy = true,\n},\nkind =\n{\nkind = \"string\",\nscope = \"config\",\nallowed = {\n\"ConsoleApp\",\n\"WindowedApp\",\n\"StaticLib\",\n\"SharedLib\"\n}\n},\nlanguage =\n{\nkind = \"string\",\nsco" |
| 86 | | "pe = \"container\",\nallowed = {\n\"C\",\n\"C++\",\n\"C#\"\n}\n},\nlibdirs =\n{\nkind = \"dirlist\",\nscope = \"config\",\nlinkagecopy = true,\n},\nlinkoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nlinks =\n{\nkind = \"list\",\nscope = \"config\",\nallowed = function(value)\nif value:find('/', nil, true) then\nvalue = path.getabsolute(value)\nend\nreturn value\nend,\nlinkagecopy = true,\n},\nlocation =\n{\nkind = \"path\",\nscope = \"container\",\n},\nmakesettings =\n{\nkind = \"list\",\nscope = \"config\",\n},\nmessageskip =\n{\nkind = \"list\",\nscope = \"solution\",\nisflags = true,\nusagecopy = true,\nallowed = function(value)\nlocal allowed_messages = {\nSkipCreatingMessage = 1,\nSkipBuildingMessage = 1,\nSkipCleaningMessage = 1,\n}\nlocal lowervalue = value:lower()\nfor v, _ in pairs(allowed_messages) do\nif v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid message to skip\"\nend,\n},\nmsgarchiving =\n{\nkind = \"string\",\nscope = \"config\",\n},\nmsgcompile =\n{\n" |
| 87 | | "kind = \"string\",\nscope = \"config\",\n},\nmsgresource =\n{\nkind = \"string\",\nscope = \"config\",\n},\nmsglinking =\n{\nkind = \"string\",\nscope = \"config\",\n},\nobjdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\noptions =\n{\nkind = \"list\",\nscope = \"container\",\nisflags = true,\nusagecopy = true,\nallowed = function(value)\nlocal allowed_options = {\nForceCPP = 1,\nArchiveSplit = 1\n}\nlocal lowervalue = value:lower()\nfor v, _ in pairs(allowed_options) do\nif v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid option\"\nend,\n},\npchheader =\n{\nkind = \"string\",\nscope = \"config\",\n},\npchsource =\n{\nkind = \"path\",\nscope = \"config\",\n},\nplatforms =\n{\nkind = \"list\",\nscope = \"solution\",\nallowed = table.keys(premake.platforms),\n},\npostbuildcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nprebuildcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nprelinkcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nresdefines =\n{\n" |
| 88 | | "kind = \"list\",\nscope = \"config\",\n},\nresincludedirs =\n{\nkind = \"dirlist\",\nscope = \"config\",\n},\nresoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nstartproject =\n{\nkind = \"string\",\nscope = \"solution\",\n},\ntargetdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\ntargetsubdir =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetextension =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetname =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetprefix =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetsuffix =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntrimpaths =\n{\nkind = \"dirlist\",\nscope = \"config\",\n},\nuuid =\n{\nkind = \"string\",\nscope = \"container\",\nallowed = function(value)\nlocal ok = true\nif (#value ~= 36) then ok = false end\nfor i=1,36 do\nlocal ch = value:sub(i,i)\nif (not ch:find(\"[ABCDEFabcdef0123456789-]\")) then ok = false end\nend\nif (value:sub(9,9) ~= \"-\") then ok = false end\nif (value:sub(14,14) ~= \"-\")" |
| 89 | | " then ok = false end\nif (value:sub(19,19) ~= \"-\") then ok = false end\nif (value:sub(24,24) ~= \"-\") then ok = false end\nif (not ok) then\nreturn nil, \"invalid UUID\"\nend\nreturn value:upper()\nend\n},\nuses =\n{\nkind = \"list\",\nscope = \"config\",\n},\nvpaths =\n{\nkind = \"keypath\",\nscope = \"container\",\n},\n}\nfunction premake.checkvalue(value, allowed)\nif (allowed) then\nif (type(allowed) == \"function\") then\nreturn allowed(value)\nelse\nfor _,v in ipairs(allowed) do\nif (value:lower() == v:lower()) then\nreturn v\nend\nend\nreturn nil, \"invalid value '\" .. value .. \"'\"\nend\nelse\nreturn value\nend\nend\nfunction premake.getobject(t)\nlocal container\nif (t == \"container\" or t == \"solution\") then\ncontainer = premake.CurrentContainer\nelse\ncontainer = premake.CurrentConfiguration\nend\nif t == \"solution\" then\nif type(container) == \"project\" then\ncontainer = container.solution\nend\nif type(container) ~= \"solution\" then\ncontainer = nil\nend\nend\nlocal msg\nif (not conta" |
| 90 | | "iner) then\nif (t == \"container\") then\nmsg = \"no active solution or project\"\nelseif (t == \"solution\") then\nmsg = \"no active solution\"\nelse\nmsg = \"no active solution, project, or configuration\"\nend\nend\nreturn container, msg\nend\nfunction premake.setarray(obj, fieldname, value, allowed)\nobj[fieldname] = obj[fieldname] or {}\nlocal function add(value, depth)\nif type(value) == \"table\" then\nfor _,v in ipairs(value) do\nadd(v, depth + 1)\nend\nelse\nvalue, err = premake.checkvalue(value, allowed)\nif not value then\nerror(err, depth)\nend\ntable.insert(obj[fieldname], value)\nend\nend\nif value then\nadd(value, 5)\nend\nreturn obj[fieldname]\nend\nlocal function domatchedarray(ctype, fieldname, value, matchfunc)\nlocal result = { }\nfunction makeabsolute(value, depth)\nif (type(value) == \"table\") then\nfor _, item in ipairs(value) do\nmakeabsolute(item, depth + 1)\nend\nelseif type(value) == \"string\" then\nif value:find(\"*\") then\nmakeabsolute(matchfunc(value), depth + 1)\nelse\ntable.i" |
| 91 | | "nsert(result, path.getabsolute(value))\nend\nelse\nerror(\"Invalid value in list: expected string, got \" .. type(value), depth)\nend\nend\nmakeabsolute(value, 3)\nreturn premake.setarray(ctype, fieldname, result)\nend\nfunction premake.setdirarray(ctype, fieldname, value)\nreturn domatchedarray(ctype, fieldname, value, os.matchdirs)\nend\nfunction premake.setfilearray(ctype, fieldname, value)\nreturn domatchedarray(ctype, fieldname, value, os.matchfiles)\nend\nfunction premake.setkeyvalue(ctype, fieldname, values)\nlocal container, err = premake.getobject(ctype)\nif not container then\nerror(err, 4)\nend\nif not container[fieldname] then\ncontainer[fieldname] = {}\nend\nif type(values) ~= \"table\" then\nerror(\"invalid value; table expected\", 4)\nend\nlocal field = container[fieldname]\nfor key,value in pairs(values) do\nif not field[key] then\nfield[key] = {}\nend\ntable.insertflat(field[key], value)\nend\nreturn field\nend\nfunction premake.setstring(ctype, fieldname, value, allowed)\nlocal container, err" |
| 92 | | " = premake.getobject(ctype)\nif (not container) then\nerror(err, 4)\nend\nif (value) then\nvalue, err = premake.checkvalue(value, allowed)\nif (not value) then\nerror(err, 4)\nend\ncontainer[fieldname] = value\nend\nreturn container[fieldname]\nend\nfunction premake.remove(fieldname, value)\nlocal cfg = premake.CurrentConfiguration\ncfg.removes = cfg.removes or {}\ncfg.removes[fieldname] = premake.setarray(cfg.removes, fieldname, value)\nend\nlocal function accessor(name, value)\nlocal kind = premake.fields[name].kind\nlocal scope = premake.fields[name].scope\nlocal allowed = premake.fields[name].allowed\nif (kind == \"string\" or kind == \"path\") and value then\nif type(value) ~= \"string\" then\nerror(\"string value expected\", 3)\nend\nend\nlocal container, err = premake.getobject(scope)\nif (not container) then\nerror(err, 3)\nend\nif kind == \"string\" then\nreturn premake.setstring(scope, name, value, allowed)\nelseif kind == \"path\" then\nif value then value = path.getabsolute(value) end\nreturn " |
| 93 | | "premake.setstring(scope, name, value)\nelseif kind == \"list\" then\nreturn premake.setarray(container, name, value, allowed)\nelseif kind == \"dirlist\" then\nreturn premake.setdirarray(container, name, value)\nelseif kind == \"filelist\" or kind == \"absolutefilelist\" then\nreturn premake.setfilearray(container, name, value)\nelseif kind == \"keyvalue\" or kind == \"keypath\" then\nreturn premake.setkeyvalue(scope, name, value)\nend\nend\nfor name, info in pairs(premake.fields) do\n_G[name] = function(value)\nreturn accessor(name, value)\nend\nif info.kind == \"list\" or \n info.kind == \"dirlist\" or \n info.kind == \"filelist\" or\n info.kind == \"absolutefilelist\" \nthen\n_G[\"remove\"..name] = function(value)\npremake.remove(name, value)\nend\nend\nend\nfunction configuration(terms)\nif not terms then\nreturn premake.CurrentConfiguration\nend\nlocal container, err = premake.getobject(\"container\")\nif (not container) then\nerror(err, 2)\nend\nlocal cfg = { }\ncfg.terms = table.flatten({terms})\n" |
| 94 | | "table.insert(container.blocks, cfg)\npremake.CurrentConfiguration = cfg\ncfg.keywords = { }\nfor _, word in ipairs(cfg.terms) do\ntable.insert(cfg.keywords, path.wildcards(word):lower())\nend\nfor name, field in pairs(premake.fields) do\nif (field.kind ~= \"string\" and field.kind ~= \"path\") then\ncfg[name] = { }\nend\nend\nreturn cfg\nend\nlocal function creategroup(name, sln, parent, inpath)\nlocal group = {}\nsetmetatable(group, {\n__type = \"group\"\n})\ntable.insert(sln.groups, group)\nsln.groups[inpath] = group\ngroup.solution = sln\ngroup.name = name\ngroup.uuid = os.uuid(group.name)\ngroup.parent = parent\nreturn group\nend\nlocal function creategroupsfrompath(inpath, sln)\nif inpath == nil then return nil end\ninpath = path.translate(inpath, \"/\")\nlocal groups = string.explode(inpath, \"/\")\nlocal curpath = \"\"\nlocal lastgroup = nil\nfor i, v in ipairs(groups) do\ncurpath = curpath .. \"/\" .. v:lower()\nlocal group = sln.groups[curpath]\nif group == nil then\ngroup = creategroup(v, sln, lastgr" |
| 95 | | "oup, curpath)\nend\nlastgroup = group\nend\nreturn lastgroup\nend\nlocal function createproject(name, sln, isUsage)\nlocal prj = {}\nsetmetatable(prj, {\n__type = \"project\",\n})\ntable.insert(sln.projects, prj)\nif(isUsage) then\nif(sln.projects[name]) then\nsln.projects[name].usageProj = prj;\nelse\nsln.projects[name] = prj\nend\nelse\nif(sln.projects[name]) then\nprj.usageProj = sln.projects[name];\nend\nsln.projects[name] = prj\nend\nlocal group = creategroupsfrompath(premake.CurrentGroup, sln)\nprj.solution = sln\nprj.name = name\nprj.basedir = os.getcwd()\nprj.uuid = os.uuid(prj.name)\nprj.blocks = { }\nprj.usage = isUsage\nprj.group = group\nreturn prj;\nend\nfunction usage(name)\nif (not name) then\nif(type(premake.CurrentContainer) ~= \"project\") then return nil end\nif(not premake.CurrentContainer.usage) then return nil end\nreturn premake.CurrentContainer\nend\nlocal sln\nif (type(premake.CurrentContainer) == \"project\") then\nsln = premake.Curr" |
| 96 | | "entContainer.solution\nelse\nsln = premake.CurrentContainer\nend\nif (type(sln) ~= \"solution\") then\nerror(\"no active solution\", 2)\nend\n -- if this is a new project, or the project in that slot doesn't have a usage, create it\n if((not sln.projects[name]) or\n ((not sln.projects[name].usage) and (not sln.projects[name].usageProj))) then\n premake.CurrentContainer = createproject(name, sln, true)\n else\n premake.CurrentContainer = iff(sln.projects[name].usage,\n sln.projects[name], sln.projects[name].usageProj)\n end\n -- add an empty, global configuration to the project\n configuration { }\n return premake.CurrentContainer\n end\n function project(name)\n if (not name) then\n --Only return non-usage projects\n if(type(premake.CurrentContainer) ~= \"project\") then return nil end\n if(premake.CurrentContainer.usage) then return nil end\n return premake.CurrentContainer\nend\n -- identify the parent solution\n local sln\n if (type(premake.CurrentContainer) == \"project\") then\n sln " |
| 97 | | "= premake.CurrentContainer.solution\n else\n sln = premake.CurrentContainer\n end\n if (type(sln) ~= \"solution\") then\n error(\"no active solution\", 2)\n end\n -- if this is a new project, or the old project is a usage project, create it\n if((not sln.projects[name]) or sln.projects[name].usage) then\n premake.CurrentContainer = createproject(name, sln)\n else\n premake.CurrentContainer = sln.projects[name];\n end\nconfiguration { }\nreturn premake.CurrentContainer\nend\nfunction solution(name)\nif not name then\nif type(premake.CurrentContainer) == \"project\" then\nreturn premake.CurrentContainer.solution\nelse\nreturn premake.CurrentContainer\nend\nend\npremake.CurrentContainer = premake.solution.get(name)\nif (not premake.CurrentContainer) then\npremake.CurrentContainer = premake.solution.new(name)\nend\nconfiguration { }\nreturn premake.CurrentContainer\nend\nfunction group(name)\nif not name then \nreturn premake.CurrentGroup\nend\npremake.CurrentGroup = name\nreturn premake.CurrentGroup\n" |
| 98 | | "end\nfunction newaction(a)\npremake.action.add(a)\nend\nfunction newoption(opt)\npremake.option.add(opt)\nend\n", |
| 83 | "premake.fields =\n{\narchivesplit_size =\n{\nkind = \"string\",\nscope = \"config\",\n},\nbasedir =\n{\nkind = \"path\",\nscope = \"container\",\n},\nbuildaction =\n{\nkind = \"string\",\nscope = \"config\",\nallowed = {\n\"Compile\",\n\"Copy\",\n\"Embed\",\n\"None\"\n}\n},\nbuildoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nbuildoptions_cpp =\n{\nkind = \"list\",\nscope = \"config\",\n},\nconfigurations =\n{\nkind = \"list\",\nscope = \"solution\",\n},\ndebugargs =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndebugdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\ndebugenvs =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndefines =\n{\nkind = \"list\",\nscope = \"config\",\n},\ndeploymentoptions =\n{\nkind = \"list\",\nscope = \"config\",\nusagecopy = true,\n},\nexcludes =\n{\nkind = \"filelist\",\nscope = \"config\",\n},\nfiles =\n{\nkind = \"filelist\",\nscope = \"config\",\n},\nflags =\n{\nkind = \"list\",\nscope = \"config\",\nisflags = true,\nusagecopy = true,\nallowed = functi" |
| 84 | "on(value)\nlocal allowed_flags = {\nATL = 1,\nDebugEnvsDontMerge = 1,\nDebugEnvsInherit = 1,\nEnableMinimalRebuild = 1,\nEnableSSE = 1,\nEnableSSE2 = 1,\nExtraWarnings = 1,\nFatalWarnings = 1,\nFloatFast = 1,\nFloatStrict = 1,\nManaged = 1,\nMFC = 1,\nNativeWChar = 1,\nNo64BitChecks = 1,\nNoEditAndContinue = 1,\nNoExceptions = 1,\nNoFramePointer = 1,\nNoImportLib = 1,\nNoIncrementalLink = 1,\nNoManifest = 1,\nNoMultiProcessorCompilation = 1,\nNoNativeWChar = 1,\nNoPCH = 1,\nNoRTTI = 1,\nOptimize = 1,\nOptimizeSize = 1,\nOptimizeSpeed = 1,\nSEH = 1,\nStaticATL = 1,\nStaticRuntime = 1,\nSymbols = 1,\nUnicode = 1,\nUnsafe = 1,\nUnsignedChar = 1,\nWinMain = 1,\n}\nlocal englishToAmericanSpelling =\n{\noptimise = 'optimize',\noptimisesize = 'optimizesize',\noptimisespeed = 'optimizespeed',\n}\nlocal lowervalue = value:lower()\nlowervalue = englishToAmericanSpelling[lowervalue] or lowervalue\nfor v, _ in pairs(allowed_flags) do\nif v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid flag\"\nend," |
| 85 | "\n},\nframework =\n{\nkind = \"string\",\nscope = \"container\",\nallowed = {\n\"1.0\",\n\"1.1\",\n\"2.0\",\n\"3.0\",\n\"3.5\",\n\"4.0\",\n\"4.5\",\n}\n},\nforcedincludes = \n{\nkind = \"absolutefilelist\",\nscope = \"config\",\n},\nimagepath =\n{\nkind = \"path\",\nscope = \"config\",\n},\nimageoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nimplibdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\nimplibextension =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibname =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibprefix =\n{\nkind = \"string\",\nscope = \"config\",\n},\nimplibsuffix =\n{\nkind = \"string\",\nscope = \"config\",\n},\nincludedirs =\n{\nkind = \"dirlist\",\nscope = \"config\",\nusagecopy = true,\n},\nkind =\n{\nkind = \"string\",\nscope = \"config\",\nallowed = {\n\"ConsoleApp\",\n\"WindowedApp\",\n\"StaticLib\",\n\"SharedLib\"\n}\n},\nlanguage =\n{\nkind = \"string\",\nscope = \"container\",\nallowed = {\n\"C\",\n\"C++\",\n\"C#\"\n}\n},\nlibdirs =\n{\nkind " |
| 86 | " = \"dirlist\",\nscope = \"config\",\nlinkagecopy = true,\n},\nlinkoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nlinks =\n{\nkind = \"list\",\nscope = \"config\",\nallowed = function(value)\nif value:find('/', nil, true) then\nvalue = path.getabsolute(value)\nend\nreturn value\nend,\nlinkagecopy = true,\n},\nlocation =\n{\nkind = \"path\",\nscope = \"container\",\n},\nmakesettings =\n{\nkind = \"list\",\nscope = \"config\",\n},\nmessageskip =\n{\nkind = \"list\",\nscope = \"solution\",\nisflags = true,\nusagecopy = true,\nallowed = function(value)\nlocal allowed_messages = {\nSkipCreatingMessage = 1,\nSkipBuildingMessage = 1,\nSkipCleaningMessage = 1,\n}\nlocal lowervalue = value:lower()\nfor v, _ in pairs(allowed_messages) do\nif v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid message to skip\"\nend,\n},\nmsgarchiving =\n{\nkind = \"string\",\nscope = \"config\",\n},\nmsgcompile =\n{\nkind = \"string\",\nscope = \"config\",\n},\nmsgresource =\n{\nkind = \"string\",\ns" |
| 87 | "cope = \"config\",\n},\nmsglinking =\n{\nkind = \"string\",\nscope = \"config\",\n},\nobjdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\noptions =\n{\nkind = \"list\",\nscope = \"container\",\nisflags = true,\nusagecopy = true,\nallowed = function(value)\nlocal allowed_options = {\nForceCPP = 1,\nArchiveSplit = 1\n}\nlocal lowervalue = value:lower()\nfor v, _ in pairs(allowed_options) do\nif v:lower() == lowervalue then\nreturn v\nend\nend\nreturn nil, \"invalid option\"\nend,\n},\npchheader =\n{\nkind = \"string\",\nscope = \"config\",\n},\npchsource =\n{\nkind = \"path\",\nscope = \"config\",\n},\nplatforms =\n{\nkind = \"list\",\nscope = \"solution\",\nallowed = table.keys(premake.platforms),\n},\npostbuildcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nprebuildcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nprelinkcommands =\n{\nkind = \"list\",\nscope = \"config\",\n},\nresdefines =\n{\nkind = \"list\",\nscope = \"config\",\n},\nresincludedirs =\n{\nkind = \"dirlist\"," |
| 88 | "\nscope = \"config\",\n},\nresoptions =\n{\nkind = \"list\",\nscope = \"config\",\n},\nstartproject =\n{\nkind = \"string\",\nscope = \"solution\",\n},\ntargetdir =\n{\nkind = \"path\",\nscope = \"config\",\n},\ntargetsubdir =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetextension =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetname =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetprefix =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntargetsuffix =\n{\nkind = \"string\",\nscope = \"config\",\n},\ntrimpaths =\n{\nkind = \"dirlist\",\nscope = \"config\",\n},\nuuid =\n{\nkind = \"string\",\nscope = \"container\",\nallowed = function(value)\nlocal ok = true\nif (#value ~= 36) then ok = false end\nfor i=1,36 do\nlocal ch = value:sub(i,i)\nif (not ch:find(\"[ABCDEFabcdef0123456789-]\")) then ok = false end\nend\nif (value:sub(9,9) ~= \"-\") then ok = false end\nif (value:sub(14,14) ~= \"-\") then ok = false end\nif (value:sub(19,19) ~= \"-\") then ok = false end\nif (value:s" |
| 89 | "ub(24,24) ~= \"-\") then ok = false end\nif (not ok) then\nreturn nil, \"invalid UUID\"\nend\nreturn value:upper()\nend\n},\nuses =\n{\nkind = \"list\",\nscope = \"config\",\n},\nvpaths =\n{\nkind = \"keypath\",\nscope = \"container\",\n},\n}\nfunction premake.checkvalue(value, allowed)\nif (allowed) then\nif (type(allowed) == \"function\") then\nreturn allowed(value)\nelse\nfor _,v in ipairs(allowed) do\nif (value:lower() == v:lower()) then\nreturn v\nend\nend\nreturn nil, \"invalid value '\" .. value .. \"'\"\nend\nelse\nreturn value\nend\nend\nfunction premake.getobject(t)\nlocal container\nif (t == \"container\" or t == \"solution\") then\ncontainer = premake.CurrentContainer\nelse\ncontainer = premake.CurrentConfiguration\nend\nif t == \"solution\" then\nif type(container) == \"project\" then\ncontainer = container.solution\nend\nif type(container) ~= \"solution\" then\ncontainer = nil\nend\nend\nlocal msg\nif (not container) then\nif (t == \"container\") then\nmsg = \"no active solution or project\"\nel" |
| 90 | "seif (t == \"solution\") then\nmsg = \"no active solution\"\nelse\nmsg = \"no active solution, project, or configuration\"\nend\nend\nreturn container, msg\nend\nfunction premake.setarray(obj, fieldname, value, allowed)\nobj[fieldname] = obj[fieldname] or {}\nlocal function add(value, depth)\nif type(value) == \"table\" then\nfor _,v in ipairs(value) do\nadd(v, depth + 1)\nend\nelse\nvalue, err = premake.checkvalue(value, allowed)\nif not value then\nerror(err, depth)\nend\ntable.insert(obj[fieldname], value)\nend\nend\nif value then\nadd(value, 5)\nend\nreturn obj[fieldname]\nend\nlocal function domatchedarray(ctype, fieldname, value, matchfunc)\nlocal result = { }\nfunction makeabsolute(value, depth)\nif (type(value) == \"table\") then\nfor _, item in ipairs(value) do\nmakeabsolute(item, depth + 1)\nend\nelseif type(value) == \"string\" then\nif value:find(\"*\") then\nmakeabsolute(matchfunc(value), depth + 1)\nelse\ntable.insert(result, path.getabsolute(value))\nend\nelse\nerror(\"Invalid value in list: exp" |
| 91 | "ected string, got \" .. type(value), depth)\nend\nend\nmakeabsolute(value, 3)\nreturn premake.setarray(ctype, fieldname, result)\nend\nfunction premake.setdirarray(ctype, fieldname, value)\nreturn domatchedarray(ctype, fieldname, value, os.matchdirs)\nend\nfunction premake.setfilearray(ctype, fieldname, value)\nreturn domatchedarray(ctype, fieldname, value, os.matchfiles)\nend\nfunction premake.setkeyvalue(ctype, fieldname, values)\nlocal container, err = premake.getobject(ctype)\nif not container then\nerror(err, 4)\nend\nif not container[fieldname] then\ncontainer[fieldname] = {}\nend\nif type(values) ~= \"table\" then\nerror(\"invalid value; table expected\", 4)\nend\nlocal field = container[fieldname]\nfor key,value in pairs(values) do\nif not field[key] then\nfield[key] = {}\nend\ntable.insertflat(field[key], value)\nend\nreturn field\nend\nfunction premake.setstring(ctype, fieldname, value, allowed)\nlocal container, err = premake.getobject(ctype)\nif (not container) then\nerror(err, 4)\nend\nif (value) " |
| 92 | "then\nvalue, err = premake.checkvalue(value, allowed)\nif (not value) then\nerror(err, 4)\nend\ncontainer[fieldname] = value\nend\nreturn container[fieldname]\nend\nfunction premake.remove(fieldname, value)\nlocal cfg = premake.CurrentConfiguration\ncfg.removes = cfg.removes or {}\ncfg.removes[fieldname] = premake.setarray(cfg.removes, fieldname, value)\nend\nlocal function accessor(name, value)\nlocal kind = premake.fields[name].kind\nlocal scope = premake.fields[name].scope\nlocal allowed = premake.fields[name].allowed\nif (kind == \"string\" or kind == \"path\") and value then\nif type(value) ~= \"string\" then\nerror(\"string value expected\", 3)\nend\nend\nlocal container, err = premake.getobject(scope)\nif (not container) then\nerror(err, 3)\nend\nif kind == \"string\" then\nreturn premake.setstring(scope, name, value, allowed)\nelseif kind == \"path\" then\nif value then value = path.getabsolute(value) end\nreturn premake.setstring(scope, name, value)\nelseif kind == \"list\" then\nreturn premake.s" |
| 93 | "etarray(container, name, value, allowed)\nelseif kind == \"dirlist\" then\nreturn premake.setdirarray(container, name, value)\nelseif kind == \"filelist\" or kind == \"absolutefilelist\" then\nreturn premake.setfilearray(container, name, value)\nelseif kind == \"keyvalue\" or kind == \"keypath\" then\nreturn premake.setkeyvalue(scope, name, value)\nend\nend\nfor name, info in pairs(premake.fields) do\n_G[name] = function(value)\nreturn accessor(name, value)\nend\nif info.kind == \"list\" or \n info.kind == \"dirlist\" or \n info.kind == \"filelist\" or\n info.kind == \"absolutefilelist\" \nthen\n_G[\"remove\"..name] = function(value)\npremake.remove(name, value)\nend\nend\nend\nfunction configuration(terms)\nif not terms then\nreturn premake.CurrentConfiguration\nend\nlocal container, err = premake.getobject(\"container\")\nif (not container) then\nerror(err, 2)\nend\nlocal cfg = { }\ncfg.terms = table.flatten({terms})\ntable.insert(container.blocks, cfg)\npremake.CurrentConfiguration = cfg\ncfg.keywords" |
| 94 | " = { }\nfor _, word in ipairs(cfg.terms) do\ntable.insert(cfg.keywords, path.wildcards(word):lower())\nend\nfor name, field in pairs(premake.fields) do\nif (field.kind ~= \"string\" and field.kind ~= \"path\") then\ncfg[name] = { }\nend\nend\nreturn cfg\nend\nlocal function creategroup(name, sln, parent, inpath)\nlocal group = {}\nsetmetatable(group, {\n__type = \"group\"\n})\ntable.insert(sln.groups, group)\nsln.groups[inpath] = group\ngroup.solution = sln\ngroup.name = name\ngroup.uuid = os.uuid(group.name)\ngroup.parent = parent\nreturn group\nend\nlocal function creategroupsfrompath(inpath, sln)\nif inpath == nil then return nil end\ninpath = path.translate(inpath, \"/\")\nlocal groups = string.explode(inpath, \"/\")\nlocal curpath = \"\"\nlocal lastgroup = nil\nfor i, v in ipairs(groups) do\ncurpath = curpath .. \"/\" .. v:lower()\nlocal group = sln.groups[curpath]\nif group == nil then\ngroup = creategroup(v, sln, lastgroup, curpath)\nend\nlastgroup = group\nend\nreturn lastgroup\nend\nlocal function cre" |
| 95 | "ateproject(name, sln, isUsage)\nlocal prj = {}\nsetmetatable(prj, {\n__type = \"project\",\n})\ntable.insert(sln.projects, prj)\nif(isUsage) then\nif(sln.projects[name]) then\nsln.projects[name].usageProj = prj;\nelse\nsln.projects[name] = prj\nend\nelse\nif(sln.projects[name]) then\nprj.usageProj = sln.projects[name];\nend\nsln.projects[name] = prj\nend\nlocal group = creategroupsfrompath(premake.CurrentGroup, sln)\nprj.solution = sln\nprj.name = name\nprj.basedir = os.getcwd()\nprj.uuid = os.uuid(prj.name)\nprj.blocks = { }\nprj.usage = isUsage\nprj.group = group\nreturn prj;\nend\nfunction usage(name)\nif (not name) then\nif(type(premake.CurrentContainer) ~= \"project\") then return nil end\nif(not premake.CurrentContainer.usage) then return nil end\nreturn premake.CurrentContainer\nend\nlocal sln\nif (type(premake.CurrentContainer) == \"project\") then\nsln = premake.CurrentContainer.solution\nelse\nsln = premake.CurrentContainer\nend\nif (type(sln) ~= \"" |
| 96 | "solution\") then\nerror(\"no active solution\", 2)\nend\n -- if this is a new project, or the project in that slot doesn't have a usage, create it\n if((not sln.projects[name]) or\n ((not sln.projects[name].usage) and (not sln.projects[name].usageProj))) then\n premake.CurrentContainer = createproject(name, sln, true)\n else\n premake.CurrentContainer = iff(sln.projects[name].usage,\n sln.projects[name], sln.projects[name].usageProj)\n end\n -- add an empty, global configuration to the project\n configuration { }\n return premake.CurrentContainer\n end\n function project(name)\n if (not name) then\n --Only return non-usage projects\n if(type(premake.CurrentContainer) ~= \"project\") then return nil end\n if(premake.CurrentContainer.usage) then return nil end\n return premake.CurrentContainer\nend\n -- identify the parent solution\n local sln\n if (type(premake.CurrentContainer) == \"project\") then\n sln = premake.CurrentContainer.solution\n else\n sln = premake.CurrentContainer\n end" |
| 97 | "\n if (type(sln) ~= \"solution\") then\n error(\"no active solution\", 2)\n end\n -- if this is a new project, or the old project is a usage project, create it\n if((not sln.projects[name]) or sln.projects[name].usage) then\n premake.CurrentContainer = createproject(name, sln)\n else\n premake.CurrentContainer = sln.projects[name];\n end\nconfiguration { }\nreturn premake.CurrentContainer\nend\nfunction solution(name)\nif not name then\nif type(premake.CurrentContainer) == \"project\" then\nreturn premake.CurrentContainer.solution\nelse\nreturn premake.CurrentContainer\nend\nend\npremake.CurrentContainer = premake.solution.get(name)\nif (not premake.CurrentContainer) then\npremake.CurrentContainer = premake.solution.new(name)\nend\nconfiguration { }\nreturn premake.CurrentContainer\nend\nfunction group(name)\nif not name then \nreturn premake.CurrentGroup\nend\npremake.CurrentGroup = name\nreturn premake.CurrentGroup\nend\nfunction newaction(a)\npremake.action.add(a)\nend\nfunction newoption(opt)\npre" |
| 98 | "make.option.add(opt)\nend\n", |
| 99 | 99 | |
| 100 | 100 | /* base/cmdline.lua */ |
| 101 | 101 | "newoption \n{\ntrigger = \"cc\",\nvalue = \"VALUE\",\ndescription = \"Choose a C/C++ compiler set\",\nallowed = {\n{ \"gcc\", \"GNU GCC (gcc/g++)\" },\n{ \"ow\", \"OpenWatcom\" },\n}\n}\nnewoption\n{\ntrigger = \"dotnet\",\nvalue = \"VALUE\",\ndescription = \"Choose a .NET compiler set\",\nallowed = {\n{ \"msnet\", \"Microsoft .NET (csc)\" },\n{ \"mono\", \"Novell Mono (mcs)\" },\n{ \"pnet\", \"Portable.NET (cscc)\" },\n}\n}\nnewoption\n{\ntrigger = \"file\",\nvalue = \"FILE\",\ndescription = \"Read FILE as a Premake script; default is 'premake4.lua'\"\n}\nnewoption\n{\ntrigger = \"help\",\ndescription = \"Display this information\"\n}\nnewoption\n{\ntrigger = \"os\",\nvalue = \"VALUE\",\ndescription = \"Generate files for a different operating system\",\nallowed = {\n{ \"bsd\", \"OpenBSD, NetBSD, or FreeBSD\" },\n{ \"linux\", \"Linux\" },\n{ \"macosx\", \"Apple Mac OS X\" },\n{ \"windows\", \"Microsoft Windows\" },\n}\n}\nnewoption\n{" |
| r244651 | r244652 | |
| 185 | 185 | "$(SILENT) if exist $(subst /,\\\\\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\\\\\,$(OBJDIR))')\n_p('endif')\n_p('')\n_p('prebuild:')\n_p('\\t$(PREBUILDCMDS)')\n_p('')\n_p('prelink:')\n_p('\\t$(PRELINKCMDS)')\n_p('')\ncpp.pchrules(prj)\ncpp.fileRules(prj)\n_p('-include $(OBJECTS:%%.o=%%.d)')\n_p('ifneq (,$(PCH))')\n_p(' -include $(OBJDIR)/$(notdir $(PCH)).d')\n_p('endif')\nend\nfunction premake.gmake_cpp_header(prj, cc, platforms)\n_p('# %s project makefile autogenerated by GENie', premake.action.current().shortname)\n_p('ifndef config')\n_p(' config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true)))\n_p('endif')\n_p('')\n_p('ifndef verbose')\n_p(' SILENT = @')\n_p('endif')\n_p('')\n_p('SHELLTYPE := msdos')\n_p('ifeq (,$(ComSpec)$(COMSPEC))')\n_p(' SHELLTYPE := posix')\n_p('endif')\n_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')\n_p(' SHELLTYPE := posix')\n_p('endif')\n_p('')\n_p('ifeq (posix,$(SHELLTYPE))')\n_p(' MKDIR = $(SILENT) mkdir -p \"$(1)\"')\n_p(' COPY = $(" |
| 186 | 186 | "SILENT) cp -fR \"$(1)\" \"$(2)\"')\n_p('else')\n_p(' MKDIR = $(SILENT) mkdir \"$(subst /,\\\\\\\\,$(1))\" 2> nul || exit 0')\n_p(' COPY = $(SILENT) copy /Y \"$(subst /,\\\\\\\\,$(1))\" \"$(subst /,\\\\\\\\,$(2))\"')\n_p('endif')\n_p('')\n_p('CC = %s', cc.cc)\n_p('CXX = %s', cc.cxx)\n_p('AR = %s', cc.ar)\n_p('')\n_p('ifndef RESCOMP')\n_p(' ifdef WINDRES')\n_p(' RESCOMP = $(WINDRES)')\n_p(' else')\n_p(' RESCOMP = windres')\n_p(' endif')\n_p('endif')\n_p('')\nend\nfunction premake.gmake_cpp_config(prj, cfg, cc)\n_p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname))\ncpp.platformtools(cfg, cc)\n_p(' OBJDIR = %s', _MAKE.esc(cfg.objectsdir))\n_p(' TARGETDIR = %s', _MAKE.esc(cfg.buildtarget.directory))\n_p(' TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name))\n_p(' DEFINES +=%s', make.list(cc.getdefines(cfg.defines)))\n_p(' INCLUDES +=%s', make.list(cc.getincludedirs(cfg.includedirs)))\ncpp.pchconfig(cfg)\ncpp.flags(cfg, cc)\ncpp.linker(cfg, cc)\n_p(' OBJECTS := \\\\')\nfor _, fi" |
| 187 | 187 | "le in ipairs(prj.files) do\nif path.iscppfile(file) then\nlocal excluded = false\nfor _, exclude in ipairs(cfg.excludes) do\nexcluded = (exclude == file)\nif (excluded) then break end\nend\nif excluded == false then\n_p('\\t$(OBJDIR)/%s.o \\\\'\n, _MAKE.esc(path.trimdots(path.removeext(file)))\n)\nend\nend\nend\n_p('')\n_p(' define PREBUILDCMDS')\nif #cfg.prebuildcommands > 0 then\n_p('\\t@echo Running pre-build commands')\n_p('\\t%s', table.implode(cfg.prebuildcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\n_p(' define PRELINKCMDS')\nif #cfg.prelinkcommands > 0 then\n_p('\\t@echo Running pre-link commands')\n_p('\\t%s', table.implode(cfg.prelinkcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\n_p(' define POSTBUILDCMDS')\nif #cfg.postbuildcommands > 0 then\n_p('\\t@echo Running post-build commands')\n_p('\\t%s', table.implode(cfg.postbuildcommands, \"\", \"\", \"\\n\\t\"))\nend\n_p(' endef')\nmake.settings(cfg, cc)\n_p('endif')\n_p('')\nend\nfunction cpp.platformtools(cfg, cc)\nlocal platfor" |
| 188 | | "m = cc.platforms[cfg.platform]\nif platform.cc then\n_p(' CC = %s', platform.cc)\nend\nif platform.cxx then\n_p(' CXX = %s', platform.cxx)\nend\nif platform.ar then\n_p(' AR = %s', platform.ar)\nend\nend\nfunction cpp.flags(cfg, cc)\nif cfg.pchheader and not cfg.flags.NoPCH then\n_p(' FORCE_INCLUDE += -include $(OBJDIR)/$(notdir $(PCH))')\nend\nif #cfg.forcedincludes > 0 then\n_p(' FORCE_INCLUDE += -include %s'\n,premake.esc(table.concat(cfg.forcedincludes, \";\")))\nend\n_p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), \" \"))\n_p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c)))\n_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp)))\n_p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s',\n make.list(table.join(cc.getdefines(cfg.resd" |
| 189 | | "efines),\n cc.getincludedirs(cfg.resincludedirs), cfg.resoptions)))\nend\nfunction cpp.linker(cfg, cc)\n_p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(table.join(cc.getlibdirflags(cfg), cc.getldflags(cfg), cfg.linkoptions)))\n_p(' LDDEPS +=%s', make.list(_MAKE.esc(premake.getlinks(cfg, \"siblings\", \"fullpath\"))))\n_p(' LIBS += $(LDDEPS)%s', make.list(cc.getlinkflags(cfg)))\nif cfg.kind == \"StaticLib\" then\nif cfg.platform:startswith(\"Universal\") then\n_p(' LINKCMD = libtool -o $(TARGET)')\nelse\nif cc.llvm then\n_p(' LINKCMD = $(AR) rcs $(TARGET)')\nelse\n_p(' LINKCMD = $(AR) -rcs $(TARGET)')\nend\nend\nelse\nlocal tool = iif(cfg.language == \"C\", \"CC\", \"CXX\")\n_p(' LINKCMD = $(%s) -o $(TARGET) $(OBJECTS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) $(LIBS)', tool)\nend\nend\nfunction cpp.pchconfig(cfg)\nif not cfg.pchheader or cfg.flags.NoPCH then\nreturn\nend\nlocal pch = cfg.pchheader\nfor _, incdir in ipairs(cfg.includedirs) do\nlocal abspath = p" |
| 190 | | "ath.getabsolute(path.join(cfg.project.location, incdir))\nlocal testname = path.join(abspath, pch)\nif os.isfile(testname) then\npch = path.getrelative(cfg.location, testname)\nbreak\nend\nend\n_p(' PCH = %s', _MAKE.esc(pch))\n_p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch')\nend\nfunction cpp.pchrules(prj)\n_p('ifneq (,$(PCH))')\n_p('$(GCH): $(PCH)')\n_p('\\t@echo $(notdir $<)')\nlocal cmd = iif(prj.language == \"C\", \"$(CC) -x c-header $(ALL_CFLAGS)\", \"$(CXX) -x c++-header $(ALL_CXXFLAGS)\")\n_p('\\t$(SILENT) %s -MMD -MP $(DEFINES) $(INCLUDES) -o \"$@\" -MF \"$(@:%%.gch=%%.d)\" -c \"$<\"', cmd)\n_p('endif')\n_p('')\nend\nfunction cpp.fileRules(prj)\nfor _, file in ipairs(prj.files or {}) do\nif path.iscppfile(file) then\n_p('$(OBJDIR)/%s.o: %s'\n, _MAKE.esc(path.trimdots(path.removeext(file)))\n, _MAKE.esc(file)\n)\nif prj.msgcompile then\n_p('\\t@echo ' .. prj.msgcompile)\nelse\n_p('\\t@echo $(notdir $<)')\nend\ncpp.buildcommand(path.iscfile(file) and not prj.options.ForceCPP, \"o\")\n_p('')\n" |
| 191 | | "elseif (path.getextension(file) == \".rc\") then\n_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))\nif prj.msgresource then\n_p('\\t@echo ' .. prj.msgresource)\nelse\n_p('\\t@echo $(notdir $<)')\nend\n_p('\\t$(SILENT) $(RESCOMP) $< -O coff -o \"$@\" $(ALL_RESFLAGS)')\n_p('')\nend\nend\nend\nfunction cpp.buildcommand(iscfile, objext)\nlocal flags = iif(iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)')\n_p('\\t$(SILENT) %s $(FORCE_INCLUDE) -o \"$@\" -MF $(@:%%.%s=%%.d) -c \"$<\"', flags, objext)\nend\n", |
| 188 | "m = cc.platforms[cfg.platform]\nif platform.cc then\n_p(' CC = %s', platform.cc)\nend\nif platform.cxx then\n_p(' CXX = %s', platform.cxx)\nend\nif platform.ar then\n_p(' AR = %s', platform.ar)\nend\nend\nfunction cpp.flags(cfg, cc)\nif cfg.pchheader and not cfg.flags.NoPCH then\n_p(' FORCE_INCLUDE += -include $(OBJDIR)/$(notdir $(PCH))')\nend\nif #cfg.forcedincludes > 0 then\n_p(' FORCE_INCLUDE += -include %s'\n,premake.esc(table.concat(cfg.forcedincludes, \";\")))\nend\n_p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), \" \"))\n_p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions)))\n_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CFLAGS)%s', make.list(table.join(cc.getcxxflags(cfg), cfg.buildoptions_cpp)))\n_p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s',\n make.list(table.join(cc.getdefines(cfg.resdefines),\n cc.getincludedir" |
| 189 | "s(cfg.resincludedirs), cfg.resoptions)))\nend\nfunction cpp.linker(cfg, cc)\n_p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(table.join(cc.getlibdirflags(cfg), cc.getldflags(cfg), cfg.linkoptions)))\n_p(' LDDEPS +=%s', make.list(_MAKE.esc(premake.getlinks(cfg, \"siblings\", \"fullpath\"))))\n_p(' LIBS += $(LDDEPS)%s', make.list(cc.getlinkflags(cfg)))\nif cfg.kind == \"StaticLib\" then\nif cfg.platform:startswith(\"Universal\") then\n_p(' LINKCMD = libtool -o $(TARGET)')\nelse\nif cc.llvm then\n_p(' LINKCMD = $(AR) rcs $(TARGET)')\nelse\n_p(' LINKCMD = $(AR) -rcs $(TARGET)')\nend\nend\nelse\nlocal tool = iif(cfg.language == \"C\", \"CC\", \"CXX\")\n_p(' LINKCMD = $(%s) -o $(TARGET) $(OBJECTS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) $(LIBS)', tool)\nend\nend\nfunction cpp.pchconfig(cfg)\nif not cfg.pchheader or cfg.flags.NoPCH then\nreturn\nend\nlocal pch = cfg.pchheader\nfor _, incdir in ipairs(cfg.includedirs) do\nlocal abspath = path.getabsolute(path.join(cfg.project.location, incdir))\n" |
| 190 | "local testname = path.join(abspath, pch)\nif os.isfile(testname) then\npch = path.getrelative(cfg.location, testname)\nbreak\nend\nend\n_p(' PCH = %s', _MAKE.esc(pch))\n_p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch')\nend\nfunction cpp.pchrules(prj)\n_p('ifneq (,$(PCH))')\n_p('$(GCH): $(PCH)')\n_p('\\t@echo $(notdir $<)')\nlocal cmd = iif(prj.language == \"C\", \"$(CC) -x c-header $(ALL_CFLAGS)\", \"$(CXX) -x c++-header $(ALL_CXXFLAGS)\")\n_p('\\t$(SILENT) %s -MMD -MP $(DEFINES) $(INCLUDES) -o \"$@\" -MF \"$(@:%%.gch=%%.d)\" -c \"$<\"', cmd)\n_p('endif')\n_p('')\nend\nfunction cpp.fileRules(prj)\nfor _, file in ipairs(prj.files or {}) do\nif path.iscppfile(file) then\n_p('$(OBJDIR)/%s.o: %s'\n, _MAKE.esc(path.trimdots(path.removeext(file)))\n, _MAKE.esc(file)\n)\nif prj.msgcompile then\n_p('\\t@echo ' .. prj.msgcompile)\nelse\n_p('\\t@echo $(notdir $<)')\nend\ncpp.buildcommand(path.iscfile(file) and not prj.options.ForceCPP, \"o\")\n_p('')\nelseif (path.getextension(file) == \".rc\") then\n_p('$(OB" |
| 191 | "JDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))\nif prj.msgresource then\n_p('\\t@echo ' .. prj.msgresource)\nelse\n_p('\\t@echo $(notdir $<)')\nend\n_p('\\t$(SILENT) $(RESCOMP) $< -O coff -o \"$@\" $(ALL_RESFLAGS)')\n_p('')\nend\nend\nend\nfunction cpp.buildcommand(iscfile, objext)\nlocal flags = iif(iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)')\n_p('\\t$(SILENT) %s $(FORCE_INCLUDE) -o \"$@\" -MF $(@:%%.%s=%%.d) -c \"$<\"', flags, objext)\nend\n", |
| 192 | 192 | |
| 193 | 193 | /* actions/make/make_csharp.lua */ |
| 194 | 194 | "local function getresourcefilename(cfg, fname)\nif path.getextension(fname) == \".resx\" then\n local name = cfg.buildtarget.basename .. \".\"\n local dir = path.getdirectory(fname)\n if dir ~= \".\" then \nname = name .. path.translate(dir, \".\") .. \".\"\nend\nreturn \"$(OBJDIR)/\" .. _MAKE.esc(name .. path.getbasename(fname)) .. \".resources\"\nelse\nreturn fname\nend\nend\nfunction premake.make_csharp(prj)\nlocal csc = premake.dotnet\nlocal cfglibs = { }\nlocal cfgpairs = { }\nlocal anycfg\nfor cfg in premake.eachconfig(prj) do\nanycfg = cfg\ncfglibs[cfg] = premake.getlinks(cfg, \"siblings\", \"fullpath\")\ncfgpairs[cfg] = { }\nfor _, fname in ipairs(cfglibs[cfg]) do\nif path.getdirectory(fname) ~= cfg.buildtarget.directory then\ncfgpairs[cfg][\"$(TARGETDIR)/\" .. _MAKE.esc(path.getname(fname))] = _MAKE.esc(fname)\nend\nend\nend\nlocal sources = {}\nlocal embedded = { }\nlocal copypairs = { }\nfor fcfg in premake.project.eachfile(prj) do\nlocal action = csc.getbuildaction(fcfg)\nif action == \"Co" |
trunk/src/mame/drivers/ssv.c
| r244651 | r244652 | |
| 179 | 179 | m_maincpu->set_input_line(0, (m_requested_int & m_irq_enable)? ASSERT_LINE : CLEAR_LINE); |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | | IRQ_CALLBACK_MEMBER(ssv_state::irq_callback) |
| 182 | IRQ_CALLBACK_MEMBER(ssv_state::ssv_irq_callback) |
| 183 | 183 | { |
| 184 | 184 | int i; |
| 185 | 185 | for ( i = 0; i <= 7; i++ ) |
| r244651 | r244652 | |
| 193 | 193 | return 0; |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | | WRITE16_MEMBER(ssv_state::irq_ack_w) |
| 196 | WRITE16_MEMBER(ssv_state::ssv_irq_ack_w) |
| 197 | 197 | { |
| 198 | 198 | int level = ((offset * 2) & 0x70) >> 4; |
| 199 | 199 | |
| r244651 | r244652 | |
| 220 | 220 | ultrax: 40,00 at the start then 42,4a |
| 221 | 221 | twineag2: 40,00 at the start then 42,4a |
| 222 | 222 | */ |
| 223 | | WRITE16_MEMBER(ssv_state::irq_enable_w) |
| 223 | WRITE16_MEMBER(ssv_state::ssv_irq_enable_w) |
| 224 | 224 | { |
| 225 | 225 | COMBINE_DATA(&m_irq_enable); |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | | TIMER_DEVICE_CALLBACK_MEMBER(ssv_state::interrupt) |
| 228 | TIMER_DEVICE_CALLBACK_MEMBER(ssv_state::ssv_interrupt) |
| 229 | 229 | { |
| 230 | 230 | int scanline = param; |
| 231 | 231 | |
| r244651 | r244652 | |
| 283 | 283 | survarts: 83 |
| 284 | 284 | sxyreact: 80 |
| 285 | 285 | */ |
| 286 | | WRITE16_MEMBER(ssv_state::lockout_w) |
| 286 | WRITE16_MEMBER(ssv_state::ssv_lockout_w) |
| 287 | 287 | { |
| 288 | 288 | // popmessage("%02X",data & 0xff); |
| 289 | 289 | if (ACCESSING_BITS_0_7) |
| r244651 | r244652 | |
| 293 | 293 | coin_counter_w(machine(), 1, data & 0x04); |
| 294 | 294 | coin_counter_w(machine(), 0, data & 0x08); |
| 295 | 295 | // data & 0x40? |
| 296 | | enable_video(data & 0x80); |
| 296 | ssv_enable_video(data & 0x80); |
| 297 | 297 | } |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | /* Same as above but with inverted lockout lines */ |
| 301 | | WRITE16_MEMBER(ssv_state::lockout_inv_w) |
| 301 | WRITE16_MEMBER(ssv_state::ssv_lockout_inv_w) |
| 302 | 302 | { |
| 303 | 303 | // popmessage("%02X",data & 0xff); |
| 304 | 304 | if (ACCESSING_BITS_0_7) |
| r244651 | r244652 | |
| 308 | 308 | coin_counter_w(machine(), 1, data & 0x04); |
| 309 | 309 | coin_counter_w(machine(), 0, data & 0x08); |
| 310 | 310 | // data & 0x40? |
| 311 | | enable_video(data & 0x80); |
| 311 | ssv_enable_video(data & 0x80); |
| 312 | 312 | } |
| 313 | 313 | } |
| 314 | 314 | |
| r244651 | r244652 | |
| 396 | 396 | AM_RANGE(0x100000, 0x13ffff) AM_RAM AM_SHARE("spriteram") /* Sprites */ \ |
| 397 | 397 | AM_RANGE(0x140000, 0x15ffff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") /* Palette */\ |
| 398 | 398 | AM_RANGE(0x160000, 0x17ffff) AM_RAM /* */ \ |
| 399 | | AM_RANGE(0x1c0000, 0x1c0001) AM_READ(vblank_r ) /* Vblank? */ \ |
| 399 | AM_RANGE(0x1c0000, 0x1c0001) AM_READ(ssv_vblank_r ) /* Vblank? */ \ |
| 400 | 400 | /**/AM_RANGE(0x1c0002, 0x1c007f) AM_READONLY /* Scroll */ \ |
| 401 | | AM_RANGE(0x1c0000, 0x1c007f) AM_WRITE(scroll_w) AM_SHARE("scroll") /* Scroll */ \ |
| 401 | AM_RANGE(0x1c0000, 0x1c007f) AM_WRITE(ssv_scroll_w) AM_SHARE("scroll") /* Scroll */ \ |
| 402 | 402 | AM_RANGE(0x210002, 0x210003) AM_READ_PORT("DSW1") \ |
| 403 | 403 | AM_RANGE(0x210004, 0x210005) AM_READ_PORT("DSW2") \ |
| 404 | 404 | AM_RANGE(0x210008, 0x210009) AM_READ_PORT("P1") \ |
| 405 | 405 | AM_RANGE(0x21000a, 0x21000b) AM_READ_PORT("P2") \ |
| 406 | 406 | AM_RANGE(0x21000c, 0x21000d) AM_READ_PORT("SYSTEM") \ |
| 407 | | AM_RANGE(0x21000e, 0x21000f) AM_READNOP AM_WRITE(lockout_w) /* Lockout */ \ |
| 407 | AM_RANGE(0x21000e, 0x21000f) AM_READNOP AM_WRITE(ssv_lockout_w) /* Lockout */ \ |
| 408 | 408 | AM_RANGE(0x210010, 0x210011) AM_WRITENOP \ |
| 409 | 409 | AM_RANGE(0x230000, 0x230071) AM_WRITEONLY AM_SHARE("irq_vectors") /* IRQ Vec */ \ |
| 410 | | AM_RANGE(0x240000, 0x240071) AM_WRITE(irq_ack_w ) /* IRQ Ack */ \ |
| 411 | | AM_RANGE(0x260000, 0x260001) AM_WRITE(irq_enable_w) /* IRQ En */ \ |
| 410 | AM_RANGE(0x240000, 0x240071) AM_WRITE(ssv_irq_ack_w ) /* IRQ Ack */ \ |
| 411 | AM_RANGE(0x260000, 0x260001) AM_WRITE(ssv_irq_enable_w) /* IRQ En */ \ |
| 412 | 412 | AM_RANGE(0x300000, 0x30007f) AM_DEVREADWRITE8("ensoniq", es5506_device, read, write, 0x00ff) /* Sound */ \ |
| 413 | 413 | AM_RANGE(_ROM, 0xffffff) AM_ROM AM_REGION("maincpu", 0) /* ROM */ |
| 414 | 414 | /*************************************************************************** |
| r244651 | r244652 | |
| 513 | 513 | static ADDRESS_MAP_START( hypreact_map, AS_PROGRAM, 16, ssv_state ) |
| 514 | 514 | AM_RANGE(0x210000, 0x210001) AM_READ(watchdog_reset16_r) // Watchdog |
| 515 | 515 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 5 at the start |
| 516 | | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(lockout_inv_w) // Inverted lockout lines |
| 516 | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(ssv_lockout_inv_w) // Inverted lockout lines |
| 517 | 517 | // AM_RANGE(0x280000, 0x280001) AM_READNOP // ? read at the start, value not used |
| 518 | 518 | AM_RANGE(0xc00000, 0xc00001) AM_READ(hypreact_input_r) // Inputs |
| 519 | 519 | AM_RANGE(0xc00006, 0xc00007) AM_RAM AM_SHARE("input_sel") // |
| r244651 | r244652 | |
| 529 | 529 | static ADDRESS_MAP_START( hypreac2_map, AS_PROGRAM, 16, ssv_state ) |
| 530 | 530 | AM_RANGE(0x210000, 0x210001) AM_READ(watchdog_reset16_r) // Watchdog |
| 531 | 531 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 5 at the start |
| 532 | | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(lockout_inv_w) // Inverted lockout lines |
| 532 | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(ssv_lockout_inv_w) // Inverted lockout lines |
| 533 | 533 | // AM_RANGE(0x280000, 0x280001) AM_READNOP // ? read at the start, value not used |
| 534 | 534 | AM_RANGE(0x500000, 0x500001) AM_READ(hypreact_input_r) // Inputs |
| 535 | 535 | AM_RANGE(0x500002, 0x500003) AM_READ(hypreact_input_r) // (again?) |
| r244651 | r244652 | |
| 587 | 587 | |
| 588 | 588 | /* Monster Slider needs the RAM mirrored for the gameplay logic to work correctly */ |
| 589 | 589 | |
| 590 | | READ16_MEMBER(ssv_state::mainram_r) |
| 590 | READ16_MEMBER(ssv_state::ssv_mainram_r) |
| 591 | 591 | { |
| 592 | 592 | return m_mainram[offset]; |
| 593 | 593 | } |
| 594 | 594 | |
| 595 | | WRITE16_MEMBER(ssv_state::mainram_w) |
| 595 | WRITE16_MEMBER(ssv_state::ssv_mainram_w) |
| 596 | 596 | { |
| 597 | 597 | COMBINE_DATA(&m_mainram[offset]); |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | static ADDRESS_MAP_START( mslider_map, AS_PROGRAM, 16, ssv_state ) |
| 601 | | AM_RANGE(0x010000, 0x01ffff) AM_READWRITE(mainram_r, mainram_w) // RAM Mirror |
| 601 | AM_RANGE(0x010000, 0x01ffff) AM_READWRITE(ssv_mainram_r, ssv_mainram_w) // RAM Mirror |
| 602 | 602 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 1 at the start |
| 603 | 603 | AM_RANGE(0x400000, 0x47ffff) AM_WRITEONLY // ? |
| 604 | 604 | // AM_RANGE(0x500000, 0x500001) AM_WRITENOP // ? ff at the start |
| r244651 | r244652 | |
| 684 | 684 | AM_RANGE(0x010000, 0x050faf) AM_RAM // More RAM |
| 685 | 685 | AM_RANGE(0x210000, 0x210001) AM_READ(watchdog_reset16_r) // Watchdog |
| 686 | 686 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 0,4 at the start |
| 687 | | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(lockout_inv_w) // Coin Counters / Lockouts |
| 687 | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(ssv_lockout_inv_w) // Coin Counters / Lockouts |
| 688 | 688 | AM_RANGE(0x300076, 0x300077) AM_READ(srmp7_irqv_r) // Sound |
| 689 | 689 | // 0x540000, 0x540003, related to lev 5 irq? |
| 690 | 690 | AM_RANGE(0x580000, 0x580001) AM_WRITE(srmp7_sound_bank_w) // Sound Bank |
| r244651 | r244652 | |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | 753 | static ADDRESS_MAP_START( sxyreact_map, AS_PROGRAM, 16, ssv_state ) |
| 754 | | // AM_RANGE(0x020000, 0x03ffff) AM_READWRITE(mainram_r, mainram_w) // sxyreac2 reads / writes here, why? |
| 754 | // AM_RANGE(0x020000, 0x03ffff) AM_READWRITE(ssv_mainram_r, ssv_mainram_w) // sxyreac2 reads / writes here, why? |
| 755 | 755 | AM_RANGE(0x210000, 0x210001) AM_READ(watchdog_reset16_r) // Watchdog |
| 756 | 756 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 1 at the start |
| 757 | | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(lockout_inv_w) // Inverted lockout lines |
| 757 | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(ssv_lockout_inv_w) // Inverted lockout lines |
| 758 | 758 | AM_RANGE(0x500002, 0x500003) AM_READ(sxyreact_ballswitch_r) // ? |
| 759 | 759 | AM_RANGE(0x500004, 0x500005) AM_READWRITE(sxyreact_dial_r, sxyreact_motor_w) // Dial Value (serial) |
| 760 | 760 | AM_RANGE(0x520000, 0x520001) AM_WRITE(sxyreact_dial_w) // Dial Value (advance 1 bit) |
| r244651 | r244652 | |
| 828 | 828 | } |
| 829 | 829 | |
| 830 | 830 | static ADDRESS_MAP_START( jsk_map, AS_PROGRAM, 16, ssv_state ) |
| 831 | | AM_RANGE(0x050000, 0x05ffff) AM_READWRITE(mainram_r, mainram_w) // RAM Mirror? |
| 831 | AM_RANGE(0x050000, 0x05ffff) AM_READWRITE(ssv_mainram_r, ssv_mainram_w) // RAM Mirror? |
| 832 | 832 | AM_RANGE(0x210000, 0x210001) AM_WRITE(watchdog_reset16_w) // Watchdog |
| 833 | 833 | AM_RANGE(0x400000, 0x47ffff) AM_RAM // RAM? |
| 834 | 834 | AM_RANGE(0x900000, 0x900007) AM_READWRITE(latch16_r, latch16_w) |
| r244651 | r244652 | |
| 898 | 898 | AM_RANGE(0x180000, 0x1bffff) AM_READWRITE(eaglshot_gfxram_r, eaglshot_gfxram_w) |
| 899 | 899 | AM_RANGE(0x210000, 0x210001) AM_READNOP /*AM_READ(watchdog_reset16_r)*/ // Watchdog |
| 900 | 900 | // AM_RANGE(0x210002, 0x210003) AM_WRITENOP // ? 0,4 at the start |
| 901 | | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(lockout_inv_w) // Inverted lockout lines |
| 901 | AM_RANGE(0x21000e, 0x21000f) AM_WRITE(ssv_lockout_inv_w) // Inverted lockout lines |
| 902 | 902 | AM_RANGE(0x800000, 0x800001) AM_WRITE(eaglshot_gfxrom_bank_w) |
| 903 | 903 | AM_RANGE(0x900000, 0x900001) AM_WRITE(eaglshot_trackball_w) |
| 904 | 904 | AM_RANGE(0xa00000, 0xbfffff) AM_ROMBANK("gfxrom") |
| r244651 | r244652 | |
| 2481 | 2481 | |
| 2482 | 2482 | ***************************************************************************/ |
| 2483 | 2483 | |
| 2484 | | void ssv_state::init(int interrupt_ultrax) |
| 2484 | void ssv_state::init_ssv(int interrupt_ultrax) |
| 2485 | 2485 | { |
| 2486 | 2486 | int i; |
| 2487 | 2487 | for (i = 0; i < 16; i++) |
| r244651 | r244652 | |
| 2489 | 2489 | ( (i & 4) ? (2 << 16) : 0 ) + |
| 2490 | 2490 | ( (i & 2) ? (4 << 16) : 0 ) + |
| 2491 | 2491 | ( (i & 1) ? (8 << 16) : 0 ) ; |
| 2492 | | enable_video(1); |
| 2492 | ssv_enable_video(1); |
| 2493 | 2493 | m_interrupt_ultrax = interrupt_ultrax; |
| 2494 | | |
| 2495 | | save_item(NAME(m_requested_int)); |
| 2496 | | save_item(NAME(m_irq_enable)); |
| 2497 | 2494 | } |
| 2498 | 2495 | |
| 2499 | 2496 | void ssv_state::init_hypreac2_common() |
| r244651 | r244652 | |
| 2531 | 2528 | } |
| 2532 | 2529 | } |
| 2533 | 2530 | |
| 2534 | | DRIVER_INIT_MEMBER(ssv_state,drifto94) { init(0); init_st010(); } |
| 2535 | | DRIVER_INIT_MEMBER(ssv_state,eaglshot) { init(0); init_eaglshot_banking(); save_item(NAME(m_trackball_select)); } |
| 2536 | | DRIVER_INIT_MEMBER(ssv_state,gdfs) { init(0); save_item(NAME(m_gdfs_lightgun_select)); save_item(NAME(m_gdfs_eeprom_old)); } |
| 2537 | | DRIVER_INIT_MEMBER(ssv_state,hypreact) { init(0); } |
| 2538 | | DRIVER_INIT_MEMBER(ssv_state,hypreac2) { init(0); init_hypreac2_common(); } |
| 2539 | | DRIVER_INIT_MEMBER(ssv_state,janjans1) { init(0); } |
| 2540 | | DRIVER_INIT_MEMBER(ssv_state,keithlcy) { init(0); } |
| 2541 | | DRIVER_INIT_MEMBER(ssv_state,meosism) { init(0); } |
| 2542 | | DRIVER_INIT_MEMBER(ssv_state,mslider) { init(0); } |
| 2543 | | DRIVER_INIT_MEMBER(ssv_state,ryorioh) { init(0); } |
| 2544 | | DRIVER_INIT_MEMBER(ssv_state,srmp4) { init(0); |
| 2531 | DRIVER_INIT_MEMBER(ssv_state,drifto94) { init_ssv(0); init_st010(); } |
| 2532 | DRIVER_INIT_MEMBER(ssv_state,eaglshot) { init_ssv(0); init_eaglshot_banking(); } |
| 2533 | DRIVER_INIT_MEMBER(ssv_state,gdfs) { init_ssv(0); } |
| 2534 | DRIVER_INIT_MEMBER(ssv_state,hypreact) { init_ssv(0); } |
| 2535 | DRIVER_INIT_MEMBER(ssv_state,hypreac2) { init_ssv(0); init_hypreac2_common(); } |
| 2536 | DRIVER_INIT_MEMBER(ssv_state,janjans1) { init_ssv(0); } |
| 2537 | DRIVER_INIT_MEMBER(ssv_state,keithlcy) { init_ssv(0); } |
| 2538 | DRIVER_INIT_MEMBER(ssv_state,meosism) { init_ssv(0); } |
| 2539 | DRIVER_INIT_MEMBER(ssv_state,mslider) { init_ssv(0); } |
| 2540 | DRIVER_INIT_MEMBER(ssv_state,ryorioh) { init_ssv(0); } |
| 2541 | DRIVER_INIT_MEMBER(ssv_state,srmp4) { init_ssv(0); |
| 2545 | 2542 | // ((UINT16 *)memregion("maincpu")->base())[0x2b38/2] = 0x037a; /* patch to see gal test mode */ |
| 2546 | 2543 | } |
| 2547 | | DRIVER_INIT_MEMBER(ssv_state,srmp7) { init(0); } |
| 2548 | | DRIVER_INIT_MEMBER(ssv_state,stmblade) { init(0); init_st010(); } |
| 2549 | | DRIVER_INIT_MEMBER(ssv_state,survarts) { init(0); } |
| 2550 | | DRIVER_INIT_MEMBER(ssv_state,dynagear) { init(0); } |
| 2551 | | DRIVER_INIT_MEMBER(ssv_state,sxyreact) { init(0); init_hypreac2_common(); save_item(NAME(m_sxyreact_serial)); save_item(NAME(m_sxyreact_dial)); } |
| 2552 | | DRIVER_INIT_MEMBER(ssv_state,cairblad) { init(0); init_hypreac2_common(); } |
| 2553 | | DRIVER_INIT_MEMBER(ssv_state,sxyreac2) { init(0); init_hypreac2_common(); save_item(NAME(m_sxyreact_serial)); save_item(NAME(m_sxyreact_dial)); } |
| 2554 | | DRIVER_INIT_MEMBER(ssv_state,twineag2) { init(1); init_st010(); } |
| 2555 | | DRIVER_INIT_MEMBER(ssv_state,ultrax) { init(1); } |
| 2556 | | DRIVER_INIT_MEMBER(ssv_state,vasara) { init(0); } |
| 2557 | | DRIVER_INIT_MEMBER(ssv_state,jsk) { init(0); save_item(NAME(m_latches)); } |
| 2544 | DRIVER_INIT_MEMBER(ssv_state,srmp7) { init_ssv(0); } |
| 2545 | DRIVER_INIT_MEMBER(ssv_state,stmblade) { init_ssv(0); init_st010(); } |
| 2546 | DRIVER_INIT_MEMBER(ssv_state,survarts) { init_ssv(0); } |
| 2547 | DRIVER_INIT_MEMBER(ssv_state,dynagear) { init_ssv(0); } |
| 2548 | DRIVER_INIT_MEMBER(ssv_state,sxyreact) { init_ssv(0); init_hypreac2_common(); } |
| 2549 | DRIVER_INIT_MEMBER(ssv_state,cairblad) { init_ssv(0); init_hypreac2_common(); } |
| 2550 | DRIVER_INIT_MEMBER(ssv_state,sxyreac2) { init_ssv(0); init_hypreac2_common(); } |
| 2551 | DRIVER_INIT_MEMBER(ssv_state,twineag2) { init_ssv(1); init_st010(); } |
| 2552 | DRIVER_INIT_MEMBER(ssv_state,ultrax) { init_ssv(1); } |
| 2553 | DRIVER_INIT_MEMBER(ssv_state,vasara) { init_ssv(0); } |
| 2554 | DRIVER_INIT_MEMBER(ssv_state,jsk) { init_ssv(0); } |
| 2558 | 2555 | |
| 2559 | 2556 | #define SSV_MASTER_CLOCK XTAL_48MHz/3 |
| 2560 | 2557 | |
| r244651 | r244652 | |
| 2570 | 2567 | |
| 2571 | 2568 | /* basic machine hardware */ |
| 2572 | 2569 | MCFG_CPU_ADD("maincpu", V60, SSV_MASTER_CLOCK) /* Based on STA-0001 & STA-0001B System boards */ |
| 2573 | | MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(ssv_state,irq_callback) |
| 2570 | MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(ssv_state,ssv_irq_callback) |
| 2574 | 2571 | |
| 2575 | | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", ssv_state, interrupt, "screen", 0, 1) |
| 2572 | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", ssv_state, ssv_interrupt, "screen", 0, 1) |
| 2576 | 2573 | |
| 2577 | 2574 | /* video hardware */ |
| 2578 | 2575 | MCFG_SCREEN_ADD("screen", RASTER) |
| 2579 | 2576 | MCFG_SCREEN_RAW_PARAMS(SSV_PIXEL_CLOCK,SSV_HTOTAL,SSV_HBEND,SSV_HBSTART,SSV_VTOTAL,SSV_VBEND,SSV_VBSTART) |
| 2580 | | MCFG_SCREEN_UPDATE_DRIVER(ssv_state, screen_update) |
| 2577 | MCFG_SCREEN_UPDATE_DRIVER(ssv_state, screen_update_ssv) |
| 2581 | 2578 | MCFG_SCREEN_PALETTE("palette") |
| 2582 | 2579 | |
| 2583 | 2580 | MCFG_GFXDECODE_ADD("gfxdecode", "palette", ssv) |
| r244651 | r244652 | |
| 4709 | 4706 | |
| 4710 | 4707 | // year rom clone machine inputs init monitor manufacturer title flags |
| 4711 | 4708 | |
| 4712 | | GAME( 1993, dynagear, 0, dynagear, dynagear, ssv_state, dynagear, ROT0, "Sammy", "Dyna Gear", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4709 | GAME( 1993, dynagear, 0, dynagear, dynagear, ssv_state, dynagear, ROT0, "Sammy", "Dyna Gear", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4713 | 4710 | |
| 4714 | | GAME( 1993, keithlcy, 0, keithlcy, keithlcy, ssv_state, keithlcy, ROT0, "Visco", "Dramatic Adventure Quiz Keith & Lucy (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4711 | GAME( 1993, keithlcy, 0, keithlcy, keithlcy, ssv_state, keithlcy, ROT0, "Visco", "Dramatic Adventure Quiz Keith & Lucy (Japan)", GAME_NO_COCKTAIL ) |
| 4715 | 4712 | |
| 4716 | | GAME( 1993, srmp4, 0, srmp4, srmp4, ssv_state, srmp4, ROT0, "Seta", "Super Real Mahjong PIV (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4717 | | GAME( 1993, srmp4o, srmp4, srmp4, srmp4, ssv_state, srmp4, ROT0, "Seta", "Super Real Mahjong PIV (Japan, older set)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) // by the numbering of the program roms this should be older |
| 4713 | GAME( 1993, srmp4, 0, srmp4, srmp4, ssv_state, srmp4, ROT0, "Seta", "Super Real Mahjong PIV (Japan)", GAME_NO_COCKTAIL ) |
| 4714 | GAME( 1993, srmp4o, srmp4, srmp4, srmp4, ssv_state, srmp4, ROT0, "Seta", "Super Real Mahjong PIV (Japan, older set)", GAME_NO_COCKTAIL ) // by the numbering of the program roms this should be older |
| 4718 | 4715 | |
| 4719 | | GAME( 1993, survarts, 0, survarts, survarts, ssv_state, survarts, ROT0, "Sammy", "Survival Arts (World)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4720 | | GAME( 1993, survartsu, survarts, survarts, survarts, ssv_state, survarts, ROT0, "American Sammy", "Survival Arts (USA)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4721 | | GAME( 1993, survartsj, survarts, survarts, survarts, ssv_state, survarts, ROT0, "Sammy", "Survival Arts (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4716 | GAME( 1993, survarts, 0, survarts, survarts, ssv_state, survarts, ROT0, "Sammy", "Survival Arts (World)", GAME_NO_COCKTAIL ) |
| 4717 | GAME( 1993, survartsu, survarts, survarts, survarts, ssv_state, survarts, ROT0, "American Sammy", "Survival Arts (USA)", GAME_NO_COCKTAIL ) |
| 4718 | GAME( 1993, survartsj, survarts, survarts, survarts, ssv_state, survarts, ROT0, "Sammy", "Survival Arts (Japan)", GAME_NO_COCKTAIL ) |
| 4722 | 4719 | |
| 4723 | | GAME( 1994, drifto94, 0, drifto94, drifto94, ssv_state, drifto94, ROT0, "Visco", "Drift Out '94 - The Hard Order (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4720 | GAME( 1994, drifto94, 0, drifto94, drifto94, ssv_state, drifto94, ROT0, "Visco", "Drift Out '94 - The Hard Order (Japan)", GAME_NO_COCKTAIL ) |
| 4724 | 4721 | |
| 4725 | | GAME( 1994, eaglshot, 0, eaglshot, eaglshot, ssv_state, eaglshot, ROT0, "Sammy", "Eagle Shot Golf", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4722 | GAME( 1994, eaglshot, 0, eaglshot, eaglshot, ssv_state, eaglshot, ROT0, "Sammy", "Eagle Shot Golf", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4726 | 4723 | |
| 4727 | | GAME( 1995, hypreact, 0, hypreact, hypreact, ssv_state, hypreact, ROT0, "Sammy", "Mahjong Hyper Reaction (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4724 | GAME( 1995, hypreact, 0, hypreact, hypreact, ssv_state, hypreact, ROT0, "Sammy", "Mahjong Hyper Reaction (Japan)", GAME_NO_COCKTAIL ) |
| 4728 | 4725 | |
| 4729 | | GAME( 1994, twineag2, 0, twineag2, twineag2, ssv_state, twineag2, ROT270, "Seta", "Twin Eagle II - The Rescue Mission", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4726 | GAME( 1994, twineag2, 0, twineag2, twineag2, ssv_state, twineag2, ROT270, "Seta", "Twin Eagle II - The Rescue Mission", GAME_NO_COCKTAIL ) |
| 4730 | 4727 | |
| 4731 | | GAME( 1995, gdfs, 0, gdfs, gdfs, ssv_state, gdfs, ROT0, "Banpresto", "Mobil Suit Gundam Final Shooting (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4728 | GAME( 1995, gdfs, 0, gdfs, gdfs, ssv_state, gdfs, ROT0, "Banpresto", "Mobil Suit Gundam Final Shooting (Japan)", GAME_NO_COCKTAIL ) |
| 4732 | 4729 | |
| 4733 | | GAME( 1995, ultrax, 0, ultrax, ultrax, ssv_state, ultrax, ROT270, "Banpresto / Tsuburaya Productions", "Ultra X Weapons / Ultra Keibitai", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) // 95-01-30 13:27:15 on startup |
| 4734 | | GAME( 1995, ultraxg, ultrax, ultrax, ultrax, ssv_state, ultrax, ROT270, "Banpresto / Tsuburaya Productions", "Ultra X Weapons / Ultra Keibitai (GAMEST review build)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) // 95-02-16 15:30:24 on startup (newer, but could have pause functionality due to being a review build so left as clone) |
| 4730 | GAME( 1995, ultrax, 0, ultrax, ultrax, ssv_state, ultrax, ROT270, "Banpresto / Tsuburaya Productions", "Ultra X Weapons / Ultra Keibitai", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) // 95-01-30 13:27:15 on startup |
| 4731 | GAME( 1995, ultraxg, ultrax, ultrax, ultrax, ssv_state, ultrax, ROT270, "Banpresto / Tsuburaya Productions", "Ultra X Weapons / Ultra Keibitai (GAMEST review build)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) // 95-02-16 15:30:24 on startup (newer, but could have pause functionality due to being a review build so left as clone) |
| 4735 | 4732 | |
| 4736 | | GAME( 1996, janjans1, 0, janjans1, janjans1, ssv_state, janjans1, ROT0, "Visco", "Lovely Pop Mahjong JangJang Shimasho (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4733 | GAME( 1996, janjans1, 0, janjans1, janjans1, ssv_state, janjans1, ROT0, "Visco", "Lovely Pop Mahjong JangJang Shimasho (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4737 | 4734 | |
| 4738 | | GAME( 1996?, meosism, 0, meosism, meosism, ssv_state, meosism, ROT0, "Sammy", "Meosis Magic (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4735 | GAME( 1996?, meosism, 0, meosism, meosism, ssv_state, meosism, ROT0, "Sammy", "Meosis Magic (Japan)", GAME_NO_COCKTAIL ) |
| 4739 | 4736 | |
| 4740 | | GAME( 1996, stmblade, 0, stmblade, stmblade, ssv_state, stmblade, ROT270, "Visco", "Storm Blade (US)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4741 | | GAME( 1996, stmbladej, stmblade, stmblade, stmblade, ssv_state, stmblade, ROT270, "Visco", "Storm Blade (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4737 | GAME( 1996, stmblade, 0, stmblade, stmblade, ssv_state, stmblade, ROT270, "Visco", "Storm Blade (US)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4738 | GAME( 1996, stmbladej, stmblade, stmblade, stmblade, ssv_state, stmblade, ROT270, "Visco", "Storm Blade (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4742 | 4739 | |
| 4743 | | GAME( 1997, hypreac2, 0, hypreac2, hypreac2, ssv_state, hypreac2, ROT0, "Sammy", "Mahjong Hyper Reaction 2 (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4740 | GAME( 1997, hypreac2, 0, hypreac2, hypreac2, ssv_state, hypreac2, ROT0, "Sammy", "Mahjong Hyper Reaction 2 (Japan)", GAME_NO_COCKTAIL ) |
| 4744 | 4741 | |
| 4745 | | GAME( 1997, jsk, 0, jsk, jsk, ssv_state, jsk, ROT0, "Visco", "Joryuu Syougi Kyoushitsu (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4742 | GAME( 1997, jsk, 0, jsk, jsk, ssv_state, jsk, ROT0, "Visco", "Joryuu Syougi Kyoushitsu (Japan)", GAME_NO_COCKTAIL ) |
| 4746 | 4743 | |
| 4747 | | GAME( 1997, koikois2, 0, janjans1, koikois2, ssv_state, janjans1, ROT0, "Visco", "Koi Koi Shimasho 2 - Super Real Hanafuda (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4744 | GAME( 1997, koikois2, 0, janjans1, koikois2, ssv_state, janjans1, ROT0, "Visco", "Koi Koi Shimasho 2 - Super Real Hanafuda (Japan)", GAME_NO_COCKTAIL ) |
| 4748 | 4745 | |
| 4749 | | GAME( 1997, mslider, 0, mslider, mslider, ssv_state, mslider, ROT0, "Visco / Datt Japan", "Monster Slider (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4746 | GAME( 1997, mslider, 0, mslider, mslider, ssv_state, mslider, ROT0, "Visco / Datt Japan", "Monster Slider (Japan)", GAME_NO_COCKTAIL ) |
| 4750 | 4747 | |
| 4751 | | GAME( 1997, srmp7, 0, srmp7, srmp7, ssv_state, srmp7, ROT0, "Seta", "Super Real Mahjong P7 (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 4748 | GAME( 1997, srmp7, 0, srmp7, srmp7, ssv_state, srmp7, ROT0, "Seta", "Super Real Mahjong P7 (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_SOUND ) |
| 4752 | 4749 | |
| 4753 | | GAME( 1998, ryorioh, 0, ryorioh, ryorioh, ssv_state, ryorioh, ROT0, "Visco", "Gourmet Battle Quiz Ryohrioh CooKing (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4750 | GAME( 1998, ryorioh, 0, ryorioh, ryorioh, ssv_state, ryorioh, ROT0, "Visco", "Gourmet Battle Quiz Ryohrioh CooKing (Japan)", GAME_NO_COCKTAIL ) |
| 4754 | 4751 | |
| 4755 | | GAME( 1998, sxyreact, 0, sxyreact, sxyreact, ssv_state, sxyreact, ROT0, "Sammy", "Pachinko Sexy Reaction (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4752 | GAME( 1998, sxyreact, 0, sxyreact, sxyreact, ssv_state, sxyreact, ROT0, "Sammy", "Pachinko Sexy Reaction (Japan)", GAME_NO_COCKTAIL ) |
| 4756 | 4753 | |
| 4757 | | GAME( 1999, sxyreac2, 0, sxyreac2, sxyreact, ssv_state, sxyreac2, ROT0, "Sammy", "Pachinko Sexy Reaction 2 (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4754 | GAME( 1999, sxyreac2, 0, sxyreac2, sxyreact, ssv_state, sxyreac2, ROT0, "Sammy", "Pachinko Sexy Reaction 2 (Japan)", GAME_NO_COCKTAIL ) |
| 4758 | 4755 | |
| 4759 | | GAME( 1999, cairblad, 0, cairblad, cairblad, ssv_state, cairblad, ROT270, "Sammy", "Change Air Blade (Japan)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4756 | GAME( 1999, cairblad, 0, cairblad, cairblad, ssv_state, cairblad, ROT270, "Sammy", "Change Air Blade (Japan)", GAME_NO_COCKTAIL ) |
| 4760 | 4757 | |
| 4761 | | GAME( 2000, janjans2, 0, janjans1, janjans2, ssv_state, janjans1, ROT0, "Visco", "Lovely Pop Mahjong JangJang Shimasho 2 (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS | GAME_SUPPORTS_SAVE ) |
| 4758 | GAME( 2000, janjans2, 0, janjans1, janjans2, ssv_state, janjans1, ROT0, "Visco", "Lovely Pop Mahjong JangJang Shimasho 2 (Japan)", GAME_NO_COCKTAIL | GAME_IMPERFECT_GRAPHICS ) |
| 4762 | 4759 | |
| 4763 | | GAME( 2000, vasara, 0, vasara, vasara, ssv_state, vasara, ROT270, "Visco", "Vasara", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4760 | GAME( 2000, vasara, 0, vasara, vasara, ssv_state, vasara, ROT270, "Visco", "Vasara", GAME_NO_COCKTAIL ) |
| 4764 | 4761 | |
| 4765 | | GAME( 2001, vasara2, 0, vasara, vasara2, ssv_state, vasara, ROT270, "Visco", "Vasara 2 (set 1)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4766 | | GAME( 2001, vasara2a, vasara2, vasara, vasara2, ssv_state, vasara, ROT270, "Visco", "Vasara 2 (set 2)", GAME_NO_COCKTAIL | GAME_SUPPORTS_SAVE ) |
| 4762 | GAME( 2001, vasara2, 0, vasara, vasara2, ssv_state, vasara, ROT270, "Visco", "Vasara 2 (set 1)", GAME_NO_COCKTAIL ) |
| 4763 | GAME( 2001, vasara2a, vasara2, vasara, vasara2, ssv_state, vasara, ROT270, "Visco", "Vasara 2 (set 2)", GAME_NO_COCKTAIL ) |
trunk/src/mess/drivers/mbee.c
| r244651 | r244652 | |
| 88 | 88 | 3. At the Basic prompt, type in EDASM press enter. At the memory size |
| 89 | 89 | prompt press enter. Now, make sure the keyboard works properly. |
| 90 | 90 | |
| 91 | | How to use the config switch for PIO B7: |
| 92 | | - Teleterm: Must use RTC. Anything else makes teleterm go crazy. |
| 93 | | - 256TC, 128, 128p: Doesn't seem to matter, leave at the default. |
| 94 | | - Standard: Has no effect, best left at "Tied High" |
| 95 | | - Other rom-based models: "VS" to make the Telcom clock work, or "Tied high". |
| 96 | | - 56k: not sure yet, leave as "Tied high" until more is known. |
| 97 | | |
| 98 | | How to use programs that need functions keys on models that use the old |
| 99 | | keyboard (for example, to run Simply Write on a 128k model). |
| 100 | | Press Ctrl+Shift+number, eg for F1 press hold down Ctrl Shift, press 1. |
| 101 | | |
| 102 | 91 | *************************************************************************** |
| 103 | 92 | |
| 104 | 93 | TODO/not working: |
| r244651 | r244652 | |
| 119 | 108 | crashes due to a bug in z80pio emulation. |
| 120 | 109 | |
| 121 | 110 | - 256tc: Keyboard ROM U60 needs to be dumped. |
| 122 | | - 128k, 64k: PALs need to be dumped for the bankswitching. |
| 111 | - 128k: GOLD PAL needs to be dumped for the bankswitching. |
| 112 | - 64k: RED PAL needs to be dumped for the bankswitching. |
| 123 | 113 | |
| 124 | | - Teleterm: keyboard has problems. The schematic shows it using the old-style keyboard, |
| 125 | | however it actually uses the new keyboard with interrupts. |
| 114 | - Teleterm: keyboard has multiple severe problems. Also, the schematic shows |
| 115 | it using the old-style keyboard, however this must be wrong since |
| 116 | the computer has function keys, which are only available on the |
| 117 | new keyboard. |
| 126 | 118 | |
| 127 | 119 | - Mouse: a few programs support the use of a serial mouse which interfaced |
| 128 | 120 | directly to the Z80PIO. However there's little info to be found. |
| r244651 | r244652 | |
| 143 | 135 | |
| 144 | 136 | static ADDRESS_MAP_START(mbee_mem, AS_PROGRAM, 8, mbee_state) |
| 145 | 137 | ADDRESS_MAP_UNMAP_HIGH |
| 146 | | AM_RANGE(0x0000, 0x3fff) AM_RAM |
| 138 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 139 | AM_RANGE(0x1000, 0x3fff) AM_RAM |
| 140 | AM_RANGE(0x4000, 0x7fff) AM_WRITENOP // Needed because quickload to here will crash MESS |
| 147 | 141 | AM_RANGE(0x8000, 0xefff) AM_ROM |
| 148 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 149 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 142 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbee_low_r, mbee_low_w) |
| 143 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbee_high_r, mbee_high_w) |
| 150 | 144 | ADDRESS_MAP_END |
| 151 | 145 | |
| 152 | 146 | static ADDRESS_MAP_START(mbeeic_mem, AS_PROGRAM, 8, mbee_state) |
| 153 | | AM_RANGE(0x0000, 0x7fff) AM_RAM |
| 147 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 148 | AM_RANGE(0x1000, 0x7fff) AM_RAM |
| 154 | 149 | AM_RANGE(0x8000, 0xbfff) AM_ROM |
| 155 | 150 | AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("pak") |
| 156 | 151 | AM_RANGE(0xe000, 0xefff) AM_ROM |
| 157 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 158 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 152 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbee_low_r, mbee_low_w) |
| 153 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeic_high_r, mbeeic_high_w) |
| 159 | 154 | ADDRESS_MAP_END |
| 160 | 155 | |
| 161 | 156 | static ADDRESS_MAP_START(mbeepc_mem, AS_PROGRAM, 8, mbee_state) |
| 162 | | AM_RANGE(0x0000, 0x7fff) AM_RAM |
| 157 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 158 | AM_RANGE(0x1000, 0x7fff) AM_RAM |
| 163 | 159 | AM_RANGE(0x8000, 0xbfff) AM_ROM |
| 164 | 160 | AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("pak") |
| 165 | 161 | AM_RANGE(0xe000, 0xefff) AM_ROMBANK("telcom") |
| 166 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 167 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 162 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbee_low_r, mbee_low_w) |
| 163 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeic_high_r, mbeeic_high_w) |
| 168 | 164 | ADDRESS_MAP_END |
| 169 | 165 | |
| 166 | static ADDRESS_MAP_START(mbeepc85_mem, AS_PROGRAM, 8, mbee_state) |
| 167 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 168 | AM_RANGE(0x1000, 0x7fff) AM_RAM |
| 169 | AM_RANGE(0x8000, 0xbfff) AM_ROM |
| 170 | AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("pak") |
| 171 | AM_RANGE(0xe000, 0xefff) AM_ROMBANK("telcom") |
| 172 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbee_low_r, mbee_low_w) |
| 173 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeic_high_r, mbeeic_high_w) |
| 174 | ADDRESS_MAP_END |
| 175 | |
| 170 | 176 | static ADDRESS_MAP_START(mbeeppc_mem, AS_PROGRAM, 8, mbee_state) |
| 171 | | AM_RANGE(0x0000, 0x7fff) AM_RAM |
| 177 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 178 | AM_RANGE(0x1000, 0x7fff) AM_RAM |
| 172 | 179 | AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("basic") |
| 173 | 180 | AM_RANGE(0xa000, 0xbfff) AM_ROM |
| 174 | 181 | AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("pak") |
| 175 | 182 | AM_RANGE(0xe000, 0xefff) AM_ROMBANK("telcom") |
| 176 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 177 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 183 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbeeppc_low_r, mbeeppc_low_w) |
| 184 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeppc_high_r, mbeeppc_high_w) |
| 178 | 185 | ADDRESS_MAP_END |
| 179 | 186 | |
| 180 | 187 | static ADDRESS_MAP_START(mbee56_mem, AS_PROGRAM, 8, mbee_state) |
| 181 | | AM_RANGE(0x0000, 0xdfff) AM_RAM |
| 188 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 189 | AM_RANGE(0x1000, 0xdfff) AM_RAM |
| 182 | 190 | AM_RANGE(0xe000, 0xefff) AM_ROM |
| 183 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 184 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 191 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbee_low_r, mbee_low_w) |
| 192 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeic_high_r, mbeeic_high_w) |
| 185 | 193 | ADDRESS_MAP_END |
| 186 | 194 | |
| 187 | 195 | static ADDRESS_MAP_START(mbee256_mem, AS_PROGRAM, 8, mbee_state) |
| r244651 | r244652 | |
| 204 | 212 | ADDRESS_MAP_END |
| 205 | 213 | |
| 206 | 214 | static ADDRESS_MAP_START(mbeett_mem, AS_PROGRAM, 8, mbee_state) |
| 207 | | AM_RANGE(0x0000, 0x7fff) AM_RAM |
| 215 | AM_RANGE(0x0000, 0x0fff) AM_RAMBANK("boot") |
| 216 | AM_RANGE(0x1000, 0x7fff) AM_RAM |
| 208 | 217 | AM_RANGE(0x8000, 0x9fff) AM_ROM |
| 209 | 218 | AM_RANGE(0xa000, 0xbfff) AM_RAM |
| 210 | 219 | AM_RANGE(0xc000, 0xdfff) AM_ROMBANK("pak") |
| 211 | 220 | AM_RANGE(0xe000, 0xefff) AM_ROMBANK("telcom") |
| 212 | | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(video_low_r, video_low_w) |
| 213 | | AM_RANGE(0xf800, 0xffff) AM_READWRITE(video_high_r, video_high_w) |
| 221 | AM_RANGE(0xf000, 0xf7ff) AM_READWRITE(mbeeppc_low_r, mbeeppc_low_w) |
| 222 | AM_RANGE(0xf800, 0xffff) AM_READWRITE(mbeeppc_high_r, mbeeppc_high_w) |
| 214 | 223 | ADDRESS_MAP_END |
| 215 | 224 | |
| 216 | 225 | static ADDRESS_MAP_START(mbee_io, AS_IO, 8, mbee_state) |
| 217 | 226 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 218 | 227 | ADDRESS_MAP_UNMAP_HIGH |
| 219 | 228 | AM_RANGE(0x00, 0x03) AM_MIRROR(0x10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 220 | | AM_RANGE(0x0b, 0x0b) AM_MIRROR(0x10) AM_WRITE(port0b_w) |
| 229 | AM_RANGE(0x0b, 0x0b) AM_MIRROR(0x10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 221 | 230 | AM_RANGE(0x0c, 0x0c) AM_MIRROR(0x10) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 222 | 231 | AM_RANGE(0x0d, 0x0d) AM_MIRROR(0x10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 223 | 232 | ADDRESS_MAP_END |
| r244651 | r244652 | |
| 226 | 235 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 227 | 236 | ADDRESS_MAP_UNMAP_HIGH |
| 228 | 237 | AM_RANGE(0x00, 0x03) AM_MIRROR(0x10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 229 | | AM_RANGE(0x08, 0x08) AM_MIRROR(0x10) AM_READWRITE(port08_r, port08_w) |
| 230 | | AM_RANGE(0x09, 0x09) AM_WRITENOP /* Listed as "Colour Wait Off" or "USART 2651" but doesn't appear in the schematics */ |
| 231 | | AM_RANGE(0x0a, 0x0a) AM_MIRROR(0x10) AM_WRITE(port0a_w) |
| 232 | | AM_RANGE(0x0b, 0x0b) AM_MIRROR(0x10) AM_WRITE(port0b_w) |
| 238 | AM_RANGE(0x08, 0x08) AM_MIRROR(0x10) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 239 | AM_RANGE(0x09, 0x09) AM_MIRROR(0x10) AM_NOP /* Listed as "Colour Wait Off" or "USART 2651" but doesn't appear in the schematics */ |
| 240 | AM_RANGE(0x0a, 0x0a) AM_MIRROR(0x10) AM_READWRITE(mbeeic_0a_r, mbeeic_0a_w) |
| 241 | AM_RANGE(0x0b, 0x0b) AM_MIRROR(0x10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 233 | 242 | AM_RANGE(0x0c, 0x0c) AM_MIRROR(0x10) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 234 | 243 | AM_RANGE(0x0d, 0x0d) AM_MIRROR(0x10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 235 | 244 | ADDRESS_MAP_END |
| r244651 | r244652 | |
| 237 | 246 | static ADDRESS_MAP_START(mbeepc_io, AS_IO, 8, mbee_state) |
| 238 | 247 | ADDRESS_MAP_UNMAP_HIGH |
| 239 | 248 | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 240 | | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff10) AM_READWRITE(port08_r, port08_w) |
| 241 | | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xff00) AM_WRITENOP |
| 242 | | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff10) AM_WRITE(port0b_w) |
| 249 | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff10) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 250 | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_low_r, mbeeic_0a_w) |
| 251 | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 243 | 252 | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff10) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 244 | 253 | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 245 | | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(telcom_low_r, port0a_w) |
| 246 | | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(telcom_high_r, port0a_w) |
| 254 | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_high_r, mbeeic_0a_w) |
| 247 | 255 | ADDRESS_MAP_END |
| 248 | 256 | |
| 249 | | static ADDRESS_MAP_START(mbeeppc_io, AS_IO, 8, mbee_state) |
| 257 | static ADDRESS_MAP_START(mbeepc85_io, AS_IO, 8, mbee_state) |
| 250 | 258 | ADDRESS_MAP_UNMAP_HIGH |
| 251 | 259 | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 252 | | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff10) AM_READWRITE(port08_r, port08_w) |
| 253 | | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xff00) AM_WRITENOP |
| 254 | | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff10) AM_WRITE(port0b_w) |
| 255 | | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff00) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 260 | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff10) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 261 | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_low_r, mbeeic_0a_w) |
| 262 | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 263 | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff10) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 256 | 264 | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 257 | | AM_RANGE(0x001c, 0x001c) AM_MIRROR(0xff00) AM_READWRITE(port1c_r, port1c_w) |
| 258 | | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(telcom_low_r, port0a_w) |
| 259 | | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(telcom_high_r, port0a_w) |
| 265 | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_high_r, mbeeic_0a_w) |
| 260 | 266 | ADDRESS_MAP_END |
| 261 | 267 | |
| 262 | | static ADDRESS_MAP_START(mbeett_io, AS_IO, 8, mbee_state) |
| 268 | static ADDRESS_MAP_START(mbeeppc_io, AS_IO, 8, mbee_state) |
| 263 | 269 | ADDRESS_MAP_UNMAP_HIGH |
| 264 | | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff00) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 265 | | AM_RANGE(0x0004, 0x0004) AM_MIRROR(0xff00) AM_WRITE(port04_w) |
| 266 | | AM_RANGE(0x0006, 0x0006) AM_MIRROR(0xff00) AM_WRITE(port06_w) |
| 267 | | AM_RANGE(0x0007, 0x0007) AM_MIRROR(0xff00) AM_READ(port07_r) |
| 268 | | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff00) AM_READWRITE(port08_r, port08_w) |
| 269 | | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff00) AM_WRITE(port0b_w) |
| 270 | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 271 | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff10) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 272 | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_low_r, mbeeic_0a_w) |
| 273 | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 270 | 274 | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff00) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 271 | | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff00) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 272 | | AM_RANGE(0x0018, 0x001b) AM_MIRROR(0xff00) AM_READ(port18_r) |
| 273 | | AM_RANGE(0x001c, 0x001f) AM_MIRROR(0xff00) AM_READWRITE(port1c_r, port1c_w) |
| 274 | | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xfe00) AM_READ(speed_low_r) |
| 275 | | AM_RANGE(0x0109, 0x0109) AM_MIRROR(0xfe00) AM_READ(speed_high_r) |
| 276 | | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe00) AM_READWRITE(telcom_low_r, port0a_w) |
| 277 | | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe00) AM_READWRITE(telcom_high_r, port0a_w) |
| 278 | | AM_RANGE(0x0068, 0x006f) AM_MIRROR(0xff00) AM_DEVREADWRITE("scc", scc8530_t, reg_r, reg_w) |
| 275 | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 276 | AM_RANGE(0x001c, 0x001c) AM_MIRROR(0xff00) AM_READWRITE(mbeeppc_1c_r, mbeeppc_1c_w) |
| 277 | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_high_r, mbeeic_0a_w) |
| 279 | 278 | ADDRESS_MAP_END |
| 280 | 279 | |
| 281 | 280 | static ADDRESS_MAP_START(mbee56_io, AS_IO, 8, mbee_state) |
| 282 | 281 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 283 | 282 | ADDRESS_MAP_UNMAP_HIGH |
| 284 | | AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 285 | | AM_RANGE(0x08, 0x08) AM_READWRITE(port08_r, port08_w) |
| 286 | | AM_RANGE(0x09, 0x09) AM_WRITENOP |
| 287 | | AM_RANGE(0x0b, 0x0b) AM_WRITE(port0b_w) |
| 288 | | AM_RANGE(0x0c, 0x0c) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 289 | | AM_RANGE(0x0d, 0x0d) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 283 | AM_RANGE(0x00, 0x03) AM_MIRROR(0x10) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 284 | AM_RANGE(0x08, 0x08) AM_MIRROR(0x10) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 285 | AM_RANGE(0x0b, 0x0b) AM_MIRROR(0x10) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 286 | AM_RANGE(0x0c, 0x0c) AM_MIRROR(0x10) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 287 | AM_RANGE(0x0d, 0x0d) AM_MIRROR(0x10) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 290 | 288 | AM_RANGE(0x44, 0x47) AM_DEVREADWRITE("fdc", wd2793_t, read, write) |
| 291 | 289 | AM_RANGE(0x48, 0x4f) AM_READWRITE(fdc_status_r, fdc_motor_w) |
| 292 | 290 | ADDRESS_MAP_END |
| r244651 | r244652 | |
| 295 | 293 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 296 | 294 | ADDRESS_MAP_UNMAP_HIGH |
| 297 | 295 | AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 298 | | AM_RANGE(0x04, 0x04) AM_WRITE(port04_w) |
| 299 | | AM_RANGE(0x06, 0x06) AM_WRITE(port06_w) |
| 300 | | AM_RANGE(0x07, 0x07) AM_READ(port07_r) |
| 301 | | AM_RANGE(0x08, 0x08) AM_READWRITE(port08_r, port08_w) |
| 302 | | AM_RANGE(0x09, 0x09) AM_WRITENOP |
| 303 | | AM_RANGE(0x0b, 0x0b) AM_WRITE(port0b_w) |
| 296 | AM_RANGE(0x04, 0x04) AM_WRITE(mbee_04_w) |
| 297 | AM_RANGE(0x06, 0x06) AM_WRITE(mbee_06_w) |
| 298 | AM_RANGE(0x07, 0x07) AM_READ(mbee_07_r) |
| 299 | AM_RANGE(0x08, 0x08) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 300 | AM_RANGE(0x0b, 0x0b) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 304 | 301 | AM_RANGE(0x0c, 0x0c) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 305 | 302 | AM_RANGE(0x0d, 0x0d) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 306 | | AM_RANGE(0x1c, 0x1f) AM_READWRITE(port1c_r, port1c_w) |
| 303 | AM_RANGE(0x1c, 0x1f) AM_READWRITE(mbeeppc_1c_r, mbee256_1c_w) |
| 307 | 304 | AM_RANGE(0x44, 0x47) AM_DEVREADWRITE("fdc", wd2793_t, read, write) |
| 308 | 305 | AM_RANGE(0x48, 0x4f) AM_READWRITE(fdc_status_r, fdc_motor_w) |
| 309 | 306 | AM_RANGE(0x50, 0x57) AM_WRITE(mbee128_50_w) |
| r244651 | r244652 | |
| 312 | 309 | static ADDRESS_MAP_START(mbee256_io, AS_IO, 8, mbee_state) |
| 313 | 310 | ADDRESS_MAP_UNMAP_HIGH |
| 314 | 311 | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff00) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 315 | | AM_RANGE(0x0004, 0x0004) AM_MIRROR(0xff00) AM_WRITE(port04_w) |
| 316 | | AM_RANGE(0x0006, 0x0006) AM_MIRROR(0xff00) AM_WRITE(port06_w) |
| 317 | | AM_RANGE(0x0007, 0x0007) AM_MIRROR(0xff00) AM_READ(port07_r) |
| 318 | | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff00) AM_READWRITE(port08_r, port08_w) |
| 319 | | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xfd00) AM_READ(speed_low_r) |
| 320 | | AM_RANGE(0x0209, 0x0209) AM_MIRROR(0xfd00) AM_READ(speed_high_r) |
| 321 | | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xff00) AM_WRITENOP |
| 322 | | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff00) AM_WRITE(port0b_w) |
| 312 | AM_RANGE(0x0004, 0x0004) AM_MIRROR(0xff00) AM_WRITE(mbee_04_w) |
| 313 | AM_RANGE(0x0006, 0x0006) AM_MIRROR(0xff00) AM_WRITE(mbee_06_w) |
| 314 | AM_RANGE(0x0007, 0x0007) AM_MIRROR(0xff00) AM_READ(mbee_07_r) |
| 315 | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff00) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 316 | AM_RANGE(0x0009, 0x0009) AM_MIRROR(0xfd00) AM_READ(mbee256_speed_low_r) |
| 317 | AM_RANGE(0x0209, 0x0209) AM_MIRROR(0xfd00) AM_READ(mbee256_speed_high_r) |
| 318 | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff00) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 323 | 319 | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff00) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 324 | 320 | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff00) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 325 | 321 | // AM_RANGE(0x0010, 0x0013) AM_MIRROR(0xff00) Optional SN76489AN audio chip |
| 326 | | AM_RANGE(0x0018, 0x001b) AM_MIRROR(0xff00) AM_READ(port18_r) |
| 327 | | AM_RANGE(0x001c, 0x001f) AM_MIRROR(0xff00) AM_READWRITE(port1c_r, port1c_w) |
| 322 | AM_RANGE(0x0018, 0x001b) AM_MIRROR(0xff00) AM_READ(mbee256_18_r) |
| 323 | AM_RANGE(0x001c, 0x001f) AM_MIRROR(0xff00) AM_READWRITE(mbeeppc_1c_r, mbee256_1c_w) |
| 328 | 324 | AM_RANGE(0x0044, 0x0047) AM_MIRROR(0xff00) AM_DEVREADWRITE("fdc", wd2793_t, read, write) |
| 329 | 325 | AM_RANGE(0x0048, 0x004f) AM_MIRROR(0xff00) AM_READWRITE(fdc_status_r, fdc_motor_w) |
| 330 | 326 | AM_RANGE(0x0050, 0x0057) AM_MIRROR(0xff00) AM_WRITE(mbee256_50_w) |
| r244651 | r244652 | |
| 333 | 329 | // AM_RANGE(0x0068, 0x006f) AM_MIRROR(0xff00) Reserved for 8530 SCC (unused) |
| 334 | 330 | ADDRESS_MAP_END |
| 335 | 331 | |
| 332 | static ADDRESS_MAP_START(mbeett_io, AS_IO, 8, mbee_state) |
| 333 | ADDRESS_MAP_UNMAP_HIGH |
| 334 | AM_RANGE(0x0000, 0x0003) AM_MIRROR(0xff00) AM_DEVREADWRITE("z80pio", z80pio_device, read_alt, write_alt) |
| 335 | AM_RANGE(0x0004, 0x0004) AM_MIRROR(0xff00) AM_WRITE(mbee_04_w) |
| 336 | AM_RANGE(0x0006, 0x0006) AM_MIRROR(0xff00) AM_WRITE(mbee_06_w) |
| 337 | AM_RANGE(0x0007, 0x0007) AM_MIRROR(0xff00) AM_READ(mbee_07_r) |
| 338 | AM_RANGE(0x0008, 0x0008) AM_MIRROR(0xff00) AM_READWRITE(mbeeic_08_r, mbeeic_08_w) |
| 339 | AM_RANGE(0x000b, 0x000b) AM_MIRROR(0xff00) AM_READWRITE(mbee_0b_r, mbee_0b_w) |
| 340 | AM_RANGE(0x000c, 0x000c) AM_MIRROR(0xff00) AM_READWRITE(m6545_status_r, m6545_index_w) |
| 341 | AM_RANGE(0x000d, 0x000d) AM_MIRROR(0xff00) AM_READWRITE(m6545_data_r, m6545_data_w) |
| 342 | AM_RANGE(0x0018, 0x001b) AM_MIRROR(0xff00) AM_READ(mbee256_18_r) |
| 343 | AM_RANGE(0x001c, 0x001f) AM_MIRROR(0xff00) AM_READWRITE(mbeeppc_1c_r,mbee256_1c_w) |
| 344 | AM_RANGE(0x000a, 0x000a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_low_r, mbeeic_0a_w) |
| 345 | AM_RANGE(0x010a, 0x010a) AM_MIRROR(0xfe10) AM_READWRITE(mbeepc_telcom_high_r, mbeeic_0a_w) |
| 346 | // AM_RANGE(0x0068, 0x006f) AM_MIRROR(0xff00) 8530 SCC |
| 347 | ADDRESS_MAP_END |
| 348 | |
| 336 | 349 | static INPUT_PORTS_START( mbee ) |
| 337 | 350 | PORT_START("X.0") /* IN0 KEY ROW 0 [000] */ |
| 338 | 351 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("@") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR('@') PORT_CHAR('`') |
| r244651 | r244652 | |
| 406 | 419 | |
| 407 | 420 | PORT_START("X.7") /* IN7 KEY ROW 7 [380] */ |
| 408 | 421 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("(Up)") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) |
| 409 | | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 422 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) |
| 410 | 423 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("(Down)") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 411 | 424 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("(Left)") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 412 | 425 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| r244651 | r244652 | |
| 431 | 444 | PORT_CONFNAME( 0xc0, 0x80, "PIO B7") |
| 432 | 445 | PORT_CONFSETTING( 0x00, "VS") // sync pulse to enable telcom clock |
| 433 | 446 | PORT_CONFSETTING( 0x40, "RTC") // optional board usually not fitted |
| 434 | | PORT_CONFSETTING( 0x80, "Tied high") // default resistor to vcc |
| 435 | | PORT_CONFSETTING( 0xc0, "Reserved for net") |
| 447 | PORT_CONFSETTING( 0x80, "Not used") // default resistor to vcc |
| 448 | PORT_CONFSETTING( 0xc0, "Centronics") // busy line |
| 436 | 449 | INPUT_PORTS_END |
| 437 | 450 | |
| 438 | 451 | static INPUT_PORTS_START( mbee256 ) |
| r244651 | r244652 | |
| 563 | 576 | PORT_CONFSETTING( 0x00, DEF_STR(No)) |
| 564 | 577 | PORT_CONFSETTING( 0x01, DEF_STR(Yes)) |
| 565 | 578 | // Wire links on motherboard |
| 566 | | PORT_CONFNAME( 0xc0, 0x40, "PIO B7") |
| 579 | PORT_CONFNAME( 0xc0, 0x80, "PIO B7") // default - do nothing |
| 567 | 580 | PORT_CONFSETTING( 0x00, "VS") // sync pulse to enable telcom clock |
| 568 | | PORT_CONFSETTING( 0x40, "RTC") // RTC IRQ must be used on teleterm |
| 569 | | PORT_CONFSETTING( 0x80, "Tied high") // default resistor to vcc |
| 570 | | PORT_CONFSETTING( 0xc0, "Reserved for net") |
| 581 | PORT_CONFSETTING( 0x40, "RTC") // optional board usually not fitted |
| 582 | PORT_CONFSETTING( 0x80, "Not used") // default resistor to vcc |
| 583 | PORT_CONFSETTING( 0xc0, "Centronics") // busy line |
| 571 | 584 | INPUT_PORTS_END |
| 572 | 585 | |
| 573 | 586 | static const z80_daisy_config mbee_daisy_chain[] = |
| r244651 | r244652 | |
| 731 | 744 | MCFG_CPU_IO_MAP(mbeepc_io) |
| 732 | 745 | MACHINE_CONFIG_END |
| 733 | 746 | |
| 734 | | static MACHINE_CONFIG_DERIVED( mbeepc85b, mbeepc ) |
| 747 | static MACHINE_CONFIG_DERIVED( mbeepc85, mbeeic ) |
| 748 | MCFG_CPU_MODIFY( "maincpu" ) |
| 749 | MCFG_CPU_PROGRAM_MAP(mbeepc85_mem) |
| 750 | MCFG_CPU_IO_MAP(mbeepc85_io) |
| 751 | MACHINE_CONFIG_END |
| 752 | |
| 753 | static MACHINE_CONFIG_DERIVED( mbeepc85b, mbeepc85 ) |
| 735 | 754 | MCFG_PALETTE_MODIFY("palette") |
| 736 | 755 | MCFG_PALETTE_INIT_OWNER(mbee_state, mbeepc85b) |
| 737 | 756 | MACHINE_CONFIG_END |
| r244651 | r244652 | |
| 745 | 764 | MCFG_PALETTE_MODIFY("palette") |
| 746 | 765 | MCFG_PALETTE_ENTRIES(16) |
| 747 | 766 | MCFG_PALETTE_INIT_OWNER(mbee_state, premium) |
| 748 | | MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) |
| 749 | | MCFG_MC146818_IRQ_HANDLER(WRITELINE(mbee_state, rtc_irq_w)) |
| 750 | 767 | MACHINE_CONFIG_END |
| 751 | 768 | |
| 752 | 769 | static MACHINE_CONFIG_DERIVED( mbee56, mbeeic ) |
| r244651 | r244652 | |
| 767 | 784 | MCFG_CPU_IO_MAP(mbee128_io) |
| 768 | 785 | MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbee128) |
| 769 | 786 | MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) |
| 770 | | MCFG_MC146818_IRQ_HANDLER(WRITELINE(mbee_state, rtc_irq_w)) |
| 771 | 787 | MACHINE_CONFIG_END |
| 772 | 788 | |
| 773 | 789 | static MACHINE_CONFIG_DERIVED( mbee128p, mbeeppc ) |
| r244651 | r244652 | |
| 775 | 791 | MCFG_CPU_PROGRAM_MAP(mbee256_mem) |
| 776 | 792 | MCFG_CPU_IO_MAP(mbee128_io) |
| 777 | 793 | MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbee128) |
| 794 | MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) |
| 778 | 795 | MCFG_WD2793x_ADD("fdc", XTAL_4MHz / 4) |
| 779 | 796 | MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(mbee_state, fdc_intrq_w)) |
| 780 | 797 | MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(mbee_state, fdc_drq_w)) |
| r244651 | r244652 | |
| 799 | 816 | MCFG_CPU_PROGRAM_MAP(mbeett_mem) |
| 800 | 817 | MCFG_CPU_IO_MAP(mbeett_io) |
| 801 | 818 | MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbeett) |
| 802 | | MCFG_DEVICE_REMOVE("quickload") |
| 803 | | MCFG_DEVICE_REMOVE("quickload2") |
| 804 | | MCFG_DEVICE_ADD("scc", SCC8530, 4000000) // clock unknown |
| 819 | MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) |
| 805 | 820 | MACHINE_CONFIG_END |
| 806 | 821 | |
| 807 | 822 | /* Unused roms: |
| r244651 | r244652 | |
| 1137 | 1152 | COMP( 1982, mbee, 0, 0, mbee, mbee, mbee_state, mbee, "Applied Technology", "Microbee 16 Standard" , 0 ) |
| 1138 | 1153 | COMP( 1982, mbeeic, mbee, 0, mbeeic, mbee, mbee_state, mbeeic, "Applied Technology", "Microbee 32 IC" , 0 ) |
| 1139 | 1154 | COMP( 1982, mbeepc, mbee, 0, mbeepc, mbee, mbee_state, mbeepc, "Applied Technology", "Microbee Personal Communicator" , 0 ) |
| 1140 | | COMP( 1985, mbeepc85, mbee, 0, mbeepc, mbee, mbee_state, mbeepc85, "Applied Technology", "Microbee PC85" , 0 ) |
| 1155 | COMP( 1985, mbeepc85, mbee, 0, mbeepc85, mbee, mbee_state, mbeepc85, "Applied Technology", "Microbee PC85" , 0 ) |
| 1141 | 1156 | COMP( 1985, mbeepc85b,mbee, 0, mbeepc85b,mbee, mbee_state, mbeepc85, "Applied Technology", "Microbee PC85 (New version)" , 0 ) |
| 1142 | | COMP( 1985, mbeepc85s,mbee, 0, mbeepc, mbee, mbee_state, mbeepc85, "Applied Technology", "Microbee PC85 (Swedish)" , 0 ) |
| 1157 | COMP( 1985, mbeepc85s,mbee, 0, mbeepc85, mbee, mbee_state, mbeepc85, "Applied Technology", "Microbee PC85 (Swedish)" , 0 ) |
| 1143 | 1158 | COMP( 1986, mbeeppc, mbee, 0, mbeeppc, mbee, mbee_state, mbeeppc, "Applied Technology", "Microbee Premium PC85" , 0 ) |
| 1144 | 1159 | COMP( 1986, mbeett, mbee, 0, mbeett, mbee256, mbee_state, mbeett, "Applied Technology", "Microbee Teleterm" , GAME_NOT_WORKING ) |
| 1145 | 1160 | COMP( 1986, mbee56, mbee, 0, mbee56, mbee, mbee_state, mbee56, "Applied Technology", "Microbee 56k" , GAME_NOT_WORKING ) |
trunk/src/osd/modules/render/d3d/d3dhlsl.c
| r0 | r244652 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Aaron Giles |
| 3 | //============================================================ |
| 4 | // |
| 5 | // d3dhlsl.c - Win32 Direct3D HLSL 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 | #include "screen.h" |
| 37 | |
| 38 | // MAMEOS headers |
| 39 | #include "d3dintf.h" |
| 40 | #include "winmain.h" |
| 41 | #include "window.h" |
| 42 | #include "config.h" |
| 43 | #include "d3dcomm.h" |
| 44 | #include "modules/render/drawd3d.h" |
| 45 | #include "strconv.h" |
| 46 | |
| 47 | |
| 48 | |
| 49 | //============================================================ |
| 50 | // GLOBALS |
| 51 | //============================================================ |
| 52 | |
| 53 | static slider_state *g_slider_list; |
| 54 | static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx); |
| 55 | |
| 56 | namespace d3d |
| 57 | { |
| 58 | hlsl_options shaders::s_hlsl_presets[4] = |
| 59 | { |
| 60 | { // 25% Shadow mask, 50% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 61 | true, |
| 62 | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 63 | 0.03f, 0.03f, |
| 64 | 0.5f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 65 | { 0.0f, 0.0f }, |
| 66 | { 0.0f, 0.0f, 0.0f }, |
| 67 | { 0.0f, 0.0f, 0.0f }, |
| 68 | { 0.0f, 0.0f, 0.0f }, |
| 69 | { 0.0f, 0.0f, 0.0f }, |
| 70 | { 1.0f, 0.0f, 0.0f }, |
| 71 | { 0.0f, 1.0f, 0.0f }, |
| 72 | { 0.0f, 0.0f, 1.0f }, |
| 73 | { 0.0f, 0.0f, 0.0f }, |
| 74 | { 1.0f, 1.0f, 1.0f }, |
| 75 | { 0.9f, 0.9f, 0.9f }, |
| 76 | { 0.05f,0.05f,0.05f}, |
| 77 | { 0.25f,0.25f,0.25f}, |
| 78 | 1.2f, |
| 79 | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 80 | 0.9f, 4.0f, |
| 81 | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 82 | }, |
| 83 | { // 25% Shadow mask, 0% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 84 | true, |
| 85 | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 86 | 0.03f, 0.03f, |
| 87 | 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 88 | { 0.0f, 0.0f }, |
| 89 | { 0.0f, 0.0f, 0.0f }, |
| 90 | { 0.0f, 0.0f, 0.0f }, |
| 91 | { 0.0f, 0.0f, 0.0f }, |
| 92 | { 0.0f, 0.0f, 0.0f }, |
| 93 | { 1.0f, 0.0f, 0.0f }, |
| 94 | { 0.0f, 1.0f, 0.0f }, |
| 95 | { 0.0f, 0.0f, 1.0f }, |
| 96 | { 0.0f, 0.0f, 0.0f }, |
| 97 | { 1.0f, 1.0f, 1.0f }, |
| 98 | { 0.9f, 0.9f, 0.9f }, |
| 99 | { 0.05f,0.05f,0.05f}, |
| 100 | { 0.25f,0.25f,0.25f}, |
| 101 | 1.2f, |
| 102 | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 103 | 0.9f, 4.0f, |
| 104 | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 105 | }, |
| 106 | { // 25% Shadow mask, 0% Scanlines, 0% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 107 | true, |
| 108 | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 109 | 0.0f, 0.0f, |
| 110 | 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 111 | { 0.0f, 0.0f }, |
| 112 | { 0.0f, 0.0f, 0.0f }, |
| 113 | { 0.0f, 0.0f, 0.0f }, |
| 114 | { 0.0f, 0.0f, 0.0f }, |
| 115 | { 0.0f, 0.0f, 0.0f }, |
| 116 | { 1.0f, 0.0f, 0.0f }, |
| 117 | { 0.0f, 1.0f, 0.0f }, |
| 118 | { 0.0f, 0.0f, 1.0f }, |
| 119 | { 0.0f, 0.0f, 0.0f }, |
| 120 | { 1.0f, 1.0f, 1.0f }, |
| 121 | { 0.9f, 0.9f, 0.9f }, |
| 122 | { 0.05f,0.05f,0.05f}, |
| 123 | { 0.25f,0.25f,0.25f}, |
| 124 | 1.2f, |
| 125 | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 126 | 0.9f, 4.0f, |
| 127 | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 128 | }, |
| 129 | { // 25% Shadow mask, 100% Scanlines, 15% Pincushion, 3 defocus, 24-degree Tint Out, 1.5 Exponent, 5% Floor, 70% Phosphor Return, 80% Saturation, Bad Convergence |
| 130 | true, |
| 131 | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 132 | 0.15f, 0.15f, |
| 133 | 1.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, |
| 134 | { 3.0f, 3.0f }, |
| 135 | { 0.5f,-0.33f,0.7f }, |
| 136 | { 0.0f,-1.0f, 0.5f }, |
| 137 | { 0.0f, 0.2f, 0.3f }, |
| 138 | { 0.0f, 0.2f, 0.0f }, |
| 139 | { 0.8f, 0.2f, 0.0f }, |
| 140 | { 0.0f, 0.8f, 0.2f}, |
| 141 | { 0.2f, 0.0f, 0.8f}, |
| 142 | { 0.0f, 0.0f, 0.0f }, |
| 143 | { 1.0f, 1.0f, 1.0f }, |
| 144 | { 1.5f, 1.5f, 1.5f }, |
| 145 | { 0.05f,0.05f,0.05f}, |
| 146 | { 0.7f, 0.7f, 0.7f}, |
| 147 | 0.8f, |
| 148 | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 149 | 0.9f, 4.0f, |
| 150 | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 151 | }, |
| 152 | }; |
| 153 | |
| 154 | //============================================================ |
| 155 | // PROTOTYPES |
| 156 | //============================================================ |
| 157 | |
| 158 | static void get_vector(const char *data, int count, float *out, int report_error); |
| 159 | |
| 160 | |
| 161 | //============================================================ |
| 162 | // TYPE DEFINITIONS |
| 163 | //============================================================ |
| 164 | |
| 165 | typedef HRESULT (WINAPI *direct3dx9_loadeffect_ptr)(LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors); |
| 166 | static direct3dx9_loadeffect_ptr g_load_effect = NULL; |
| 167 | |
| 168 | //============================================================ |
| 169 | // shader manager constructor |
| 170 | //============================================================ |
| 171 | |
| 172 | shaders::shaders() |
| 173 | { |
| 174 | master_enable = false; |
| 175 | vector_enable = true; |
| 176 | prescale_size_x = 1; |
| 177 | prescale_size_y = 1; |
| 178 | prescale_force_x = 0; |
| 179 | prescale_force_y = 0; |
| 180 | preset = -1; |
| 181 | shadow_texture = NULL; |
| 182 | options = NULL; |
| 183 | paused = true; |
| 184 | lastidx = -1; |
| 185 | targethead = NULL; |
| 186 | cachehead = NULL; |
| 187 | initialized = false; |
| 188 | } |
| 189 | |
| 190 | |
| 191 | |
| 192 | //============================================================ |
| 193 | // shaders destructor |
| 194 | //============================================================ |
| 195 | |
| 196 | shaders::~shaders() |
| 197 | { |
| 198 | global_free(options); |
| 199 | cache_target *currcache = cachehead; |
| 200 | while(cachehead != NULL) |
| 201 | { |
| 202 | cachehead = currcache->next; |
| 203 | global_free(currcache); |
| 204 | currcache = cachehead; |
| 205 | } |
| 206 | |
| 207 | render_target *currtarget = targethead; |
| 208 | while(targethead != NULL) |
| 209 | { |
| 210 | targethead = currtarget->next; |
| 211 | global_free(currtarget); |
| 212 | currtarget = targethead; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | |
| 217 | |
| 218 | //============================================================ |
| 219 | // shaders::window_save |
| 220 | //============================================================ |
| 221 | |
| 222 | void shaders::window_save() |
| 223 | { |
| 224 | if (!master_enable || !d3dintf->post_fx_available) |
| 225 | return; |
| 226 | |
| 227 | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &snap_copy_texture); |
| 228 | if (result != D3D_OK) |
| 229 | { |
| 230 | osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); |
| 231 | return; |
| 232 | } |
| 233 | (*d3dintf->texture.get_surface_level)(snap_copy_texture, 0, &snap_copy_target); |
| 234 | |
| 235 | result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &snap_texture); |
| 236 | if (result != D3D_OK) |
| 237 | { |
| 238 | osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); |
| 239 | return; |
| 240 | } |
| 241 | (*d3dintf->texture.get_surface_level)(snap_texture, 0, &snap_target); |
| 242 | |
| 243 | render_snap = true; |
| 244 | snap_rendered = false; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | |
| 249 | //============================================================ |
| 250 | // shaders::window_record |
| 251 | //============================================================ |
| 252 | |
| 253 | void shaders::window_record() |
| 254 | { |
| 255 | if (!master_enable || !d3dintf->post_fx_available) |
| 256 | return; |
| 257 | |
| 258 | windows_options &options = downcast<windows_options &>(machine->options()); |
| 259 | const char *filename = options.d3d_hlsl_write(); |
| 260 | |
| 261 | if (avi_output_file != NULL) |
| 262 | end_avi_recording(); |
| 263 | else if (filename[0] != 0) |
| 264 | begin_avi_recording(filename); |
| 265 | } |
| 266 | |
| 267 | |
| 268 | //============================================================ |
| 269 | // shaders::avi_update_snap |
| 270 | //============================================================ |
| 271 | |
| 272 | void shaders::avi_update_snap(surface *surface) |
| 273 | { |
| 274 | if (!master_enable || !d3dintf->post_fx_available) |
| 275 | return; |
| 276 | |
| 277 | D3DLOCKED_RECT rect; |
| 278 | |
| 279 | // if we don't have a bitmap, or if it's not the right size, allocate a new one |
| 280 | if (!avi_snap.valid() || (int)snap_width != avi_snap.width() || (int)snap_height != avi_snap.height()) |
| 281 | { |
| 282 | avi_snap.allocate((int)snap_width, (int)snap_height); |
| 283 | } |
| 284 | |
| 285 | // copy the texture |
| 286 | HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, avi_copy_surface); |
| 287 | if (result != D3D_OK) |
| 288 | { |
| 289 | return; |
| 290 | } |
| 291 | |
| 292 | // lock the texture |
| 293 | result = (*d3dintf->surface.lock_rect)(avi_copy_surface, &rect, NULL, D3DLOCK_DISCARD); |
| 294 | if (result != D3D_OK) |
| 295 | { |
| 296 | return; |
| 297 | } |
| 298 | |
| 299 | // loop over Y |
| 300 | for (int srcy = 0; srcy < (int)snap_height; srcy++) |
| 301 | { |
| 302 | DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch); |
| 303 | UINT32 *dst = &avi_snap.pix32(srcy); |
| 304 | |
| 305 | for(int x = 0; x < snap_width; x++) |
| 306 | *dst++ = *src++; |
| 307 | } |
| 308 | |
| 309 | // unlock |
| 310 | result = (*d3dintf->surface.unlock_rect)(avi_copy_surface); |
| 311 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 312 | } |
| 313 | |
| 314 | |
| 315 | |
| 316 | //============================================================ |
| 317 | // hlsl_render_snapshot |
| 318 | //============================================================ |
| 319 | |
| 320 | void shaders::render_snapshot(surface *surface) |
| 321 | { |
| 322 | if (!master_enable || !d3dintf->post_fx_available) |
| 323 | return; |
| 324 | |
| 325 | D3DLOCKED_RECT rect; |
| 326 | |
| 327 | render_snap = false; |
| 328 | |
| 329 | // if we don't have a bitmap, or if it's not the right size, allocate a new one |
| 330 | if (!avi_snap.valid() || snap_width != (avi_snap.width() / 2) || snap_height != (avi_snap.height() / 2)) |
| 331 | { |
| 332 | avi_snap.allocate(snap_width / 2, snap_height / 2); |
| 333 | } |
| 334 | |
| 335 | // copy the texture |
| 336 | HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, snap_copy_target); |
| 337 | if (result != D3D_OK) |
| 338 | { |
| 339 | return; |
| 340 | } |
| 341 | |
| 342 | // lock the texture |
| 343 | result = (*d3dintf->surface.lock_rect)(snap_copy_target, &rect, NULL, D3DLOCK_DISCARD); |
| 344 | if (result != D3D_OK) |
| 345 | { |
| 346 | return; |
| 347 | } |
| 348 | |
| 349 | for(int cy = 0; cy < 2; cy++) |
| 350 | { |
| 351 | for(int cx = 0; cx < 2; cx++) |
| 352 | { |
| 353 | // loop over Y |
| 354 | for (int srcy = 0; srcy < snap_height / 2; srcy++) |
| 355 | { |
| 356 | int toty = (srcy + cy * (snap_height / 2)); |
| 357 | int totx = cx * (snap_width / 2); |
| 358 | DWORD *src = (DWORD *)((BYTE *)rect.pBits + toty * rect.Pitch + totx * 4); |
| 359 | UINT32 *dst = &avi_snap.pix32(srcy); |
| 360 | |
| 361 | for(int x = 0; x < snap_width / 2; x++) |
| 362 | *dst++ = *src++; |
| 363 | } |
| 364 | |
| 365 | int idx = cy * 2 + cx; |
| 366 | |
| 367 | emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); |
| 368 | file_error filerr = open_next(d3d, file, NULL, "png", idx); |
| 369 | if (filerr != FILERR_NONE) |
| 370 | return; |
| 371 | |
| 372 | // add two text entries describing the image |
| 373 | astring text1(emulator_info::get_appname(), " ", build_version); |
| 374 | astring text2(machine->system().manufacturer, " ", machine->system().description); |
| 375 | png_info pnginfo = { 0 }; |
| 376 | png_add_text(&pnginfo, "Software", text1); |
| 377 | png_add_text(&pnginfo, "System", text2); |
| 378 | |
| 379 | // now do the actual work |
| 380 | png_error error = png_write_bitmap(file, &pnginfo, avi_snap, 1 << 24, NULL); |
| 381 | if (error != PNGERR_NONE) |
| 382 | osd_printf_error("Error generating PNG for HLSL snapshot: png_error = %d\n", error); |
| 383 | |
| 384 | // free any data allocated |
| 385 | png_free(&pnginfo); |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | // unlock |
| 390 | result = (*d3dintf->surface.unlock_rect)(snap_copy_target); |
| 391 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 392 | |
| 393 | if(snap_texture != NULL) |
| 394 | { |
| 395 | (*d3dintf->texture.release)(snap_texture); |
| 396 | snap_texture = NULL; |
| 397 | } |
| 398 | |
| 399 | if(snap_target != NULL) |
| 400 | { |
| 401 | (*d3dintf->surface.release)(snap_target); |
| 402 | snap_target = NULL; |
| 403 | } |
| 404 | |
| 405 | if(snap_copy_texture != NULL) |
| 406 | { |
| 407 | (*d3dintf->texture.release)(snap_copy_texture); |
| 408 | snap_copy_texture = NULL; |
| 409 | } |
| 410 | |
| 411 | if(snap_copy_target != NULL) |
| 412 | { |
| 413 | (*d3dintf->surface.release)(snap_copy_target); |
| 414 | snap_copy_target = NULL; |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | |
| 419 | //============================================================ |
| 420 | // shaders::record_texture |
| 421 | //============================================================ |
| 422 | |
| 423 | void shaders::record_texture() |
| 424 | { |
| 425 | if (!master_enable || !d3dintf->post_fx_available) |
| 426 | return; |
| 427 | |
| 428 | surface *surface = avi_final_target; |
| 429 | |
| 430 | // ignore if nothing to do |
| 431 | if (avi_output_file == NULL || surface == NULL) |
| 432 | return; |
| 433 | |
| 434 | // get the current time |
| 435 | attotime curtime = machine->time(); |
| 436 | |
| 437 | avi_update_snap(surface); |
| 438 | |
| 439 | // loop until we hit the right time |
| 440 | while (avi_next_frame_time <= curtime) |
| 441 | { |
| 442 | // handle an AVI recording |
| 443 | // write the next frame |
| 444 | avi_error avierr = avi_append_video_frame(avi_output_file, avi_snap); |
| 445 | if (avierr != AVIERR_NONE) |
| 446 | { |
| 447 | end_avi_recording(); |
| 448 | return; |
| 449 | } |
| 450 | |
| 451 | // advance time |
| 452 | avi_next_frame_time += avi_frame_period; |
| 453 | avi_frame++; |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | |
| 458 | //============================================================ |
| 459 | // shaders::end_hlsl_avi_recording |
| 460 | //============================================================ |
| 461 | |
| 462 | void shaders::end_avi_recording() |
| 463 | { |
| 464 | if (!master_enable || !d3dintf->post_fx_available) |
| 465 | return; |
| 466 | |
| 467 | if (avi_output_file != NULL) |
| 468 | avi_close(avi_output_file); |
| 469 | |
| 470 | avi_output_file = NULL; |
| 471 | avi_frame = 0; |
| 472 | } |
| 473 | |
| 474 | |
| 475 | //============================================================ |
| 476 | // shaders::toggle |
| 477 | //============================================================ |
| 478 | |
| 479 | void shaders::toggle() |
| 480 | { |
| 481 | if (master_enable) |
| 482 | { |
| 483 | if (initialized) |
| 484 | { |
| 485 | delete_resources(false); |
| 486 | } |
| 487 | master_enable = !master_enable; |
| 488 | } |
| 489 | else |
| 490 | { |
| 491 | if (!initialized) |
| 492 | { |
| 493 | master_enable = !master_enable; |
| 494 | bool failed = create_resources(false); |
| 495 | if (failed) |
| 496 | { |
| 497 | master_enable = false; |
| 498 | } |
| 499 | } |
| 500 | else |
| 501 | { |
| 502 | master_enable = !master_enable; |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | //============================================================ |
| 508 | // shaders::begin_avi_recording |
| 509 | //============================================================ |
| 510 | |
| 511 | void shaders::begin_avi_recording(const char *name) |
| 512 | { |
| 513 | if (!master_enable || !d3dintf->post_fx_available) |
| 514 | return; |
| 515 | |
| 516 | // stop any existing recording |
| 517 | end_avi_recording(); |
| 518 | |
| 519 | // reset the state |
| 520 | avi_frame = 0; |
| 521 | avi_next_frame_time = machine->time(); |
| 522 | |
| 523 | // build up information about this new movie |
| 524 | avi_movie_info info; |
| 525 | info.video_format = 0; |
| 526 | info.video_timescale = 1000 * ((machine->first_screen() != NULL) ? ATTOSECONDS_TO_HZ(machine->first_screen()->frame_period().attoseconds) : screen_device::DEFAULT_FRAME_RATE); |
| 527 | info.video_sampletime = 1000; |
| 528 | info.video_numsamples = 0; |
| 529 | info.video_width = snap_width; |
| 530 | info.video_height = snap_height; |
| 531 | info.video_depth = 24; |
| 532 | |
| 533 | info.audio_format = 0; |
| 534 | info.audio_timescale = machine->sample_rate(); |
| 535 | info.audio_sampletime = 1; |
| 536 | info.audio_numsamples = 0; |
| 537 | info.audio_channels = 2; |
| 538 | info.audio_samplebits = 16; |
| 539 | info.audio_samplerate = machine->sample_rate(); |
| 540 | |
| 541 | // create a new temporary movie file |
| 542 | file_error filerr; |
| 543 | astring fullpath; |
| 544 | { |
| 545 | emu_file tempfile(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); |
| 546 | if (name != NULL) |
| 547 | { |
| 548 | filerr = tempfile.open(name); |
| 549 | } |
| 550 | else |
| 551 | { |
| 552 | filerr = open_next(d3d, tempfile, NULL, "avi", 0); |
| 553 | } |
| 554 | |
| 555 | // compute the frame time |
| 556 | { |
| 557 | avi_frame_period = attotime::from_seconds(1000) / info.video_timescale; |
| 558 | } |
| 559 | |
| 560 | // if we succeeded, make a copy of the name and create the real file over top |
| 561 | if (filerr == FILERR_NONE) |
| 562 | { |
| 563 | fullpath = tempfile.fullpath(); |
| 564 | } |
| 565 | } |
| 566 | |
| 567 | if (filerr == FILERR_NONE) |
| 568 | { |
| 569 | // create the file and free the string |
| 570 | avi_error avierr = avi_create(fullpath, &info, &avi_output_file); |
| 571 | if (avierr != AVIERR_NONE) |
| 572 | { |
| 573 | osd_printf_error("Error creating AVI: %s\n", avi_error_string(avierr)); |
| 574 | } |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | |
| 579 | //============================================================ |
| 580 | // remove_cache_target - remove an active cache target when |
| 581 | // refcount hits zero |
| 582 | //============================================================ |
| 583 | |
| 584 | void shaders::remove_cache_target(cache_target *cache) |
| 585 | { |
| 586 | if (cache != NULL) |
| 587 | { |
| 588 | if (cache == cachehead) |
| 589 | { |
| 590 | cachehead = cachehead->next; |
| 591 | } |
| 592 | |
| 593 | if (cache->prev != NULL) |
| 594 | { |
| 595 | cache->prev->next = cache->next; |
| 596 | } |
| 597 | |
| 598 | if (cache->next != NULL) |
| 599 | { |
| 600 | cache->next->prev = cache->prev; |
| 601 | } |
| 602 | |
| 603 | global_free(cache); |
| 604 | } |
| 605 | } |
| 606 | |
| 607 | |
| 608 | //============================================================ |
| 609 | // remove_render_target - remove an active target |
| 610 | //============================================================ |
| 611 | |
| 612 | void shaders::remove_render_target(texture_info *texture) |
| 613 | { |
| 614 | remove_render_target(find_render_target(texture)); |
| 615 | } |
| 616 | |
| 617 | void shaders::remove_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) |
| 618 | { |
| 619 | render_target *target = find_render_target(width, height, screen_index, page_index); |
| 620 | if (target != NULL) |
| 621 | { |
| 622 | remove_render_target(target); |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | void shaders::remove_render_target(render_target *rt) |
| 627 | { |
| 628 | if (rt != NULL) |
| 629 | { |
| 630 | if (rt == targethead) |
| 631 | { |
| 632 | targethead = targethead->next; |
| 633 | } |
| 634 | |
| 635 | if (rt->prev != NULL) |
| 636 | { |
| 637 | rt->prev->next = rt->next; |
| 638 | } |
| 639 | |
| 640 | if (rt->next != NULL) |
| 641 | { |
| 642 | rt->next->prev = rt->prev; |
| 643 | } |
| 644 | |
| 645 | cache_target *cache = find_cache_target(rt->screen_index, rt->width, rt->height); |
| 646 | if (cache != NULL) |
| 647 | { |
| 648 | remove_cache_target(cache); |
| 649 | } |
| 650 | |
| 651 | int screen_index = rt->screen_index; |
| 652 | int other_page = 1 - rt->page_index; |
| 653 | int width = rt->width; |
| 654 | int height = rt->height; |
| 655 | |
| 656 | global_free(rt); |
| 657 | |
| 658 | // Remove other double-buffered page (if it exists) |
| 659 | remove_render_target(width, height, screen_index, other_page); |
| 660 | } |
| 661 | } |
| 662 | |
| 663 | |
| 664 | //============================================================ |
| 665 | // shaders::set_texture |
| 666 | //============================================================ |
| 667 | |
| 668 | void shaders::set_texture(texture_info *texture) |
| 669 | { |
| 670 | if (!master_enable || !d3dintf->post_fx_available) |
| 671 | return; |
| 672 | |
| 673 | if(texture != NULL) |
| 674 | { |
| 675 | paused = texture->paused(); |
| 676 | texture->advance_frame(); |
| 677 | } |
| 678 | |
| 679 | texture_info *default_texture = d3d->get_default_texture(); |
| 680 | default_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 681 | if (options->yiq_enable) |
| 682 | yiq_encode_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 683 | else |
| 684 | color_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 685 | } |
| 686 | |
| 687 | |
| 688 | //============================================================ |
| 689 | // shaders::init |
| 690 | //============================================================ |
| 691 | |
| 692 | void shaders::init(base *d3dintf, running_machine *machine, d3d::renderer *renderer) |
| 693 | { |
| 694 | if (!d3dintf->post_fx_available) |
| 695 | return; |
| 696 | |
| 697 | g_load_effect = (direct3dx9_loadeffect_ptr)GetProcAddress(d3dintf->libhandle, "D3DXCreateEffectFromFileW"); |
| 698 | if (g_load_effect == NULL) |
| 699 | { |
| 700 | printf("Direct3D: Unable to find D3DXCreateEffectFromFileW\n"); |
| 701 | d3dintf->post_fx_available = false; |
| 702 | return; |
| 703 | } |
| 704 | |
| 705 | this->d3dintf = d3dintf; |
| 706 | this->machine = machine; |
| 707 | this->d3d = renderer; |
| 708 | |
| 709 | master_enable = downcast<windows_options &>(machine->options()).d3d_hlsl_enable(); |
| 710 | prescale_size_x = 1; |
| 711 | prescale_size_y = 1; |
| 712 | preset = downcast<windows_options &>(machine->options()).d3d_hlsl_preset(); |
| 713 | if (preset < -1 || preset > 3) |
| 714 | { |
| 715 | preset = -1; |
| 716 | } |
| 717 | |
| 718 | snap_width = downcast<windows_options &>(machine->options()).d3d_snap_width(); |
| 719 | snap_height = downcast<windows_options &>(machine->options()).d3d_snap_height(); |
| 720 | prescale_force_x = 0; |
| 721 | prescale_force_y = 0; |
| 722 | |
| 723 | windows_options &winoptions = downcast<windows_options &>(machine->options()); |
| 724 | |
| 725 | options = (hlsl_options*)global_alloc_clear(hlsl_options); |
| 726 | |
| 727 | options->params_dirty = true; |
| 728 | strcpy(options->shadow_mask_texture, downcast<windows_options &>(machine->options()).screen_shadow_mask_texture()); // unsafe |
| 729 | |
| 730 | prescale_force_x = winoptions.d3d_hlsl_prescale_x(); |
| 731 | prescale_force_y = winoptions.d3d_hlsl_prescale_y(); |
| 732 | if(preset == -1) |
| 733 | { |
| 734 | options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha(); |
| 735 | options->shadow_mask_count_x = winoptions.screen_shadow_mask_count_x(); |
| 736 | options->shadow_mask_count_y = winoptions.screen_shadow_mask_count_y(); |
| 737 | options->shadow_mask_u_size = winoptions.screen_shadow_mask_u_size(); |
| 738 | options->shadow_mask_v_size = winoptions.screen_shadow_mask_v_size(); |
| 739 | options->curvature = winoptions.screen_curvature(); |
| 740 | options->pincushion = winoptions.screen_pincushion(); |
| 741 | options->scanline_alpha = winoptions.screen_scanline_amount(); |
| 742 | options->scanline_scale = winoptions.screen_scanline_scale(); |
| 743 | options->scanline_height = winoptions.screen_scanline_height(); |
| 744 | options->scanline_bright_scale = winoptions.screen_scanline_bright_scale(); |
| 745 | options->scanline_bright_offset = winoptions.screen_scanline_bright_offset(); |
| 746 | options->scanline_offset = winoptions.screen_scanline_offset(); |
| 747 | get_vector(winoptions.screen_defocus(), 2, options->defocus, TRUE); |
| 748 | get_vector(winoptions.screen_converge_x(), 3, options->converge_x, TRUE); |
| 749 | get_vector(winoptions.screen_converge_y(), 3, options->converge_y, TRUE); |
| 750 | get_vector(winoptions.screen_radial_converge_x(), 3, options->radial_converge_x, TRUE); |
| 751 | get_vector(winoptions.screen_radial_converge_y(), 3, options->radial_converge_y, TRUE); |
| 752 | get_vector(winoptions.screen_red_ratio(), 3, options->red_ratio, TRUE); |
| 753 | get_vector(winoptions.screen_grn_ratio(), 3, options->grn_ratio, TRUE); |
| 754 | get_vector(winoptions.screen_blu_ratio(), 3, options->blu_ratio, TRUE); |
| 755 | get_vector(winoptions.screen_offset(), 3, options->offset, TRUE); |
| 756 | get_vector(winoptions.screen_scale(), 3, options->scale, TRUE); |
| 757 | get_vector(winoptions.screen_power(), 3, options->power, TRUE); |
| 758 | get_vector(winoptions.screen_floor(), 3, options->floor, TRUE); |
| 759 | get_vector(winoptions.screen_phosphor(), 3, options->phosphor, TRUE); |
| 760 | options->saturation = winoptions.screen_saturation(); |
| 761 | } |
| 762 | else |
| 763 | { |
| 764 | options = &s_hlsl_presets[preset]; |
| 765 | } |
| 766 | |
| 767 | options->yiq_enable = winoptions.screen_yiq_enable(); |
| 768 | options->yiq_cc = winoptions.screen_yiq_cc(); |
| 769 | options->yiq_a = winoptions.screen_yiq_a(); |
| 770 | options->yiq_b = winoptions.screen_yiq_b(); |
| 771 | options->yiq_o = winoptions.screen_yiq_o(); |
| 772 | options->yiq_p = winoptions.screen_yiq_p(); |
| 773 | options->yiq_n = winoptions.screen_yiq_n(); |
| 774 | options->yiq_y = winoptions.screen_yiq_y(); |
| 775 | options->yiq_i = winoptions.screen_yiq_i(); |
| 776 | options->yiq_q = winoptions.screen_yiq_q(); |
| 777 | options->yiq_scan_time = winoptions.screen_yiq_scan_time(); |
| 778 | options->yiq_phase_count = winoptions.screen_yiq_phase_count(); |
| 779 | options->vector_length_scale = winoptions.screen_vector_length_scale(); |
| 780 | options->vector_length_ratio = winoptions.screen_vector_length_ratio(); |
| 781 | options->vector_bloom_scale = winoptions.screen_vector_bloom_scale(); |
| 782 | options->raster_bloom_scale = winoptions.screen_raster_bloom_scale(); |
| 783 | options->bloom_level0_weight = winoptions.screen_bloom_lvl0_weight(); |
| 784 | options->bloom_level1_weight = winoptions.screen_bloom_lvl1_weight(); |
| 785 | options->bloom_level2_weight = winoptions.screen_bloom_lvl2_weight(); |
| 786 | options->bloom_level3_weight = winoptions.screen_bloom_lvl3_weight(); |
| 787 | options->bloom_level4_weight = winoptions.screen_bloom_lvl4_weight(); |
| 788 | options->bloom_level5_weight = winoptions.screen_bloom_lvl5_weight(); |
| 789 | options->bloom_level6_weight = winoptions.screen_bloom_lvl6_weight(); |
| 790 | options->bloom_level7_weight = winoptions.screen_bloom_lvl7_weight(); |
| 791 | options->bloom_level8_weight = winoptions.screen_bloom_lvl8_weight(); |
| 792 | options->bloom_level9_weight = winoptions.screen_bloom_lvl9_weight(); |
| 793 | options->bloom_level10_weight = winoptions.screen_bloom_lvl10_weight(); |
| 794 | |
| 795 | options->params_dirty = true; |
| 796 | |
| 797 | g_slider_list = init_slider_list(); |
| 798 | } |
| 799 | |
| 800 | |
| 801 | |
| 802 | //============================================================ |
| 803 | // shaders::init_fsfx_quad |
| 804 | //============================================================ |
| 805 | |
| 806 | void shaders::init_fsfx_quad(void *vertbuf) |
| 807 | { |
| 808 | // Called at the start of each frame by the D3D code in order to reserve two triangles |
| 809 | // that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2 |
| 810 | // instead of having to do bookkeeping about a specific screen quad |
| 811 | if (!master_enable || !d3dintf->post_fx_available) |
| 812 | return; |
| 813 | |
| 814 | // get a pointer to the vertex buffer |
| 815 | fsfx_vertices = (vertex *)vertbuf; |
| 816 | if (fsfx_vertices == NULL) |
| 817 | return; |
| 818 | |
| 819 | // fill in the vertexes clockwise |
| 820 | fsfx_vertices[0].x = 0.0f; |
| 821 | fsfx_vertices[0].y = 0.0f; |
| 822 | fsfx_vertices[1].x = d3d->get_width(); |
| 823 | fsfx_vertices[1].y = 0.0f; |
| 824 | fsfx_vertices[2].x = 0.0f; |
| 825 | fsfx_vertices[2].y = d3d->get_height(); |
| 826 | fsfx_vertices[3].x = d3d->get_width(); |
| 827 | fsfx_vertices[3].y = 0.0f; |
| 828 | fsfx_vertices[4].x = 0.0f; |
| 829 | fsfx_vertices[4].y = d3d->get_height(); |
| 830 | fsfx_vertices[5].x = d3d->get_width(); |
| 831 | fsfx_vertices[5].y = d3d->get_height(); |
| 832 | |
| 833 | fsfx_vertices[0].u0 = 0.0f; |
| 834 | fsfx_vertices[0].v0 = 0.0f; |
| 835 | |
| 836 | fsfx_vertices[1].u0 = 1.0f; |
| 837 | fsfx_vertices[1].v0 = 0.0f; |
| 838 | |
| 839 | fsfx_vertices[2].u0 = 0.0f; |
| 840 | fsfx_vertices[2].v0 = 1.0f; |
| 841 | |
| 842 | fsfx_vertices[3].u0 = 1.0f; |
| 843 | fsfx_vertices[3].v0 = 0.0f; |
| 844 | |
| 845 | fsfx_vertices[4].u0 = 0.0f; |
| 846 | fsfx_vertices[4].v0 = 1.0f; |
| 847 | |
| 848 | fsfx_vertices[5].u0 = 1.0f; |
| 849 | fsfx_vertices[5].v0 = 1.0f; |
| 850 | |
| 851 | fsfx_vertices[0].u1 = 0.0f; |
| 852 | fsfx_vertices[0].v1 = 0.0f; |
| 853 | fsfx_vertices[1].u1 = 0.0f; |
| 854 | fsfx_vertices[1].v1 = 0.0f; |
| 855 | fsfx_vertices[2].u1 = 0.0f; |
| 856 | fsfx_vertices[2].v1 = 0.0f; |
| 857 | fsfx_vertices[3].u1 = 0.0f; |
| 858 | fsfx_vertices[3].v1 = 0.0f; |
| 859 | fsfx_vertices[4].u1 = 0.0f; |
| 860 | fsfx_vertices[4].v1 = 0.0f; |
| 861 | fsfx_vertices[5].u1 = 0.0f; |
| 862 | fsfx_vertices[5].v1 = 0.0f; |
| 863 | |
| 864 | // set the color, Z parameters to standard values |
| 865 | for (int i = 0; i < 6; i++) |
| 866 | { |
| 867 | fsfx_vertices[i].z = 0.0f; |
| 868 | fsfx_vertices[i].rhw = 1.0f; |
| 869 | fsfx_vertices[i].color = D3DCOLOR_ARGB(255, 255, 255, 255); |
| 870 | } |
| 871 | } |
| 872 | |
| 873 | |
| 874 | |
| 875 | //============================================================ |
| 876 | // shaders::create_resources |
| 877 | //============================================================ |
| 878 | |
| 879 | int shaders::create_resources(bool reset) |
| 880 | { |
| 881 | if (!master_enable || !d3dintf->post_fx_available) |
| 882 | return 0; |
| 883 | |
| 884 | HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); |
| 885 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 886 | |
| 887 | result = (*d3dintf->device.create_texture)(d3d->get_device(), 4, 4, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &black_texture); |
| 888 | if (result != D3D_OK) |
| 889 | { |
| 890 | osd_printf_verbose("Direct3D: Unable to init video-memory target for black texture (%08x)\n", (UINT32)result); |
| 891 | return 1; |
| 892 | } |
| 893 | (*d3dintf->texture.get_surface_level)(black_texture, 0, &black_surface); |
| 894 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, black_surface); |
| 895 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 896 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 897 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 898 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 899 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 900 | |
| 901 | result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &avi_copy_texture); |
| 902 | if (result != D3D_OK) |
| 903 | { |
| 904 | osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); |
| 905 | return 1; |
| 906 | } |
| 907 | (*d3dintf->texture.get_surface_level)(avi_copy_texture, 0, &avi_copy_surface); |
| 908 | |
| 909 | result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &avi_final_texture); |
| 910 | if (result != D3D_OK) |
| 911 | { |
| 912 | osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); |
| 913 | return 1; |
| 914 | } |
| 915 | (*d3dintf->texture.get_surface_level)(avi_final_texture, 0, &avi_final_target); |
| 916 | |
| 917 | emu_file file(machine->options().art_path(), OPEN_FLAG_READ); |
| 918 | render_load_png(shadow_bitmap, file, NULL, options->shadow_mask_texture); |
| 919 | |
| 920 | // experimental: if we have a shadow bitmap, create a texture for it |
| 921 | if (shadow_bitmap.valid()) |
| 922 | { |
| 923 | render_texinfo texture; |
| 924 | |
| 925 | // fake in the basic data so it looks like it came from render.c |
| 926 | texture.base = shadow_bitmap.raw_pixptr(0); |
| 927 | texture.rowpixels = shadow_bitmap.rowpixels(); |
| 928 | texture.width = shadow_bitmap.width(); |
| 929 | texture.height = shadow_bitmap.height(); |
| 930 | texture.palette = NULL; |
| 931 | texture.seqid = 0; |
| 932 | |
| 933 | // FIXME: should shadow bitmap really use prescale? |
| 934 | // now create it |
| 935 | shadow_texture = new texture_info(d3d->get_texture_manager(), &texture, video_config.prescale, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); |
| 936 | } |
| 937 | |
| 938 | const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir(); |
| 939 | |
| 940 | default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); |
| 941 | post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir); |
| 942 | prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); |
| 943 | phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir); |
| 944 | focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir); |
| 945 | deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir); |
| 946 | color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir); |
| 947 | yiq_encode_effect = new effect(this, d3d->get_device(), "yiq_encode.fx", fx_dir); |
| 948 | yiq_decode_effect = new effect(this, d3d->get_device(), "yiq_decode.fx", fx_dir); |
| 949 | bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir); |
| 950 | downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir); |
| 951 | vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir); |
| 952 | |
| 953 | if (!default_effect->is_valid()) return 1; |
| 954 | if (!post_effect->is_valid()) return 1; |
| 955 | if (!prescale_effect->is_valid()) return 1; |
| 956 | if (!phosphor_effect->is_valid()) return 1; |
| 957 | if (!focus_effect->is_valid()) return 1; |
| 958 | if (!deconverge_effect->is_valid()) return 1; |
| 959 | if (!color_effect->is_valid()) return 1; |
| 960 | if (!yiq_encode_effect->is_valid()) return 1; |
| 961 | if (!yiq_decode_effect->is_valid()) return 1; |
| 962 | if (!bloom_effect->is_valid()) return 1; |
| 963 | if (!downsample_effect->is_valid()) return 1; |
| 964 | if (!vector_effect->is_valid()) return 1; |
| 965 | |
| 966 | yiq_encode_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 967 | yiq_encode_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 968 | yiq_encode_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 969 | yiq_encode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); |
| 970 | yiq_encode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); |
| 971 | yiq_encode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); |
| 972 | yiq_encode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); |
| 973 | yiq_encode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); |
| 974 | yiq_encode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); |
| 975 | yiq_encode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); |
| 976 | yiq_encode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); |
| 977 | yiq_encode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); |
| 978 | |
| 979 | yiq_decode_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 980 | yiq_decode_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 981 | yiq_decode_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 982 | yiq_decode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); |
| 983 | yiq_decode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); |
| 984 | yiq_decode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); |
| 985 | yiq_decode_effect->add_uniform("OValue", uniform::UT_FLOAT, uniform::CU_NTSC_O); |
| 986 | yiq_decode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); |
| 987 | yiq_decode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); |
| 988 | yiq_decode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); |
| 989 | yiq_decode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); |
| 990 | yiq_decode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); |
| 991 | yiq_decode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); |
| 992 | |
| 993 | color_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 994 | color_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 995 | |
| 996 | color_effect->add_uniform("YIQEnable", uniform::UT_FLOAT, uniform::CU_NTSC_ENABLE); |
| 997 | color_effect->add_uniform("RedRatios", uniform::UT_VEC3, uniform::CU_COLOR_RED_RATIOS); |
| 998 | color_effect->add_uniform("GrnRatios", uniform::UT_VEC3, uniform::CU_COLOR_GRN_RATIOS); |
| 999 | color_effect->add_uniform("BluRatios", uniform::UT_VEC3, uniform::CU_COLOR_BLU_RATIOS); |
| 1000 | color_effect->add_uniform("Offset", uniform::UT_VEC3, uniform::CU_COLOR_OFFSET); |
| 1001 | color_effect->add_uniform("Scale", uniform::UT_VEC3, uniform::CU_COLOR_SCALE); |
| 1002 | color_effect->add_uniform("Saturation", uniform::UT_FLOAT, uniform::CU_COLOR_SATURATION); |
| 1003 | |
| 1004 | prescale_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1005 | prescale_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1006 | |
| 1007 | deconverge_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1008 | deconverge_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1009 | deconverge_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 1010 | deconverge_effect->add_uniform("ConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_X); |
| 1011 | deconverge_effect->add_uniform("ConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_Y); |
| 1012 | deconverge_effect->add_uniform("RadialConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_RADIAL_X); |
| 1013 | deconverge_effect->add_uniform("RadialConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_RADIAL_Y); |
| 1014 | |
| 1015 | focus_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1016 | focus_effect->add_uniform("Defocus", uniform::UT_VEC2, uniform::CU_FOCUS_SIZE); |
| 1017 | |
| 1018 | phosphor_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1019 | phosphor_effect->add_uniform("Phosphor", uniform::UT_VEC3, uniform::CU_PHOSPHOR_LIFE); |
| 1020 | phosphor_effect->add_uniform("Passthrough", uniform::UT_FLOAT, uniform::CU_PHOSPHOR_IGNORE); |
| 1021 | |
| 1022 | post_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1023 | post_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 1024 | post_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1025 | |
| 1026 | post_effect->add_uniform("PincushionAmount", uniform::UT_FLOAT, uniform::CU_POST_PINCUSHION); |
| 1027 | post_effect->add_uniform("CurvatureAmount", uniform::UT_FLOAT, uniform::CU_POST_CURVATURE); |
| 1028 | |
| 1029 | post_effect->add_uniform("ShadowAlpha", uniform::UT_FLOAT, uniform::CU_POST_SHADOW_ALPHA); |
| 1030 | post_effect->add_uniform("ShadowCount", uniform::UT_VEC2, uniform::CU_POST_SHADOW_COUNT); |
| 1031 | post_effect->add_uniform("ShadowUV", uniform::UT_VEC2, uniform::CU_POST_SHADOW_UV); |
| 1032 | post_effect->add_uniform("ShadowDims", uniform::UT_VEC2, uniform::CU_POST_SHADOW_DIMS); |
| 1033 | |
| 1034 | post_effect->add_uniform("ScanlineAlpha", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_ALPHA); |
| 1035 | post_effect->add_uniform("ScanlineScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_SCALE); |
| 1036 | post_effect->add_uniform("ScanlineHeight", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_HEIGHT); |
| 1037 | post_effect->add_uniform("ScanlineBrightScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_SCALE); |
| 1038 | post_effect->add_uniform("ScanlineBrightOffset", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_OFFSET); |
| 1039 | post_effect->add_uniform("Power", uniform::UT_VEC3, uniform::CU_POST_POWER); |
| 1040 | post_effect->add_uniform("Floor", uniform::UT_VEC3, uniform::CU_POST_FLOOR); |
| 1041 | |
| 1042 | initialized = true; |
| 1043 | |
| 1044 | return 0; |
| 1045 | } |
| 1046 | |
| 1047 | |
| 1048 | //============================================================ |
| 1049 | // shaders::begin_draw |
| 1050 | //============================================================ |
| 1051 | |
| 1052 | void shaders::begin_draw() |
| 1053 | { |
| 1054 | if (!master_enable || !d3dintf->post_fx_available) |
| 1055 | return; |
| 1056 | |
| 1057 | curr_effect = default_effect; |
| 1058 | |
| 1059 | default_effect->set_technique("TestTechnique"); |
| 1060 | post_effect->set_technique("ScanMaskTechnique"); |
| 1061 | phosphor_effect->set_technique("TestTechnique"); |
| 1062 | focus_effect->set_technique("TestTechnique"); |
| 1063 | deconverge_effect->set_technique("DeconvergeTechnique"); |
| 1064 | color_effect->set_technique("ColorTechnique"); |
| 1065 | yiq_encode_effect->set_technique("EncodeTechnique"); |
| 1066 | yiq_decode_effect->set_technique("DecodeTechnique"); |
| 1067 | |
| 1068 | HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); |
| 1069 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 1070 | } |
| 1071 | |
| 1072 | |
| 1073 | //============================================================ |
| 1074 | // shaders::begin_frame |
| 1075 | //============================================================ |
| 1076 | |
| 1077 | void shaders::begin_frame() |
| 1078 | { |
| 1079 | record_texture(); |
| 1080 | } |
| 1081 | |
| 1082 | |
| 1083 | //============================================================ |
| 1084 | // shaders::blit |
| 1085 | //============================================================ |
| 1086 | |
| 1087 | void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, |
| 1088 | UINT32 prim_index, UINT32 prim_count, int dstw, int dsth) |
| 1089 | { |
| 1090 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); |
| 1091 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1092 | |
| 1093 | curr_effect = default_effect; |
| 1094 | |
| 1095 | curr_effect->set_texture("Diffuse", src); |
| 1096 | |
| 1097 | float dst_dims[2] = { (float)dstw, (float)dsth }; |
| 1098 | curr_effect->set_vector("ScreenDims", 2, dst_dims); |
| 1099 | curr_effect->set_float("PostPass", 1.0f); |
| 1100 | curr_effect->set_float("PincushionAmount", options->pincushion); |
| 1101 | curr_effect->set_float("Brighten", 0.0f); |
| 1102 | |
| 1103 | unsigned int num_passes = 0; |
| 1104 | curr_effect->begin(&num_passes, 0); |
| 1105 | |
| 1106 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1107 | { |
| 1108 | curr_effect->begin_pass(pass); |
| 1109 | // add the primitives |
| 1110 | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); |
| 1111 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1112 | curr_effect->end_pass(); |
| 1113 | } |
| 1114 | |
| 1115 | curr_effect->end(); |
| 1116 | |
| 1117 | if (new_dst) |
| 1118 | { |
| 1119 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); |
| 1120 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1121 | } |
| 1122 | } |
| 1123 | |
| 1124 | |
| 1125 | |
| 1126 | //============================================================ |
| 1127 | // shaders::blit |
| 1128 | //============================================================ |
| 1129 | |
| 1130 | void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, |
| 1131 | UINT32 prim_index, UINT32 prim_count) |
| 1132 | { |
| 1133 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); |
| 1134 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1135 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); |
| 1136 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1137 | |
| 1138 | curr_effect = default_effect; |
| 1139 | |
| 1140 | curr_effect->set_texture("Diffuse", src); |
| 1141 | |
| 1142 | vec2f screendims = d3d->get_dims(); |
| 1143 | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1144 | curr_effect->set_float("PostPass", 1.0f); |
| 1145 | curr_effect->set_float("PincushionAmount", options->pincushion); |
| 1146 | curr_effect->set_float("Brighten", 1.0f); |
| 1147 | |
| 1148 | unsigned int num_passes = 0; |
| 1149 | curr_effect->begin(&num_passes, 0); |
| 1150 | |
| 1151 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1152 | { |
| 1153 | curr_effect->begin_pass(pass); |
| 1154 | // add the primitives |
| 1155 | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); |
| 1156 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1157 | curr_effect->end_pass(); |
| 1158 | } |
| 1159 | |
| 1160 | curr_effect->end(); |
| 1161 | |
| 1162 | curr_effect->set_float("Brighten", 0.0f); |
| 1163 | |
| 1164 | if (new_dst) |
| 1165 | { |
| 1166 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); |
| 1167 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1168 | } |
| 1169 | } |
| 1170 | |
| 1171 | //============================================================ |
| 1172 | // shaders::end_frame |
| 1173 | //============================================================ |
| 1174 | |
| 1175 | void shaders::end_frame() |
| 1176 | { |
| 1177 | if (!master_enable || !d3dintf->post_fx_available) |
| 1178 | return; |
| 1179 | |
| 1180 | if(render_snap && snap_rendered) |
| 1181 | { |
| 1182 | render_snapshot(snap_target); |
| 1183 | } |
| 1184 | |
| 1185 | if (!lines_pending) |
| 1186 | return; |
| 1187 | |
| 1188 | lines_pending = false; |
| 1189 | |
| 1190 | /*render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1191 | if (rt == NULL) |
| 1192 | { |
| 1193 | return; |
| 1194 | } |
| 1195 | |
| 1196 | blit(backbuffer, rt->render_texture[1], NULL, vecbuf_type, vecbuf_index, vecbuf_count); |
| 1197 | |
| 1198 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1199 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1200 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1201 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1202 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1203 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);*/ |
| 1204 | } |
| 1205 | |
| 1206 | |
| 1207 | //============================================================ |
| 1208 | // shaders::init_effect_info |
| 1209 | //============================================================ |
| 1210 | |
| 1211 | void shaders::init_effect_info(poly_info *poly) |
| 1212 | { |
| 1213 | if (!master_enable || !d3dintf->post_fx_available) |
| 1214 | return; |
| 1215 | |
| 1216 | texture_info *texture = poly->get_texture(); |
| 1217 | |
| 1218 | if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && texture != NULL) |
| 1219 | { |
| 1220 | // Plug in all of the shader settings we're going to need |
| 1221 | // This is extremely slow, but we're not rendering models here, |
| 1222 | // just post-processing. |
| 1223 | curr_effect = post_effect; |
| 1224 | |
| 1225 | curr_effect->set_float("ScanlineOffset", (texture->get_cur_frame() == 0) ? 0.0f : options->scanline_offset); |
| 1226 | } |
| 1227 | else |
| 1228 | { |
| 1229 | curr_effect = default_effect; |
| 1230 | |
| 1231 | curr_effect->set_float("FixedAlpha", 1.0f); |
| 1232 | } |
| 1233 | } |
| 1234 | |
| 1235 | |
| 1236 | //============================================================ |
| 1237 | // shaders::find_render_target |
| 1238 | //============================================================ |
| 1239 | |
| 1240 | render_target* shaders::find_render_target(texture_info *info) |
| 1241 | { |
| 1242 | render_target *curr = targethead; |
| 1243 | UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; |
| 1244 | UINT32 screen_index = screen_index_data >> 1; |
| 1245 | UINT32 page_index = screen_index_data & 1; |
| 1246 | |
| 1247 | while (curr != NULL && (curr->screen_index != screen_index || curr->page_index != page_index || |
| 1248 | curr->width != info->get_texinfo().width || curr->height != info->get_texinfo().height)) |
| 1249 | { |
| 1250 | curr = curr->next; |
| 1251 | } |
| 1252 | |
| 1253 | return curr; |
| 1254 | } |
| 1255 | |
| 1256 | |
| 1257 | //============================================================ |
| 1258 | // shaders::find_render_target |
| 1259 | //============================================================ |
| 1260 | |
| 1261 | render_target* shaders::find_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) |
| 1262 | { |
| 1263 | render_target *curr = targethead; |
| 1264 | |
| 1265 | while (curr != NULL && (curr->width != width || curr->height != height || curr->screen_index != screen_index || curr->page_index != page_index)) |
| 1266 | { |
| 1267 | curr = curr->next; |
| 1268 | } |
| 1269 | |
| 1270 | return curr; |
| 1271 | } |
| 1272 | |
| 1273 | |
| 1274 | //============================================================ |
| 1275 | // shaders::find_cache_target |
| 1276 | //============================================================ |
| 1277 | |
| 1278 | cache_target* shaders::find_cache_target(UINT32 screen_index, int width, int height) |
| 1279 | { |
| 1280 | cache_target *curr = cachehead; |
| 1281 | |
| 1282 | while (curr != NULL && (curr->screen_index != screen_index || curr->width != width || curr->height != height)) |
| 1283 | { |
| 1284 | curr = curr->next; |
| 1285 | } |
| 1286 | |
| 1287 | return curr; |
| 1288 | } |
| 1289 | |
| 1290 | void shaders::ntsc_pass(render_target *rt, vec2f &sourcedims, vec2f &delta) |
| 1291 | { |
| 1292 | UINT num_passes = 0; |
| 1293 | |
| 1294 | if(options->yiq_enable) |
| 1295 | { |
| 1296 | // Convert our signal into YIQ |
| 1297 | curr_effect = yiq_encode_effect; |
| 1298 | curr_effect->update_uniforms(); |
| 1299 | |
| 1300 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[4]); |
| 1301 | |
| 1302 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1303 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1304 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1305 | |
| 1306 | curr_effect->begin(&num_passes, 0); |
| 1307 | |
| 1308 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1309 | { |
| 1310 | curr_effect->begin_pass(pass); |
| 1311 | // add the primitives |
| 1312 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1313 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1314 | curr_effect->end_pass(); |
| 1315 | } |
| 1316 | |
| 1317 | curr_effect->end(); |
| 1318 | |
| 1319 | // Convert our signal from YIQ |
| 1320 | curr_effect = yiq_decode_effect; |
| 1321 | |
| 1322 | curr_effect->set_texture("Composite", rt->render_texture[4]); |
| 1323 | curr_effect->set_texture("Diffuse", curr_texture->get_finaltex()); |
| 1324 | curr_effect->update_uniforms(); |
| 1325 | |
| 1326 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); |
| 1327 | |
| 1328 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1329 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1330 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1331 | |
| 1332 | curr_effect->begin(&num_passes, 0); |
| 1333 | |
| 1334 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1335 | { |
| 1336 | curr_effect->begin_pass(pass); |
| 1337 | // add the primitives |
| 1338 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1339 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1340 | curr_effect->end_pass(); |
| 1341 | } |
| 1342 | |
| 1343 | curr_effect->end(); |
| 1344 | |
| 1345 | curr_effect = color_effect; |
| 1346 | |
| 1347 | curr_effect->set_texture("Diffuse", rt->render_texture[3]); |
| 1348 | } |
| 1349 | } |
| 1350 | |
| 1351 | void shaders::color_convolution_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims) |
| 1352 | { |
| 1353 | UINT num_passes = 0; |
| 1354 | |
| 1355 | curr_effect = color_effect; |
| 1356 | curr_effect->update_uniforms(); |
| 1357 | |
| 1358 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->smalltarget); |
| 1359 | |
| 1360 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1361 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1362 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1363 | |
| 1364 | curr_effect->begin(&num_passes, 0); |
| 1365 | |
| 1366 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1367 | { |
| 1368 | curr_effect->begin_pass(pass); |
| 1369 | // add the primitives |
| 1370 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1371 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1372 | curr_effect->end_pass(); |
| 1373 | } |
| 1374 | |
| 1375 | curr_effect->end(); |
| 1376 | } |
| 1377 | |
| 1378 | void shaders::prescale_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims) |
| 1379 | { |
| 1380 | UINT num_passes = 0; |
| 1381 | |
| 1382 | curr_effect = prescale_effect; |
| 1383 | curr_effect->update_uniforms(); |
| 1384 | curr_effect->set_texture("Diffuse", rt->smalltexture); |
| 1385 | |
| 1386 | curr_effect->begin(&num_passes, 0); |
| 1387 | |
| 1388 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->prescaletarget); |
| 1389 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1390 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1391 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1392 | |
| 1393 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1394 | { |
| 1395 | curr_effect->begin_pass(pass); |
| 1396 | // add the primitives |
| 1397 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1398 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1399 | curr_effect->end_pass(); |
| 1400 | } |
| 1401 | |
| 1402 | curr_effect->end(); |
| 1403 | } |
| 1404 | |
| 1405 | void shaders::deconverge_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims) |
| 1406 | { |
| 1407 | UINT num_passes = 0; |
| 1408 | |
| 1409 | curr_effect = deconverge_effect; |
| 1410 | curr_effect->update_uniforms(); |
| 1411 | curr_effect->set_texture("Diffuse", rt->prescaletexture); |
| 1412 | |
| 1413 | curr_effect->begin(&num_passes, 0); |
| 1414 | |
| 1415 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); |
| 1416 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1417 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1418 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1419 | |
| 1420 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1421 | { |
| 1422 | curr_effect->begin_pass(pass); |
| 1423 | // add the primitives |
| 1424 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1425 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1426 | curr_effect->end_pass(); |
| 1427 | } |
| 1428 | |
| 1429 | curr_effect->end(); |
| 1430 | } |
| 1431 | |
| 1432 | void shaders::defocus_pass(render_target *rt, vec2f &texsize) |
| 1433 | { |
| 1434 | UINT num_passes = 0; |
| 1435 | |
| 1436 | // Defocus pass 1 |
| 1437 | curr_effect = focus_effect; |
| 1438 | curr_effect->update_uniforms(); |
| 1439 | curr_effect->set_texture("Diffuse", rt->render_texture[2]); |
| 1440 | |
| 1441 | curr_effect->begin(&num_passes, 0); |
| 1442 | |
| 1443 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1444 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1445 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1446 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1447 | |
| 1448 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1449 | { |
| 1450 | curr_effect->begin_pass(pass); |
| 1451 | // add the primitives |
| 1452 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1453 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1454 | curr_effect->end_pass(); |
| 1455 | } |
| 1456 | |
| 1457 | curr_effect->end(); |
| 1458 | |
| 1459 | // Defocus pass 2 |
| 1460 | |
| 1461 | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1462 | |
| 1463 | curr_effect->begin(&num_passes, 0); |
| 1464 | |
| 1465 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1466 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 7\n", (int)result); |
| 1467 | |
| 1468 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1469 | { |
| 1470 | curr_effect->begin_pass(pass); |
| 1471 | // add the primitives |
| 1472 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1473 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1474 | curr_effect->end_pass(); |
| 1475 | } |
| 1476 | |
| 1477 | curr_effect->end(); |
| 1478 | } |
| 1479 | |
| 1480 | void shaders::phosphor_pass(render_target *rt, cache_target *ct, vec2f &texsize, bool focus_enable) |
| 1481 | { |
| 1482 | UINT num_passes = 0; |
| 1483 | |
| 1484 | curr_effect = phosphor_effect; |
| 1485 | phosphor_passthrough = false; |
| 1486 | curr_effect->update_uniforms(); |
| 1487 | |
| 1488 | float rtsize[2] = { rt->target_width, rt->target_height }; |
| 1489 | curr_effect->set_vector("TargetDims", 2, rtsize); |
| 1490 | |
| 1491 | curr_effect->set_texture("Diffuse", focus_enable ? rt->render_texture[1] : rt->render_texture[2]); |
| 1492 | curr_effect->set_texture("LastPass", ct->last_texture); |
| 1493 | |
| 1494 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1495 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); |
| 1496 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1497 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1498 | |
| 1499 | curr_effect->begin(&num_passes, 0); |
| 1500 | |
| 1501 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1502 | { |
| 1503 | curr_effect->begin_pass(pass); |
| 1504 | // add the primitives |
| 1505 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1506 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1507 | curr_effect->end_pass(); |
| 1508 | } |
| 1509 | |
| 1510 | curr_effect->end(); |
| 1511 | |
| 1512 | // Pass along our phosphor'd screen |
| 1513 | phosphor_passthrough = true; |
| 1514 | curr_effect->update_uniforms(); |
| 1515 | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1516 | curr_effect->set_texture("LastPass", rt->render_texture[0]); |
| 1517 | |
| 1518 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, ct->last_target); // Avoid changing targets due to page flipping |
| 1519 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 5\n", (int)result); |
| 1520 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1521 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1522 | |
| 1523 | curr_effect->begin(&num_passes, 0); |
| 1524 | |
| 1525 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1526 | { |
| 1527 | curr_effect->begin_pass(pass); |
| 1528 | // add the primitives |
| 1529 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1530 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1531 | curr_effect->end_pass(); |
| 1532 | } |
| 1533 | |
| 1534 | curr_effect->end(); |
| 1535 | } |
| 1536 | |
| 1537 | void shaders::avi_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum) |
| 1538 | { |
| 1539 | UINT num_passes = 0; |
| 1540 | |
| 1541 | curr_effect = post_effect; |
| 1542 | curr_effect->update_uniforms(); |
| 1543 | curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); |
| 1544 | |
| 1545 | // Scanlines and shadow mask, at high res for AVI logging |
| 1546 | if(avi_output_file != NULL) |
| 1547 | { |
| 1548 | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1549 | |
| 1550 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, avi_final_target); |
| 1551 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1552 | |
| 1553 | curr_effect->begin(&num_passes, 0); |
| 1554 | |
| 1555 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1556 | { |
| 1557 | curr_effect->begin_pass(pass); |
| 1558 | // add the primitives |
| 1559 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1560 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1561 | curr_effect->end_pass(); |
| 1562 | } |
| 1563 | |
| 1564 | curr_effect->end(); |
| 1565 | } |
| 1566 | |
| 1567 | if(render_snap) |
| 1568 | { |
| 1569 | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1570 | |
| 1571 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, snap_target); |
| 1572 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1573 | |
| 1574 | curr_effect->begin(&num_passes, 0); |
| 1575 | |
| 1576 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1577 | { |
| 1578 | curr_effect->begin_pass(pass); |
| 1579 | // add the primitives |
| 1580 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1581 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1582 | curr_effect->end_pass(); |
| 1583 | } |
| 1584 | |
| 1585 | curr_effect->end(); |
| 1586 | |
| 1587 | snap_rendered = true; |
| 1588 | } |
| 1589 | } |
| 1590 | |
| 1591 | void shaders::screen_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum) |
| 1592 | { |
| 1593 | UINT num_passes = 0; |
| 1594 | |
| 1595 | curr_effect = post_effect; |
| 1596 | curr_effect->update_uniforms(); |
| 1597 | curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); |
| 1598 | |
| 1599 | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1600 | |
| 1601 | d3d->set_wrap(D3DTADDRESS_MIRROR); |
| 1602 | |
| 1603 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); |
| 1604 | |
| 1605 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); |
| 1606 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1607 | |
| 1608 | curr_effect->begin(&num_passes, 0); |
| 1609 | |
| 1610 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1611 | { |
| 1612 | curr_effect->begin_pass(pass); |
| 1613 | // add the primitives |
| 1614 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1615 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1616 | curr_effect->end_pass(); |
| 1617 | } |
| 1618 | |
| 1619 | curr_effect->end(); |
| 1620 | |
| 1621 | d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(poly->get_texture()->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); |
| 1622 | } |
| 1623 | |
| 1624 | void shaders::raster_bloom_pass(render_target *rt, vec2f &texsize, vec2f &delta, poly_info *poly, int vertnum) |
| 1625 | { |
| 1626 | UINT num_passes = 0; |
| 1627 | |
| 1628 | curr_effect = downsample_effect; |
| 1629 | |
| 1630 | curr_effect->set_texture("Diffuse", rt->render_texture[2]); |
| 1631 | curr_effect->set_float("BloomRescale", options->raster_bloom_scale); |
| 1632 | |
| 1633 | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 1634 | int bloom_index = 0; |
| 1635 | float bloom_width = rt->target_width; |
| 1636 | float bloom_height = rt->target_height; |
| 1637 | vec2f screendims = d3d->get_dims(); |
| 1638 | curr_effect->set_vector("ScreenSize", 2, &screendims.c.x); |
| 1639 | float bloom_dims[11][2]; |
| 1640 | for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 1641 | { |
| 1642 | bloom_dims[bloom_index][0] = bloom_width; |
| 1643 | bloom_dims[bloom_index][1] = bloom_height; |
| 1644 | curr_effect->set_vector("TargetSize", 2, bloom_dims[bloom_index]); |
| 1645 | |
| 1646 | curr_effect->begin(&num_passes, 0); |
| 1647 | |
| 1648 | curr_effect->set_texture("DiffuseTexture", (bloom_index == 0) ? rt->render_texture[2] : rt->bloom_texture[bloom_index - 1]); |
| 1649 | |
| 1650 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); |
| 1651 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1652 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1653 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1654 | |
| 1655 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1656 | { |
| 1657 | curr_effect->begin_pass(pass); |
| 1658 | // add the primitives |
| 1659 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1660 | //result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1661 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1662 | curr_effect->end_pass(); |
| 1663 | } |
| 1664 | |
| 1665 | curr_effect->end(); |
| 1666 | |
| 1667 | bloom_index++; |
| 1668 | bloom_width *= 0.5f; |
| 1669 | bloom_height *= 0.5f; |
| 1670 | } |
| 1671 | |
| 1672 | curr_effect = bloom_effect; |
| 1673 | |
| 1674 | float target_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1675 | curr_effect->set_vector("TargetSize", 2, target_size); |
| 1676 | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, options->bloom_level2_weight, options->bloom_level3_weight }; |
| 1677 | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, options->bloom_level6_weight, options->bloom_level7_weight }; |
| 1678 | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, options->bloom_level10_weight }; |
| 1679 | curr_effect->set_vector("Level0123Weight", 4, weight0123); |
| 1680 | curr_effect->set_vector("Level4567Weight", 4, weight4567); |
| 1681 | curr_effect->set_vector("Level89AWeight", 3, weight89A); |
| 1682 | curr_effect->set_vector("Level01Size", 4, bloom_dims[0]); |
| 1683 | curr_effect->set_vector("Level23Size", 4, bloom_dims[2]); |
| 1684 | curr_effect->set_vector("Level45Size", 4, bloom_dims[4]); |
| 1685 | curr_effect->set_vector("Level67Size", 4, bloom_dims[6]); |
| 1686 | curr_effect->set_vector("Level89Size", 4, bloom_dims[8]); |
| 1687 | curr_effect->set_vector("LevelASize", 2, bloom_dims[10]); |
| 1688 | |
| 1689 | curr_effect->set_texture("DiffuseA", rt->render_texture[2]); |
| 1690 | |
| 1691 | char name[9] = "Diffuse*"; |
| 1692 | for(int index = 1; index < bloom_index; index++) |
| 1693 | { |
| 1694 | name[7] = 'A' + index; |
| 1695 | curr_effect->set_texture(name, rt->bloom_texture[index - 1]); |
| 1696 | } |
| 1697 | for(int index = bloom_index; index < 11; index++) |
| 1698 | { |
| 1699 | name[7] = 'A' + index; |
| 1700 | curr_effect->set_texture(name, black_texture); |
| 1701 | } |
| 1702 | |
| 1703 | curr_effect->begin(&num_passes, 0); |
| 1704 | |
| 1705 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1706 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1707 | |
| 1708 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1709 | { |
| 1710 | curr_effect->begin_pass(pass); |
| 1711 | // add the primitives |
| 1712 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1713 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1714 | curr_effect->end_pass(); |
| 1715 | } |
| 1716 | |
| 1717 | curr_effect->end(); |
| 1718 | } |
| 1719 | |
| 1720 | //============================================================ |
| 1721 | // shaders::render_quad |
| 1722 | //============================================================ |
| 1723 | |
| 1724 | void shaders::render_quad(poly_info *poly, int vertnum) |
| 1725 | { |
| 1726 | if (!master_enable || !d3dintf->post_fx_available) |
| 1727 | return; |
| 1728 | |
| 1729 | UINT num_passes = 0; |
| 1730 | curr_texture = poly->get_texture(); |
| 1731 | |
| 1732 | if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && curr_texture != NULL) |
| 1733 | { |
| 1734 | render_target *rt = find_render_target(curr_texture); |
| 1735 | if (rt == NULL) |
| 1736 | { |
| 1737 | return; |
| 1738 | } |
| 1739 | cache_target *ct = find_cache_target(rt->screen_index, curr_texture->get_texinfo().width, curr_texture->get_texinfo().height); |
| 1740 | |
| 1741 | vec2f& sourcedims = curr_texture->get_rawdims(); |
| 1742 | vec2f delta = curr_texture->get_uvstop() - curr_texture->get_uvstart(); |
| 1743 | vec2f texsize(rt->width, rt->height); |
| 1744 | float defocus_x = options->defocus[0]; |
| 1745 | float defocus_y = options->defocus[1]; |
| 1746 | bool focus_enable = defocus_x != 0.0f || defocus_y != 0.0f; |
| 1747 | |
| 1748 | ntsc_pass(rt, sourcedims, delta); |
| 1749 | color_convolution_pass(rt, texsize, sourcedims); |
| 1750 | prescale_pass(rt, texsize, sourcedims); |
| 1751 | deconverge_pass(rt, texsize, delta, sourcedims); |
| 1752 | if (focus_enable) |
| 1753 | { |
| 1754 | defocus_pass(rt, texsize); |
| 1755 | } |
| 1756 | phosphor_pass(rt, ct, texsize, focus_enable); |
| 1757 | avi_post_pass(rt, texsize, delta, sourcedims, poly, vertnum); |
| 1758 | screen_post_pass(rt, texsize, delta, sourcedims, poly, vertnum); |
| 1759 | raster_bloom_pass(rt, texsize, delta, poly, vertnum); |
| 1760 | |
| 1761 | curr_texture->increment_frame_count(); |
| 1762 | curr_texture->mask_frame_count(options->yiq_phase_count); |
| 1763 | |
| 1764 | options->params_dirty = false; |
| 1765 | |
| 1766 | } |
| 1767 | else if(PRIMFLAG_GET_VECTOR(poly->get_flags()) && vector_enable) |
| 1768 | { |
| 1769 | render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1770 | if (rt == NULL) |
| 1771 | { |
| 1772 | return; |
| 1773 | } |
| 1774 | |
| 1775 | lines_pending = true; |
| 1776 | |
| 1777 | curr_effect = vector_effect; |
| 1778 | |
| 1779 | if(options->params_dirty) |
| 1780 | { |
| 1781 | vec2f screendims = d3d->get_dims(); |
| 1782 | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1783 | } |
| 1784 | |
| 1785 | float time_params[2] = { 0.0f, 0.0f }; |
| 1786 | float length_params[3] = { poly->get_line_length(), options->vector_length_scale, options->vector_length_ratio }; |
| 1787 | curr_effect->set_vector("TimeParams", 2, time_params); |
| 1788 | curr_effect->set_vector("LengthParams", 3, length_params); |
| 1789 | |
| 1790 | curr_effect->begin(&num_passes, 0); |
| 1791 | |
| 1792 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1793 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1794 | |
| 1795 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1796 | { |
| 1797 | curr_effect->begin_pass(pass); |
| 1798 | // add the primitives |
| 1799 | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1800 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1801 | curr_effect->end_pass(); |
| 1802 | } |
| 1803 | |
| 1804 | curr_effect->end(); |
| 1805 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1806 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1807 | |
| 1808 | curr_effect = default_effect; |
| 1809 | |
| 1810 | curr_effect->set_float("FixedAlpha", 1.0f); |
| 1811 | } |
| 1812 | else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable) |
| 1813 | { |
| 1814 | render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1815 | |
| 1816 | /* Bloom */ |
| 1817 | curr_effect = downsample_effect; |
| 1818 | |
| 1819 | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1820 | curr_effect->set_float("BloomRescale", options->vector_bloom_scale); |
| 1821 | |
| 1822 | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 1823 | int bloom_index = 0; |
| 1824 | float bloom_width = rt->target_width; |
| 1825 | float bloom_height = rt->target_height; |
| 1826 | float screen_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1827 | curr_effect->set_vector("ScreenSize", 2, screen_size); |
| 1828 | float bloom_dims[11][2]; |
| 1829 | for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 1830 | { |
| 1831 | bloom_dims[bloom_index][0] = bloom_width; |
| 1832 | bloom_dims[bloom_index][1] = bloom_height; |
| 1833 | curr_effect->set_vector("TargetSize", 2, bloom_dims[bloom_index]); |
| 1834 | |
| 1835 | curr_effect->begin(&num_passes, 0); |
| 1836 | |
| 1837 | curr_effect->set_texture("DiffuseTexture", (bloom_index == 0) ? rt->render_texture[0] : rt->bloom_texture[bloom_index - 1]); |
| 1838 | |
| 1839 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); |
| 1840 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1841 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1842 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1843 | |
| 1844 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1845 | { |
| 1846 | curr_effect->begin_pass(pass); |
| 1847 | // add the primitives |
| 1848 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1849 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1850 | curr_effect->end_pass(); |
| 1851 | } |
| 1852 | |
| 1853 | curr_effect->end(); |
| 1854 | |
| 1855 | bloom_index++; |
| 1856 | bloom_width *= 0.5f; |
| 1857 | bloom_height *= 0.5f; |
| 1858 | } |
| 1859 | |
| 1860 | // Bloom composite pass |
| 1861 | curr_effect = bloom_effect; |
| 1862 | |
| 1863 | float target_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1864 | curr_effect->set_vector("TargetSize", 2, target_size); |
| 1865 | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, |
| 1866 | options->bloom_level2_weight, options->bloom_level3_weight }; |
| 1867 | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, |
| 1868 | options->bloom_level6_weight, options->bloom_level7_weight }; |
| 1869 | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, |
| 1870 | options->bloom_level10_weight }; |
| 1871 | curr_effect->set_vector("Level0123Weight", 4, weight0123); |
| 1872 | curr_effect->set_vector("Level4567Weight", 4, weight4567); |
| 1873 | curr_effect->set_vector("Level89AWeight", 3, weight89A); |
| 1874 | curr_effect->set_vector("Level01Size", 4, bloom_dims[0]); |
| 1875 | curr_effect->set_vector("Level23Size", 4, bloom_dims[2]); |
| 1876 | curr_effect->set_vector("Level45Size", 4, bloom_dims[4]); |
| 1877 | curr_effect->set_vector("Level67Size", 4, bloom_dims[6]); |
| 1878 | curr_effect->set_vector("Level89Size", 4, bloom_dims[8]); |
| 1879 | curr_effect->set_vector("LevelASize", 2, bloom_dims[10]); |
| 1880 | |
| 1881 | curr_effect->set_texture("DiffuseA", rt->render_texture[0]); |
| 1882 | |
| 1883 | char name[9] = "Diffuse*"; |
| 1884 | for(int index = 1; index < bloom_index; index++) |
| 1885 | { |
| 1886 | name[7] = 'A' + index; |
| 1887 | curr_effect->set_texture(name, rt->bloom_texture[index - 1]); |
| 1888 | } |
| 1889 | for(int index = bloom_index; index < 11; index++) |
| 1890 | { |
| 1891 | name[7] = 'A' + index; |
| 1892 | curr_effect->set_texture(name, black_texture); |
| 1893 | } |
| 1894 | |
| 1895 | curr_effect->begin(&num_passes, 0); |
| 1896 | |
| 1897 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1898 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1899 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1900 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1901 | |
| 1902 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1903 | { |
| 1904 | curr_effect->begin_pass(pass); |
| 1905 | // add the primitives |
| 1906 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1907 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1908 | curr_effect->end_pass(); |
| 1909 | } |
| 1910 | |
| 1911 | curr_effect->end(); |
| 1912 | |
| 1913 | /* Phosphor */ |
| 1914 | curr_effect = phosphor_effect; |
| 1915 | |
| 1916 | if(options->params_dirty) |
| 1917 | { |
| 1918 | vec2f screendims = d3d->get_dims(); |
| 1919 | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1920 | curr_effect->set_vector("Phosphor", 3, options->phosphor); |
| 1921 | } |
| 1922 | float target_dims[2] = { d3d->get_width(), d3d->get_height() }; |
| 1923 | curr_effect->set_vector("TargetDims", 2, target_dims); |
| 1924 | curr_effect->set_float("Passthrough", 0.0f); |
| 1925 | |
| 1926 | curr_effect->set_texture("Diffuse", rt->render_texture[1]); |
| 1927 | curr_effect->set_texture("LastPass", rt->render_texture[2]); |
| 1928 | |
| 1929 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); |
| 1930 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); |
| 1931 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1932 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1933 | |
| 1934 | curr_effect->begin(&num_passes, 0); |
| 1935 | |
| 1936 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1937 | { |
| 1938 | curr_effect->begin_pass(pass); |
| 1939 | // add the primitives |
| 1940 | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1941 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1942 | curr_effect->end_pass(); |
| 1943 | } |
| 1944 | |
| 1945 | curr_effect->end(); |
| 1946 | |
| 1947 | blit(rt->target[2], rt->render_texture[3], NULL, poly->get_type(), vertnum, poly->get_count()); |
| 1948 | blit(backbuffer, rt->render_texture[3], backbuffer, poly->get_type(), vertnum, poly->get_count()); |
| 1949 | |
| 1950 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1951 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1952 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1953 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1954 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1955 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1956 | |
| 1957 | lines_pending = false; |
| 1958 | } |
| 1959 | else |
| 1960 | { |
| 1961 | curr_effect = default_effect; |
| 1962 | |
| 1963 | vec2f screendims = d3d->get_dims(); |
| 1964 | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1965 | curr_effect->set_float("PostPass", 0.0f); |
| 1966 | |
| 1967 | curr_effect->begin(&num_passes, 0); |
| 1968 | |
| 1969 | for (UINT pass = 0; pass < num_passes; pass++) |
| 1970 | { |
| 1971 | curr_effect->begin_pass(pass); |
| 1972 | // add the primitives |
| 1973 | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1974 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1975 | curr_effect->end_pass(); |
| 1976 | } |
| 1977 | |
| 1978 | curr_effect->end(); |
| 1979 | } |
| 1980 | |
| 1981 | curr_texture = NULL; |
| 1982 | } |
| 1983 | |
| 1984 | |
| 1985 | |
| 1986 | //============================================================ |
| 1987 | // shaders::end_draw |
| 1988 | //============================================================ |
| 1989 | |
| 1990 | void shaders::end_draw() |
| 1991 | { |
| 1992 | if (!master_enable || !d3dintf->post_fx_available) |
| 1993 | return; |
| 1994 | |
| 1995 | (*d3dintf->surface.release)(backbuffer); |
| 1996 | } |
| 1997 | |
| 1998 | |
| 1999 | //============================================================ |
| 2000 | // shaders::register_prescaled_texture |
| 2001 | //============================================================ |
| 2002 | |
| 2003 | bool shaders::register_prescaled_texture(texture_info *texture) |
| 2004 | { |
| 2005 | return register_texture(texture); |
| 2006 | } |
| 2007 | |
| 2008 | |
| 2009 | //============================================================ |
| 2010 | // shaders::add_cache_target - register a cache target |
| 2011 | //============================================================ |
| 2012 | bool shaders::add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index) |
| 2013 | { |
| 2014 | cache_target* target = (cache_target*)global_alloc_clear(cache_target); |
| 2015 | |
| 2016 | if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) |
| 2017 | { |
| 2018 | global_free(target); |
| 2019 | return false; |
| 2020 | } |
| 2021 | |
| 2022 | if (info != NULL) |
| 2023 | { |
| 2024 | target->width = info->get_texinfo().width; |
| 2025 | target->height = info->get_texinfo().height; |
| 2026 | } |
| 2027 | else |
| 2028 | { |
| 2029 | target->width = d3d->get_width(); |
| 2030 | target->height = d3d->get_height(); |
| 2031 | } |
| 2032 | |
| 2033 | target->next = cachehead; |
| 2034 | target->prev = NULL; |
| 2035 | |
| 2036 | target->screen_index = screen_index; |
| 2037 | |
| 2038 | if (cachehead != NULL) |
| 2039 | { |
| 2040 | cachehead->prev = target; |
| 2041 | } |
| 2042 | cachehead = target; |
| 2043 | |
| 2044 | return true; |
| 2045 | } |
| 2046 | |
| 2047 | render_target* shaders::get_vector_target() |
| 2048 | { |
| 2049 | if (!vector_enable) |
| 2050 | { |
| 2051 | return NULL; |
| 2052 | } |
| 2053 | |
| 2054 | return find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 2055 | } |
| 2056 | |
| 2057 | void shaders::create_vector_target(render_primitive *prim) |
| 2058 | { |
| 2059 | if (!add_render_target(d3d, NULL, d3d->get_width(), d3d->get_height(), 1, 1)) |
| 2060 | { |
| 2061 | vector_enable = false; |
| 2062 | } |
| 2063 | } |
| 2064 | |
| 2065 | //============================================================ |
| 2066 | // shaders::add_render_target - register a render target |
| 2067 | //============================================================ |
| 2068 | |
| 2069 | bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale) |
| 2070 | { |
| 2071 | UINT32 screen_index = 0; |
| 2072 | UINT32 page_index = 0; |
| 2073 | if (info != NULL) |
| 2074 | { |
| 2075 | render_target *existing_target = find_render_target(info); |
| 2076 | if (existing_target != NULL) |
| 2077 | { |
| 2078 | remove_render_target(existing_target); |
| 2079 | } |
| 2080 | |
| 2081 | UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; |
| 2082 | screen_index = screen_index_data >> 1; |
| 2083 | page_index = screen_index_data & 1; |
| 2084 | } |
| 2085 | else |
| 2086 | { |
| 2087 | render_target *existing_target = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 2088 | if (existing_target != NULL) |
| 2089 | { |
| 2090 | remove_render_target(existing_target); |
| 2091 | } |
| 2092 | } |
| 2093 | |
| 2094 | render_target* target = (render_target*)global_alloc_clear(render_target); |
| 2095 | |
| 2096 | if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) |
| 2097 | { |
| 2098 | global_free(target); |
| 2099 | return false; |
| 2100 | } |
| 2101 | |
| 2102 | if (info != NULL) |
| 2103 | { |
| 2104 | target->width = info->get_texinfo().width; |
| 2105 | target->height = info->get_texinfo().height; |
| 2106 | } |
| 2107 | else |
| 2108 | { |
| 2109 | target->width = d3d->get_width(); |
| 2110 | target->height = d3d->get_height(); |
| 2111 | } |
| 2112 | |
| 2113 | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, target->target[0]); |
| 2114 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 2115 | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 2116 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 2117 | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 2118 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 2119 | |
| 2120 | target->screen_index = screen_index; |
| 2121 | target->page_index = page_index; |
| 2122 | |
| 2123 | cache_target* cache = find_cache_target(target->screen_index, target->width, target->height); |
| 2124 | if (cache == NULL) |
| 2125 | { |
| 2126 | if (!add_cache_target(d3d, info, width, height, xprescale, yprescale, target->screen_index)) |
| 2127 | { |
| 2128 | global_free(target); |
| 2129 | return false; |
| 2130 | } |
| 2131 | } |
| 2132 | |
| 2133 | target->next = targethead; |
| 2134 | target->prev = NULL; |
| 2135 | |
| 2136 | if (targethead != NULL) |
| 2137 | { |
| 2138 | targethead->prev = target; |
| 2139 | } |
| 2140 | targethead = target; |
| 2141 | |
| 2142 | return true; |
| 2143 | } |
| 2144 | |
| 2145 | //============================================================ |
| 2146 | // shaders::enumerate_screens |
| 2147 | //============================================================ |
| 2148 | void shaders::enumerate_screens() |
| 2149 | { |
| 2150 | screen_device_iterator iter(machine->root_device()); |
| 2151 | num_screens = iter.count(); |
| 2152 | } |
| 2153 | |
| 2154 | |
| 2155 | //============================================================ |
| 2156 | // shaders::register_texture(texture::info) |
| 2157 | //============================================================ |
| 2158 | |
| 2159 | bool shaders::register_texture(texture_info *texture) |
| 2160 | { |
| 2161 | int width = texture->get_width(); |
| 2162 | int height = texture->get_height(); |
| 2163 | int xscale = texture->get_xscale(); |
| 2164 | int yscale = texture->get_yscale(); |
| 2165 | |
| 2166 | if (!master_enable || !d3dintf->post_fx_available) |
| 2167 | { |
| 2168 | return false; |
| 2169 | } |
| 2170 | |
| 2171 | enumerate_screens(); |
| 2172 | |
| 2173 | int hlsl_prescale_x = prescale_force_x; |
| 2174 | int hlsl_prescale_y = prescale_force_y; |
| 2175 | |
| 2176 | // Find the nearest prescale factor that is over our screen size |
| 2177 | if (hlsl_prescale_x == 0) |
| 2178 | { |
| 2179 | hlsl_prescale_x = 1; |
| 2180 | while (width * xscale * hlsl_prescale_x <= d3d->get_width()) |
| 2181 | { |
| 2182 | hlsl_prescale_x++; |
| 2183 | } |
| 2184 | hlsl_prescale_x--; |
| 2185 | } |
| 2186 | |
| 2187 | if (hlsl_prescale_y == 0) |
| 2188 | { |
| 2189 | hlsl_prescale_y = 1; |
| 2190 | while (height * yscale * hlsl_prescale_y <= d3d->get_height()) |
| 2191 | { |
| 2192 | hlsl_prescale_y++; |
| 2193 | } |
| 2194 | hlsl_prescale_y--; |
| 2195 | } |
| 2196 | |
| 2197 | hlsl_prescale_x = ((hlsl_prescale_x == 0) ? 1 : hlsl_prescale_x); |
| 2198 | hlsl_prescale_y = ((hlsl_prescale_y == 0) ? 1 : hlsl_prescale_y); |
| 2199 | |
| 2200 | if (!add_render_target(d3d, texture, width, height, xscale * hlsl_prescale_x, yscale * hlsl_prescale_y)) |
| 2201 | return false; |
| 2202 | |
| 2203 | options->params_dirty = true; |
| 2204 | |
| 2205 | return true; |
| 2206 | } |
| 2207 | |
| 2208 | //============================================================ |
| 2209 | // shaders::delete_resources |
| 2210 | //============================================================ |
| 2211 | |
| 2212 | void shaders::delete_resources(bool reset) |
| 2213 | { |
| 2214 | if (!master_enable || !d3dintf->post_fx_available) |
| 2215 | return; |
| 2216 | |
| 2217 | initialized = false; |
| 2218 | |
| 2219 | cache_target *currcache = cachehead; |
| 2220 | while(cachehead != NULL) |
| 2221 | { |
| 2222 | cachehead = currcache->next; |
| 2223 | global_free(currcache); |
| 2224 | currcache = cachehead; |
| 2225 | } |
| 2226 | |
| 2227 | render_target *currtarget = targethead; |
| 2228 | while(targethead != NULL) |
| 2229 | { |
| 2230 | targethead = currtarget->next; |
| 2231 | global_free(currtarget); |
| 2232 | currtarget = targethead; |
| 2233 | } |
| 2234 | |
| 2235 | if (downsample_effect != NULL) |
| 2236 | { |
| 2237 | delete downsample_effect; |
| 2238 | downsample_effect = NULL; |
| 2239 | } |
| 2240 | if (bloom_effect != NULL) |
| 2241 | { |
| 2242 | delete bloom_effect; |
| 2243 | bloom_effect = NULL; |
| 2244 | } |
| 2245 | if (vector_effect != NULL) |
| 2246 | { |
| 2247 | delete vector_effect; |
| 2248 | vector_effect = NULL; |
| 2249 | } |
| 2250 | if (default_effect != NULL) |
| 2251 | { |
| 2252 | delete default_effect; |
| 2253 | default_effect = NULL; |
| 2254 | } |
| 2255 | if (post_effect != NULL) |
| 2256 | { |
| 2257 | delete post_effect; |
| 2258 | post_effect = NULL; |
| 2259 | } |
| 2260 | if (prescale_effect != NULL) |
| 2261 | { |
| 2262 | delete prescale_effect; |
| 2263 | prescale_effect = NULL; |
| 2264 | } |
| 2265 | if (phosphor_effect != NULL) |
| 2266 | { |
| 2267 | delete phosphor_effect; |
| 2268 | phosphor_effect = NULL; |
| 2269 | } |
| 2270 | if (focus_effect != NULL) |
| 2271 | { |
| 2272 | delete focus_effect; |
| 2273 | focus_effect = NULL; |
| 2274 | } |
| 2275 | if (deconverge_effect != NULL) |
| 2276 | { |
| 2277 | delete deconverge_effect; |
| 2278 | deconverge_effect = NULL; |
| 2279 | } |
| 2280 | if (color_effect != NULL) |
| 2281 | { |
| 2282 | delete color_effect; |
| 2283 | color_effect = NULL; |
| 2284 | } |
| 2285 | if (yiq_encode_effect != NULL) |
| 2286 | { |
| 2287 | delete yiq_encode_effect; |
| 2288 | yiq_encode_effect = NULL; |
| 2289 | } |
| 2290 | if (yiq_decode_effect != NULL) |
| 2291 | { |
| 2292 | delete yiq_decode_effect; |
| 2293 | yiq_decode_effect = NULL; |
| 2294 | } |
| 2295 | |
| 2296 | if (backbuffer != NULL) |
| 2297 | { |
| 2298 | (*d3dintf->surface.release)(backbuffer); |
| 2299 | backbuffer = NULL; |
| 2300 | } |
| 2301 | |
| 2302 | if (black_surface != NULL) |
| 2303 | { |
| 2304 | (*d3dintf->surface.release)(black_surface); |
| 2305 | black_surface = NULL; |
| 2306 | } |
| 2307 | if (black_texture != NULL) |
| 2308 | { |
| 2309 | (*d3dintf->texture.release)(black_texture); |
| 2310 | black_texture = NULL; |
| 2311 | } |
| 2312 | |
| 2313 | if (avi_copy_texture != NULL) |
| 2314 | { |
| 2315 | (*d3dintf->texture.release)(avi_copy_texture); |
| 2316 | avi_copy_texture = NULL; |
| 2317 | } |
| 2318 | |
| 2319 | if (avi_copy_surface != NULL) |
| 2320 | { |
| 2321 | (*d3dintf->surface.release)(avi_copy_surface); |
| 2322 | avi_copy_surface = NULL; |
| 2323 | } |
| 2324 | |
| 2325 | if (avi_final_texture != NULL) |
| 2326 | { |
| 2327 | (*d3dintf->texture.release)(avi_final_texture); |
| 2328 | avi_final_texture = NULL; |
| 2329 | } |
| 2330 | |
| 2331 | if (avi_final_target != NULL) |
| 2332 | { |
| 2333 | (*d3dintf->surface.release)(avi_final_target); |
| 2334 | avi_final_target = NULL; |
| 2335 | } |
| 2336 | |
| 2337 | shadow_bitmap.reset(); |
| 2338 | } |
| 2339 | |
| 2340 | |
| 2341 | //============================================================ |
| 2342 | // get_vector |
| 2343 | //============================================================ |
| 2344 | |
| 2345 | static void get_vector(const char *data, int count, float *out, int report_error) |
| 2346 | { |
| 2347 | if (count > 3) |
| 2348 | { |
| 2349 | if (sscanf(data, "%f,%f,%f,%f", &out[0], &out[1], &out[2], &out[3]) < 4 && report_error) |
| 2350 | osd_printf_error("Illegal quad vector value = %s\n", data); |
| 2351 | } |
| 2352 | else if(count > 2) |
| 2353 | { |
| 2354 | if (sscanf(data, "%f,%f,%f", &out[0], &out[1], &out[2]) < 3 && report_error) |
| 2355 | osd_printf_error("Illegal triple vector value = %s\n", data); |
| 2356 | } |
| 2357 | else if(count > 1) |
| 2358 | { |
| 2359 | if (sscanf(data, "%f,%f", &out[0], &out[1]) < 2 && report_error) |
| 2360 | osd_printf_error("Illegal double vector value = %s\n", data); |
| 2361 | } |
| 2362 | else if(count > 0) |
| 2363 | { |
| 2364 | if (sscanf(data, "%f", &out[0]) < 1 && report_error) |
| 2365 | osd_printf_error("Illegal single vector value = %s\n", data); |
| 2366 | } |
| 2367 | } |
| 2368 | |
| 2369 | |
| 2370 | /*------------------------------------------------- |
| 2371 | slider_alloc - allocate a new slider entry |
| 2372 | currently duplicated from ui.c, this could |
| 2373 | be done in a more ideal way. |
| 2374 | -------------------------------------------------*/ |
| 2375 | |
| 2376 | static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg) |
| 2377 | { |
| 2378 | int size = sizeof(slider_state) + strlen(title); |
| 2379 | slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size); |
| 2380 | |
| 2381 | state->minval = minval; |
| 2382 | state->defval = defval; |
| 2383 | state->maxval = maxval; |
| 2384 | state->incval = incval; |
| 2385 | state->update = update; |
| 2386 | state->arg = arg; |
| 2387 | strcpy(state->description, title); |
| 2388 | |
| 2389 | return state; |
| 2390 | } |
| 2391 | |
| 2392 | |
| 2393 | //============================================================ |
| 2394 | // assorted global slider accessors |
| 2395 | //============================================================ |
| 2396 | |
| 2397 | static INT32 slider_set(float *option, float scale, const char *fmt, astring *string, INT32 newval) |
| 2398 | { |
| 2399 | if (option != NULL && newval != SLIDER_NOCHANGE) *option = (float)newval * scale; |
| 2400 | if (string != NULL) string->printf(fmt, *option); |
| 2401 | return floor(*option / scale + 0.5f); |
| 2402 | } |
| 2403 | |
| 2404 | static INT32 slider_shadow_mask_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2405 | { |
| 2406 | return slider_set(&(((hlsl_options*)arg)->shadow_mask_alpha), 0.01f, "%2.2f", string, newval); |
| 2407 | } |
| 2408 | |
| 2409 | static INT32 slider_shadow_mask_x_count(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2410 | { |
| 2411 | hlsl_options *options = (hlsl_options*)arg; |
| 2412 | if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_x = newval; |
| 2413 | if (string != NULL) string->printf("%d", options->shadow_mask_count_x); |
| 2414 | options->params_dirty = true; |
| 2415 | return options->shadow_mask_count_x; |
| 2416 | } |
| 2417 | |
| 2418 | static INT32 slider_shadow_mask_y_count(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2419 | { |
| 2420 | hlsl_options *options = (hlsl_options*)arg; |
| 2421 | if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_y = newval; |
| 2422 | if (string != NULL) string->printf("%d", options->shadow_mask_count_y); |
| 2423 | options->params_dirty = true; |
| 2424 | return options->shadow_mask_count_y; |
| 2425 | } |
| 2426 | |
| 2427 | static INT32 slider_shadow_mask_usize(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2428 | { |
| 2429 | ((hlsl_options*)arg)->params_dirty = true; |
| 2430 | return slider_set(&(((hlsl_options*)arg)->shadow_mask_u_size), 1.0f / 32.0f, "%2.5f", string, newval); |
| 2431 | } |
| 2432 | |
| 2433 | static INT32 slider_shadow_mask_vsize(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2434 | { |
| 2435 | ((hlsl_options*)arg)->params_dirty = true; |
| 2436 | return slider_set(&(((hlsl_options*)arg)->shadow_mask_v_size), 1.0f / 32.0f, "%2.5f", string, newval); |
| 2437 | } |
| 2438 | |
| 2439 | static INT32 slider_curvature(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2440 | { |
| 2441 | ((hlsl_options*)arg)->params_dirty = true; |
| 2442 | return slider_set(&(((hlsl_options*)arg)->curvature), 0.01f, "%2.2f", string, newval); |
| 2443 | } |
| 2444 | |
| 2445 | static INT32 slider_pincushion(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2446 | { |
| 2447 | ((hlsl_options*)arg)->params_dirty = true; |
| 2448 | return slider_set(&(((hlsl_options*)arg)->pincushion), 0.01f, "%2.2f", string, newval); |
| 2449 | } |
| 2450 | |
| 2451 | static INT32 slider_scanline_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2452 | { |
| 2453 | ((hlsl_options*)arg)->params_dirty = true; |
| 2454 | return slider_set(&(((hlsl_options*)arg)->scanline_alpha), 0.01f, "%2.2f", string, newval); |
| 2455 | } |
| 2456 | |
| 2457 | static INT32 slider_scanline_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2458 | { |
| 2459 | ((hlsl_options*)arg)->params_dirty = true; |
| 2460 | return slider_set(&(((hlsl_options*)arg)->scanline_scale), 0.05f, "%2.2f", string, newval); |
| 2461 | } |
| 2462 | |
| 2463 | static INT32 slider_scanline_height(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2464 | { |
| 2465 | ((hlsl_options*)arg)->params_dirty = true; |
| 2466 | return slider_set(&(((hlsl_options*)arg)->scanline_height), 0.05f, "%2.2f", string, newval); |
| 2467 | } |
| 2468 | |
| 2469 | static INT32 slider_scanline_bright_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2470 | { |
| 2471 | ((hlsl_options*)arg)->params_dirty = true; |
| 2472 | return slider_set(&(((hlsl_options*)arg)->scanline_bright_scale), 0.05f, "%2.2f", string, newval); |
| 2473 | } |
| 2474 | |
| 2475 | static INT32 slider_scanline_bright_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2476 | { |
| 2477 | ((hlsl_options*)arg)->params_dirty = true; |
| 2478 | return slider_set(&(((hlsl_options*)arg)->scanline_bright_offset), 0.05f, "%2.2f", string, newval); |
| 2479 | } |
| 2480 | |
| 2481 | static INT32 slider_scanline_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2482 | { |
| 2483 | ((hlsl_options*)arg)->params_dirty = true; |
| 2484 | return slider_set(&(((hlsl_options*)arg)->scanline_offset), 0.05f, "%2.2f", string, newval); |
| 2485 | } |
| 2486 | |
| 2487 | static INT32 slider_defocus_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2488 | { |
| 2489 | ((hlsl_options*)arg)->params_dirty = true; |
| 2490 | return slider_set(&(((hlsl_options*)arg)->defocus[0]), 0.5f, "%2.1f", string, newval); |
| 2491 | } |
| 2492 | |
| 2493 | static INT32 slider_defocus_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2494 | { |
| 2495 | ((hlsl_options*)arg)->params_dirty = true; |
| 2496 | return slider_set(&(((hlsl_options*)arg)->defocus[1]), 0.5f, "%2.1f", string, newval); |
| 2497 | } |
| 2498 | |
| 2499 | static INT32 slider_red_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2500 | { |
| 2501 | ((hlsl_options*)arg)->params_dirty = true; |
| 2502 | return slider_set(&(((hlsl_options*)arg)->converge_x[0]), 0.1f, "%3.1f", string, newval); |
| 2503 | } |
| 2504 | |
| 2505 | static INT32 slider_red_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2506 | { |
| 2507 | ((hlsl_options*)arg)->params_dirty = true; |
| 2508 | return slider_set(&(((hlsl_options*)arg)->converge_y[0]), 0.1f, "%3.1f", string, newval); |
| 2509 | } |
| 2510 | |
| 2511 | static INT32 slider_green_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2512 | { |
| 2513 | ((hlsl_options*)arg)->params_dirty = true; |
| 2514 | return slider_set(&(((hlsl_options*)arg)->converge_x[1]), 0.1f, "%3.1f", string, newval); |
| 2515 | } |
| 2516 | |
| 2517 | static INT32 slider_green_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2518 | { |
| 2519 | ((hlsl_options*)arg)->params_dirty = true; |
| 2520 | return slider_set(&(((hlsl_options*)arg)->converge_y[1]), 0.1f, "%3.1f", string, newval); |
| 2521 | } |
| 2522 | |
| 2523 | static INT32 slider_blue_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2524 | { |
| 2525 | ((hlsl_options*)arg)->params_dirty = true; |
| 2526 | return slider_set(&(((hlsl_options*)arg)->converge_x[2]), 0.1f, "%3.1f", string, newval); |
| 2527 | } |
| 2528 | |
| 2529 | static INT32 slider_blue_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2530 | { |
| 2531 | ((hlsl_options*)arg)->params_dirty = true; |
| 2532 | return slider_set(&(((hlsl_options*)arg)->converge_y[2]), 0.1f, "%3.1f", string, newval); |
| 2533 | } |
| 2534 | |
| 2535 | static INT32 slider_red_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2536 | { |
| 2537 | ((hlsl_options*)arg)->params_dirty = true; |
| 2538 | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[0]), 0.1f, "%3.1f", string, newval); |
| 2539 | } |
| 2540 | |
| 2541 | static INT32 slider_red_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2542 | { |
| 2543 | ((hlsl_options*)arg)->params_dirty = true; |
| 2544 | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[0]), 0.1f, "%3.1f", string, newval); |
| 2545 | } |
| 2546 | |
| 2547 | static INT32 slider_green_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2548 | { |
| 2549 | ((hlsl_options*)arg)->params_dirty = true; |
| 2550 | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[1]), 0.1f, "%3.1f", string, newval); |
| 2551 | } |
| 2552 | |
| 2553 | static INT32 slider_green_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2554 | { |
| 2555 | ((hlsl_options*)arg)->params_dirty = true; |
| 2556 | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[1]), 0.1f, "%3.1f", string, newval); |
| 2557 | } |
| 2558 | |
| 2559 | static INT32 slider_blue_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2560 | { |
| 2561 | ((hlsl_options*)arg)->params_dirty = true; |
| 2562 | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[2]), 0.1f, "%3.1f", string, newval); |
| 2563 | } |
| 2564 | |
| 2565 | static INT32 slider_blue_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2566 | { |
| 2567 | ((hlsl_options*)arg)->params_dirty = true; |
| 2568 | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[2]), 0.1f, "%3.1f", string, newval); |
| 2569 | } |
| 2570 | |
| 2571 | static INT32 slider_red_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2572 | { |
| 2573 | ((hlsl_options*)arg)->params_dirty = true; |
| 2574 | return slider_set(&(((hlsl_options*)arg)->red_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2575 | } |
| 2576 | |
| 2577 | static INT32 slider_red_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2578 | { |
| 2579 | ((hlsl_options*)arg)->params_dirty = true; |
| 2580 | return slider_set(&(((hlsl_options*)arg)->red_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2581 | } |
| 2582 | |
| 2583 | static INT32 slider_red_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2584 | { |
| 2585 | ((hlsl_options*)arg)->params_dirty = true; |
| 2586 | return slider_set(&(((hlsl_options*)arg)->red_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2587 | } |
| 2588 | |
| 2589 | static INT32 slider_green_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2590 | { |
| 2591 | ((hlsl_options*)arg)->params_dirty = true; |
| 2592 | return slider_set(&(((hlsl_options*)arg)->grn_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2593 | } |
| 2594 | |
| 2595 | static INT32 slider_green_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2596 | { |
| 2597 | ((hlsl_options*)arg)->params_dirty = true; |
| 2598 | return slider_set(&(((hlsl_options*)arg)->grn_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2599 | } |
| 2600 | |
| 2601 | static INT32 slider_green_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2602 | { |
| 2603 | ((hlsl_options*)arg)->params_dirty = true; |
| 2604 | return slider_set(&(((hlsl_options*)arg)->grn_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2605 | } |
| 2606 | |
| 2607 | static INT32 slider_blue_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2608 | { |
| 2609 | ((hlsl_options*)arg)->params_dirty = true; |
| 2610 | return slider_set(&(((hlsl_options*)arg)->blu_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2611 | } |
| 2612 | |
| 2613 | static INT32 slider_blue_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2614 | { |
| 2615 | ((hlsl_options*)arg)->params_dirty = true; |
| 2616 | return slider_set(&(((hlsl_options*)arg)->blu_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2617 | } |
| 2618 | |
| 2619 | static INT32 slider_blue_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2620 | { |
| 2621 | ((hlsl_options*)arg)->params_dirty = true; |
| 2622 | return slider_set(&(((hlsl_options*)arg)->blu_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2623 | } |
| 2624 | |
| 2625 | static INT32 slider_red_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2626 | { |
| 2627 | ((hlsl_options*)arg)->params_dirty = true; |
| 2628 | return slider_set(&(((hlsl_options*)arg)->offset[0]), 0.01f, "%2.2f", string, newval); |
| 2629 | } |
| 2630 | |
| 2631 | static INT32 slider_green_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2632 | { |
| 2633 | ((hlsl_options*)arg)->params_dirty = true; |
| 2634 | return slider_set(&(((hlsl_options*)arg)->offset[1]), 0.01f, "%2.2f", string, newval); |
| 2635 | } |
| 2636 | |
| 2637 | static INT32 slider_blue_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2638 | { |
| 2639 | ((hlsl_options*)arg)->params_dirty = true; |
| 2640 | return slider_set(&(((hlsl_options*)arg)->offset[2]), 0.01f, "%2.2f", string, newval); |
| 2641 | } |
| 2642 | |
| 2643 | static INT32 slider_red_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2644 | { |
| 2645 | ((hlsl_options*)arg)->params_dirty = true; |
| 2646 | return slider_set(&(((hlsl_options*)arg)->scale[0]), 0.01f, "%2.2f", string, newval); |
| 2647 | } |
| 2648 | |
| 2649 | static INT32 slider_green_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2650 | { |
| 2651 | ((hlsl_options*)arg)->params_dirty = true; |
| 2652 | return slider_set(&(((hlsl_options*)arg)->scale[1]), 0.01f, "%2.2f", string, newval); |
| 2653 | } |
| 2654 | |
| 2655 | static INT32 slider_blue_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2656 | { |
| 2657 | ((hlsl_options*)arg)->params_dirty = true; |
| 2658 | return slider_set(&(((hlsl_options*)arg)->scale[2]), 0.01f, "%2.2f", string, newval); |
| 2659 | } |
| 2660 | |
| 2661 | static INT32 slider_red_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2662 | { |
| 2663 | ((hlsl_options*)arg)->params_dirty = true; |
| 2664 | return slider_set(&(((hlsl_options*)arg)->power[0]), 0.05f, "%2.2f", string, newval); |
| 2665 | } |
| 2666 | |
| 2667 | static INT32 slider_green_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2668 | { |
| 2669 | ((hlsl_options*)arg)->params_dirty = true; |
| 2670 | return slider_set(&(((hlsl_options*)arg)->power[1]), 0.05f, "%2.2f", string, newval); |
| 2671 | } |
| 2672 | |
| 2673 | static INT32 slider_blue_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2674 | { |
| 2675 | ((hlsl_options*)arg)->params_dirty = true; |
| 2676 | return slider_set(&(((hlsl_options*)arg)->power[2]), 0.05f, "%2.2f", string, newval); |
| 2677 | } |
| 2678 | |
| 2679 | static INT32 slider_red_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2680 | { |
| 2681 | ((hlsl_options*)arg)->params_dirty = true; |
| 2682 | return slider_set(&(((hlsl_options*)arg)->floor[0]), 0.01f, "%2.2f", string, newval); |
| 2683 | } |
| 2684 | |
| 2685 | static INT32 slider_green_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2686 | { |
| 2687 | ((hlsl_options*)arg)->params_dirty = true; |
| 2688 | return slider_set(&(((hlsl_options*)arg)->floor[1]), 0.01f, "%2.2f", string, newval); |
| 2689 | } |
| 2690 | |
| 2691 | static INT32 slider_blue_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2692 | { |
| 2693 | ((hlsl_options*)arg)->params_dirty = true; |
| 2694 | return slider_set(&(((hlsl_options*)arg)->floor[2]), 0.01f, "%2.2f", string, newval); |
| 2695 | } |
| 2696 | |
| 2697 | static INT32 slider_red_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2698 | { |
| 2699 | ((hlsl_options*)arg)->params_dirty = true; |
| 2700 | return slider_set(&(((hlsl_options*)arg)->phosphor[0]), 0.01f, "%2.2f", string, newval); |
| 2701 | } |
| 2702 | |
| 2703 | static INT32 slider_green_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2704 | { |
| 2705 | ((hlsl_options*)arg)->params_dirty = true; |
| 2706 | return slider_set(&(((hlsl_options*)arg)->phosphor[1]), 0.01f, "%2.2f", string, newval); |
| 2707 | } |
| 2708 | |
| 2709 | static INT32 slider_blue_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2710 | { |
| 2711 | ((hlsl_options*)arg)->params_dirty = true; |
| 2712 | return slider_set(&(((hlsl_options*)arg)->phosphor[2]), 0.01f, "%2.2f", string, newval); |
| 2713 | } |
| 2714 | |
| 2715 | static INT32 slider_saturation(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2716 | { |
| 2717 | ((hlsl_options*)arg)->params_dirty = true; |
| 2718 | return slider_set(&(((hlsl_options*)arg)->saturation), 0.01f, "%2.2f", string, newval); |
| 2719 | } |
| 2720 | |
| 2721 | static INT32 slider_vector_attenuation(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2722 | { |
| 2723 | ((hlsl_options*)arg)->params_dirty = true; |
| 2724 | return slider_set(&(((hlsl_options*)arg)->vector_length_scale), 0.01f, "%1.2f", string, newval); |
| 2725 | } |
| 2726 | |
| 2727 | static INT32 slider_vector_length_max(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2728 | { |
| 2729 | ((hlsl_options*)arg)->params_dirty = true; |
| 2730 | return slider_set(&(((hlsl_options*)arg)->vector_length_ratio), 1.0f, "%4f", string, newval); |
| 2731 | } |
| 2732 | |
| 2733 | static INT32 slider_vector_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2734 | { |
| 2735 | ((hlsl_options*)arg)->params_dirty = true; |
| 2736 | return slider_set(&(((hlsl_options*)arg)->vector_bloom_scale), 0.001f, "%1.3f", string, newval); |
| 2737 | } |
| 2738 | |
| 2739 | static INT32 slider_raster_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2740 | { |
| 2741 | ((hlsl_options*)arg)->params_dirty = true; |
| 2742 | return slider_set(&(((hlsl_options*)arg)->raster_bloom_scale), 0.001f, "%1.3f", string, newval); |
| 2743 | } |
| 2744 | |
| 2745 | static INT32 slider_bloom_lvl0_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2746 | { |
| 2747 | ((hlsl_options*)arg)->params_dirty = true; |
| 2748 | return slider_set(&(((hlsl_options*)arg)->bloom_level0_weight), 0.01f, "%1.2f", string, newval); |
| 2749 | } |
| 2750 | |
| 2751 | static INT32 slider_bloom_lvl1_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2752 | { |
| 2753 | ((hlsl_options*)arg)->params_dirty = true; |
| 2754 | return slider_set(&(((hlsl_options*)arg)->bloom_level1_weight), 0.01f, "%1.2f", string, newval); |
| 2755 | } |
| 2756 | |
| 2757 | static INT32 slider_bloom_lvl2_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2758 | { |
| 2759 | ((hlsl_options*)arg)->params_dirty = true; |
| 2760 | return slider_set(&(((hlsl_options*)arg)->bloom_level2_weight), 0.01f, "%1.2f", string, newval); |
| 2761 | } |
| 2762 | |
| 2763 | static INT32 slider_bloom_lvl3_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2764 | { |
| 2765 | ((hlsl_options*)arg)->params_dirty = true; |
| 2766 | return slider_set(&(((hlsl_options*)arg)->bloom_level3_weight), 0.01f, "%1.2f", string, newval); |
| 2767 | } |
| 2768 | |
| 2769 | static INT32 slider_bloom_lvl4_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2770 | { |
| 2771 | ((hlsl_options*)arg)->params_dirty = true; |
| 2772 | return slider_set(&(((hlsl_options*)arg)->bloom_level4_weight), 0.01f, "%1.2f", string, newval); |
| 2773 | } |
| 2774 | |
| 2775 | static INT32 slider_bloom_lvl5_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2776 | { |
| 2777 | ((hlsl_options*)arg)->params_dirty = true; |
| 2778 | return slider_set(&(((hlsl_options*)arg)->bloom_level5_weight), 0.01f, "%1.2f", string, newval); |
| 2779 | } |
| 2780 | |
| 2781 | static INT32 slider_bloom_lvl6_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2782 | { |
| 2783 | ((hlsl_options*)arg)->params_dirty = true; |
| 2784 | return slider_set(&(((hlsl_options*)arg)->bloom_level6_weight), 0.01f, "%1.2f", string, newval); |
| 2785 | } |
| 2786 | |
| 2787 | static INT32 slider_bloom_lvl7_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2788 | { |
| 2789 | ((hlsl_options*)arg)->params_dirty = true; |
| 2790 | return slider_set(&(((hlsl_options*)arg)->bloom_level7_weight), 0.01f, "%1.2f", string, newval); |
| 2791 | } |
| 2792 | |
| 2793 | static INT32 slider_bloom_lvl8_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2794 | { |
| 2795 | ((hlsl_options*)arg)->params_dirty = true; |
| 2796 | return slider_set(&(((hlsl_options*)arg)->bloom_level8_weight), 0.01f, "%1.2f", string, newval); |
| 2797 | } |
| 2798 | |
| 2799 | static INT32 slider_bloom_lvl9_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2800 | { |
| 2801 | ((hlsl_options*)arg)->params_dirty = true; |
| 2802 | return slider_set(&(((hlsl_options*)arg)->bloom_level9_weight), 0.01f, "%1.2f", string, newval); |
| 2803 | } |
| 2804 | |
| 2805 | static INT32 slider_bloom_lvl10_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2806 | { |
| 2807 | ((hlsl_options*)arg)->params_dirty = true; |
| 2808 | return slider_set(&(((hlsl_options*)arg)->bloom_level10_weight), 0.01f, "%1.2f", string, newval); |
| 2809 | } |
| 2810 | |
| 2811 | //============================================================ |
| 2812 | // init_slider_list |
| 2813 | //============================================================ |
| 2814 | |
| 2815 | shaders::slider_desc shaders::s_sliders[] = |
| 2816 | { |
| 2817 | { "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha }, |
| 2818 | { "Shadow Mask X Count", 1, 320, 1024, 1, slider_shadow_mask_x_count }, |
| 2819 | { "Shadow Mask Y Count", 1, 240, 1024, 1, slider_shadow_mask_y_count }, |
| 2820 | { "Shadow Mask Pixel Count X", 1, 6, 64, 1, slider_shadow_mask_usize }, |
| 2821 | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2822 | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2823 | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2824 | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2825 | { "Screen Curvature", 0, 3, 100, 1, slider_curvature }, |
| 2826 | { "Image Pincushion", 0, 3, 100, 1, slider_pincushion }, |
| 2827 | { "Scanline Darkness", 0, 100, 100, 1, slider_scanline_alpha }, |
| 2828 | { "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale }, |
| 2829 | { "Scanline Indiv. Height", 1, 20, 80, 1, slider_scanline_height }, |
| 2830 | { "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale }, |
| 2831 | { "Scanline Brightness Overdrive", 0, 0, 20, 1, slider_scanline_bright_offset }, |
| 2832 | { "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset }, |
| 2833 | { "Defocus X", 0, 0, 64, 1, slider_defocus_x }, |
| 2834 | { "Defocus Y", 0, 0, 64, 1, slider_defocus_y }, |
| 2835 | { "Red Position Offset X", -1500, 3, 1500, 1, slider_red_converge_x }, |
| 2836 | { "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y }, |
| 2837 | { "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x }, |
| 2838 | { "Green Position Offset Y", -1500, 3, 1500, 1, slider_green_converge_y }, |
| 2839 | { "Blue Position Offset X", -1500, 3, 1500, 1, slider_blue_converge_x }, |
| 2840 | { "Blue Position Offset Y", -1500, 3, 1500, 1, slider_blue_converge_y }, |
| 2841 | { "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x }, |
| 2842 | { "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y }, |
| 2843 | { "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x }, |
| 2844 | { "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y }, |
| 2845 | { "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x }, |
| 2846 | { "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y }, |
| 2847 | { "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r }, |
| 2848 | { "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g }, |
| 2849 | { "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b }, |
| 2850 | { "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r }, |
| 2851 | { "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g }, |
| 2852 | { "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b }, |
| 2853 | { "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r }, |
| 2854 | { "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g }, |
| 2855 | { "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b }, |
| 2856 | { "Saturation", 0, 140, 400, 1, slider_saturation }, |
| 2857 | { "Red DC Offset", -100, 0, 100, 1, slider_red_offset }, |
| 2858 | { "Green DC Offset", -100, 0, 100, 1, slider_green_offset }, |
| 2859 | { "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset }, |
| 2860 | { "Red Scale", -200, 95, 200, 1, slider_red_scale }, |
| 2861 | { "Green Scale", -200, 95, 200, 1, slider_green_scale }, |
| 2862 | { "Blue Scale", -200, 95, 200, 1, slider_blue_scale }, |
| 2863 | { "Red Gamma", -80, 16, 80, 1, slider_red_power }, |
| 2864 | { "Green Gamma", -80, 16, 80, 1, slider_green_power }, |
| 2865 | { "Blue Gamma", -80, 16, 80, 1, slider_blue_power }, |
| 2866 | { "Red Floor", 0, 5, 100, 1, slider_red_floor }, |
| 2867 | { "Green Floor", 0, 5, 100, 1, slider_green_floor }, |
| 2868 | { "Blue Floor", 0, 5, 100, 1, slider_blue_floor }, |
| 2869 | { "Red Phosphor Life", 0, 40, 100, 1, slider_red_phosphor_life }, |
| 2870 | { "Green Phosphor Life", 0, 40, 100, 1, slider_green_phosphor_life }, |
| 2871 | { "Blue Phosphor Life", 0, 40, 100, 1, slider_blue_phosphor_life }, |
| 2872 | { "Vector Length Attenuation", 0, 80, 100, 1, slider_vector_attenuation }, |
| 2873 | { "Vector Attenuation Length Limit", 1, 500, 1000, 1, slider_vector_length_max }, |
| 2874 | { "Vector Bloom Scale", 0, 300, 1000, 5, slider_vector_bloom_scale }, |
| 2875 | { "Raster Bloom Scale", 0, 225, 1000, 5, slider_raster_bloom_scale }, |
| 2876 | { "Bloom Level 0 Scale", 0, 100, 100, 1, slider_bloom_lvl0_scale }, |
| 2877 | { "Bloom Level 1 Scale", 0, 21, 100, 1, slider_bloom_lvl1_scale }, |
| 2878 | { "Bloom Level 2 Scale", 0, 19, 100, 1, slider_bloom_lvl2_scale }, |
| 2879 | { "Bloom Level 3 Scale", 0, 17, 100, 1, slider_bloom_lvl3_scale }, |
| 2880 | { "Bloom Level 4 Scale", 0, 15, 100, 1, slider_bloom_lvl4_scale }, |
| 2881 | { "Bloom Level 5 Scale", 0, 14, 100, 1, slider_bloom_lvl5_scale }, |
| 2882 | { "Bloom Level 6 Scale", 0, 13, 100, 1, slider_bloom_lvl6_scale }, |
| 2883 | { "Bloom Level 7 Scale", 0, 12, 100, 1, slider_bloom_lvl7_scale }, |
| 2884 | { "Bloom Level 8 Scale", 0, 11, 100, 1, slider_bloom_lvl8_scale }, |
| 2885 | { "Bloom Level 9 Scale", 0, 10, 100, 1, slider_bloom_lvl9_scale }, |
| 2886 | { "Bloom Level 10 Scale", 0, 9, 100, 1, slider_bloom_lvl10_scale }, |
| 2887 | { NULL, 0, 0, 0, 0, NULL }, |
| 2888 | }; |
| 2889 | |
| 2890 | slider_state *shaders::init_slider_list() |
| 2891 | { |
| 2892 | if (!master_enable || !d3dintf->post_fx_available) |
| 2893 | { |
| 2894 | g_slider_list = NULL; |
| 2895 | return NULL; |
| 2896 | } |
| 2897 | |
| 2898 | slider_state *listhead = NULL; |
| 2899 | slider_state **tailptr = &listhead; |
| 2900 | |
| 2901 | for (int index = 0; s_sliders[index].name != NULL; index++) |
| 2902 | { |
| 2903 | slider_desc *slider = &s_sliders[index]; |
| 2904 | *tailptr = slider_alloc(*machine, slider->name, slider->minval, slider->defval, slider->maxval, slider->step, slider->adjustor, (void*)options); |
| 2905 | tailptr = &(*tailptr)->next; |
| 2906 | } |
| 2907 | |
| 2908 | return listhead; |
| 2909 | } |
| 2910 | |
| 2911 | //============================================================ |
| 2912 | // uniform functions |
| 2913 | //============================================================ |
| 2914 | |
| 2915 | uniform::uniform(effect *shader, const char *name, uniform_type type, int id) |
| 2916 | { |
| 2917 | m_shader = shader; |
| 2918 | m_type = type; |
| 2919 | m_next = NULL; |
| 2920 | m_handle = m_shader->get_parameter(NULL, name); |
| 2921 | m_ival = 0; |
| 2922 | memset(m_vec, 0, sizeof(float) * 4); |
| 2923 | m_mval = NULL; |
| 2924 | m_texture = NULL; |
| 2925 | m_id = id; |
| 2926 | |
| 2927 | switch (type) |
| 2928 | { |
| 2929 | case UT_INT: |
| 2930 | case UT_FLOAT: |
| 2931 | case UT_MATRIX: |
| 2932 | case UT_SAMPLER: |
| 2933 | m_count = 1; |
| 2934 | break; |
| 2935 | case UT_VEC2: |
| 2936 | m_count = 2; |
| 2937 | break; |
| 2938 | case UT_VEC3: |
| 2939 | m_count = 3; |
| 2940 | break; |
| 2941 | case UT_VEC4: |
| 2942 | m_count = 4; |
| 2943 | break; |
| 2944 | default: |
| 2945 | m_count = 1; |
| 2946 | break; |
| 2947 | } |
| 2948 | } |
| 2949 | |
| 2950 | void uniform::set_next(uniform *next) |
| 2951 | { |
| 2952 | m_next = next; |
| 2953 | } |
| 2954 | |
| 2955 | void uniform::update() |
| 2956 | { |
| 2957 | if (m_id >= CU_COUNT) |
| 2958 | { |
| 2959 | return; |
| 2960 | } |
| 2961 | |
| 2962 | shaders *shadersys = m_shader->m_shaders; |
| 2963 | hlsl_options *options = shadersys->options; |
| 2964 | renderer *d3d = shadersys->d3d; |
| 2965 | |
| 2966 | |
| 2967 | switch(m_id) |
| 2968 | { |
| 2969 | case CU_SCREEN_DIMS: |
| 2970 | { |
| 2971 | vec2f screendims = d3d->get_dims(); |
| 2972 | m_shader->set_vector("ScreenDims", 2, &screendims.c.x); |
| 2973 | break; |
| 2974 | } |
| 2975 | case CU_SOURCE_DIMS: |
| 2976 | { |
| 2977 | vec2f& sourcedims = shadersys->curr_texture->get_rawdims(); |
| 2978 | m_shader->set_vector("SourceDims", 2, &sourcedims.c.x); |
| 2979 | break; |
| 2980 | } |
| 2981 | case CU_SOURCE_RECT: |
| 2982 | { |
| 2983 | vec2f delta = shadersys->curr_texture->get_uvstop() - shadersys->curr_texture->get_uvstart(); |
| 2984 | m_shader->set_vector("SourceRect", 2, &delta.c.x); |
| 2985 | break; |
| 2986 | } |
| 2987 | |
| 2988 | case CU_NTSC_CCFREQ: |
| 2989 | m_shader->set_float("CCValue", options->yiq_cc); |
| 2990 | break; |
| 2991 | case CU_NTSC_A: |
| 2992 | m_shader->set_float("AValue", options->yiq_a); |
| 2993 | break; |
| 2994 | case CU_NTSC_B: |
| 2995 | m_shader->set_float("BValue", options->yiq_b); |
| 2996 | break; |
| 2997 | case CU_NTSC_O: |
| 2998 | m_shader->set_float("OValue", options->yiq_o); |
| 2999 | break; |
| 3000 | case CU_NTSC_P: |
| 3001 | m_shader->set_float("PValue", options->yiq_p); |
| 3002 | break; |
| 3003 | case CU_NTSC_NOTCH: |
| 3004 | m_shader->set_float("NotchHalfWidth", options->yiq_n); |
| 3005 | break; |
| 3006 | case CU_NTSC_YFREQ: |
| 3007 | m_shader->set_float("YFreqResponse", options->yiq_y); |
| 3008 | break; |
| 3009 | case CU_NTSC_IFREQ: |
| 3010 | m_shader->set_float("IFreqResponse", options->yiq_i); |
| 3011 | break; |
| 3012 | case CU_NTSC_QFREQ: |
| 3013 | m_shader->set_float("QFreqResponse", options->yiq_q); |
| 3014 | break; |
| 3015 | case CU_NTSC_HTIME: |
| 3016 | m_shader->set_float("ScanTime", options->yiq_scan_time); |
| 3017 | break; |
| 3018 | case CU_NTSC_ENABLE: |
| 3019 | m_shader->set_float("YIQEnable", options->yiq_enable ? 1.0f : 0.0f); |
| 3020 | break; |
| 3021 | |
| 3022 | case CU_COLOR_RED_RATIOS: |
| 3023 | m_shader->set_vector("RedRatios", 3, options->red_ratio); |
| 3024 | break; |
| 3025 | case CU_COLOR_GRN_RATIOS: |
| 3026 | m_shader->set_vector("GrnRatios", 3, options->grn_ratio); |
| 3027 | break; |
| 3028 | case CU_COLOR_BLU_RATIOS: |
| 3029 | m_shader->set_vector("BluRatios", 3, options->blu_ratio); |
| 3030 | break; |
| 3031 | case CU_COLOR_OFFSET: |
| 3032 | m_shader->set_vector("Offset", 3, options->offset); |
| 3033 | break; |
| 3034 | case CU_COLOR_SCALE: |
| 3035 | m_shader->set_vector("Scale", 3, options->scale); |
| 3036 | break; |
| 3037 | case CU_COLOR_SATURATION: |
| 3038 | m_shader->set_float("Saturation", options->saturation); |
| 3039 | break; |
| 3040 | |
| 3041 | case CU_CONVERGE_LINEAR_X: |
| 3042 | m_shader->set_vector("ConvergeX", 3, options->converge_x); |
| 3043 | break; |
| 3044 | case CU_CONVERGE_LINEAR_Y: |
| 3045 | m_shader->set_vector("ConvergeY", 3, options->converge_y); |
| 3046 | break; |
| 3047 | case CU_CONVERGE_RADIAL_X: |
| 3048 | m_shader->set_vector("RadialConvergeX", 3, options->radial_converge_x); |
| 3049 | break; |
| 3050 | case CU_CONVERGE_RADIAL_Y: |
| 3051 | m_shader->set_vector("RadialConvergeY", 3, options->radial_converge_y); |
| 3052 | break; |
| 3053 | |
| 3054 | case CU_FOCUS_SIZE: |
| 3055 | m_shader->set_vector("Defocus", 2, &options->defocus[0]); |
| 3056 | break; |
| 3057 | |
| 3058 | case CU_PHOSPHOR_LIFE: |
| 3059 | m_shader->set_vector("Phosphor", 3, options->phosphor); |
| 3060 | break; |
| 3061 | case CU_PHOSPHOR_IGNORE: |
| 3062 | m_shader->set_float("Passthrough", shadersys->phosphor_passthrough ? 1.0f : 0.0f); |
| 3063 | break; |
| 3064 | |
| 3065 | case CU_POST_PINCUSHION: |
| 3066 | m_shader->set_float("PincushionAmount", options->pincushion); |
| 3067 | break; |
| 3068 | case CU_POST_CURVATURE: |
| 3069 | m_shader->set_float("CurvatureAmount", options->curvature); |
| 3070 | break; |
| 3071 | case CU_POST_SHADOW_ALPHA: |
| 3072 | m_shader->set_float("ShadowAlpha", shadersys->shadow_texture == NULL ? 0.0f : options->shadow_mask_alpha); |
| 3073 | break; |
| 3074 | case CU_POST_SHADOW_COUNT: |
| 3075 | { |
| 3076 | float shadowcount[2] = { options->shadow_mask_count_x, options->shadow_mask_count_y }; |
| 3077 | m_shader->set_vector("ShadowCount", 2, shadowcount); |
| 3078 | break; |
| 3079 | } |
| 3080 | case CU_POST_SHADOW_UV: |
| 3081 | { |
| 3082 | float shadowuv[2] = { options->shadow_mask_u_size, options->shadow_mask_v_size }; |
| 3083 | m_shader->set_vector("ShadowUV", 2, shadowuv); |
| 3084 | break; |
| 3085 | } |
| 3086 | case CU_POST_SHADOW_DIMS: |
| 3087 | { |
| 3088 | vec2f shadow_dims; |
| 3089 | |
| 3090 | if (shadersys->shadow_texture) |
| 3091 | { |
| 3092 | shadow_dims = shadersys->shadow_texture->get_rawdims(); |
| 3093 | } |
| 3094 | else |
| 3095 | { |
| 3096 | shadow_dims.c.x = 1.0f; |
| 3097 | shadow_dims.c.y = 1.0f; |
| 3098 | } |
| 3099 | |
| 3100 | m_shader->set_vector("ShadowDims", 2, &shadow_dims.c.x); |
| 3101 | break; |
| 3102 | } |
| 3103 | case CU_POST_SCANLINE_ALPHA: |
| 3104 | m_shader->set_float("ScanlineAlpha", options->scanline_alpha); |
| 3105 | break; |
| 3106 | case CU_POST_SCANLINE_SCALE: |
| 3107 | m_shader->set_float("ScanlineScale", options->scanline_scale); |
| 3108 | break; |
| 3109 | case CU_POST_SCANLINE_HEIGHT: |
| 3110 | m_shader->set_float("ScanlineHeight", options->scanline_height); |
| 3111 | break; |
| 3112 | case CU_POST_SCANLINE_BRIGHT_SCALE: |
| 3113 | m_shader->set_float("ScanlineBrightScale", options->scanline_bright_scale); |
| 3114 | break; |
| 3115 | case CU_POST_SCANLINE_BRIGHT_OFFSET: |
| 3116 | m_shader->set_float("ScanlineBrightOffset", options->scanline_bright_offset); |
| 3117 | break; |
| 3118 | case CU_POST_POWER: |
| 3119 | m_shader->set_vector("Power", 3, options->power); |
| 3120 | break; |
| 3121 | case CU_POST_FLOOR: |
| 3122 | m_shader->set_vector("Floor", 3, options->floor); |
| 3123 | break; |
| 3124 | |
| 3125 | case CU_BLOOM_RESCALE: |
| 3126 | m_shader->set_float("BloomRescale", options->raster_bloom_scale); |
| 3127 | break; |
| 3128 | case CU_BLOOM_LVL0123_WEIGHTS: |
| 3129 | { |
| 3130 | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, options->bloom_level2_weight, options->bloom_level3_weight }; |
| 3131 | m_shader->set_vector("Level0123Weight", 4, weight0123); |
| 3132 | break; |
| 3133 | } |
| 3134 | case CU_BLOOM_LVL4567_WEIGHTS: |
| 3135 | { |
| 3136 | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, options->bloom_level6_weight, options->bloom_level7_weight }; |
| 3137 | m_shader->set_vector("Level4567Weight", 4, weight4567); |
| 3138 | break; |
| 3139 | } |
| 3140 | case CU_BLOOM_LVL89A_WEIGHTS: |
| 3141 | { |
| 3142 | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, options->bloom_level10_weight }; |
| 3143 | m_shader->set_vector("Level89AWeight", 3, weight89A); |
| 3144 | break; |
| 3145 | } |
| 3146 | } |
| 3147 | } |
| 3148 | |
| 3149 | void uniform::set(float x, float y, float z, float w) |
| 3150 | { |
| 3151 | m_vec[0] = x; |
| 3152 | m_vec[1] = y; |
| 3153 | m_vec[2] = z; |
| 3154 | m_vec[3] = w; |
| 3155 | } |
| 3156 | |
| 3157 | void uniform::set(float x, float y, float z) |
| 3158 | { |
| 3159 | m_vec[0] = x; |
| 3160 | m_vec[1] = y; |
| 3161 | m_vec[2] = z; |
| 3162 | } |
| 3163 | |
| 3164 | void uniform::set(float x, float y) |
| 3165 | { |
| 3166 | m_vec[0] = x; |
| 3167 | m_vec[1] = y; |
| 3168 | } |
| 3169 | |
| 3170 | void uniform::set(float x) |
| 3171 | { |
| 3172 | m_vec[0] = x; |
| 3173 | } |
| 3174 | |
| 3175 | void uniform::set(int x) |
| 3176 | { |
| 3177 | m_ival = x; |
| 3178 | } |
| 3179 | |
| 3180 | void uniform::set(matrix *mat) |
| 3181 | { |
| 3182 | m_mval = mat; |
| 3183 | } |
| 3184 | |
| 3185 | void uniform::set(texture *tex) |
| 3186 | { |
| 3187 | m_texture = tex; |
| 3188 | } |
| 3189 | |
| 3190 | void uniform::upload() |
| 3191 | { |
| 3192 | switch(m_type) |
| 3193 | { |
| 3194 | case UT_INT: |
| 3195 | m_shader->set_int(m_handle, m_ival); |
| 3196 | break; |
| 3197 | case UT_FLOAT: |
| 3198 | m_shader->set_float(m_handle, m_vec[0]); |
| 3199 | break; |
| 3200 | case UT_VEC2: |
| 3201 | case UT_VEC3: |
| 3202 | case UT_VEC4: |
| 3203 | m_shader->set_vector(m_handle, m_count, m_vec); |
| 3204 | break; |
| 3205 | case UT_MATRIX: |
| 3206 | m_shader->set_matrix(m_handle, m_mval); |
| 3207 | break; |
| 3208 | case UT_SAMPLER: |
| 3209 | m_shader->set_texture(m_handle, m_texture); |
| 3210 | break; |
| 3211 | } |
| 3212 | } |
| 3213 | |
| 3214 | //============================================================ |
| 3215 | // effect functions |
| 3216 | //============================================================ |
| 3217 | |
| 3218 | effect::effect(shaders *shadersys, device *dev, const char *name, const char *path) |
| 3219 | { |
| 3220 | IDirect3DDevice9 *device = (IDirect3DDevice9 *)dev; |
| 3221 | LPD3DXBUFFER buffer_errors = NULL; |
| 3222 | |
| 3223 | m_shaders = shadersys; |
| 3224 | m_uniform_head = NULL; |
| 3225 | m_uniform_tail = NULL; |
| 3226 | m_effect = NULL; |
| 3227 | m_valid = false; |
| 3228 | |
| 3229 | char name_cstr[1024]; |
| 3230 | sprintf(name_cstr, "%s\\%s", path, name); |
| 3231 | TCHAR *effect_name = tstring_from_utf8(name_cstr); |
| 3232 | |
| 3233 | HRESULT hr = (*g_load_effect)(device, effect_name, NULL, NULL, 0, NULL, &m_effect, &buffer_errors); |
| 3234 | if(FAILED(hr)) |
| 3235 | { |
| 3236 | if(buffer_errors != NULL) |
| 3237 | { |
| 3238 | LPVOID compile_errors = buffer_errors->GetBufferPointer(); |
| 3239 | printf("Unable to compile shader: %s\n", (const char*)compile_errors); fflush(stdout); |
| 3240 | } |
| 3241 | else |
| 3242 | { |
| 3243 | printf("Shader %s is missing, corrupt or cannot be compiled.\n", (const char*)name); fflush(stdout); |
| 3244 | } |
| 3245 | } |
| 3246 | else |
| 3247 | { |
| 3248 | m_valid = true; |
| 3249 | } |
| 3250 | |
| 3251 | osd_free(effect_name); |
| 3252 | } |
| 3253 | |
| 3254 | effect::~effect() |
| 3255 | { |
| 3256 | m_effect->Release(); |
| 3257 | m_effect = NULL; |
| 3258 | uniform *curr = m_uniform_head; |
| 3259 | while (curr != NULL) |
| 3260 | { |
| 3261 | uniform *next = curr->get_next(); |
| 3262 | delete curr; |
| 3263 | curr = next; |
| 3264 | } |
| 3265 | m_uniform_head = NULL; |
| 3266 | m_uniform_tail = NULL; |
| 3267 | } |
| 3268 | |
| 3269 | void effect::add_uniform(const char *name, uniform::uniform_type type, int id) |
| 3270 | { |
| 3271 | uniform *newuniform = new uniform(this, name, type, id); |
| 3272 | if (newuniform == NULL) |
| 3273 | { |
| 3274 | return; |
| 3275 | } |
| 3276 | |
| 3277 | if (m_uniform_head == NULL) |
| 3278 | { |
| 3279 | m_uniform_head = newuniform; |
| 3280 | } |
| 3281 | if (m_uniform_tail != NULL) |
| 3282 | { |
| 3283 | m_uniform_tail->set_next(newuniform); |
| 3284 | } |
| 3285 | m_uniform_tail = newuniform; |
| 3286 | } |
| 3287 | |
| 3288 | void effect::update_uniforms() |
| 3289 | { |
| 3290 | uniform *curr = m_uniform_head; |
| 3291 | while(curr != NULL) |
| 3292 | { |
| 3293 | curr->update(); |
| 3294 | curr = curr->get_next(); |
| 3295 | } |
| 3296 | } |
| 3297 | |
| 3298 | void effect::begin(UINT *passes, DWORD flags) |
| 3299 | { |
| 3300 | m_effect->Begin(passes, flags); |
| 3301 | } |
| 3302 | |
| 3303 | void effect::end() |
| 3304 | { |
| 3305 | m_effect->End(); |
| 3306 | } |
| 3307 | |
| 3308 | void effect::begin_pass(UINT pass) |
| 3309 | { |
| 3310 | m_effect->BeginPass(pass); |
| 3311 | } |
| 3312 | |
| 3313 | void effect::end_pass() |
| 3314 | { |
| 3315 | m_effect->EndPass(); |
| 3316 | } |
| 3317 | |
| 3318 | void effect::set_technique(const char *name) |
| 3319 | { |
| 3320 | m_effect->SetTechnique(name); |
| 3321 | } |
| 3322 | |
| 3323 | void effect::set_vector(D3DXHANDLE param, int count, float *vector) |
| 3324 | { |
| 3325 | static D3DXVECTOR4 out_vector; |
| 3326 | if (count > 0) |
| 3327 | out_vector.x = vector[0]; |
| 3328 | if (count > 1) |
| 3329 | out_vector.y = vector[1]; |
| 3330 | if (count > 2) |
| 3331 | out_vector.z = vector[2]; |
| 3332 | if (count > 3) |
| 3333 | out_vector.w = vector[3]; |
| 3334 | m_effect->SetVector(param, &out_vector); |
| 3335 | } |
| 3336 | |
| 3337 | void effect::set_float(D3DXHANDLE param, float value) |
| 3338 | { |
| 3339 | m_effect->SetFloat(param, value); |
| 3340 | } |
| 3341 | |
| 3342 | void effect::set_int(D3DXHANDLE param, int value) |
| 3343 | { |
| 3344 | m_effect->SetInt(param, value); |
| 3345 | } |
| 3346 | |
| 3347 | void effect::set_matrix(D3DXHANDLE param, matrix *matrix) |
| 3348 | { |
| 3349 | m_effect->SetMatrix(param, (D3DXMATRIX*)matrix); |
| 3350 | } |
| 3351 | |
| 3352 | void effect::set_texture(D3DXHANDLE param, texture *tex) |
| 3353 | { |
| 3354 | m_effect->SetTexture(param, (IDirect3DTexture9*)tex); |
| 3355 | } |
| 3356 | |
| 3357 | D3DXHANDLE effect::get_parameter(D3DXHANDLE param, const char *name) |
| 3358 | { |
| 3359 | return m_effect->GetParameterByName(param, name); |
| 3360 | } |
| 3361 | |
| 3362 | ULONG effect::release() |
| 3363 | { |
| 3364 | return m_effect->Release(); |
| 3365 | } |
| 3366 | |
| 3367 | }; |
| 3368 | |
| 3369 | //============================================================ |
| 3370 | // get_slider_list |
| 3371 | //============================================================ |
| 3372 | |
| 3373 | void *windows_osd_interface::get_slider_list() |
| 3374 | { |
| 3375 | return (void*)g_slider_list; |
| 3376 | } |
| 3377 | |
| 3378 | |
| 3379 | |
| 3380 | // NOTE: The function below is taken directly from src/emu/video.c and should likely be moved into a global helper function. |
| 3381 | //------------------------------------------------- |
| 3382 | // open_next - open the next non-existing file of |
| 3383 | // type filetype according to our numbering |
| 3384 | // scheme |
| 3385 | //------------------------------------------------- |
| 3386 | |
| 3387 | static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx) |
| 3388 | { |
| 3389 | UINT32 origflags = file.openflags(); |
| 3390 | |
| 3391 | // handle defaults |
| 3392 | const char *snapname = templ ? templ : d3d->window().machine().options().snap_name(); |
| 3393 | |
| 3394 | if (snapname == NULL || snapname[0] == 0) |
| 3395 | snapname = "%g/%i"; |
| 3396 | astring snapstr(snapname); |
| 3397 | |
| 3398 | // strip any extension in the provided name |
| 3399 | int index = snapstr.rchr(0, '.'); |
| 3400 | if (index != -1) |
| 3401 | snapstr.substr(0, index); |
| 3402 | |
| 3403 | // handle %d in the template (for image devices) |
| 3404 | astring snapdev("%d_"); |
| 3405 | int pos = snapstr.find(0, snapdev); |
| 3406 | |
| 3407 | if (pos != -1) |
| 3408 | { |
| 3409 | // if more %d are found, revert to default and ignore them all |
| 3410 | if (snapstr.find(pos + 3, snapdev) != -1) |
| 3411 | snapstr.cpy("%g/%i"); |
| 3412 | // else if there is a single %d, try to create the correct snapname |
| 3413 | else |
| 3414 | { |
| 3415 | int name_found = 0; |
| 3416 | |
| 3417 | // find length of the device name |
| 3418 | int end1 = snapstr.find(pos + 3, "/"); |
| 3419 | int end2 = snapstr.find(pos + 3, "%"); |
| 3420 | int end = -1; |
| 3421 | |
| 3422 | if ((end1 != -1) && (end2 != -1)) |
| 3423 | end = MIN(end1, end2); |
| 3424 | else if (end1 != -1) |
| 3425 | end = end1; |
| 3426 | else if (end2 != -1) |
| 3427 | end = end2; |
| 3428 | else |
| 3429 | end = snapstr.len(); |
| 3430 | |
| 3431 | if (end - pos < 3) |
| 3432 | fatalerror("Something very wrong is going on!!!\n"); |
| 3433 | |
| 3434 | // copy the device name to an astring |
| 3435 | astring snapdevname; |
| 3436 | snapdevname.cpysubstr(snapstr, pos + 3, end - pos - 3); |
| 3437 | |
| 3438 | // verify that there is such a device for this system |
| 3439 | image_interface_iterator iter(d3d->window().machine().root_device()); |
| 3440 | for (device_image_interface *image = iter.first(); image != NULL; iter.next()) |
| 3441 | { |
| 3442 | // get the device name |
| 3443 | astring tempdevname(image->brief_instance_name()); |
| 3444 | |
| 3445 | if (snapdevname.cmp(tempdevname) == 0) |
| 3446 | { |
| 3447 | // verify that such a device has an image mounted |
| 3448 | if (image->basename() != NULL) |
| 3449 | { |
| 3450 | astring filename(image->basename()); |
| 3451 | |
| 3452 | // strip extension |
| 3453 | filename.substr(0, filename.rchr(0, '.')); |
| 3454 | |
| 3455 | // setup snapname and remove the %d_ |
| 3456 | snapstr.replace(0, snapdevname, filename); |
| 3457 | snapstr.del(pos, 3); |
| 3458 | |
| 3459 | name_found = 1; |
| 3460 | } |
| 3461 | } |
| 3462 | } |
| 3463 | |
| 3464 | // or fallback to default |
| 3465 | if (name_found == 0) |
| 3466 | snapstr.cpy("%g/%i"); |
| 3467 | } |
| 3468 | } |
| 3469 | |
| 3470 | // add our own index |
| 3471 | // add our own extension |
| 3472 | snapstr.cat(".").cat(extension); |
| 3473 | |
| 3474 | // substitute path and gamename up front |
| 3475 | snapstr.replace(0, "/", PATH_SEPARATOR); |
| 3476 | snapstr.replace(0, "%g", d3d->window().machine().basename()); |
| 3477 | |
| 3478 | // determine if the template has an index; if not, we always use the same name |
| 3479 | astring fname; |
| 3480 | if (snapstr.find(0, "%i") == -1) |
| 3481 | fname.cpy(snapstr); |
| 3482 | |
| 3483 | // otherwise, we scan for the next available filename |
| 3484 | else |
| 3485 | { |
| 3486 | // try until we succeed |
| 3487 | astring seqtext; |
| 3488 | file.set_openflags(OPEN_FLAG_READ); |
| 3489 | for (int seq = 0; ; seq++) |
| 3490 | { |
| 3491 | // build up the filename |
| 3492 | fname.cpy(snapstr).replace(0, "%i", seqtext.format("%04d_%d", seq, idx).cstr()); |
| 3493 | |
| 3494 | // try to open the file; stop when we fail |
| 3495 | file_error filerr = file.open(fname); |
| 3496 | if (filerr != FILERR_NONE) |
| 3497 | break; |
| 3498 | } |
| 3499 | } |
| 3500 | |
| 3501 | // create the final file |
| 3502 | file.set_openflags(origflags); |
| 3503 | return file.open(fname); |
| 3504 | } |
trunk/src/osd/modules/render/draw13.c
| r0 | r244652 | |
| 1 | //============================================================ |
| 2 | // |
| 3 | // draw13.c - SDL 2.0 drawing implementation |
| 4 | // |
| 5 | // Copyright (c) 1996-2014, Nicola Salmoria and the MAME Team. |
| 6 | // Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | // |
| 8 | // SDLMAME by Olivier Galibert and R. Belmont |
| 9 | // |
| 10 | //============================================================ |
| 11 | |
| 12 | // standard C headers |
| 13 | #include <math.h> |
| 14 | #include <stdio.h> |
| 15 | |
| 16 | // MAME headers |
| 17 | #include "emu.h" |
| 18 | #include "options.h" |
| 19 | |
| 20 | // standard SDL headers |
| 21 | #include "sdlinc.h" |
| 22 | |
| 23 | // OSD headers |
| 24 | #include "osdsdl.h" |
| 25 | #include "window.h" |
| 26 | |
| 27 | |
| 28 | //============================================================ |
| 29 | // DEBUGGING |
| 30 | //============================================================ |
| 31 | |
| 32 | //============================================================ |
| 33 | // CONSTANTS |
| 34 | //============================================================ |
| 35 | |
| 36 | #define STAT_PIXEL_THRESHOLD (150*150) |
| 37 | |
| 38 | enum |
| 39 | { |
| 40 | TEXTURE_TYPE_NONE, |
| 41 | TEXTURE_TYPE_PLAIN, |
| 42 | TEXTURE_TYPE_SURFACE |
| 43 | }; |
| 44 | |
| 45 | |
| 46 | //============================================================ |
| 47 | // Inline functions |
| 48 | //============================================================ |
| 49 | |
| 50 | static inline bool is_opaque(const float &a) |
| 51 | { |
| 52 | return (a >= 1.0f); |
| 53 | } |
| 54 | |
| 55 | static inline bool is_transparent(const float &a) |
| 56 | { |
| 57 | return (a < 0.0001f); |
| 58 | } |
| 59 | |
| 60 | //============================================================ |
| 61 | // TYPES |
| 62 | //============================================================ |
| 63 | |
| 64 | |
| 65 | struct quad_setup_data |
| 66 | { |
| 67 | quad_setup_data() |
| 68 | : dudx(0), dvdx(0), dudy(0), dvdy(0), startu(0), startv(0), |
| 69 | rotwidth(0), rotheight(0) |
| 70 | {} |
| 71 | void compute(const render_primitive &prim, const int prescale); |
| 72 | |
| 73 | INT32 dudx, dvdx, dudy, dvdy; |
| 74 | INT32 startu, startv; |
| 75 | INT32 rotwidth, rotheight; |
| 76 | }; |
| 77 | |
| 78 | //============================================================ |
| 79 | // Textures |
| 80 | //============================================================ |
| 81 | |
| 82 | class sdl_info13; |
| 83 | struct copy_info_t; |
| 84 | |
| 85 | /* texture_info holds information about a texture */ |
| 86 | class texture_info |
| 87 | { |
| 88 | friend class simple_list<texture_info>; |
| 89 | public: |
| 90 | texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const UINT32 flags); |
| 91 | ~texture_info(); |
| 92 | |
| 93 | void set_data(const render_texinfo &texsource, const UINT32 flags); |
| 94 | void render_quad(const render_primitive *prim, const int x, const int y); |
| 95 | bool matches(const render_primitive &prim, const quad_setup_data &setup); |
| 96 | |
| 97 | copy_info_t *compute_size_type(); |
| 98 | |
| 99 | void *m_pixels; // pixels for the texture |
| 100 | int m_pitch; |
| 101 | |
| 102 | copy_info_t *m_copyinfo; |
| 103 | quad_setup_data m_setup; |
| 104 | |
| 105 | osd_ticks_t m_last_access; |
| 106 | |
| 107 | int raw_width() const { return m_texinfo.width; } |
| 108 | int raw_height() const { return m_texinfo.height; } |
| 109 | |
| 110 | texture_info *next() { return m_next; } |
| 111 | const render_texinfo &texinfo() const { return m_texinfo; } |
| 112 | render_texinfo &texinfo() { return m_texinfo; } |
| 113 | |
| 114 | const HashT hash() const { return m_hash; } |
| 115 | const UINT32 flags() const { return m_flags; } |
| 116 | // FIXME: |
| 117 | const bool is_pixels_owned() const; |
| 118 | |
| 119 | private: |
| 120 | Uint32 m_sdl_access; |
| 121 | SDL_Renderer * m_sdl_renderer; |
| 122 | render_texinfo m_texinfo; // copy of the texture info |
| 123 | HashT m_hash; // hash value for the texture (must be >= pointer size) |
| 124 | UINT32 m_flags; // rendering flags |
| 125 | |
| 126 | SDL_Texture * m_texture_id; |
| 127 | bool m_is_rotated; |
| 128 | |
| 129 | int m_format; // texture format |
| 130 | SDL_BlendMode m_sdl_blendmode; |
| 131 | |
| 132 | texture_info * m_next; // next texture in the list |
| 133 | }; |
| 134 | |
| 135 | //============================================================ |
| 136 | // TEXCOPY FUNCS |
| 137 | //============================================================ |
| 138 | |
| 139 | #include "blit13.h" |
| 140 | |
| 141 | /* sdl_info is the information about SDL for the current screen */ |
| 142 | class sdl_info13 : public osd_renderer |
| 143 | { |
| 144 | public: |
| 145 | sdl_info13(osd_window *w) |
| 146 | : osd_renderer(w, FLAG_NONE), m_blittimer(0), m_sdl_renderer(NULL), |
| 147 | m_last_hofs(0), m_last_vofs(0), |
| 148 | m_width(0), m_height(0), |
| 149 | m_blit_dim(0,0), |
| 150 | m_last_blit_time(0), m_last_blit_pixels(0) |
| 151 | {} |
| 152 | |
| 153 | /* virtual */ int create(); |
| 154 | /* virtual */ int draw(const int update); |
| 155 | /* virtual */ int xy_to_render_target(const int x, const int y, int *xt, int *yt); |
| 156 | /* virtual */ void destroy(); |
| 157 | /* virtual */ render_primitive_list *get_primitives() |
| 158 | { |
| 159 | osd_dim nd = window().blit_surface_size(); |
| 160 | if (nd != m_blit_dim) |
| 161 | { |
| 162 | m_blit_dim = nd; |
| 163 | notify_changed(); |
| 164 | } |
| 165 | window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); |
| 166 | return &window().target()->get_primitives(); |
| 167 | } |
| 168 | |
| 169 | private: |
| 170 | void render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y); |
| 171 | |
| 172 | texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); |
| 173 | texture_info *texture_update(const render_primitive &prim); |
| 174 | |
| 175 | void destroy_all_textures(); |
| 176 | |
| 177 | INT32 m_blittimer; |
| 178 | |
| 179 | #if (SDLMAME_SDL2) |
| 180 | //SDL_GLContext m_gl_context_id; |
| 181 | #else |
| 182 | // SDL surface |
| 183 | SDL_Surface *m_sdlsurf; |
| 184 | #endif |
| 185 | |
| 186 | SDL_Renderer * m_sdl_renderer; |
| 187 | simple_list<texture_info> m_texlist; // list of active textures |
| 188 | |
| 189 | float m_last_hofs; |
| 190 | float m_last_vofs; |
| 191 | |
| 192 | int m_width; |
| 193 | int m_height; |
| 194 | |
| 195 | osd_dim m_blit_dim; |
| 196 | |
| 197 | // Stats |
| 198 | INT64 m_last_blit_time; |
| 199 | INT64 m_last_blit_pixels; |
| 200 | }; |
| 201 | |
| 202 | struct copy_info_t { |
| 203 | int src_fmt; |
| 204 | Uint32 dst_fmt; |
| 205 | const blit_base *blitter; |
| 206 | Uint32 bm_mask; |
| 207 | const char *srcname; |
| 208 | const char *dstname; |
| 209 | /* Statistics */ |
| 210 | UINT64 pixel_count; |
| 211 | INT64 time; |
| 212 | int samples; |
| 213 | int perf; |
| 214 | /* list */ |
| 215 | copy_info_t *next; |
| 216 | }; |
| 217 | |
| 218 | |
| 219 | //============================================================ |
| 220 | // PROTOTYPES |
| 221 | //============================================================ |
| 222 | |
| 223 | // core functions |
| 224 | |
| 225 | static void drawsdl2_exit(void); |
| 226 | |
| 227 | //============================================================ |
| 228 | // STATIC VARIABLES |
| 229 | //============================================================ |
| 230 | |
| 231 | #define SDL_TEXFORMAT_LAST SDL_TEXFORMAT_PALETTE16A |
| 232 | #define BM_ALL (-1) |
| 233 | //( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD) |
| 234 | |
| 235 | #define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} |
| 236 | #define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} |
| 237 | #define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} |
| 238 | |
| 239 | static copy_info_t blit_info_default[] = |
| 240 | { |
| 241 | /* no rotation */ |
| 242 | ENTRY(ARGB32, ARGB8888, argb32_argb32), |
| 243 | ENTRY_LR(ARGB32, RGB888, argb32_rgb32), |
| 244 | /* Entry primarily for directfb */ |
| 245 | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), |
| 246 | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), |
| 247 | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), |
| 248 | |
| 249 | ENTRY(RGB32, ARGB8888, rgb32_argb32), |
| 250 | ENTRY(RGB32, RGB888, rgb32_rgb32), |
| 251 | |
| 252 | ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), |
| 253 | ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), |
| 254 | |
| 255 | ENTRY(YUY16, UYVY, yuv16_uyvy), |
| 256 | ENTRY(YUY16, YUY2, yuv16_yuy2), |
| 257 | ENTRY(YUY16, YVYU, yuv16_yvyu), |
| 258 | ENTRY(YUY16, ARGB8888, yuv16_argb32), |
| 259 | ENTRY(YUY16, RGB888, yuv16_argb32), |
| 260 | |
| 261 | ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), |
| 262 | ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), |
| 263 | ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), |
| 264 | ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), |
| 265 | ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), |
| 266 | |
| 267 | ENTRY(PALETTE16, ARGB8888, pal16_argb32), |
| 268 | ENTRY(PALETTE16, RGB888, pal16_argb32), |
| 269 | |
| 270 | ENTRY(RGB15, RGB555, rgb15_rgb555), |
| 271 | ENTRY(RGB15, ARGB1555, rgb15_argb1555), |
| 272 | ENTRY(RGB15, ARGB8888, rgb15_argb32), |
| 273 | ENTRY(RGB15, RGB888, rgb15_argb32), |
| 274 | |
| 275 | ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), |
| 276 | ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), |
| 277 | |
| 278 | ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), |
| 279 | ENTRY(PALETTE16A, RGB888, pal16a_rgb32), |
| 280 | |
| 281 | /* rotation */ |
| 282 | ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), |
| 283 | ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), |
| 284 | /* Entry primarily for directfb */ |
| 285 | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), |
| 286 | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), |
| 287 | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), |
| 288 | |
| 289 | ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), |
| 290 | ENTRY(RGB32, RGB888, rot_argb32_argb32), |
| 291 | |
| 292 | ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), |
| 293 | ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), |
| 294 | |
| 295 | ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), |
| 296 | ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), |
| 297 | |
| 298 | ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), |
| 299 | ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), |
| 300 | |
| 301 | ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), |
| 302 | ENTRY(PALETTE16, RGB888, rot_pal16_argb32), |
| 303 | |
| 304 | ENTRY(RGB15, RGB555, rot_rgb15_argb1555), |
| 305 | ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), |
| 306 | ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), |
| 307 | ENTRY(RGB15, RGB888, rot_rgb15_argb32), |
| 308 | |
| 309 | ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), |
| 310 | ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), |
| 311 | |
| 312 | ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), |
| 313 | ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), |
| 314 | |
| 315 | { -1 }, |
| 316 | }; |
| 317 | |
| 318 | static copy_info_t *blit_info[SDL_TEXFORMAT_LAST+1]; |
| 319 | |
| 320 | static struct |
| 321 | { |
| 322 | Uint32 format; |
| 323 | int status; |
| 324 | } fmt_support[30] = { { 0, 0 } }; |
| 325 | |
| 326 | |
| 327 | //============================================================ |
| 328 | // INLINES |
| 329 | //============================================================ |
| 330 | |
| 331 | |
| 332 | INLINE float round_nearest(float f) |
| 333 | { |
| 334 | return floor(f + 0.5f); |
| 335 | } |
| 336 | |
| 337 | INLINE HashT texture_compute_hash(const render_texinfo &texture, const UINT32 flags) |
| 338 | { |
| 339 | return (HashT)texture.base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 340 | } |
| 341 | |
| 342 | INLINE SDL_BlendMode map_blendmode(const int blendmode) |
| 343 | { |
| 344 | switch (blendmode) |
| 345 | { |
| 346 | case BLENDMODE_NONE: |
| 347 | return SDL_BLENDMODE_NONE; |
| 348 | case BLENDMODE_ALPHA: |
| 349 | return SDL_BLENDMODE_BLEND; |
| 350 | case BLENDMODE_RGB_MULTIPLY: |
| 351 | return SDL_BLENDMODE_MOD; |
| 352 | case BLENDMODE_ADD: |
| 353 | return SDL_BLENDMODE_ADD; |
| 354 | default: |
| 355 | osd_printf_warning("Unknown Blendmode %d", blendmode); |
| 356 | } |
| 357 | return SDL_BLENDMODE_NONE; |
| 358 | } |
| 359 | |
| 360 | INLINE void set_coloralphamode(SDL_Texture *texture_id, const render_color *color) |
| 361 | { |
| 362 | UINT32 sr = (UINT32)(255.0f * color->r); |
| 363 | UINT32 sg = (UINT32)(255.0f * color->g); |
| 364 | UINT32 sb = (UINT32)(255.0f * color->b); |
| 365 | UINT32 sa = (UINT32)(255.0f * color->a); |
| 366 | |
| 367 | |
| 368 | if (color->r >= 1.0f && color->g >= 1.0f && color->b >= 1.0f && is_opaque(color->a)) |
| 369 | { |
| 370 | SDL_SetTextureColorMod(texture_id, 0xFF, 0xFF, 0xFF); |
| 371 | SDL_SetTextureAlphaMod(texture_id, 0xFF); |
| 372 | } |
| 373 | /* coloring-only case */ |
| 374 | else if (is_opaque(color->a)) |
| 375 | { |
| 376 | SDL_SetTextureColorMod(texture_id, sr, sg, sb); |
| 377 | SDL_SetTextureAlphaMod(texture_id, 0xFF); |
| 378 | } |
| 379 | /* alpha and/or coloring case */ |
| 380 | else if (!is_transparent(color->a)) |
| 381 | { |
| 382 | SDL_SetTextureColorMod(texture_id, sr, sg, sb); |
| 383 | SDL_SetTextureAlphaMod(texture_id, sa); |
| 384 | } |
| 385 | else |
| 386 | { |
| 387 | SDL_SetTextureColorMod(texture_id, 0xFF, 0xFF, 0xFF); |
| 388 | SDL_SetTextureAlphaMod(texture_id, 0x00); |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | void texture_info::render_quad(const render_primitive *prim, const int x, const int y) |
| 393 | { |
| 394 | SDL_Rect target_rect; |
| 395 | |
| 396 | target_rect.x = x; |
| 397 | target_rect.y = y; |
| 398 | target_rect.w = round_nearest(prim->bounds.x1 - prim->bounds.x0); |
| 399 | target_rect.h = round_nearest(prim->bounds.y1 - prim->bounds.y0); |
| 400 | |
| 401 | SDL_SetTextureBlendMode(m_texture_id, m_sdl_blendmode); |
| 402 | set_coloralphamode(m_texture_id, &prim->color); |
| 403 | SDL_RenderCopy(m_sdl_renderer, m_texture_id, NULL, &target_rect); |
| 404 | } |
| 405 | |
| 406 | void sdl_info13::render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y) |
| 407 | { |
| 408 | SDL_Rect target_rect; |
| 409 | |
| 410 | target_rect.x = x; |
| 411 | target_rect.y = y; |
| 412 | target_rect.w = round_nearest(prim->bounds.x1 - prim->bounds.x0); |
| 413 | target_rect.h = round_nearest(prim->bounds.y1 - prim->bounds.y0); |
| 414 | |
| 415 | if (texture) |
| 416 | { |
| 417 | copy_info_t *copyinfo = texture->m_copyinfo; |
| 418 | copyinfo->time -= osd_ticks(); |
| 419 | texture->render_quad(prim, x, y); |
| 420 | copyinfo->time += osd_ticks(); |
| 421 | |
| 422 | copyinfo->pixel_count += MAX(STAT_PIXEL_THRESHOLD , (texture->raw_width() * texture->raw_height())); |
| 423 | if (m_last_blit_pixels) |
| 424 | { |
| 425 | copyinfo->time += (m_last_blit_time * (INT64) (texture->raw_width() * texture->raw_height())) / (INT64) m_last_blit_pixels; |
| 426 | } |
| 427 | copyinfo->samples++; |
| 428 | copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time; |
| 429 | } |
| 430 | else |
| 431 | { |
| 432 | UINT32 sr = (UINT32)(255.0f * prim->color.r); |
| 433 | UINT32 sg = (UINT32)(255.0f * prim->color.g); |
| 434 | UINT32 sb = (UINT32)(255.0f * prim->color.b); |
| 435 | UINT32 sa = (UINT32)(255.0f * prim->color.a); |
| 436 | |
| 437 | SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
| 438 | SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa); |
| 439 | SDL_RenderFillRect(m_sdl_renderer, &target_rect); |
| 440 | } |
| 441 | } |
| 442 | |
| 443 | static int RendererSupportsFormat(SDL_Renderer *renderer, Uint32 format, Uint32 access, const char *sformat) |
| 444 | { |
| 445 | int i; |
| 446 | SDL_Texture *texid; |
| 447 | for (i=0; fmt_support[i].format != 0; i++) |
| 448 | { |
| 449 | if (format == fmt_support[i].format) |
| 450 | { |
| 451 | return fmt_support[i].status; |
| 452 | } |
| 453 | } |
| 454 | /* not tested yet */ |
| 455 | fmt_support[i].format = format; |
| 456 | fmt_support[i + 1].format = 0; |
| 457 | texid = SDL_CreateTexture(renderer, format, access, 16, 16); |
| 458 | if (texid) |
| 459 | { |
| 460 | fmt_support[i].status = 1; |
| 461 | SDL_DestroyTexture(texid); |
| 462 | return 1; |
| 463 | } |
| 464 | osd_printf_verbose("Pixelformat <%s> error %s \n", sformat, SDL_GetError()); |
| 465 | osd_printf_verbose("Pixelformat <%s> not supported\n", sformat); |
| 466 | fmt_support[i].status = 0; |
| 467 | return 0; |
| 468 | } |
| 469 | |
| 470 | //============================================================ |
| 471 | // drawsdl_init |
| 472 | //============================================================ |
| 473 | |
| 474 | static void add_list(copy_info_t **head, copy_info_t *element, Uint32 bm) |
| 475 | { |
| 476 | copy_info_t *newci = global_alloc(copy_info_t); |
| 477 | *newci = *element; |
| 478 | |
| 479 | newci->bm_mask = bm; |
| 480 | newci->next = *head; |
| 481 | *head = newci; |
| 482 | } |
| 483 | |
| 484 | static void expand_copy_info(copy_info_t *list) |
| 485 | { |
| 486 | copy_info_t *bi; |
| 487 | |
| 488 | for (bi = list; bi->src_fmt != -1; bi++) |
| 489 | { |
| 490 | if (bi->bm_mask == BM_ALL) |
| 491 | { |
| 492 | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE); |
| 493 | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD); |
| 494 | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD); |
| 495 | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND); |
| 496 | } |
| 497 | else |
| 498 | add_list(&blit_info[bi->src_fmt], bi, bi->bm_mask); |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | static osd_renderer *drawsdl2_create(osd_window *window) |
| 503 | { |
| 504 | return global_alloc(sdl_info13(window)); |
| 505 | } |
| 506 | |
| 507 | // FIXME: machine only used to access options. |
| 508 | int drawsdl2_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 509 | { |
| 510 | const char *stemp; |
| 511 | |
| 512 | // fill in the callbacks |
| 513 | callbacks->exit = drawsdl2_exit; |
| 514 | callbacks->create = drawsdl2_create; |
| 515 | |
| 516 | osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); |
| 517 | |
| 518 | expand_copy_info(blit_info_default); |
| 519 | |
| 520 | #if USE_OPENGL |
| 521 | // Load the GL library now - else MT will fail |
| 522 | stemp = downcast<sdl_options &>(machine.options()).gl_lib(); |
| 523 | #else |
| 524 | stemp = NULL; |
| 525 | #endif |
| 526 | if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) == 0) |
| 527 | stemp = NULL; |
| 528 | |
| 529 | // No fatalerror here since not all video drivers support GL ! |
| 530 | if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==NULL |
| 531 | osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); |
| 532 | else |
| 533 | osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); |
| 534 | |
| 535 | return 0; |
| 536 | } |
| 537 | |
| 538 | |
| 539 | //============================================================ |
| 540 | // drawsdl_exit |
| 541 | //============================================================ |
| 542 | |
| 543 | static void drawsdl2_exit(void) |
| 544 | { |
| 545 | int i; |
| 546 | copy_info_t *bi, *freeme; |
| 547 | for (i = 0; i <= SDL_TEXFORMAT_LAST; i++) |
| 548 | for (bi = blit_info[i]; bi != NULL; ) |
| 549 | { |
| 550 | if (bi->pixel_count) |
| 551 | osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname, |
| 552 | bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples, |
| 553 | (int) bi->perf); |
| 554 | freeme = bi; |
| 555 | bi = bi->next; |
| 556 | global_free(freeme); |
| 557 | } |
| 558 | } |
| 559 | |
| 560 | //============================================================ |
| 561 | // sdl_info::create |
| 562 | // a |
| 563 | // a |
| 564 | // a |
| 565 | // a |
| 566 | // a |
| 567 | // a |
| 568 | // a |
| 569 | // a |
| 570 | // a |
| 571 | // a |
| 572 | // a |
| 573 | // a |
| 574 | // a |
| 575 | // a |
| 576 | // a |
| 577 | // a |
| 578 | // a |
| 579 | // a |
| 580 | // a |
| 581 | // a |
| 582 | // a |
| 583 | // a |
| 584 | // a |
| 585 | // a |
| 586 | // a |
| 587 | // a |
| 588 | //============================================================ |
| 589 | |
| 590 | int sdl_info13::create() |
| 591 | { |
| 592 | #if (SDLMAME_SDL2) |
| 593 | // create renderer |
| 594 | |
| 595 | /* Enable bilinear filtering in case it is supported. |
| 596 | * This applies to all texture operations. However, artwort is pre-scaled |
| 597 | * and thus shouldn't be affected. |
| 598 | */ |
| 599 | if (video_config.filter) |
| 600 | { |
| 601 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); |
| 602 | } |
| 603 | else |
| 604 | { |
| 605 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); |
| 606 | } |
| 607 | |
| 608 | if (video_config.waitvsync) |
| 609 | m_sdl_renderer = SDL_CreateRenderer(window().sdl_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); |
| 610 | else |
| 611 | m_sdl_renderer = SDL_CreateRenderer(window().sdl_window(), -1, SDL_RENDERER_ACCELERATED); |
| 612 | |
| 613 | if (!m_sdl_renderer) |
| 614 | { |
| 615 | fatalerror("Error on creating renderer: %s\n", SDL_GetError()); |
| 616 | } |
| 617 | |
| 618 | //SDL_SelectRenderer(window().sdl_window); |
| 619 | |
| 620 | m_blittimer = 3; |
| 621 | |
| 622 | SDL_RenderPresent(m_sdl_renderer); |
| 623 | osd_printf_verbose("Leave sdl_info13::create\n"); |
| 624 | |
| 625 | #else |
| 626 | |
| 627 | #endif |
| 628 | return 0; |
| 629 | } |
| 630 | |
| 631 | |
| 632 | //============================================================ |
| 633 | // sdl_info::destroy |
| 634 | //============================================================ |
| 635 | |
| 636 | void sdl_info13::destroy() |
| 637 | { |
| 638 | destroy_all_textures(); |
| 639 | } |
| 640 | |
| 641 | |
| 642 | //============================================================ |
| 643 | // drawsdl_xy_to_render_target |
| 644 | //============================================================ |
| 645 | |
| 646 | int sdl_info13::xy_to_render_target(int x, int y, int *xt, int *yt) |
| 647 | { |
| 648 | *xt = x - m_last_hofs; |
| 649 | *yt = y - m_last_vofs; |
| 650 | if (*xt<0 || *xt >= m_blit_dim.width()) |
| 651 | return 0; |
| 652 | if (*yt<0 || *yt >= m_blit_dim.height()) |
| 653 | return 0; |
| 654 | return 1; |
| 655 | } |
| 656 | |
| 657 | //============================================================ |
| 658 | // drawsdl_destroy_all_textures |
| 659 | //============================================================ |
| 660 | |
| 661 | void sdl_info13::destroy_all_textures() |
| 662 | { |
| 663 | if(window().m_primlist) |
| 664 | { |
| 665 | window().m_primlist->acquire_lock(); |
| 666 | m_texlist.reset(); |
| 667 | window().m_primlist->release_lock(); |
| 668 | } |
| 669 | else |
| 670 | m_texlist.reset(); |
| 671 | } |
| 672 | |
| 673 | //============================================================ |
| 674 | // sdl_info::draw |
| 675 | //============================================================ |
| 676 | |
| 677 | int sdl_info13::draw(int update) |
| 678 | { |
| 679 | render_primitive *prim; |
| 680 | texture_info *texture=NULL; |
| 681 | float vofs, hofs; |
| 682 | int blit_pixels = 0; |
| 683 | |
| 684 | if (video_config.novideo) |
| 685 | { |
| 686 | return 0; |
| 687 | } |
| 688 | |
| 689 | osd_dim wdim = window().get_size(); |
| 690 | |
| 691 | if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) |
| 692 | { |
| 693 | destroy_all_textures(); |
| 694 | m_width = wdim.width(); |
| 695 | m_height = wdim.height(); |
| 696 | SDL_RenderSetViewport(m_sdl_renderer, NULL); |
| 697 | m_blittimer = 3; |
| 698 | clear_flags(FI_CHANGED); |
| 699 | } |
| 700 | |
| 701 | //SDL_SelectRenderer(window().sdl_window); |
| 702 | |
| 703 | if (m_blittimer > 0) |
| 704 | { |
| 705 | /* SDL Underlays need alpha = 0 ! */ |
| 706 | SDL_SetRenderDrawBlendMode(m_sdl_renderer, SDL_BLENDMODE_NONE); |
| 707 | //SDL_SetRenderDrawColor(0,0,0,255); |
| 708 | SDL_SetRenderDrawColor(m_sdl_renderer, 0,0,0,0); |
| 709 | SDL_RenderFillRect(m_sdl_renderer, NULL); |
| 710 | m_blittimer--; |
| 711 | } |
| 712 | |
| 713 | // compute centering parameters |
| 714 | vofs = hofs = 0.0f; |
| 715 | |
| 716 | if (video_config.centerv || video_config.centerh) |
| 717 | { |
| 718 | int ch, cw; |
| 719 | |
| 720 | ch = wdim.height(); |
| 721 | cw = wdim.width(); |
| 722 | |
| 723 | if (video_config.centerv) |
| 724 | { |
| 725 | vofs = (ch - m_blit_dim.height()) / 2.0f; |
| 726 | } |
| 727 | if (video_config.centerh) |
| 728 | { |
| 729 | hofs = (cw - m_blit_dim.width()) / 2.0f; |
| 730 | } |
| 731 | } |
| 732 | |
| 733 | m_last_hofs = hofs; |
| 734 | m_last_vofs = vofs; |
| 735 | |
| 736 | window().m_primlist->acquire_lock(); |
| 737 | |
| 738 | // now draw |
| 739 | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 740 | { |
| 741 | Uint8 sr, sg, sb, sa; |
| 742 | |
| 743 | switch (prim->type) |
| 744 | { |
| 745 | case render_primitive::LINE: |
| 746 | sr = (int)(255.0f * prim->color.r); |
| 747 | sg = (int)(255.0f * prim->color.g); |
| 748 | sb = (int)(255.0f * prim->color.b); |
| 749 | sa = (int)(255.0f * prim->color.a); |
| 750 | |
| 751 | SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
| 752 | SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa); |
| 753 | SDL_RenderDrawLine(m_sdl_renderer, prim->bounds.x0 + hofs, prim->bounds.y0 + vofs, |
| 754 | prim->bounds.x1 + hofs, prim->bounds.y1 + vofs); |
| 755 | break; |
| 756 | case render_primitive::QUAD: |
| 757 | texture = texture_update(*prim); |
| 758 | if (texture) |
| 759 | blit_pixels += (texture->raw_height() * texture->raw_width()); |
| 760 | render_quad(texture, prim, |
| 761 | round_nearest(hofs + prim->bounds.x0), |
| 762 | round_nearest(vofs + prim->bounds.y0)); |
| 763 | break; |
| 764 | default: |
| 765 | throw emu_fatalerror("Unexpected render_primitive type\n"); |
| 766 | } |
| 767 | } |
| 768 | |
| 769 | window().m_primlist->release_lock(); |
| 770 | |
| 771 | m_last_blit_pixels = blit_pixels; |
| 772 | m_last_blit_time = -osd_ticks(); |
| 773 | SDL_RenderPresent(m_sdl_renderer); |
| 774 | m_last_blit_time += osd_ticks(); |
| 775 | |
| 776 | return 0; |
| 777 | } |
| 778 | |
| 779 | |
| 780 | //============================================================ |
| 781 | // texture handling |
| 782 | //============================================================ |
| 783 | |
| 784 | //============================================================ |
| 785 | // texture_compute_size and type |
| 786 | //============================================================ |
| 787 | |
| 788 | copy_info_t *texture_info::compute_size_type() |
| 789 | { |
| 790 | copy_info_t *bi; |
| 791 | copy_info_t *result = NULL; |
| 792 | int maxperf = 0; |
| 793 | |
| 794 | for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) |
| 795 | { |
| 796 | if ((m_is_rotated == bi->blitter->m_is_rot) |
| 797 | && (m_sdl_blendmode == bi->bm_mask)) |
| 798 | { |
| 799 | if (RendererSupportsFormat(m_sdl_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) |
| 800 | { |
| 801 | int perf = bi->perf; |
| 802 | if (perf == 0) |
| 803 | return bi; |
| 804 | else if (perf > (maxperf * 102) / 100) |
| 805 | { |
| 806 | result = bi; |
| 807 | maxperf = perf; |
| 808 | } |
| 809 | } |
| 810 | } |
| 811 | } |
| 812 | if (result) |
| 813 | return result; |
| 814 | /* try last resort handlers */ |
| 815 | for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) |
| 816 | { |
| 817 | if ((m_is_rotated == bi->blitter->m_is_rot) |
| 818 | && (m_sdl_blendmode == bi->bm_mask)) |
| 819 | if (RendererSupportsFormat(m_sdl_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) |
| 820 | return bi; |
| 821 | } |
| 822 | //FIXME: crash implement a -do nothing handler */ |
| 823 | return NULL; |
| 824 | } |
| 825 | |
| 826 | // FIXME: |
| 827 | const bool texture_info::is_pixels_owned() const |
| 828 | { // do we own / allocated it ? |
| 829 | return ((m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 830 | && (m_copyinfo->blitter->m_is_passthrough)); |
| 831 | } |
| 832 | |
| 833 | //============================================================ |
| 834 | // texture_info::matches |
| 835 | //============================================================ |
| 836 | |
| 837 | bool texture_info::matches(const render_primitive &prim, const quad_setup_data &setup) |
| 838 | { |
| 839 | return texinfo().base == prim.texture.base && |
| 840 | texinfo().width == prim.texture.width && |
| 841 | texinfo().height == prim.texture.height && |
| 842 | texinfo().rowpixels == prim.texture.rowpixels && |
| 843 | m_setup.dudx == setup.dudx && |
| 844 | m_setup.dvdx == setup.dvdx && |
| 845 | m_setup.dudy == setup.dudy && |
| 846 | m_setup.dvdy == setup.dvdy && |
| 847 | ((flags() ^ prim.flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0; |
| 848 | } |
| 849 | |
| 850 | //============================================================ |
| 851 | // texture_create |
| 852 | //============================================================ |
| 853 | |
| 854 | texture_info::texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, UINT32 flags) |
| 855 | { |
| 856 | // fill in the core data |
| 857 | m_sdl_renderer = renderer; |
| 858 | m_hash = texture_compute_hash(texsource, flags); |
| 859 | m_flags = flags; |
| 860 | m_texinfo = texsource; |
| 861 | m_texinfo.seqid = -1; // force set data |
| 862 | m_is_rotated = false; |
| 863 | m_setup = setup; |
| 864 | m_sdl_blendmode = map_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); |
| 865 | m_pitch = 0; |
| 866 | |
| 867 | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 868 | { |
| 869 | case TEXFORMAT_ARGB32: |
| 870 | m_format = SDL_TEXFORMAT_ARGB32; |
| 871 | break; |
| 872 | case TEXFORMAT_RGB32: |
| 873 | m_format = texsource.palette ? SDL_TEXFORMAT_RGB32_PALETTED : SDL_TEXFORMAT_RGB32; |
| 874 | break; |
| 875 | case TEXFORMAT_PALETTE16: |
| 876 | m_format = SDL_TEXFORMAT_PALETTE16; |
| 877 | break; |
| 878 | case TEXFORMAT_PALETTEA16: |
| 879 | m_format = SDL_TEXFORMAT_PALETTE16A; |
| 880 | break; |
| 881 | case TEXFORMAT_YUY16: |
| 882 | m_format = texsource.palette ? SDL_TEXFORMAT_YUY16_PALETTED : SDL_TEXFORMAT_YUY16; |
| 883 | break; |
| 884 | |
| 885 | default: |
| 886 | osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags)); |
| 887 | } |
| 888 | |
| 889 | if (setup.rotwidth != m_texinfo.width || setup.rotheight != m_texinfo.height |
| 890 | || setup.dudx < 0 || setup.dvdy < 0) |
| 891 | m_is_rotated = true; |
| 892 | else |
| 893 | m_is_rotated = false; |
| 894 | |
| 895 | //m_sdl_access = SDL_TEXTUREACCESS_STATIC; |
| 896 | m_sdl_access = SDL_TEXTUREACCESS_STREAMING; |
| 897 | |
| 898 | // Watch out for 0x0 textures ... |
| 899 | if (!m_setup.rotwidth || !m_setup.rotheight) |
| 900 | osd_printf_warning("Trying to create texture with zero dim\n"); |
| 901 | |
| 902 | // set copy_info |
| 903 | |
| 904 | m_copyinfo = compute_size_type(); |
| 905 | |
| 906 | m_texture_id = SDL_CreateTexture(m_sdl_renderer, m_copyinfo->dst_fmt, m_sdl_access, |
| 907 | m_setup.rotwidth, m_setup.rotheight); |
| 908 | |
| 909 | if (!m_texture_id) |
| 910 | osd_printf_error("Error creating texture: %d x %d, pixelformat %s error: %s\n", m_setup.rotwidth, m_setup.rotheight, |
| 911 | m_copyinfo->dstname, SDL_GetError()); |
| 912 | |
| 913 | if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 914 | { |
| 915 | if (m_copyinfo->blitter->m_is_passthrough) |
| 916 | m_pixels = NULL; |
| 917 | else |
| 918 | m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->blitter->m_dest_bpp); |
| 919 | } |
| 920 | m_last_access = osd_ticks(); |
| 921 | |
| 922 | } |
| 923 | |
| 924 | texture_info::~texture_info() |
| 925 | { |
| 926 | if ( is_pixels_owned() && (m_pixels != NULL) ) |
| 927 | free(m_pixels); |
| 928 | SDL_DestroyTexture(m_texture_id); |
| 929 | } |
| 930 | |
| 931 | //============================================================ |
| 932 | // texture_set_data |
| 933 | //============================================================ |
| 934 | |
| 935 | void texture_info::set_data(const render_texinfo &texsource, const UINT32 flags) |
| 936 | { |
| 937 | m_copyinfo->time -= osd_ticks(); |
| 938 | if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 939 | { |
| 940 | if ( m_copyinfo->blitter->m_is_passthrough ) |
| 941 | { |
| 942 | m_pixels = texsource.base; |
| 943 | m_pitch = m_texinfo.rowpixels * m_copyinfo->blitter->m_dest_bpp; |
| 944 | } |
| 945 | else |
| 946 | { |
| 947 | m_pitch = m_setup.rotwidth * m_copyinfo->blitter->m_dest_bpp; |
| 948 | m_copyinfo->blitter->texop(this, &texsource); |
| 949 | } |
| 950 | SDL_UpdateTexture(m_texture_id, NULL, m_pixels, m_pitch); |
| 951 | } |
| 952 | else |
| 953 | { |
| 954 | SDL_LockTexture(m_texture_id, NULL, (void **) &m_pixels, &m_pitch); |
| 955 | if ( m_copyinfo->blitter->m_is_passthrough ) |
| 956 | { |
| 957 | UINT8 *src = (UINT8 *) texsource.base; |
| 958 | UINT8 *dst = (UINT8 *) m_pixels; |
| 959 | int spitch = texsource.rowpixels * m_copyinfo->blitter->m_dest_bpp; |
| 960 | int num = texsource.width * m_copyinfo->blitter->m_dest_bpp; |
| 961 | int h = texsource.height; |
| 962 | while (h--) { |
| 963 | memcpy(dst, src, num); |
| 964 | src += spitch; |
| 965 | dst += m_pitch; |
| 966 | } |
| 967 | } |
| 968 | else |
| 969 | m_copyinfo->blitter->texop(this, &texsource); |
| 970 | SDL_UnlockTexture(m_texture_id); |
| 971 | } |
| 972 | m_copyinfo->time += osd_ticks(); |
| 973 | } |
| 974 | |
| 975 | //============================================================ |
| 976 | // compute rotation setup |
| 977 | //============================================================ |
| 978 | |
| 979 | void quad_setup_data::compute(const render_primitive &prim, const int prescale) |
| 980 | { |
| 981 | const render_quad_texuv *texcoords = &prim.texcoords; |
| 982 | int texwidth = prim.texture.width; |
| 983 | int texheight = prim.texture.height; |
| 984 | float fdudx, fdvdx, fdudy, fdvdy; |
| 985 | float width, height; |
| 986 | float fscale; |
| 987 | /* determine U/V deltas */ |
| 988 | if ((PRIMFLAG_GET_SCREENTEX(prim.flags))) |
| 989 | fscale = (float) prescale; |
| 990 | else |
| 991 | fscale = 1.0f; |
| 992 | |
| 993 | fdudx = (texcoords->tr.u - texcoords->tl.u) / fscale; // a a11 |
| 994 | fdvdx = (texcoords->tr.v - texcoords->tl.v) / fscale; // c a21 |
| 995 | fdudy = (texcoords->bl.u - texcoords->tl.u) / fscale; // b a12 |
| 996 | fdvdy = (texcoords->bl.v - texcoords->tl.v) / fscale; // d a22 |
| 997 | |
| 998 | #if 0 |
| 999 | printf("tl.u %f tl.v %f\n", texcoords->tl.u, texcoords->tl.v); |
| 1000 | printf("tr.u %f tr.v %f\n", texcoords->tr.u, texcoords->tr.v); |
| 1001 | printf("bl.u %f bl.v %f\n", texcoords->bl.u, texcoords->bl.v); |
| 1002 | printf("br.u %f br.v %f\n", texcoords->br.u, texcoords->br.v); |
| 1003 | /* compute start and delta U,V coordinates now */ |
| 1004 | #endif |
| 1005 | |
| 1006 | dudx = round_nearest(65536.0f * fdudx); |
| 1007 | dvdx = round_nearest(65536.0f * fdvdx); |
| 1008 | dudy = round_nearest(65536.0f * fdudy); |
| 1009 | dvdy = round_nearest(65536.0f * fdvdy); |
| 1010 | startu = round_nearest(65536.0f * (float) texwidth * texcoords->tl.u); |
| 1011 | startv = round_nearest(65536.0f * (float) texheight * texcoords->tl.v); |
| 1012 | |
| 1013 | /* clamp to integers */ |
| 1014 | |
| 1015 | width = fabs((fdudx * (float) (texwidth) + fdvdx * (float) (texheight)) * fscale * fscale); |
| 1016 | height = fabs((fdudy * (float)(texwidth) + fdvdy * (float) (texheight)) * fscale * fscale); |
| 1017 | |
| 1018 | rotwidth = width; |
| 1019 | rotheight = height; |
| 1020 | |
| 1021 | startu += (dudx + dudy) / 2; |
| 1022 | startv += (dvdx + dvdy) / 2; |
| 1023 | |
| 1024 | } |
| 1025 | |
| 1026 | //============================================================ |
| 1027 | // texture_find |
| 1028 | //============================================================ |
| 1029 | |
| 1030 | texture_info *sdl_info13::texture_find(const render_primitive &prim, const quad_setup_data &setup) |
| 1031 | { |
| 1032 | HashT texhash = texture_compute_hash(prim.texture, prim.flags); |
| 1033 | texture_info *texture; |
| 1034 | osd_ticks_t now = osd_ticks(); |
| 1035 | |
| 1036 | // find a match |
| 1037 | for (texture = m_texlist.first(); texture != NULL; ) |
| 1038 | if (texture->hash() == texhash && |
| 1039 | texture->matches(prim, setup)) |
| 1040 | { |
| 1041 | /* would we choose another blitter based on performance ? */ |
| 1042 | if ((texture->m_copyinfo->samples & 0x7f) == 0x7f) |
| 1043 | { |
| 1044 | if (texture->m_copyinfo != texture->compute_size_type()) |
| 1045 | return NULL; |
| 1046 | } |
| 1047 | texture->m_last_access = now; |
| 1048 | return texture; |
| 1049 | } |
| 1050 | else |
| 1051 | { |
| 1052 | /* free resources not needed any longer? */ |
| 1053 | texture_info *expire = texture; |
| 1054 | texture = texture->next(); |
| 1055 | if (now - expire->m_last_access > osd_ticks_per_second()) |
| 1056 | m_texlist.remove(*expire); |
| 1057 | } |
| 1058 | |
| 1059 | // nothing found |
| 1060 | return NULL; |
| 1061 | } |
| 1062 | |
| 1063 | //============================================================ |
| 1064 | // texture_update |
| 1065 | //============================================================ |
| 1066 | |
| 1067 | texture_info * sdl_info13::texture_update(const render_primitive &prim) |
| 1068 | { |
| 1069 | quad_setup_data setup; |
| 1070 | texture_info *texture; |
| 1071 | |
| 1072 | setup.compute(prim, window().prescale()); |
| 1073 | |
| 1074 | texture = texture_find(prim, setup); |
| 1075 | |
| 1076 | // if we didn't find one, create a new texture |
| 1077 | if (texture == NULL && prim.texture.base != NULL) |
| 1078 | { |
| 1079 | texture = global_alloc(texture_info(m_sdl_renderer, prim.texture, setup, prim.flags)); |
| 1080 | /* add us to the texture list */ |
| 1081 | m_texlist.prepend(*texture); |
| 1082 | |
| 1083 | } |
| 1084 | |
| 1085 | if (texture != NULL) |
| 1086 | { |
| 1087 | if (prim.texture.base != NULL && texture->texinfo().seqid != prim.texture.seqid) |
| 1088 | { |
| 1089 | texture->texinfo().seqid = prim.texture.seqid; |
| 1090 | // if we found it, but with a different seqid, copy the data |
| 1091 | texture->set_data(prim.texture, prim.flags); |
| 1092 | } |
| 1093 | |
| 1094 | } |
| 1095 | return texture; |
| 1096 | } |
trunk/src/osd/modules/render/drawd3d.c
| r0 | r244652 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Aaron Giles |
| 3 | //============================================================ |
| 4 | // |
| 5 | // drawd3d.c - Win32 Direct3D implementation |
| 6 | // |
| 7 | //============================================================ |
| 8 | |
| 9 | // Useful info: |
| 10 | // Windows XP/2003 shipped with DirectX 8.1 |
| 11 | // Windows 2000 shipped with DirectX 7a |
| 12 | // Windows 98SE shipped with DirectX 6.1a |
| 13 | // Windows 98 shipped with DirectX 5 |
| 14 | // Windows NT shipped with DirectX 3.0a |
| 15 | // Windows 95 shipped with DirectX 2 |
| 16 | |
| 17 | // standard windows headers |
| 18 | #define WIN32_LEAN_AND_MEAN |
| 19 | #include <windows.h> |
| 20 | #include <tchar.h> |
| 21 | #include <mmsystem.h> |
| 22 | #include <d3d9.h> |
| 23 | #include <d3dx9.h> |
| 24 | #include <math.h> |
| 25 | #undef interface |
| 26 | |
| 27 | // MAME headers |
| 28 | #include "emu.h" |
| 29 | #include "render.h" |
| 30 | #include "ui/ui.h" |
| 31 | #include "rendutil.h" |
| 32 | #include "options.h" |
| 33 | #include "emuopts.h" |
| 34 | #include "aviio.h" |
| 35 | #include "png.h" |
| 36 | |
| 37 | // MAMEOS headers |
| 38 | #include "modules/render/d3d/d3dintf.h" |
| 39 | #include "winmain.h" |
| 40 | #include "window.h" |
| 41 | #include "config.h" |
| 42 | #include "strconv.h" |
| 43 | #include "modules/render/d3d/d3dcomm.h" |
| 44 | #include "drawd3d.h" |
| 45 | |
| 46 | |
| 47 | |
| 48 | //============================================================ |
| 49 | // DEBUGGING |
| 50 | //============================================================ |
| 51 | |
| 52 | extern void mtlog_add(const char *event); |
| 53 | |
| 54 | |
| 55 | |
| 56 | //============================================================ |
| 57 | // CONSTANTS |
| 58 | //============================================================ |
| 59 | |
| 60 | #define ENABLE_BORDER_PIX (1) |
| 61 | |
| 62 | enum |
| 63 | { |
| 64 | TEXTURE_TYPE_PLAIN, |
| 65 | TEXTURE_TYPE_DYNAMIC, |
| 66 | TEXTURE_TYPE_SURFACE |
| 67 | }; |
| 68 | |
| 69 | |
| 70 | |
| 71 | //============================================================ |
| 72 | // MACROS |
| 73 | //============================================================ |
| 74 | |
| 75 | #define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0) |
| 76 | |
| 77 | |
| 78 | |
| 79 | //============================================================ |
| 80 | // GLOBALS |
| 81 | //============================================================ |
| 82 | |
| 83 | static const line_aa_step line_aa_1step[] = |
| 84 | { |
| 85 | { 0.00f, 0.00f, 1.00f }, |
| 86 | { 0 } |
| 87 | }; |
| 88 | |
| 89 | static const line_aa_step line_aa_4step[] = |
| 90 | { |
| 91 | { -0.25f, 0.00f, 0.25f }, |
| 92 | { 0.25f, 0.00f, 0.25f }, |
| 93 | { 0.00f, -0.25f, 0.25f }, |
| 94 | { 0.00f, 0.25f, 0.25f }, |
| 95 | { 0 } |
| 96 | }; |
| 97 | |
| 98 | //============================================================ |
| 99 | // INLINES |
| 100 | //============================================================ |
| 101 | |
| 102 | INLINE BOOL GetClientRectExceptMenu(HWND hWnd, PRECT pRect, BOOL fullscreen) |
| 103 | { |
| 104 | static HMENU last_menu; |
| 105 | static RECT last_rect; |
| 106 | static RECT cached_rect; |
| 107 | HMENU menu = GetMenu(hWnd); |
| 108 | BOOL result = GetClientRect(hWnd, pRect); |
| 109 | |
| 110 | if (!fullscreen || !menu) |
| 111 | return result; |
| 112 | |
| 113 | // to avoid flicker use cache if we can use |
| 114 | if (last_menu != menu || memcmp(&last_rect, pRect, sizeof *pRect) != 0) |
| 115 | { |
| 116 | last_menu = menu; |
| 117 | last_rect = *pRect; |
| 118 | |
| 119 | SetMenu(hWnd, NULL); |
| 120 | result = GetClientRect(hWnd, &cached_rect); |
| 121 | SetMenu(hWnd, menu); |
| 122 | } |
| 123 | |
| 124 | *pRect = cached_rect; |
| 125 | return result; |
| 126 | } |
| 127 | |
| 128 | |
| 129 | INLINE UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) |
| 130 | { |
| 131 | /* original equations: |
| 132 | |
| 133 | C = Y - 16 |
| 134 | D = Cb - 128 |
| 135 | E = Cr - 128 |
| 136 | |
| 137 | R = clip(( 298 * C + 409 * E + 128) >> 8) |
| 138 | G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) |
| 139 | B = clip(( 298 * C + 516 * D + 128) >> 8) |
| 140 | |
| 141 | R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) |
| 142 | G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) |
| 143 | B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) |
| 144 | |
| 145 | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 146 | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 147 | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 148 | |
| 149 | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 150 | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 151 | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 152 | */ |
| 153 | int r, g, b, common; |
| 154 | |
| 155 | common = 298 * y - 298 * 16; |
| 156 | r = (common + 409 * cr - 409 * 128 + 128) >> 8; |
| 157 | g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; |
| 158 | b = (common + 516 * cb - 516 * 128 + 128) >> 8; |
| 159 | |
| 160 | if (r < 0) r = 0; |
| 161 | else if (r > 255) r = 255; |
| 162 | if (g < 0) g = 0; |
| 163 | else if (g > 255) g = 255; |
| 164 | if (b < 0) b = 0; |
| 165 | else if (b > 255) b = 255; |
| 166 | |
| 167 | return rgb_t(0xff, r, g, b); |
| 168 | } |
| 169 | |
| 170 | //============================================================ |
| 171 | // drawd3d_init |
| 172 | //============================================================ |
| 173 | |
| 174 | static d3d::base * d3dintf; // FIX ME |
| 175 | |
| 176 | //============================================================ |
| 177 | // PROTOTYPES |
| 178 | //============================================================ |
| 179 | |
| 180 | // core functions |
| 181 | static void drawd3d_exit(void); |
| 182 | |
| 183 | //============================================================ |
| 184 | // drawd3d_window_init |
| 185 | //============================================================ |
| 186 | |
| 187 | int d3d::renderer::create() |
| 188 | { |
| 189 | if (!initialize()) |
| 190 | { |
| 191 | destroy(); |
| 192 | osd_printf_error("Unable to initialize Direct3D.\n"); |
| 193 | return 1; |
| 194 | } |
| 195 | |
| 196 | return 0; |
| 197 | } |
| 198 | |
| 199 | //============================================================ |
| 200 | // drawd3d_exit |
| 201 | //============================================================ |
| 202 | |
| 203 | static void drawd3d_exit(void) |
| 204 | { |
| 205 | if (d3dintf != NULL) |
| 206 | (*d3dintf->d3d.release)(d3dintf); |
| 207 | } |
| 208 | |
| 209 | void d3d::renderer::toggle_fsfx() |
| 210 | { |
| 211 | set_restarting(true); |
| 212 | } |
| 213 | |
| 214 | void d3d::renderer::record() |
| 215 | { |
| 216 | get_shaders()->window_record(); |
| 217 | } |
| 218 | |
| 219 | void d3d::renderer::save() |
| 220 | { |
| 221 | get_shaders()->window_save(); |
| 222 | } |
| 223 | |
| 224 | |
| 225 | |
| 226 | //============================================================ |
| 227 | // drawd3d_window_destroy |
| 228 | //============================================================ |
| 229 | |
| 230 | void d3d::renderer::destroy() |
| 231 | { |
| 232 | if (get_shaders() != NULL && get_shaders()->recording()) |
| 233 | get_shaders()->window_record(); |
| 234 | |
| 235 | } |
| 236 | |
| 237 | |
| 238 | |
| 239 | //============================================================ |
| 240 | // drawd3d_window_get_primitives |
| 241 | //============================================================ |
| 242 | |
| 243 | render_primitive_list *d3d::renderer::get_primitives() |
| 244 | { |
| 245 | RECT client; |
| 246 | |
| 247 | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 248 | if (rect_width(&client) > 0 && rect_height(&client) > 0) |
| 249 | { |
| 250 | window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); |
| 251 | window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); |
| 252 | } |
| 253 | return &window().target()->get_primitives(); |
| 254 | } |
| 255 | |
| 256 | //============================================================ |
| 257 | // drawnone_create |
| 258 | //============================================================ |
| 259 | |
| 260 | static osd_renderer *drawd3d_create(osd_window *window) |
| 261 | { |
| 262 | return global_alloc(d3d::renderer(window)); |
| 263 | } |
| 264 | |
| 265 | int drawd3d_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 266 | { |
| 267 | d3dintf = NULL; |
| 268 | |
| 269 | // Use Direct3D9 |
| 270 | d3dintf = d3d::drawd3d9_init(); |
| 271 | |
| 272 | // if we failed, note the error |
| 273 | if (d3dintf == NULL) |
| 274 | { |
| 275 | osd_printf_error("Unable to initialize Direct3D.\n"); |
| 276 | return 1; |
| 277 | } |
| 278 | |
| 279 | // fill in the callbacks |
| 280 | memset(callbacks, 0, sizeof(*callbacks)); |
| 281 | callbacks->exit = drawd3d_exit; |
| 282 | callbacks->create = drawd3d_create; |
| 283 | return 0; |
| 284 | } |
| 285 | |
| 286 | //============================================================ |
| 287 | // drawd3d_window_draw |
| 288 | //============================================================ |
| 289 | |
| 290 | int d3d::renderer::draw(const int update) |
| 291 | { |
| 292 | int check = pre_window_draw_check(); |
| 293 | if (check >= 0) |
| 294 | return check; |
| 295 | |
| 296 | begin_frame(); |
| 297 | process_primitives(); |
| 298 | end_frame(); |
| 299 | |
| 300 | return 0; |
| 301 | } |
| 302 | |
| 303 | namespace d3d |
| 304 | { |
| 305 | void renderer::set_texture(texture_info *texture) |
| 306 | { |
| 307 | if (texture != m_last_texture) |
| 308 | { |
| 309 | m_last_texture = texture; |
| 310 | m_last_texture_flags = (texture == NULL ? 0 : texture->get_flags()); |
| 311 | HRESULT result = (*d3dintf->device.set_texture)(m_device, 0, (texture == NULL) ? get_default_texture()->get_finaltex() : texture->get_finaltex()); |
| 312 | m_shaders->set_texture(texture); |
| 313 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result); |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | |
| 318 | void renderer::set_filter(int filter) |
| 319 | { |
| 320 | if (filter != m_last_filter) |
| 321 | { |
| 322 | m_last_filter = filter; |
| 323 | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 324 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 325 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 326 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 327 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 328 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 329 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 330 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | |
| 335 | void renderer::set_wrap(D3DTEXTUREADDRESS wrap) |
| 336 | { |
| 337 | if (wrap != m_last_wrap) |
| 338 | { |
| 339 | m_last_wrap = wrap; |
| 340 | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap); |
| 341 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 342 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap); |
| 343 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 344 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap); |
| 345 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 346 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap); |
| 347 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | |
| 352 | void renderer::set_modmode(DWORD modmode) |
| 353 | { |
| 354 | if (modmode != m_last_modmode) |
| 355 | { |
| 356 | m_last_modmode = modmode; |
| 357 | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, modmode); |
| 358 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 359 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, modmode); |
| 360 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | |
| 365 | void renderer::set_blendmode(int blendmode) |
| 366 | { |
| 367 | int blendenable; |
| 368 | int blendop; |
| 369 | int blendsrc; |
| 370 | int blenddst; |
| 371 | |
| 372 | // choose the parameters |
| 373 | switch (blendmode) |
| 374 | { |
| 375 | default: |
| 376 | case BLENDMODE_NONE: blendenable = FALSE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break; |
| 377 | case BLENDMODE_ALPHA: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break; |
| 378 | case BLENDMODE_RGB_MULTIPLY: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_DESTCOLOR; blenddst = D3DBLEND_ZERO; break; |
| 379 | case BLENDMODE_ADD: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_ONE; break; |
| 380 | } |
| 381 | |
| 382 | // adjust the bits that changed |
| 383 | if (blendenable != m_last_blendenable) |
| 384 | { |
| 385 | m_last_blendenable = blendenable; |
| 386 | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHABLENDENABLE, blendenable); |
| 387 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 388 | } |
| 389 | |
| 390 | if (blendop != m_last_blendop) |
| 391 | { |
| 392 | m_last_blendop = blendop; |
| 393 | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_BLENDOP, blendop); |
| 394 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 395 | } |
| 396 | |
| 397 | if (blendsrc != m_last_blendsrc) |
| 398 | { |
| 399 | m_last_blendsrc = blendsrc; |
| 400 | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SRCBLEND, blendsrc); |
| 401 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 402 | } |
| 403 | |
| 404 | if (blenddst != m_last_blenddst) |
| 405 | { |
| 406 | m_last_blenddst = blenddst; |
| 407 | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DESTBLEND, blenddst); |
| 408 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | |
| 413 | void renderer::reset_render_states() |
| 414 | { |
| 415 | // this ensures subsequent calls to the above setters will force-update the data |
| 416 | m_last_texture = (texture_info *)~0; |
| 417 | m_last_filter = -1; |
| 418 | m_last_blendenable = -1; |
| 419 | m_last_blendop = -1; |
| 420 | m_last_blendsrc = -1; |
| 421 | m_last_blenddst = -1; |
| 422 | m_last_wrap = (D3DTEXTUREADDRESS)-1; |
| 423 | } |
| 424 | |
| 425 | |
| 426 | |
| 427 | texture_manager::texture_manager(renderer *d3d) |
| 428 | { |
| 429 | m_renderer = d3d; |
| 430 | |
| 431 | m_texlist = NULL; |
| 432 | m_vector_texture = NULL; |
| 433 | m_default_texture = NULL; |
| 434 | |
| 435 | // check for dynamic texture support |
| 436 | DWORD tempcaps; |
| 437 | HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps); |
| 438 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 439 | m_dynamic_supported = ((tempcaps & D3DCAPS2_DYNAMICTEXTURES) != 0); |
| 440 | if (m_dynamic_supported) osd_printf_verbose("Direct3D: Using dynamic textures\n"); |
| 441 | |
| 442 | // check for stretchrect support |
| 443 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_STRETCH_RECT_FILTER, &tempcaps); |
| 444 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 445 | m_stretch_supported = ((tempcaps & D3DPTFILTERCAPS_MAGFPOINT) != 0); |
| 446 | if (m_stretch_supported && video_config.prescale > 1) osd_printf_verbose("Direct3D: Using StretchRect for prescaling\n"); |
| 447 | |
| 448 | // get texture caps |
| 449 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_TEXTURE_CAPS, &m_texture_caps); |
| 450 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 451 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_ASPECT, &m_texture_max_aspect); |
| 452 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 453 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_WIDTH, &m_texture_max_width); |
| 454 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 455 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_HEIGHT, &m_texture_max_height); |
| 456 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 457 | |
| 458 | // pick a YUV texture format |
| 459 | m_yuv_format = D3DFMT_UYVY; |
| 460 | result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); |
| 461 | if (result != D3D_OK) |
| 462 | { |
| 463 | m_yuv_format = D3DFMT_YUY2; |
| 464 | result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); |
| 465 | if (result != D3D_OK) |
| 466 | m_yuv_format = D3DFMT_A8R8G8B8; |
| 467 | } |
| 468 | osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB"); |
| 469 | |
| 470 | // set the max texture size |
| 471 | d3d->window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); |
| 472 | osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height); |
| 473 | } |
| 474 | |
| 475 | texture_manager::~texture_manager() |
| 476 | { |
| 477 | } |
| 478 | |
| 479 | void texture_manager::create_resources() |
| 480 | { |
| 481 | // experimental: load a PNG to use for vector rendering; it is treated |
| 482 | // as a brightness map |
| 483 | emu_file file(m_renderer->window().machine().options().art_path(), OPEN_FLAG_READ); |
| 484 | render_load_png(m_vector_bitmap, file, NULL, "vector.png"); |
| 485 | if (m_vector_bitmap.valid()) |
| 486 | { |
| 487 | m_vector_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); |
| 488 | render_load_png(m_vector_bitmap, file, NULL, "vector.png", true); |
| 489 | } |
| 490 | |
| 491 | m_default_bitmap.allocate(8, 8); |
| 492 | m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); |
| 493 | |
| 494 | if (m_default_bitmap.valid()) |
| 495 | { |
| 496 | render_texinfo texture; |
| 497 | |
| 498 | // fake in the basic data so it looks like it came from render.c |
| 499 | texture.base = m_default_bitmap.raw_pixptr(0); |
| 500 | texture.rowpixels = m_default_bitmap.rowpixels(); |
| 501 | texture.width = m_default_bitmap.width(); |
| 502 | texture.height = m_default_bitmap.height(); |
| 503 | texture.palette = NULL; |
| 504 | texture.seqid = 0; |
| 505 | |
| 506 | // now create it |
| 507 | m_default_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32))); |
| 508 | } |
| 509 | |
| 510 | // experimental: if we have a vector bitmap, create a texture for it |
| 511 | if (m_vector_bitmap.valid()) |
| 512 | { |
| 513 | render_texinfo texture; |
| 514 | |
| 515 | // fake in the basic data so it looks like it came from render.c |
| 516 | texture.base = &m_vector_bitmap.pix32(0); |
| 517 | texture.rowpixels = m_vector_bitmap.rowpixels(); |
| 518 | texture.width = m_vector_bitmap.width(); |
| 519 | texture.height = m_vector_bitmap.height(); |
| 520 | texture.palette = NULL; |
| 521 | texture.seqid = 0; |
| 522 | |
| 523 | // now create it |
| 524 | m_vector_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32))); |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | void texture_manager::delete_resources() |
| 529 | { |
| 530 | // is part of m_texlist and will be free'd there |
| 531 | //global_free(m_default_texture); |
| 532 | m_default_texture = NULL; |
| 533 | |
| 534 | //global_free(m_vector_texture); |
| 535 | m_vector_texture = NULL; |
| 536 | |
| 537 | // free all textures |
| 538 | while (m_texlist != NULL) |
| 539 | { |
| 540 | texture_info *tex = m_texlist; |
| 541 | m_texlist = tex->get_next(); |
| 542 | global_free(tex); |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | UINT32 texture_manager::texture_compute_hash(const render_texinfo *texture, UINT32 flags) |
| 547 | { |
| 548 | return (FPTR)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 549 | } |
| 550 | |
| 551 | texture_info *texture_manager::find_texinfo(const render_texinfo *texinfo, UINT32 flags) |
| 552 | { |
| 553 | UINT32 hash = texture_compute_hash(texinfo, flags); |
| 554 | texture_info *texture; |
| 555 | |
| 556 | // find a match |
| 557 | for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) |
| 558 | { |
| 559 | UINT32 test_screen = (UINT32)texture->get_texinfo().osddata >> 1; |
| 560 | UINT32 test_page = (UINT32)texture->get_texinfo().osddata & 1; |
| 561 | UINT32 prim_screen = (UINT32)texinfo->osddata >> 1; |
| 562 | UINT32 prim_page = (UINT32)texinfo->osddata & 1; |
| 563 | if (test_screen != prim_screen || test_page != prim_page) |
| 564 | { |
| 565 | continue; |
| 566 | } |
| 567 | |
| 568 | if (texture->get_hash() == hash && |
| 569 | texture->get_texinfo().base == texinfo->base && |
| 570 | texture->get_texinfo().width == texinfo->width && |
| 571 | texture->get_texinfo().height == texinfo->height && |
| 572 | ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) |
| 573 | { |
| 574 | // Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache |
| 575 | if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0) |
| 576 | { |
| 577 | if (m_renderer->get_shaders()->find_render_target(texture) != NULL) |
| 578 | { |
| 579 | return texture; |
| 580 | } |
| 581 | } |
| 582 | else |
| 583 | { |
| 584 | return texture; |
| 585 | } |
| 586 | } |
| 587 | } |
| 588 | |
| 589 | // Nothing found, check if we need to unregister something with HLSL |
| 590 | if (m_renderer->get_shaders()->enabled()) |
| 591 | { |
| 592 | if (texinfo->width == 0 || texinfo->height == 0) |
| 593 | { |
| 594 | return NULL; |
| 595 | } |
| 596 | |
| 597 | UINT32 prim_screen = texinfo->osddata >> 1; |
| 598 | UINT32 prim_page = texinfo->osddata & 1; |
| 599 | |
| 600 | for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) |
| 601 | { |
| 602 | UINT32 test_screen = texture->get_texinfo().osddata >> 1; |
| 603 | UINT32 test_page = texture->get_texinfo().osddata & 1; |
| 604 | if (test_screen != prim_screen || test_page != prim_page) |
| 605 | { |
| 606 | continue; |
| 607 | } |
| 608 | |
| 609 | // Clear out our old texture reference |
| 610 | if (texture->get_hash() == hash && |
| 611 | texture->get_texinfo().base == texinfo->base && |
| 612 | ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 && |
| 613 | (texture->get_texinfo().width != texinfo->width || |
| 614 | texture->get_texinfo().height != texinfo->height)) |
| 615 | { |
| 616 | m_renderer->get_shaders()->remove_render_target(texture); |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | return NULL; |
| 622 | } |
| 623 | |
| 624 | renderer::renderer(osd_window *window) |
| 625 | : osd_renderer(window, FLAG_NONE) |
| 626 | { |
| 627 | m_device = NULL; |
| 628 | m_restarting = false; |
| 629 | m_shaders = NULL; |
| 630 | m_numverts = 0; |
| 631 | m_numpolys = 0; |
| 632 | m_vertexbuf = NULL; |
| 633 | m_lockedbuf = NULL; |
| 634 | m_vectorbatch = NULL; |
| 635 | m_last_texture = NULL; |
| 636 | m_hlsl_buf = NULL; |
| 637 | m_texture_manager = NULL; |
| 638 | } |
| 639 | |
| 640 | int renderer::initialize() |
| 641 | { |
| 642 | // configure the adapter for the mode we want |
| 643 | if (config_adapter_mode()) |
| 644 | return false; |
| 645 | |
| 646 | // create the device immediately for the full screen case (defer for window mode) |
| 647 | if (window().fullscreen() && device_create(window().m_focus_hwnd)) |
| 648 | return false; |
| 649 | |
| 650 | return true; |
| 651 | } |
| 652 | |
| 653 | int renderer::pre_window_draw_check() |
| 654 | { |
| 655 | // if we're in the middle of resizing, leave things alone |
| 656 | if (window().m_resize_state == RESIZE_STATE_RESIZING) |
| 657 | return 0; |
| 658 | |
| 659 | // if we're restarting the renderer, leave things alone |
| 660 | if (m_restarting) |
| 661 | { |
| 662 | m_shaders->toggle(); |
| 663 | |
| 664 | // free all existing resources and re-create |
| 665 | device_delete_resources(); |
| 666 | device_create_resources(); |
| 667 | |
| 668 | m_restarting = false; |
| 669 | } |
| 670 | |
| 671 | // if we have a device, check the cooperative level |
| 672 | if (m_device != NULL) |
| 673 | { |
| 674 | if (device_test_cooperative()) |
| 675 | { |
| 676 | return 1; |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | // in window mode, we need to track the window size |
| 681 | if (!window().fullscreen() || m_device == NULL) |
| 682 | { |
| 683 | // if the size changes, skip this update since the render target will be out of date |
| 684 | if (update_window_size()) |
| 685 | return 0; |
| 686 | |
| 687 | // if we have no device, after updating the size, return an error so GDI can try |
| 688 | if (m_device == NULL) |
| 689 | return 1; |
| 690 | } |
| 691 | |
| 692 | return -1; |
| 693 | } |
| 694 | |
| 695 | void texture_manager::update_textures() |
| 696 | { |
| 697 | for (render_primitive *prim = m_renderer->window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 698 | { |
| 699 | if (prim->texture.base != NULL) |
| 700 | { |
| 701 | texture_info *texture = find_texinfo(&prim->texture, prim->flags); |
| 702 | if (texture == NULL) |
| 703 | { |
| 704 | // if there isn't one, create a new texture |
| 705 | global_alloc(texture_info(this, &prim->texture, m_renderer->window().prescale(), prim->flags)); |
| 706 | } |
| 707 | else |
| 708 | { |
| 709 | // if there is one, but with a different seqid, copy the data |
| 710 | if (texture->get_texinfo().seqid != prim->texture.seqid) |
| 711 | { |
| 712 | texture->set_data(&prim->texture, prim->flags); |
| 713 | texture->get_texinfo().seqid = prim->texture.seqid; |
| 714 | } |
| 715 | } |
| 716 | } |
| 717 | else if(m_renderer->get_shaders()->vector_enabled() && PRIMFLAG_GET_VECTORBUF(prim->flags)) |
| 718 | { |
| 719 | if (!m_renderer->get_shaders()->get_vector_target()) |
| 720 | { |
| 721 | m_renderer->get_shaders()->create_vector_target(prim); |
| 722 | } |
| 723 | } |
| 724 | } |
| 725 | } |
| 726 | |
| 727 | void renderer::begin_frame() |
| 728 | { |
| 729 | HRESULT result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 730 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 731 | |
| 732 | m_shaders->begin_frame(); |
| 733 | |
| 734 | window().m_primlist->acquire_lock(); |
| 735 | |
| 736 | // first update any textures |
| 737 | m_texture_manager->update_textures(); |
| 738 | |
| 739 | // begin the scene |
| 740 | mtlog_add("drawd3d_window_draw: begin_scene"); |
| 741 | result = (*d3dintf->device.begin_scene)(m_device); |
| 742 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result); |
| 743 | |
| 744 | m_lockedbuf = NULL; |
| 745 | |
| 746 | if(m_shaders->enabled()) |
| 747 | { |
| 748 | m_hlsl_buf = (void*)mesh_alloc(6); |
| 749 | m_shaders->init_fsfx_quad(m_hlsl_buf); |
| 750 | } |
| 751 | |
| 752 | m_line_count = 0; |
| 753 | |
| 754 | // loop over primitives |
| 755 | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 756 | if (prim->type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim->flags)) |
| 757 | m_line_count++; |
| 758 | } |
| 759 | |
| 760 | void renderer::process_primitives() |
| 761 | { |
| 762 | // Rotating index for vector time offsets |
| 763 | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 764 | { |
| 765 | switch (prim->type) |
| 766 | { |
| 767 | case render_primitive::LINE: |
| 768 | if (PRIMFLAG_GET_VECTOR(prim->flags)) |
| 769 | { |
| 770 | if (m_line_count > 0) |
| 771 | batch_vectors(); |
| 772 | else |
| 773 | continue; |
| 774 | } |
| 775 | else |
| 776 | { |
| 777 | draw_line(prim); |
| 778 | } |
| 779 | break; |
| 780 | |
| 781 | case render_primitive::QUAD: |
| 782 | draw_quad(prim); |
| 783 | break; |
| 784 | |
| 785 | default: |
| 786 | throw emu_fatalerror("Unexpected render_primitive type"); |
| 787 | } |
| 788 | } |
| 789 | } |
| 790 | |
| 791 | void renderer::end_frame() |
| 792 | { |
| 793 | window().m_primlist->release_lock(); |
| 794 | |
| 795 | // flush any pending polygons |
| 796 | primitive_flush_pending(); |
| 797 | |
| 798 | m_shaders->end_frame(); |
| 799 | |
| 800 | // finish the scene |
| 801 | HRESULT result = (*d3dintf->device.end_scene)(m_device); |
| 802 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result); |
| 803 | |
| 804 | // present the current buffers |
| 805 | result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0); |
| 806 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device present call\n", (int)result); |
| 807 | } |
| 808 | |
| 809 | //============================================================ |
| 810 | // device_create |
| 811 | //============================================================ |
| 812 | |
| 813 | int renderer::device_create(HWND device_hwnd) |
| 814 | { |
| 815 | // if a device exists, free it |
| 816 | if (m_device != NULL) |
| 817 | device_delete(); |
| 818 | |
| 819 | // verify the caps |
| 820 | int verify = device_verify_caps(); |
| 821 | if (verify == 2) |
| 822 | { |
| 823 | osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n"); |
| 824 | return 1; |
| 825 | } |
| 826 | if (verify == 1) |
| 827 | osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n"); |
| 828 | |
| 829 | // verify texture formats |
| 830 | HRESULT result = (*d3dintf->d3d.check_device_format)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); |
| 831 | if (result != D3D_OK) |
| 832 | { |
| 833 | osd_printf_error("Error: A8R8G8B8 format textures not supported\n"); |
| 834 | return 1; |
| 835 | } |
| 836 | |
| 837 | m_texture_manager = global_alloc(texture_manager(this)); |
| 838 | |
| 839 | try_again: |
| 840 | // try for XRGB first |
| 841 | m_screen_format = D3DFMT_X8R8G8B8; |
| 842 | 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); |
| 843 | if (result != D3D_OK) |
| 844 | { |
| 845 | // if not, try for ARGB |
| 846 | m_screen_format = D3DFMT_A8R8G8B8; |
| 847 | 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); |
| 848 | if (result != D3D_OK && m_texture_manager->is_dynamic_supported()) |
| 849 | { |
| 850 | m_texture_manager->set_dynamic_supported(FALSE); |
| 851 | goto try_again; |
| 852 | } |
| 853 | if (result != D3D_OK) |
| 854 | { |
| 855 | osd_printf_error("Error: unable to configure a screen texture format\n"); |
| 856 | return 1; |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | // initialize the D3D presentation parameters |
| 861 | memset(&m_presentation, 0, sizeof(m_presentation)); |
| 862 | m_presentation.BackBufferWidth = m_width; |
| 863 | m_presentation.BackBufferHeight = m_height; |
| 864 | m_presentation.BackBufferFormat = m_pixformat; |
| 865 | m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; |
| 866 | m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; |
| 867 | m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; |
| 868 | m_presentation.hDeviceWindow = window().m_hwnd; |
| 869 | m_presentation.Windowed = !window().fullscreen() || window().win_has_menu(); |
| 870 | m_presentation.EnableAutoDepthStencil = FALSE; |
| 871 | m_presentation.AutoDepthStencilFormat = D3DFMT_D16; |
| 872 | m_presentation.Flags = 0; |
| 873 | m_presentation.FullScreen_RefreshRateInHz = m_refresh; |
| 874 | m_presentation.PresentationInterval = ((video_config.triplebuf && window().fullscreen()) || |
| 875 | video_config.waitvsync || video_config.syncrefresh) ? |
| 876 | D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; |
| 877 | |
| 878 | // create the D3D device |
| 879 | result = (*d3dintf->d3d.create_device)(d3dintf, m_adapter, D3DDEVTYPE_HAL, device_hwnd, |
| 880 | D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); |
| 881 | if (result != D3D_OK) |
| 882 | { |
| 883 | // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if |
| 884 | // we exceed a threshold |
| 885 | if (result == D3DERR_DEVICELOST) |
| 886 | { |
| 887 | m_create_error_count++; |
| 888 | if (m_create_error_count < 10) |
| 889 | { |
| 890 | return 0; |
| 891 | } |
| 892 | } |
| 893 | |
| 894 | // fatal error if we just can't do it |
| 895 | osd_printf_error("Unable to create the Direct3D device (%08X)\n", (UINT32)result); |
| 896 | return 1; |
| 897 | } |
| 898 | m_create_error_count = 0; |
| 899 | osd_printf_verbose("Direct3D: Device created at %dx%d\n", m_width, m_height); |
| 900 | |
| 901 | // set the gamma if we need to |
| 902 | if (window().fullscreen()) |
| 903 | { |
| 904 | // only set the gamma if it's not 1.0f |
| 905 | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 906 | float brightness = options.full_screen_brightness(); |
| 907 | float contrast = options.full_screen_contrast(); |
| 908 | float gamma = options.full_screen_gamma(); |
| 909 | if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) |
| 910 | { |
| 911 | // warn if we can't do it |
| 912 | if (!m_gamma_supported) |
| 913 | { |
| 914 | osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n"); |
| 915 | } |
| 916 | else |
| 917 | { |
| 918 | // create a standard ramp and set it |
| 919 | D3DGAMMARAMP ramp; |
| 920 | for (int i = 0; i < 256; i++) |
| 921 | { |
| 922 | ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; |
| 923 | } |
| 924 | (*d3dintf->device.set_gamma_ramp)(m_device, 0, &ramp); |
| 925 | } |
| 926 | } |
| 927 | } |
| 928 | |
| 929 | int ret = m_shaders->create_resources(false); |
| 930 | if (ret != 0) |
| 931 | return ret; |
| 932 | |
| 933 | return device_create_resources(); |
| 934 | } |
| 935 | |
| 936 | |
| 937 | |
| 938 | //============================================================ |
| 939 | // device_create_resources |
| 940 | //============================================================ |
| 941 | |
| 942 | int renderer::device_create_resources() |
| 943 | { |
| 944 | // allocate a vertex buffer to use |
| 945 | HRESULT result = (*d3dintf->device.create_vertex_buffer)(m_device, |
| 946 | sizeof(vertex) * VERTEX_BUFFER_SIZE, |
| 947 | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, |
| 948 | VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW), |
| 949 | D3DPOOL_DEFAULT, &m_vertexbuf); |
| 950 | if (result != D3D_OK) |
| 951 | { |
| 952 | osd_printf_error("Error creating vertex buffer (%08X)\n", (UINT32)result); |
| 953 | return 1; |
| 954 | } |
| 955 | |
| 956 | // set the vertex format |
| 957 | result = (*d3dintf->device.set_vertex_format)(m_device, (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && |
| 958 | d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW))); |
| 959 | if (result != D3D_OK) |
| 960 | { |
| 961 | osd_printf_error("Error setting vertex format (%08X)\n", (UINT32)result); |
| 962 | return 1; |
| 963 | } |
| 964 | |
| 965 | // set the fixed render state |
| 966 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZENABLE, D3DZB_FALSE); |
| 967 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FILLMODE, D3DFILL_SOLID); |
| 968 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SHADEMODE, D3DSHADE_FLAT); |
| 969 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZWRITEENABLE, FALSE); |
| 970 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHATESTENABLE, TRUE); |
| 971 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LASTPIXEL, TRUE); |
| 972 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CULLMODE, D3DCULL_NONE); |
| 973 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZFUNC, D3DCMP_LESS); |
| 974 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAREF, 0); |
| 975 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); |
| 976 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DITHERENABLE, FALSE); |
| 977 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FOGENABLE, FALSE); |
| 978 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SPECULARENABLE, FALSE); |
| 979 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_STENCILENABLE, FALSE); |
| 980 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_WRAP0, FALSE); |
| 981 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CLIPPING, TRUE); |
| 982 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LIGHTING, FALSE); |
| 983 | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_COLORVERTEX, TRUE); |
| 984 | |
| 985 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); |
| 986 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); |
| 987 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE); |
| 988 | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); |
| 989 | |
| 990 | // reset the local states to force updates |
| 991 | reset_render_states(); |
| 992 | |
| 993 | // clear the buffer |
| 994 | result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 995 | result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0); |
| 996 | |
| 997 | m_texture_manager->create_resources(); |
| 998 | |
| 999 | return 0; |
| 1000 | } |
| 1001 | |
| 1002 | |
| 1003 | |
| 1004 | //============================================================ |
| 1005 | // device_delete |
| 1006 | //============================================================ |
| 1007 | |
| 1008 | renderer::~renderer() |
| 1009 | { |
| 1010 | device_delete(); |
| 1011 | } |
| 1012 | |
| 1013 | void renderer::device_delete() |
| 1014 | { |
| 1015 | if (m_shaders != NULL) |
| 1016 | { |
| 1017 | // free our effects |
| 1018 | m_shaders->delete_resources(false); |
| 1019 | |
| 1020 | // delete the HLSL interface |
| 1021 | global_free(m_shaders); |
| 1022 | } |
| 1023 | |
| 1024 | // free our base resources |
| 1025 | device_delete_resources(); |
| 1026 | |
| 1027 | if (m_texture_manager != NULL) |
| 1028 | { |
| 1029 | global_free(m_texture_manager); |
| 1030 | } |
| 1031 | m_texture_manager = NULL; |
| 1032 | |
| 1033 | // free the device itself |
| 1034 | if (m_device != NULL) |
| 1035 | { |
| 1036 | (*d3dintf->device.reset)(m_device, &m_presentation); |
| 1037 | (*d3dintf->device.release)(m_device); |
| 1038 | } |
| 1039 | m_device = NULL; |
| 1040 | } |
| 1041 | |
| 1042 | //============================================================ |
| 1043 | // device_delete_resources |
| 1044 | //============================================================ |
| 1045 | |
| 1046 | void renderer::device_delete_resources() |
| 1047 | { |
| 1048 | if (m_texture_manager != NULL) |
| 1049 | m_texture_manager->delete_resources(); |
| 1050 | // free the vertex buffer |
| 1051 | if (m_vertexbuf != NULL) |
| 1052 | (*d3dintf->vertexbuf.release)(m_vertexbuf); |
| 1053 | m_vertexbuf = NULL; |
| 1054 | } |
| 1055 | |
| 1056 | |
| 1057 | |
| 1058 | //============================================================ |
| 1059 | // device_verify_caps |
| 1060 | //============================================================ |
| 1061 | |
| 1062 | int renderer::device_verify_caps() |
| 1063 | { |
| 1064 | int retval = 0; |
| 1065 | |
| 1066 | m_shaders = global_alloc_clear(shaders); |
| 1067 | // FIXME: Dynamic cast |
| 1068 | m_shaders->init(d3dintf, &window().machine(), this); |
| 1069 | |
| 1070 | DWORD tempcaps; |
| 1071 | HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_MAX_PS30_INSN_SLOTS, &tempcaps); |
| 1072 | if (result != D3D_OK) osd_printf_verbose("Direct3D Error %08X during get_caps_dword call\n", (int)result); |
| 1073 | if (tempcaps < 512) |
| 1074 | { |
| 1075 | osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); |
| 1076 | d3dintf->post_fx_available = false; |
| 1077 | } |
| 1078 | |
| 1079 | // verify presentation capabilities |
| 1080 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_PRESENTATION_INTERVALS, &tempcaps); |
| 1081 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1082 | if (!(tempcaps & D3DPRESENT_INTERVAL_IMMEDIATE)) |
| 1083 | { |
| 1084 | osd_printf_verbose("Direct3D: Error - Device does not support immediate presentations\n"); |
| 1085 | retval = 2; |
| 1086 | } |
| 1087 | if (!(tempcaps & D3DPRESENT_INTERVAL_ONE)) |
| 1088 | { |
| 1089 | osd_printf_verbose("Direct3D: Error - Device does not support per-refresh presentations\n"); |
| 1090 | retval = 2; |
| 1091 | } |
| 1092 | |
| 1093 | // verify device capabilities |
| 1094 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_DEV_CAPS, &tempcaps); |
| 1095 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1096 | if (!(tempcaps & D3DDEVCAPS_CANRENDERAFTERFLIP)) |
| 1097 | { |
| 1098 | osd_printf_verbose("Direct3D: Warning - Device does not support queued rendering after a page flip\n"); |
| 1099 | retval = 1; |
| 1100 | } |
| 1101 | if (!(tempcaps & D3DDEVCAPS_HWRASTERIZATION)) |
| 1102 | { |
| 1103 | osd_printf_verbose("Direct3D: Warning - Device does not support hardware rasterization\n"); |
| 1104 | retval = 1; |
| 1105 | } |
| 1106 | |
| 1107 | // verify texture operation capabilities |
| 1108 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_TEXTURE_OP_CAPS, &tempcaps); |
| 1109 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1110 | if (!(tempcaps & D3DTEXOPCAPS_MODULATE)) |
| 1111 | { |
| 1112 | osd_printf_verbose("Direct3D: Warning - Device does not support texture modulation\n"); |
| 1113 | retval = 1; |
| 1114 | } |
| 1115 | |
| 1116 | // set a simpler flag to indicate mod2x and mod4x texture modes |
| 1117 | m_mod2x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE2X) != 0); |
| 1118 | m_mod4x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE4X) != 0); |
| 1119 | |
| 1120 | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps); |
| 1121 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1122 | m_gamma_supported = ((tempcaps & D3DCAPS2_FULLSCREENGAMMA) != 0); |
| 1123 | |
| 1124 | return retval; |
| 1125 | } |
| 1126 | |
| 1127 | |
| 1128 | |
| 1129 | //============================================================ |
| 1130 | // device_test_cooperative |
| 1131 | //============================================================ |
| 1132 | |
| 1133 | int renderer::device_test_cooperative() |
| 1134 | { |
| 1135 | // check our current status; if we lost the device, punt to GDI |
| 1136 | HRESULT result = (*d3dintf->device.test_cooperative_level)(m_device); |
| 1137 | if (result == D3DERR_DEVICELOST) |
| 1138 | return 1; |
| 1139 | |
| 1140 | // if we're able to reset ourselves, try it |
| 1141 | if (result == D3DERR_DEVICENOTRESET) |
| 1142 | { |
| 1143 | osd_printf_verbose("Direct3D: resetting device\n"); |
| 1144 | |
| 1145 | // free all existing resources and call reset on the device |
| 1146 | //device_delete(); |
| 1147 | device_delete_resources(); |
| 1148 | m_shaders->delete_resources(true); |
| 1149 | result = (*d3dintf->device.reset)(m_device, &m_presentation); |
| 1150 | |
| 1151 | // if it didn't work, punt to GDI |
| 1152 | if (result != D3D_OK) |
| 1153 | { |
| 1154 | osd_printf_error("Unable to reset, result %08x\n", (UINT32)result); |
| 1155 | return 1; |
| 1156 | } |
| 1157 | |
| 1158 | // try to create the resources again; if that didn't work, delete the whole thing |
| 1159 | if (device_create_resources()) |
| 1160 | { |
| 1161 | osd_printf_verbose("Direct3D: failed to recreate resources for device; failing permanently\n"); |
| 1162 | device_delete(); |
| 1163 | return 1; |
| 1164 | } |
| 1165 | |
| 1166 | if (m_shaders->create_resources(true)) |
| 1167 | { |
| 1168 | osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n"); |
| 1169 | device_delete(); |
| 1170 | return 1; |
| 1171 | } |
| 1172 | } |
| 1173 | return 0; |
| 1174 | } |
| 1175 | |
| 1176 | |
| 1177 | |
| 1178 | //============================================================ |
| 1179 | // config_adapter_mode |
| 1180 | //============================================================ |
| 1181 | |
| 1182 | int renderer::config_adapter_mode() |
| 1183 | { |
| 1184 | adapter_identifier identifier; |
| 1185 | |
| 1186 | // choose the monitor number |
| 1187 | m_adapter = get_adapter_for_monitor(); |
| 1188 | |
| 1189 | // get the identifier |
| 1190 | HRESULT result = (*d3dintf->d3d.get_adapter_identifier)(d3dintf, m_adapter, 0, &identifier); |
| 1191 | if (result != D3D_OK) |
| 1192 | { |
| 1193 | osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter); |
| 1194 | return 1; |
| 1195 | } |
| 1196 | osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, identifier.Description); |
| 1197 | |
| 1198 | // get the current display mode |
| 1199 | result = (*d3dintf->d3d.get_adapter_display_mode)(d3dintf, m_adapter, &m_origmode); |
| 1200 | if (result != D3D_OK) |
| 1201 | { |
| 1202 | osd_printf_error("Error getting mode for adapter #%d\n", m_adapter); |
| 1203 | return 1; |
| 1204 | } |
| 1205 | |
| 1206 | // choose a resolution: window mode case |
| 1207 | if (!window().fullscreen() || !video_config.switchres || window().win_has_menu()) |
| 1208 | { |
| 1209 | RECT client; |
| 1210 | |
| 1211 | // bounds are from the window client rect |
| 1212 | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 1213 | m_width = client.right - client.left; |
| 1214 | m_height = client.bottom - client.top; |
| 1215 | |
| 1216 | // pix format is from the current mode |
| 1217 | m_pixformat = m_origmode.Format; |
| 1218 | m_refresh = 0; |
| 1219 | |
| 1220 | // make sure it's a pixel format we can get behind |
| 1221 | if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8) |
| 1222 | { |
| 1223 | osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename()); |
| 1224 | return 1; |
| 1225 | } |
| 1226 | } |
| 1227 | |
| 1228 | // choose a resolution: full screen mode case |
| 1229 | else |
| 1230 | { |
| 1231 | // default to the current mode exactly |
| 1232 | m_width = m_origmode.Width; |
| 1233 | m_height = m_origmode.Height; |
| 1234 | m_pixformat = m_origmode.Format; |
| 1235 | m_refresh = m_origmode.RefreshRate; |
| 1236 | |
| 1237 | // if we're allowed to switch resolutions, override with something better |
| 1238 | if (video_config.switchres) |
| 1239 | pick_best_mode(); |
| 1240 | } |
| 1241 | |
| 1242 | // see if we can handle the device type |
| 1243 | result = (*d3dintf->d3d.check_device_type)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen()); |
| 1244 | if (result != D3D_OK) |
| 1245 | { |
| 1246 | osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename()); |
| 1247 | return 1; |
| 1248 | } |
| 1249 | return 0; |
| 1250 | } |
| 1251 | |
| 1252 | |
| 1253 | |
| 1254 | //============================================================ |
| 1255 | // get_adapter_for_monitor |
| 1256 | //============================================================ |
| 1257 | |
| 1258 | int renderer::get_adapter_for_monitor() |
| 1259 | { |
| 1260 | int maxadapter = (*d3dintf->d3d.get_adapter_count)(d3dintf); |
| 1261 | |
| 1262 | // iterate over adapters until we error or find a match |
| 1263 | for (int adapternum = 0; adapternum < maxadapter; adapternum++) |
| 1264 | { |
| 1265 | // get the monitor for this adapter |
| 1266 | HMONITOR curmonitor = (*d3dintf->d3d.get_adapter_monitor)(d3dintf, adapternum); |
| 1267 | |
| 1268 | // if we match the proposed monitor, this is it |
| 1269 | if (curmonitor == window().monitor()->handle()) |
| 1270 | { |
| 1271 | return adapternum; |
| 1272 | } |
| 1273 | } |
| 1274 | |
| 1275 | // default to the default |
| 1276 | return D3DADAPTER_DEFAULT; |
| 1277 | } |
| 1278 | |
| 1279 | |
| 1280 | |
| 1281 | //============================================================ |
| 1282 | // pick_best_mode |
| 1283 | //============================================================ |
| 1284 | |
| 1285 | void renderer::pick_best_mode() |
| 1286 | { |
| 1287 | double target_refresh = 60.0; |
| 1288 | INT32 minwidth, minheight; |
| 1289 | float best_score = 0.0f; |
| 1290 | |
| 1291 | // determine the refresh rate of the primary screen |
| 1292 | const screen_device *primary_screen = window().machine().config().first_screen(); |
| 1293 | if (primary_screen != NULL) |
| 1294 | { |
| 1295 | target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); |
| 1296 | } |
| 1297 | |
| 1298 | // determine the minimum width/height for the selected target |
| 1299 | // note: technically we should not be calling this from an alternate window |
| 1300 | // thread; however, it is only done during init time, and the init code on |
| 1301 | // the main thread is waiting for us to finish, so it is safe to do so here |
| 1302 | window().target()->compute_minimum_size(minwidth, minheight); |
| 1303 | |
| 1304 | // use those as the target for now |
| 1305 | INT32 target_width = minwidth; |
| 1306 | INT32 target_height = minheight; |
| 1307 | |
| 1308 | // determine the maximum number of modes |
| 1309 | int maxmodes = (*d3dintf->d3d.get_adapter_mode_count)(d3dintf, m_adapter, D3DFMT_X8R8G8B8); |
| 1310 | |
| 1311 | // enumerate all the video modes and find the best match |
| 1312 | osd_printf_verbose("Direct3D: Selecting video mode...\n"); |
| 1313 | for (int modenum = 0; modenum < maxmodes; modenum++) |
| 1314 | { |
| 1315 | // check this mode |
| 1316 | D3DDISPLAYMODE mode; |
| 1317 | HRESULT result = (*d3dintf->d3d.enum_adapter_modes)(d3dintf, m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); |
| 1318 | if (result != D3D_OK) |
| 1319 | break; |
| 1320 | |
| 1321 | // skip non-32 bit modes |
| 1322 | if (mode.Format != D3DFMT_X8R8G8B8) |
| 1323 | continue; |
| 1324 | |
| 1325 | // compute initial score based on difference between target and current |
| 1326 | float size_score = 1.0f / (1.0f + fabs((float)(mode.Width - target_width)) + fabs((float)(mode.Height - target_height))); |
| 1327 | |
| 1328 | // if the mode is too small, give a big penalty |
| 1329 | if (mode.Width < minwidth || mode.Height < minheight) |
| 1330 | size_score *= 0.01f; |
| 1331 | |
| 1332 | // if mode is smaller than we'd like, it only scores up to 0.1 |
| 1333 | if (mode.Width < target_width || mode.Height < target_height) |
| 1334 | size_score *= 0.1f; |
| 1335 | |
| 1336 | // if we're looking for a particular mode, that's a winner |
| 1337 | if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height) |
| 1338 | size_score = 2.0f; |
| 1339 | |
| 1340 | // compute refresh score |
| 1341 | float refresh_score = 1.0f / (1.0f + fabs((double)mode.RefreshRate - target_refresh)); |
| 1342 | |
| 1343 | // if refresh is smaller than we'd like, it only scores up to 0.1 |
| 1344 | if ((double)mode.RefreshRate < target_refresh) |
| 1345 | refresh_score *= 0.1f; |
| 1346 | |
| 1347 | // if we're looking for a particular refresh, make sure it matches |
| 1348 | if (mode.RefreshRate == window().m_win_config.refresh) |
| 1349 | refresh_score = 2.0f; |
| 1350 | |
| 1351 | // weight size and refresh equally |
| 1352 | float final_score = size_score + refresh_score; |
| 1353 | |
| 1354 | // best so far? |
| 1355 | osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", mode.Width, mode.Height, mode.RefreshRate, final_score * 1000.0f); |
| 1356 | if (final_score > best_score) |
| 1357 | { |
| 1358 | best_score = final_score; |
| 1359 | m_width = mode.Width; |
| 1360 | m_height = mode.Height; |
| 1361 | m_pixformat = mode.Format; |
| 1362 | m_refresh = mode.RefreshRate; |
| 1363 | } |
| 1364 | } |
| 1365 | osd_printf_verbose("Direct3D: Mode selected = %4dx%4d@%3dHz\n", m_width, m_height, m_refresh); |
| 1366 | } |
| 1367 | |
| 1368 | |
| 1369 | |
| 1370 | //============================================================ |
| 1371 | // update_window_size |
| 1372 | //============================================================ |
| 1373 | |
| 1374 | int renderer::update_window_size() |
| 1375 | { |
| 1376 | // get the current window bounds |
| 1377 | RECT client; |
| 1378 | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 1379 | |
| 1380 | // if we have a device and matching width/height, nothing to do |
| 1381 | if (m_device != NULL && rect_width(&client) == m_width && rect_height(&client) == m_height) |
| 1382 | { |
| 1383 | // clear out any pending resizing if the area didn't change |
| 1384 | if (window().m_resize_state == RESIZE_STATE_PENDING) |
| 1385 | window().m_resize_state = RESIZE_STATE_NORMAL; |
| 1386 | return FALSE; |
| 1387 | } |
| 1388 | |
| 1389 | // if we're in the middle of resizing, leave it alone as well |
| 1390 | if (window().m_resize_state == RESIZE_STATE_RESIZING) |
| 1391 | return FALSE; |
| 1392 | |
| 1393 | // set the new bounds and create the device again |
| 1394 | m_width = rect_width(&client); |
| 1395 | m_height = rect_height(&client); |
| 1396 | if (device_create(window().m_focus_hwnd)) |
| 1397 | return FALSE; |
| 1398 | |
| 1399 | // reset the resize state to normal, and indicate we made a change |
| 1400 | window().m_resize_state = RESIZE_STATE_NORMAL; |
| 1401 | return TRUE; |
| 1402 | } |
| 1403 | |
| 1404 | //============================================================ |
| 1405 | // batch_vectors |
| 1406 | //============================================================ |
| 1407 | |
| 1408 | void renderer::batch_vectors() |
| 1409 | { |
| 1410 | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 1411 | |
| 1412 | int vector_size = (options.antialias() ? 24 : 6); |
| 1413 | m_vectorbatch = mesh_alloc(m_line_count * vector_size); |
| 1414 | m_batchindex = 0; |
| 1415 | |
| 1416 | static int start_index = 0; |
| 1417 | int line_index = 0; |
| 1418 | float period = options.screen_vector_time_period(); |
| 1419 | UINT32 cached_flags = 0; |
| 1420 | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 1421 | { |
| 1422 | switch (prim->type) |
| 1423 | { |
| 1424 | case render_primitive::LINE: |
| 1425 | if (PRIMFLAG_GET_VECTOR(prim->flags)) |
| 1426 | { |
| 1427 | if (period == 0.0f || m_line_count == 0) |
| 1428 | { |
| 1429 | batch_vector(prim, 1.0f); |
| 1430 | } |
| 1431 | else |
| 1432 | { |
| 1433 | batch_vector(prim, (float)(start_index + line_index) / ((float)m_line_count * period)); |
| 1434 | line_index++; |
| 1435 | } |
| 1436 | cached_flags = prim->flags; |
| 1437 | } |
| 1438 | break; |
| 1439 | |
| 1440 | default: |
| 1441 | // Skip |
| 1442 | break; |
| 1443 | } |
| 1444 | } |
| 1445 | |
| 1446 | // now add a polygon entry |
| 1447 | m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, m_line_count * (options.antialias() ? 8 : 2), vector_size * m_line_count, cached_flags, |
| 1448 | m_texture_manager->get_vector_texture(), D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f); |
| 1449 | m_numpolys++; |
| 1450 | |
| 1451 | start_index += (int)((float)line_index * period); |
| 1452 | if (m_line_count > 0) |
| 1453 | { |
| 1454 | start_index %= m_line_count; |
| 1455 | } |
| 1456 | |
| 1457 | m_line_count = 0; |
| 1458 | } |
| 1459 | |
| 1460 | void renderer::batch_vector(const render_primitive *prim, float line_time) |
| 1461 | { |
| 1462 | // compute the effective width based on the direction of the line |
| 1463 | float effwidth = prim->width; |
| 1464 | if (effwidth < 0.5f) |
| 1465 | { |
| 1466 | effwidth = 0.5f; |
| 1467 | } |
| 1468 | |
| 1469 | // determine the bounds of a quad to draw this line |
| 1470 | render_bounds b0, b1; |
| 1471 | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1472 | |
| 1473 | // iterate over AA steps |
| 1474 | for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; |
| 1475 | step->weight != 0; step++) |
| 1476 | { |
| 1477 | // get a pointer to the vertex buffer |
| 1478 | if (m_vectorbatch == NULL) |
| 1479 | return; |
| 1480 | |
| 1481 | m_vectorbatch[m_batchindex + 0].x = b0.x0 + step->xoffs; |
| 1482 | m_vectorbatch[m_batchindex + 0].y = b0.y0 + step->yoffs; |
| 1483 | m_vectorbatch[m_batchindex + 1].x = b0.x1 + step->xoffs; |
| 1484 | m_vectorbatch[m_batchindex + 1].y = b0.y1 + step->yoffs; |
| 1485 | m_vectorbatch[m_batchindex + 2].x = b1.x0 + step->xoffs; |
| 1486 | m_vectorbatch[m_batchindex + 2].y = b1.y0 + step->yoffs; |
| 1487 | |
| 1488 | m_vectorbatch[m_batchindex + 3].x = b0.x1 + step->xoffs; |
| 1489 | m_vectorbatch[m_batchindex + 3].y = b0.y1 + step->yoffs; |
| 1490 | m_vectorbatch[m_batchindex + 4].x = b1.x0 + step->xoffs; |
| 1491 | m_vectorbatch[m_batchindex + 4].y = b1.y0 + step->yoffs; |
| 1492 | m_vectorbatch[m_batchindex + 5].x = b1.x1 + step->xoffs; |
| 1493 | m_vectorbatch[m_batchindex + 5].y = b1.y1 + step->yoffs; |
| 1494 | |
| 1495 | float dx = b1.x1 - b0.x1; |
| 1496 | float dy = b1.y1 - b0.y1; |
| 1497 | float line_length = sqrtf(dx * dx + dy * dy); |
| 1498 | |
| 1499 | // determine the color of the line |
| 1500 | INT32 r = (INT32)(prim->color.r * step->weight * 255.0f); |
| 1501 | INT32 g = (INT32)(prim->color.g * step->weight * 255.0f); |
| 1502 | INT32 b = (INT32)(prim->color.b * step->weight * 255.0f); |
| 1503 | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1504 | if (r > 255 || g > 255 || b > 255) |
| 1505 | { |
| 1506 | if (r > 2*255 || g > 2*255 || b > 2*255) |
| 1507 | { |
| 1508 | r >>= 2; g >>= 2; b >>= 2; |
| 1509 | } |
| 1510 | else |
| 1511 | { |
| 1512 | r >>= 1; g >>= 1; b >>= 1; |
| 1513 | } |
| 1514 | } |
| 1515 | if (r > 255) r = 255; |
| 1516 | if (g > 255) g = 255; |
| 1517 | if (b > 255) b = 255; |
| 1518 | if (a > 255) a = 255; |
| 1519 | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1520 | |
| 1521 | vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart()); |
| 1522 | vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop()); |
| 1523 | |
| 1524 | m_vectorbatch[m_batchindex + 0].u0 = start.c.x; |
| 1525 | m_vectorbatch[m_batchindex + 0].v0 = start.c.y; |
| 1526 | m_vectorbatch[m_batchindex + 1].u0 = start.c.x; |
| 1527 | m_vectorbatch[m_batchindex + 1].v0 = stop.c.y; |
| 1528 | m_vectorbatch[m_batchindex + 2].u0 = stop.c.x; |
| 1529 | m_vectorbatch[m_batchindex + 2].v0 = start.c.y; |
| 1530 | |
| 1531 | m_vectorbatch[m_batchindex + 3].u0 = start.c.x; |
| 1532 | m_vectorbatch[m_batchindex + 3].v0 = stop.c.y; |
| 1533 | m_vectorbatch[m_batchindex + 4].u0 = stop.c.x; |
| 1534 | m_vectorbatch[m_batchindex + 4].v0 = start.c.y; |
| 1535 | m_vectorbatch[m_batchindex + 5].u0 = stop.c.x; |
| 1536 | m_vectorbatch[m_batchindex + 5].v0 = stop.c.y; |
| 1537 | |
| 1538 | m_vectorbatch[m_batchindex + 0].u1 = line_length; |
| 1539 | m_vectorbatch[m_batchindex + 1].u1 = line_length; |
| 1540 | m_vectorbatch[m_batchindex + 2].u1 = line_length; |
| 1541 | m_vectorbatch[m_batchindex + 3].u1 = line_length; |
| 1542 | m_vectorbatch[m_batchindex + 4].u1 = line_length; |
| 1543 | m_vectorbatch[m_batchindex + 5].u1 = line_length; |
| 1544 | |
| 1545 | // set the color, Z parameters to standard values |
| 1546 | for (int i = 0; i < 6; i++) |
| 1547 | { |
| 1548 | m_vectorbatch[m_batchindex + i].z = 0.0f; |
| 1549 | m_vectorbatch[m_batchindex + i].rhw = 1.0f; |
| 1550 | m_vectorbatch[m_batchindex + i].color = color; |
| 1551 | } |
| 1552 | |
| 1553 | m_batchindex += 6; |
| 1554 | } |
| 1555 | } |
| 1556 | |
| 1557 | //============================================================ |
| 1558 | // draw_line |
| 1559 | //============================================================ |
| 1560 | |
| 1561 | void renderer::draw_line(const render_primitive *prim) |
| 1562 | { |
| 1563 | // compute the effective width based on the direction of the line |
| 1564 | float effwidth = prim->width; |
| 1565 | if (effwidth < 0.5f) |
| 1566 | { |
| 1567 | effwidth = 0.5f; |
| 1568 | } |
| 1569 | |
| 1570 | // determine the bounds of a quad to draw this line |
| 1571 | render_bounds b0, b1; |
| 1572 | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1573 | |
| 1574 | // iterate over AA steps |
| 1575 | for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; |
| 1576 | step->weight != 0; step++) |
| 1577 | { |
| 1578 | // get a pointer to the vertex buffer |
| 1579 | vertex *vertex = mesh_alloc(4); |
| 1580 | if (vertex == NULL) |
| 1581 | return; |
| 1582 | |
| 1583 | // rotate the unit vector by 135 degrees and add to point 0 |
| 1584 | vertex[0].x = b0.x0 + step->xoffs; |
| 1585 | vertex[0].y = b0.y0 + step->yoffs; |
| 1586 | |
| 1587 | // rotate the unit vector by -135 degrees and add to point 0 |
| 1588 | vertex[1].x = b0.x1 + step->xoffs; |
| 1589 | vertex[1].y = b0.y1 + step->yoffs; |
| 1590 | |
| 1591 | // rotate the unit vector by 45 degrees and add to point 1 |
| 1592 | vertex[2].x = b1.x0 + step->xoffs; |
| 1593 | vertex[2].y = b1.y0 + step->yoffs; |
| 1594 | |
| 1595 | // rotate the unit vector by -45 degrees and add to point 1 |
| 1596 | vertex[3].x = b1.x1 + step->xoffs; |
| 1597 | vertex[3].y = b1.y1 + step->yoffs; |
| 1598 | |
| 1599 | // determine the color of the line |
| 1600 | INT32 r = (INT32)(prim->color.r * step->weight * 255.0f); |
| 1601 | INT32 g = (INT32)(prim->color.g * step->weight * 255.0f); |
| 1602 | INT32 b = (INT32)(prim->color.b * step->weight * 255.0f); |
| 1603 | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1604 | if (r > 255) r = 255; |
| 1605 | if (g > 255) g = 255; |
| 1606 | if (b > 255) b = 255; |
| 1607 | if (a > 255) a = 255; |
| 1608 | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1609 | |
| 1610 | vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart()); |
| 1611 | vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop()); |
| 1612 | |
| 1613 | vertex[0].u0 = start.c.x; |
| 1614 | vertex[0].v0 = start.c.y; |
| 1615 | |
| 1616 | vertex[2].u0 = stop.c.x; |
| 1617 | vertex[2].v0 = start.c.y; |
| 1618 | |
| 1619 | vertex[1].u0 = start.c.x; |
| 1620 | vertex[1].v0 = stop.c.y; |
| 1621 | |
| 1622 | vertex[3].u0 = stop.c.x; |
| 1623 | vertex[3].v0 = stop.c.y; |
| 1624 | |
| 1625 | // set the color, Z parameters to standard values |
| 1626 | for (int i = 0; i < 4; i++) |
| 1627 | { |
| 1628 | vertex[i].z = 0.0f; |
| 1629 | vertex[i].rhw = 1.0f; |
| 1630 | vertex[i].color = color; |
| 1631 | } |
| 1632 | |
| 1633 | // now add a polygon entry |
| 1634 | m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, get_vector_texture(), |
| 1635 | D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f); |
| 1636 | m_numpolys++; |
| 1637 | } |
| 1638 | } |
| 1639 | |
| 1640 | |
| 1641 | |
| 1642 | //============================================================ |
| 1643 | // draw_quad |
| 1644 | //============================================================ |
| 1645 | |
| 1646 | void renderer::draw_quad(const render_primitive *prim) |
| 1647 | { |
| 1648 | texture_info *texture = m_texture_manager->find_texinfo(&prim->texture, prim->flags); |
| 1649 | |
| 1650 | if (texture == NULL) |
| 1651 | { |
| 1652 | texture = get_default_texture(); |
| 1653 | } |
| 1654 | |
| 1655 | // get a pointer to the vertex buffer |
| 1656 | vertex *vertex = mesh_alloc(4); |
| 1657 | if (vertex == NULL) |
| 1658 | return; |
| 1659 | |
| 1660 | // fill in the vertexes clockwise |
| 1661 | vertex[0].x = prim->bounds.x0 - 0.5f; |
| 1662 | vertex[0].y = prim->bounds.y0 - 0.5f; |
| 1663 | vertex[1].x = prim->bounds.x1 - 0.5f; |
| 1664 | vertex[1].y = prim->bounds.y0 - 0.5f; |
| 1665 | vertex[2].x = prim->bounds.x0 - 0.5f; |
| 1666 | vertex[2].y = prim->bounds.y1 - 0.5f; |
| 1667 | vertex[3].x = prim->bounds.x1 - 0.5f; |
| 1668 | vertex[3].y = prim->bounds.y1 - 0.5f; |
| 1669 | float width = prim->bounds.x1 - prim->bounds.x0; |
| 1670 | float height = prim->bounds.y1 - prim->bounds.y0; |
| 1671 | |
| 1672 | // set the texture coordinates |
| 1673 | if(texture != NULL) |
| 1674 | { |
| 1675 | vec2f& start = texture->get_uvstart(); |
| 1676 | vec2f& stop = texture->get_uvstop(); |
| 1677 | vec2f delta = stop - start; |
| 1678 | vertex[0].u0 = start.c.x + delta.c.x * prim->texcoords.tl.u; |
| 1679 | vertex[0].v0 = start.c.y + delta.c.y * prim->texcoords.tl.v; |
| 1680 | vertex[1].u0 = start.c.x + delta.c.x * prim->texcoords.tr.u; |
| 1681 | vertex[1].v0 = start.c.y + delta.c.y * prim->texcoords.tr.v; |
| 1682 | vertex[2].u0 = start.c.x + delta.c.x * prim->texcoords.bl.u; |
| 1683 | vertex[2].v0 = start.c.y + delta.c.y * prim->texcoords.bl.v; |
| 1684 | vertex[3].u0 = start.c.x + delta.c.x * prim->texcoords.br.u; |
| 1685 | vertex[3].v0 = start.c.y + delta.c.y * prim->texcoords.br.v; |
| 1686 | } |
| 1687 | |
| 1688 | // determine the color, allowing for over modulation |
| 1689 | INT32 r = (INT32)(prim->color.r * 255.0f); |
| 1690 | INT32 g = (INT32)(prim->color.g * 255.0f); |
| 1691 | INT32 b = (INT32)(prim->color.b * 255.0f); |
| 1692 | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1693 | DWORD modmode = D3DTOP_MODULATE; |
| 1694 | if (texture != NULL) |
| 1695 | { |
| 1696 | if (m_mod2x_supported && (r > 255 || g > 255 || b > 255)) |
| 1697 | { |
| 1698 | if (m_mod4x_supported && (r > 2*255 || g > 2*255 || b > 2*255)) |
| 1699 | { |
| 1700 | r >>= 2; g >>= 2; b >>= 2; |
| 1701 | modmode = D3DTOP_MODULATE4X; |
| 1702 | } |
| 1703 | else |
| 1704 | { |
| 1705 | r >>= 1; g >>= 1; b >>= 1; |
| 1706 | modmode = D3DTOP_MODULATE2X; |
| 1707 | } |
| 1708 | } |
| 1709 | } |
| 1710 | if (r > 255) r = 255; |
| 1711 | if (g > 255) g = 255; |
| 1712 | if (b > 255) b = 255; |
| 1713 | if (a > 255) a = 255; |
| 1714 | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1715 | |
| 1716 | // set the color, Z parameters to standard values |
| 1717 | for (int i = 0; i < 4; i++) |
| 1718 | { |
| 1719 | vertex[i].z = 0.0f; |
| 1720 | vertex[i].rhw = 1.0f; |
| 1721 | vertex[i].color = color; |
| 1722 | } |
| 1723 | |
| 1724 | // now add a polygon entry |
| 1725 | m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, texture, modmode, width, height); |
| 1726 | m_numpolys++; |
| 1727 | } |
| 1728 | |
| 1729 | void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts, |
| 1730 | UINT32 flags, texture_info *texture, UINT32 modmode, |
| 1731 | float line_time, float line_length, |
| 1732 | float prim_width, float prim_height) |
| 1733 | { |
| 1734 | init(type, count, numverts, flags, texture, modmode, prim_width, prim_height); |
| 1735 | m_line_time = line_time; |
| 1736 | m_line_length = line_length; |
| 1737 | } |
| 1738 | |
| 1739 | void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts, |
| 1740 | UINT32 flags, texture_info *texture, UINT32 modmode, |
| 1741 | float prim_width, float prim_height) |
| 1742 | { |
| 1743 | m_type = type; |
| 1744 | m_count = count; |
| 1745 | m_numverts = numverts; |
| 1746 | m_flags = flags; |
| 1747 | m_texture = texture; |
| 1748 | m_modmode = modmode; |
| 1749 | m_prim_width = prim_width; |
| 1750 | m_prim_height = prim_height; |
| 1751 | } |
| 1752 | |
| 1753 | //============================================================ |
| 1754 | // primitive_alloc |
| 1755 | //============================================================ |
| 1756 | |
| 1757 | vertex *renderer::mesh_alloc(int numverts) |
| 1758 | { |
| 1759 | HRESULT result; |
| 1760 | |
| 1761 | // if we're going to overflow, flush |
| 1762 | if (m_lockedbuf != NULL && m_numverts + numverts >= VERTEX_BUFFER_SIZE) |
| 1763 | { |
| 1764 | primitive_flush_pending(); |
| 1765 | |
| 1766 | if(m_shaders->enabled()) |
| 1767 | { |
| 1768 | m_hlsl_buf = (void*)mesh_alloc(6); |
| 1769 | m_shaders->init_fsfx_quad(m_hlsl_buf); |
| 1770 | } |
| 1771 | } |
| 1772 | |
| 1773 | // if we don't have a lock, grab it now |
| 1774 | if (m_lockedbuf == NULL) |
| 1775 | { |
| 1776 | result = (*d3dintf->vertexbuf.lock)(m_vertexbuf, 0, 0, (VOID **)&m_lockedbuf, D3DLOCK_DISCARD); |
| 1777 | if (result != D3D_OK) |
| 1778 | return NULL; |
| 1779 | } |
| 1780 | |
| 1781 | // if we already have the lock and enough room, just return a pointer |
| 1782 | if (m_lockedbuf != NULL && m_numverts + numverts < VERTEX_BUFFER_SIZE) |
| 1783 | { |
| 1784 | int oldverts = m_numverts; |
| 1785 | m_numverts += numverts; |
| 1786 | return &m_lockedbuf[oldverts]; |
| 1787 | } |
| 1788 | return NULL; |
| 1789 | } |
| 1790 | |
| 1791 | |
| 1792 | |
| 1793 | //============================================================ |
| 1794 | // primitive_flush_pending |
| 1795 | //============================================================ |
| 1796 | |
| 1797 | void renderer::primitive_flush_pending() |
| 1798 | { |
| 1799 | // ignore if we're not locked |
| 1800 | if (m_lockedbuf == NULL) |
| 1801 | { |
| 1802 | return; |
| 1803 | } |
| 1804 | |
| 1805 | // unlock the buffer |
| 1806 | HRESULT result = (*d3dintf->vertexbuf.unlock)(m_vertexbuf); |
| 1807 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result); |
| 1808 | m_lockedbuf = NULL; |
| 1809 | |
| 1810 | // set the stream |
| 1811 | result = (*d3dintf->device.set_stream_source)(m_device, 0, m_vertexbuf, sizeof(vertex)); |
| 1812 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result); |
| 1813 | |
| 1814 | m_shaders->begin_draw(); |
| 1815 | |
| 1816 | int vertnum = 0; |
| 1817 | if (m_shaders->enabled()) |
| 1818 | { |
| 1819 | vertnum = 6; |
| 1820 | } |
| 1821 | |
| 1822 | // now do the polys |
| 1823 | for (int polynum = 0; polynum < m_numpolys; polynum++) |
| 1824 | { |
| 1825 | UINT32 flags = m_poly[polynum].get_flags(); |
| 1826 | texture_info *texture = m_poly[polynum].get_texture(); |
| 1827 | int newfilter; |
| 1828 | |
| 1829 | // set the texture if different |
| 1830 | set_texture(texture); |
| 1831 | |
| 1832 | // set filtering if different |
| 1833 | if (texture != NULL) |
| 1834 | { |
| 1835 | newfilter = FALSE; |
| 1836 | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 1837 | newfilter = video_config.filter; |
| 1838 | set_filter(newfilter); |
| 1839 | set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); |
| 1840 | set_modmode(m_poly[polynum].get_modmode()); |
| 1841 | |
| 1842 | m_shaders->init_effect_info(&m_poly[polynum]); |
| 1843 | } |
| 1844 | |
| 1845 | // set the blendmode if different |
| 1846 | set_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); |
| 1847 | |
| 1848 | if (vertnum + m_poly[polynum].get_vertcount() > m_numverts) |
| 1849 | { |
| 1850 | osd_printf_error("Error: vertnum (%d) plus poly vertex count (%d) > %d\n", vertnum, m_poly[polynum].get_vertcount(), m_numverts); |
| 1851 | fflush(stdout); |
| 1852 | } |
| 1853 | |
| 1854 | assert(vertnum + m_poly[polynum].get_vertcount() <= m_numverts); |
| 1855 | |
| 1856 | if(m_shaders->enabled() && d3dintf->post_fx_available) |
| 1857 | { |
| 1858 | m_shaders->render_quad(&m_poly[polynum], vertnum); |
| 1859 | } |
| 1860 | else |
| 1861 | { |
| 1862 | // add the primitives |
| 1863 | result = (*d3dintf->device.draw_primitive)(m_device, m_poly[polynum].get_type(), vertnum, |
| 1864 | m_poly[polynum].get_count()); |
| 1865 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1866 | } |
| 1867 | |
| 1868 | vertnum += m_poly[polynum].get_vertcount(); |
| 1869 | } |
| 1870 | |
| 1871 | m_shaders->end_draw(); |
| 1872 | |
| 1873 | // reset the vertex count |
| 1874 | m_numverts = 0; |
| 1875 | m_numpolys = 0; |
| 1876 | } |
| 1877 | |
| 1878 | //============================================================ |
| 1879 | // texture_info destructor |
| 1880 | //============================================================ |
| 1881 | |
| 1882 | texture_info::~texture_info() |
| 1883 | { |
| 1884 | if (m_d3dfinaltex != NULL) |
| 1885 | { |
| 1886 | if (m_d3dtex == m_d3dfinaltex) |
| 1887 | { |
| 1888 | m_d3dtex = NULL; |
| 1889 | } |
| 1890 | (*d3dintf->texture.release)(m_d3dfinaltex); |
| 1891 | m_d3dfinaltex = NULL; |
| 1892 | } |
| 1893 | if (m_d3dtex != NULL) |
| 1894 | { |
| 1895 | (*d3dintf->texture.release)(m_d3dtex); |
| 1896 | m_d3dtex = NULL; |
| 1897 | } |
| 1898 | if (m_d3dsurface != NULL) |
| 1899 | { |
| 1900 | (*d3dintf->surface.release)(m_d3dsurface); |
| 1901 | m_d3dsurface = NULL; |
| 1902 | } |
| 1903 | } |
| 1904 | |
| 1905 | //============================================================ |
| 1906 | // texture_info constructor |
| 1907 | //============================================================ |
| 1908 | |
| 1909 | texture_info::texture_info(texture_manager *manager, const render_texinfo* texsource, int prescale, UINT32 flags) |
| 1910 | { |
| 1911 | HRESULT result; |
| 1912 | |
| 1913 | // fill in the core data |
| 1914 | m_texture_manager = manager; |
| 1915 | m_renderer = m_texture_manager->get_d3d(); |
| 1916 | m_hash = m_texture_manager->texture_compute_hash(texsource, flags); |
| 1917 | m_flags = flags; |
| 1918 | m_texinfo = *texsource; |
| 1919 | m_xprescale = prescale; |
| 1920 | m_yprescale = prescale; |
| 1921 | |
| 1922 | m_d3dtex = NULL; |
| 1923 | m_d3dsurface = NULL; |
| 1924 | m_d3dfinaltex = NULL; |
| 1925 | |
| 1926 | // compute the size |
| 1927 | compute_size(texsource->width, texsource->height); |
| 1928 | |
| 1929 | // non-screen textures are easy |
| 1930 | if (!PRIMFLAG_GET_SCREENTEX(flags)) |
| 1931 | { |
| 1932 | assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); |
| 1933 | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex); |
| 1934 | if (result != D3D_OK) |
| 1935 | goto error; |
| 1936 | m_d3dfinaltex = m_d3dtex; |
| 1937 | m_type = TEXTURE_TYPE_PLAIN; |
| 1938 | } |
| 1939 | |
| 1940 | // screen textures are allocated differently |
| 1941 | else |
| 1942 | { |
| 1943 | D3DFORMAT format; |
| 1944 | DWORD usage = m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0; |
| 1945 | D3DPOOL pool = m_texture_manager->is_dynamic_supported() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; |
| 1946 | int maxdim = MAX(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight); |
| 1947 | |
| 1948 | // pick the format |
| 1949 | if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16) |
| 1950 | { |
| 1951 | format = m_texture_manager->get_yuv_format(); |
| 1952 | } |
| 1953 | else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32 || PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_PALETTEA16) |
| 1954 | { |
| 1955 | format = D3DFMT_A8R8G8B8; |
| 1956 | } |
| 1957 | else |
| 1958 | { |
| 1959 | format = m_renderer->get_screen_format(); |
| 1960 | } |
| 1961 | |
| 1962 | // don't prescale above screen size |
| 1963 | while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim) |
| 1964 | { |
| 1965 | m_xprescale--; |
| 1966 | } |
| 1967 | while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width()) |
| 1968 | { |
| 1969 | m_xprescale--; |
| 1970 | } |
| 1971 | while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim) |
| 1972 | { |
| 1973 | m_yprescale--; |
| 1974 | } |
| 1975 | while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height()) |
| 1976 | { |
| 1977 | m_yprescale--; |
| 1978 | } |
| 1979 | |
| 1980 | int prescale = m_renderer->window().prescale(); |
| 1981 | if (m_xprescale != prescale || m_yprescale != prescale) |
| 1982 | { |
| 1983 | osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale); |
| 1984 | } |
| 1985 | |
| 1986 | // loop until we allocate something or error |
| 1987 | for (int attempt = 0; attempt < 2; attempt++) |
| 1988 | { |
| 1989 | // second attempt is always 1:1 |
| 1990 | if (attempt == 1) |
| 1991 | { |
| 1992 | m_xprescale = m_yprescale = 1; |
| 1993 | } |
| 1994 | |
| 1995 | // screen textures with no prescaling are pretty easy |
| 1996 | if (m_xprescale == 1 && m_yprescale == 1) |
| 1997 | { |
| 1998 | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); |
| 1999 | if (result == D3D_OK) |
| 2000 | { |
| 2001 | m_d3dfinaltex = m_d3dtex; |
| 2002 | m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; |
| 2003 | if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this)) |
| 2004 | { |
| 2005 | goto error; |
| 2006 | } |
| 2007 | |
| 2008 | break; |
| 2009 | } |
| 2010 | } |
| 2011 | |
| 2012 | // screen textures with prescaling require two allocations |
| 2013 | else |
| 2014 | { |
| 2015 | // use an offscreen plain surface for stretching if supported |
| 2016 | // (won't work for YUY textures) |
| 2017 | if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) |
| 2018 | { |
| 2019 | result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface); |
| 2020 | if (result != D3D_OK) |
| 2021 | { |
| 2022 | continue; |
| 2023 | } |
| 2024 | m_type = TEXTURE_TYPE_SURFACE; |
| 2025 | } |
| 2026 | |
| 2027 | // otherwise, we allocate a dynamic texture for the source |
| 2028 | else |
| 2029 | { |
| 2030 | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); |
| 2031 | if (result != D3D_OK) |
| 2032 | { |
| 2033 | continue; |
| 2034 | } |
| 2035 | m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; |
| 2036 | } |
| 2037 | |
| 2038 | // for the target surface, we allocate a render target texture |
| 2039 | int scwidth = m_rawdims.c.x * m_xprescale; |
| 2040 | int scheight = m_rawdims.c.y * m_yprescale; |
| 2041 | |
| 2042 | // target surfaces typically cannot be YCbCr, so we always pick RGB in that case |
| 2043 | D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; |
| 2044 | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex); |
| 2045 | if (result == D3D_OK) |
| 2046 | { |
| 2047 | if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this)) |
| 2048 | { |
| 2049 | goto error; |
| 2050 | } |
| 2051 | break; |
| 2052 | } |
| 2053 | (*d3dintf->texture.release)(m_d3dtex); |
| 2054 | m_d3dtex = NULL; |
| 2055 | } |
| 2056 | } |
| 2057 | } |
| 2058 | |
| 2059 | // copy the data to the texture |
| 2060 | set_data(texsource, flags); |
| 2061 | |
| 2062 | //texsource->osdhandle = (void*)this; |
| 2063 | // add us to the texture list |
| 2064 | if(m_texture_manager->get_texlist() != NULL) |
| 2065 | m_texture_manager->get_texlist()->m_prev = this; |
| 2066 | m_prev = NULL; |
| 2067 | m_next = m_texture_manager->get_texlist(); |
| 2068 | m_texture_manager->set_texlist(this); |
| 2069 | return; |
| 2070 | |
| 2071 | error: |
| 2072 | d3dintf->post_fx_available = false; |
| 2073 | osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); |
| 2074 | if (m_d3dsurface != NULL) |
| 2075 | (*d3dintf->surface.release)(m_d3dsurface); |
| 2076 | if (m_d3dtex != NULL) |
| 2077 | (*d3dintf->texture.release)(m_d3dtex); |
| 2078 | } |
| 2079 | |
| 2080 | |
| 2081 | |
| 2082 | //============================================================ |
| 2083 | // texture_info::compute_size |
| 2084 | //============================================================ |
| 2085 | |
| 2086 | void texture_info::compute_size(int texwidth, int texheight) |
| 2087 | { |
| 2088 | int finalheight = texheight; |
| 2089 | int finalwidth = texwidth; |
| 2090 | |
| 2091 | // if we're not wrapping, add a 1-2 pixel border on all sides |
| 2092 | m_xborderpix = 0; |
| 2093 | m_yborderpix = 0; |
| 2094 | if (ENABLE_BORDER_PIX && !(m_flags & PRIMFLAG_TEXWRAP_MASK)) |
| 2095 | { |
| 2096 | // note we need 2 pixels in X for YUY textures |
| 2097 | m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; |
| 2098 | m_yborderpix = 1; |
| 2099 | } |
| 2100 | |
| 2101 | // compute final texture size |
| 2102 | finalwidth += 2 * m_xborderpix; |
| 2103 | finalheight += 2 * m_yborderpix; |
| 2104 | |
| 2105 | // round width/height up to nearest power of 2 if we need to |
| 2106 | if (!(m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) |
| 2107 | { |
| 2108 | // first the width |
| 2109 | if (finalwidth & (finalwidth - 1)) |
| 2110 | { |
| 2111 | finalwidth |= finalwidth >> 1; |
| 2112 | finalwidth |= finalwidth >> 2; |
| 2113 | finalwidth |= finalwidth >> 4; |
| 2114 | finalwidth |= finalwidth >> 8; |
| 2115 | finalwidth++; |
| 2116 | } |
| 2117 | |
| 2118 | // then the height |
| 2119 | if (finalheight & (finalheight - 1)) |
| 2120 | { |
| 2121 | finalheight |= finalheight >> 1; |
| 2122 | finalheight |= finalheight >> 2; |
| 2123 | finalheight |= finalheight >> 4; |
| 2124 | finalheight |= finalheight >> 8; |
| 2125 | finalheight++; |
| 2126 | } |
| 2127 | } |
| 2128 | |
| 2129 | // round up to square if we need to |
| 2130 | if (m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY) |
| 2131 | { |
| 2132 | if (finalwidth < finalheight) |
| 2133 | finalwidth = finalheight; |
| 2134 | else |
| 2135 | finalheight = finalwidth; |
| 2136 | } |
| 2137 | |
| 2138 | // adjust the aspect ratio if we need to |
| 2139 | while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) |
| 2140 | { |
| 2141 | finalwidth *= 2; |
| 2142 | } |
| 2143 | while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) |
| 2144 | { |
| 2145 | finalheight *= 2; |
| 2146 | } |
| 2147 | |
| 2148 | // if we added pixels for the border, and that just barely pushed us over, take it back |
| 2149 | if ((finalwidth > m_texture_manager->get_max_texture_width() && finalwidth - 2 * m_xborderpix <= m_texture_manager->get_max_texture_width()) || |
| 2150 | (finalheight > m_texture_manager->get_max_texture_height() && finalheight - 2 * m_yborderpix <= m_texture_manager->get_max_texture_height())) |
| 2151 | { |
| 2152 | finalwidth -= 2 * m_xborderpix; |
| 2153 | finalheight -= 2 * m_yborderpix; |
| 2154 | m_xborderpix = 0; |
| 2155 | m_yborderpix = 0; |
| 2156 | } |
| 2157 | |
| 2158 | // if we're above the max width/height, do what? |
| 2159 | if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) |
| 2160 | { |
| 2161 | static int printed = FALSE; |
| 2162 | 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()); |
| 2163 | printed = TRUE; |
| 2164 | } |
| 2165 | |
| 2166 | // compute the U/V scale factors |
| 2167 | m_start.c.x = (float)m_xborderpix / (float)finalwidth; |
| 2168 | m_start.c.y = (float)m_yborderpix / (float)finalheight; |
| 2169 | m_stop.c.x = (float)(texwidth + m_xborderpix) / (float)finalwidth; |
| 2170 | m_stop.c.y = (float)(texheight + m_yborderpix) / (float)finalheight; |
| 2171 | |
| 2172 | // set the final values |
| 2173 | m_rawdims.c.x = finalwidth; |
| 2174 | m_rawdims.c.y = finalheight; |
| 2175 | } |
| 2176 | |
| 2177 | |
| 2178 | |
| 2179 | //============================================================ |
| 2180 | // copyline_palette16 |
| 2181 | //============================================================ |
| 2182 | |
| 2183 | INLINE void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2184 | { |
| 2185 | int x; |
| 2186 | |
| 2187 | assert(xborderpix == 0 || xborderpix == 1); |
| 2188 | if (xborderpix) |
| 2189 | *dst++ = 0xff000000 | palette[*src]; |
| 2190 | for (x = 0; x < width; x++) |
| 2191 | *dst++ = 0xff000000 | palette[*src++]; |
| 2192 | if (xborderpix) |
| 2193 | *dst++ = 0xff000000 | palette[*--src]; |
| 2194 | } |
| 2195 | |
| 2196 | |
| 2197 | |
| 2198 | //============================================================ |
| 2199 | // copyline_palettea16 |
| 2200 | //============================================================ |
| 2201 | |
| 2202 | INLINE void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2203 | { |
| 2204 | int x; |
| 2205 | |
| 2206 | assert(xborderpix == 0 || xborderpix == 1); |
| 2207 | if (xborderpix) |
| 2208 | *dst++ = palette[*src]; |
| 2209 | for (x = 0; x < width; x++) |
| 2210 | *dst++ = palette[*src++]; |
| 2211 | if (xborderpix) |
| 2212 | *dst++ = palette[*--src]; |
| 2213 | } |
| 2214 | |
| 2215 | |
| 2216 | |
| 2217 | //============================================================ |
| 2218 | // copyline_rgb32 |
| 2219 | //============================================================ |
| 2220 | |
| 2221 | INLINE void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix) |
| 2222 | { |
| 2223 | int x; |
| 2224 | |
| 2225 | assert(xborderpix == 0 || xborderpix == 1); |
| 2226 | |
| 2227 | // palette (really RGB map) case |
| 2228 | if (palette != NULL) |
| 2229 | { |
| 2230 | if (xborderpix) |
| 2231 | { |
| 2232 | rgb_t srcpix = *src; |
| 2233 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2234 | } |
| 2235 | for (x = 0; x < width; x++) |
| 2236 | { |
| 2237 | rgb_t srcpix = *src++; |
| 2238 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2239 | } |
| 2240 | if (xborderpix) |
| 2241 | { |
| 2242 | rgb_t srcpix = *--src; |
| 2243 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2244 | } |
| 2245 | } |
| 2246 | |
| 2247 | // direct case |
| 2248 | else |
| 2249 | { |
| 2250 | if (xborderpix) |
| 2251 | *dst++ = 0xff000000 | *src; |
| 2252 | for (x = 0; x < width; x++) |
| 2253 | *dst++ = 0xff000000 | *src++; |
| 2254 | if (xborderpix) |
| 2255 | *dst++ = 0xff000000 | *--src; |
| 2256 | } |
| 2257 | } |
| 2258 | |
| 2259 | |
| 2260 | |
| 2261 | //============================================================ |
| 2262 | // copyline_argb32 |
| 2263 | //============================================================ |
| 2264 | |
| 2265 | INLINE void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix) |
| 2266 | { |
| 2267 | int x; |
| 2268 | |
| 2269 | assert(xborderpix == 0 || xborderpix == 1); |
| 2270 | |
| 2271 | // palette (really RGB map) case |
| 2272 | if (palette != NULL) |
| 2273 | { |
| 2274 | if (xborderpix) |
| 2275 | { |
| 2276 | rgb_t srcpix = *src; |
| 2277 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2278 | } |
| 2279 | for (x = 0; x < width; x++) |
| 2280 | { |
| 2281 | rgb_t srcpix = *src++; |
| 2282 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2283 | } |
| 2284 | if (xborderpix) |
| 2285 | { |
| 2286 | rgb_t srcpix = *--src; |
| 2287 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2288 | } |
| 2289 | } |
| 2290 | |
| 2291 | // direct case |
| 2292 | else |
| 2293 | { |
| 2294 | if (xborderpix) |
| 2295 | *dst++ = *src; |
| 2296 | for (x = 0; x < width; x++) |
| 2297 | *dst++ = *src++; |
| 2298 | if (xborderpix) |
| 2299 | *dst++ = *--src; |
| 2300 | } |
| 2301 | } |
| 2302 | |
| 2303 | |
| 2304 | |
| 2305 | //============================================================ |
| 2306 | // copyline_yuy16_to_yuy2 |
| 2307 | //============================================================ |
| 2308 | |
| 2309 | INLINE void copyline_yuy16_to_yuy2(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2310 | { |
| 2311 | int x; |
| 2312 | |
| 2313 | assert(xborderpix == 0 || xborderpix == 2); |
| 2314 | assert(width % 2 == 0); |
| 2315 | |
| 2316 | // palette (really RGB map) case |
| 2317 | if (palette != NULL) |
| 2318 | { |
| 2319 | if (xborderpix) |
| 2320 | { |
| 2321 | UINT16 srcpix0 = *src++; |
| 2322 | UINT16 srcpix1 = *src--; |
| 2323 | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8); |
| 2324 | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix1 << 8); |
| 2325 | } |
| 2326 | for (x = 0; x < width; x += 2) |
| 2327 | { |
| 2328 | UINT16 srcpix0 = *src++; |
| 2329 | UINT16 srcpix1 = *src++; |
| 2330 | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8); |
| 2331 | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8); |
| 2332 | } |
| 2333 | if (xborderpix) |
| 2334 | { |
| 2335 | UINT16 srcpix1 = *--src; |
| 2336 | UINT16 srcpix0 = *--src; |
| 2337 | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix0 << 8); |
| 2338 | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8); |
| 2339 | } |
| 2340 | } |
| 2341 | |
| 2342 | // direct case |
| 2343 | else |
| 2344 | { |
| 2345 | if (xborderpix) |
| 2346 | { |
| 2347 | UINT16 srcpix0 = *src++; |
| 2348 | UINT16 srcpix1 = *src--; |
| 2349 | *dst++ = (srcpix0 >> 8) | (srcpix0 << 8); |
| 2350 | *dst++ = (srcpix0 >> 8) | (srcpix1 << 8); |
| 2351 | } |
| 2352 | for (x = 0; x < width; x += 2) |
| 2353 | { |
| 2354 | UINT16 srcpix0 = *src++; |
| 2355 | UINT16 srcpix1 = *src++; |
| 2356 | *dst++ = (srcpix0 >> 8) | (srcpix0 << 8); |
| 2357 | *dst++ = (srcpix1 >> 8) | (srcpix1 << 8); |
| 2358 | } |
| 2359 | if (xborderpix) |
| 2360 | { |
| 2361 | UINT16 srcpix1 = *--src; |
| 2362 | UINT16 srcpix0 = *--src; |
| 2363 | *dst++ = (srcpix1 >> 8) | (srcpix0 << 8); |
| 2364 | *dst++ = (srcpix1 >> 8) | (srcpix1 << 8); |
| 2365 | } |
| 2366 | } |
| 2367 | } |
| 2368 | |
| 2369 | |
| 2370 | |
| 2371 | //============================================================ |
| 2372 | // copyline_yuy16_to_uyvy |
| 2373 | //============================================================ |
| 2374 | |
| 2375 | INLINE void copyline_yuy16_to_uyvy(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2376 | { |
| 2377 | int x; |
| 2378 | |
| 2379 | assert(xborderpix == 0 || xborderpix == 2); |
| 2380 | assert(width % 2 == 0); |
| 2381 | |
| 2382 | // palette (really RGB map) case |
| 2383 | if (palette != NULL) |
| 2384 | { |
| 2385 | if (xborderpix) |
| 2386 | { |
| 2387 | UINT16 srcpix0 = *src++; |
| 2388 | UINT16 srcpix1 = *src--; |
| 2389 | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff); |
| 2390 | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix1 & 0xff); |
| 2391 | } |
| 2392 | for (x = 0; x < width; x += 2) |
| 2393 | { |
| 2394 | UINT16 srcpix0 = *src++; |
| 2395 | UINT16 srcpix1 = *src++; |
| 2396 | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff); |
| 2397 | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff); |
| 2398 | } |
| 2399 | if (xborderpix) |
| 2400 | { |
| 2401 | UINT16 srcpix1 = *--src; |
| 2402 | UINT16 srcpix0 = *--src; |
| 2403 | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix0 & 0xff); |
| 2404 | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff); |
| 2405 | } |
| 2406 | } |
| 2407 | |
| 2408 | // direct case |
| 2409 | else |
| 2410 | { |
| 2411 | if (xborderpix) |
| 2412 | { |
| 2413 | UINT16 srcpix0 = src[0]; |
| 2414 | UINT16 srcpix1 = src[1]; |
| 2415 | *dst++ = srcpix0; |
| 2416 | *dst++ = (srcpix0 & 0xff00) | (srcpix1 & 0x00ff); |
| 2417 | } |
| 2418 | for (x = 0; x < width; x += 2) |
| 2419 | { |
| 2420 | *dst++ = *src++; |
| 2421 | *dst++ = *src++; |
| 2422 | } |
| 2423 | if (xborderpix) |
| 2424 | { |
| 2425 | UINT16 srcpix1 = *--src; |
| 2426 | UINT16 srcpix0 = *--src; |
| 2427 | *dst++ = (srcpix1 & 0xff00) | (srcpix0 & 0x00ff); |
| 2428 | *dst++ = srcpix1; |
| 2429 | } |
| 2430 | } |
| 2431 | } |
| 2432 | |
| 2433 | |
| 2434 | |
| 2435 | //============================================================ |
| 2436 | // copyline_yuy16_to_argb |
| 2437 | //============================================================ |
| 2438 | |
| 2439 | INLINE void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2440 | { |
| 2441 | int x; |
| 2442 | |
| 2443 | assert(xborderpix == 0 || xborderpix == 2); |
| 2444 | assert(width % 2 == 0); |
| 2445 | |
| 2446 | // palette (really RGB map) case |
| 2447 | if (palette != NULL) |
| 2448 | { |
| 2449 | if (xborderpix) |
| 2450 | { |
| 2451 | UINT16 srcpix0 = src[0]; |
| 2452 | UINT16 srcpix1 = src[1]; |
| 2453 | UINT8 cb = srcpix0 & 0xff; |
| 2454 | UINT8 cr = srcpix1 & 0xff; |
| 2455 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2456 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2457 | } |
| 2458 | for (x = 0; x < width / 2; x++) |
| 2459 | { |
| 2460 | UINT16 srcpix0 = *src++; |
| 2461 | UINT16 srcpix1 = *src++; |
| 2462 | UINT8 cb = srcpix0 & 0xff; |
| 2463 | UINT8 cr = srcpix1 & 0xff; |
| 2464 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2465 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2466 | } |
| 2467 | if (xborderpix) |
| 2468 | { |
| 2469 | UINT16 srcpix1 = *--src; |
| 2470 | UINT16 srcpix0 = *--src; |
| 2471 | UINT8 cb = srcpix0 & 0xff; |
| 2472 | UINT8 cr = srcpix1 & 0xff; |
| 2473 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2474 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2475 | } |
| 2476 | } |
| 2477 | |
| 2478 | // direct case |
| 2479 | else |
| 2480 | { |
| 2481 | if (xborderpix) |
| 2482 | { |
| 2483 | UINT16 srcpix0 = src[0]; |
| 2484 | UINT16 srcpix1 = src[1]; |
| 2485 | UINT8 cb = srcpix0 & 0xff; |
| 2486 | UINT8 cr = srcpix1 & 0xff; |
| 2487 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2488 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2489 | } |
| 2490 | for (x = 0; x < width; x += 2) |
| 2491 | { |
| 2492 | UINT16 srcpix0 = *src++; |
| 2493 | UINT16 srcpix1 = *src++; |
| 2494 | UINT8 cb = srcpix0 & 0xff; |
| 2495 | UINT8 cr = srcpix1 & 0xff; |
| 2496 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2497 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2498 | } |
| 2499 | if (xborderpix) |
| 2500 | { |
| 2501 | UINT16 srcpix1 = *--src; |
| 2502 | UINT16 srcpix0 = *--src; |
| 2503 | UINT8 cb = srcpix0 & 0xff; |
| 2504 | UINT8 cr = srcpix1 & 0xff; |
| 2505 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2506 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2507 | } |
| 2508 | } |
| 2509 | } |
| 2510 | |
| 2511 | |
| 2512 | |
| 2513 | //============================================================ |
| 2514 | // texture_set_data |
| 2515 | //============================================================ |
| 2516 | |
| 2517 | void texture_info::set_data(const render_texinfo *texsource, UINT32 flags) |
| 2518 | { |
| 2519 | D3DLOCKED_RECT rect; |
| 2520 | HRESULT result; |
| 2521 | |
| 2522 | // lock the texture |
| 2523 | switch (m_type) |
| 2524 | { |
| 2525 | default: |
| 2526 | case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, 0); break; |
| 2527 | case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, D3DLOCK_DISCARD); break; |
| 2528 | case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.lock_rect)(m_d3dsurface, &rect, NULL, D3DLOCK_DISCARD); break; |
| 2529 | } |
| 2530 | if (result != D3D_OK) |
| 2531 | { |
| 2532 | return; |
| 2533 | } |
| 2534 | |
| 2535 | // loop over Y |
| 2536 | int miny = 0 - m_yborderpix; |
| 2537 | int maxy = texsource->height + m_yborderpix; |
| 2538 | for (int dsty = miny; dsty < maxy; dsty++) |
| 2539 | { |
| 2540 | int srcy = (dsty < 0) ? 0 : (dsty >= texsource->height) ? texsource->height - 1 : dsty; |
| 2541 | void *dst = (BYTE *)rect.pBits + (dsty + m_yborderpix) * rect.Pitch; |
| 2542 | |
| 2543 | // switch off of the format and |
| 2544 | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2545 | { |
| 2546 | case TEXFORMAT_PALETTE16: |
| 2547 | copyline_palette16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2548 | break; |
| 2549 | |
| 2550 | case TEXFORMAT_PALETTEA16: |
| 2551 | copyline_palettea16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2552 | break; |
| 2553 | |
| 2554 | case TEXFORMAT_RGB32: |
| 2555 | copyline_rgb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2556 | break; |
| 2557 | |
| 2558 | case TEXFORMAT_ARGB32: |
| 2559 | copyline_argb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2560 | break; |
| 2561 | |
| 2562 | case TEXFORMAT_YUY16: |
| 2563 | if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2) |
| 2564 | copyline_yuy16_to_yuy2((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2565 | else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY) |
| 2566 | copyline_yuy16_to_uyvy((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2567 | else |
| 2568 | copyline_yuy16_to_argb((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2569 | break; |
| 2570 | |
| 2571 | default: |
| 2572 | osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2573 | break; |
| 2574 | } |
| 2575 | } |
| 2576 | |
| 2577 | // unlock |
| 2578 | switch (m_type) |
| 2579 | { |
| 2580 | default: |
| 2581 | case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break; |
| 2582 | case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break; |
| 2583 | case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.unlock_rect)(m_d3dsurface); break; |
| 2584 | } |
| 2585 | if (result != D3D_OK) |
| 2586 | { |
| 2587 | osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 2588 | } |
| 2589 | |
| 2590 | // prescale |
| 2591 | prescale(); |
| 2592 | } |
| 2593 | |
| 2594 | |
| 2595 | |
| 2596 | //============================================================ |
| 2597 | // texture_info::prescale |
| 2598 | //============================================================ |
| 2599 | |
| 2600 | void texture_info::prescale() |
| 2601 | { |
| 2602 | surface *scale_surface; |
| 2603 | HRESULT result; |
| 2604 | int i; |
| 2605 | |
| 2606 | // if we don't need to, just skip it |
| 2607 | if (m_d3dtex == m_d3dfinaltex) |
| 2608 | return; |
| 2609 | |
| 2610 | // for all cases, we need to get the surface of the render target |
| 2611 | result = (*d3dintf->texture.get_surface_level)(m_d3dfinaltex, 0, &scale_surface); |
| 2612 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture get_surface_level call\n", (int)result); |
| 2613 | |
| 2614 | // if we have an offscreen plain surface, we can just StretchRect to it |
| 2615 | if (m_type == TEXTURE_TYPE_SURFACE) |
| 2616 | { |
| 2617 | assert(m_d3dsurface != NULL); |
| 2618 | |
| 2619 | // set the source bounds |
| 2620 | RECT source; |
| 2621 | source.left = source.top = 0; |
| 2622 | source.right = m_texinfo.width + 2 * m_xborderpix; |
| 2623 | source.bottom = m_texinfo.height + 2 * m_yborderpix; |
| 2624 | |
| 2625 | // set the target bounds |
| 2626 | RECT dest; |
| 2627 | dest = source; |
| 2628 | dest.right *= m_xprescale; |
| 2629 | dest.bottom *= m_yprescale; |
| 2630 | |
| 2631 | // do the stretchrect |
| 2632 | result = (*d3dintf->device.stretch_rect)(m_renderer->get_device(), m_d3dsurface, &source, scale_surface, &dest, D3DTEXF_POINT); |
| 2633 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device stretct_rect call\n", (int)result); |
| 2634 | } |
| 2635 | |
| 2636 | // if we are using a texture render target, we need to do more preparations |
| 2637 | else |
| 2638 | { |
| 2639 | surface *backbuffer; |
| 2640 | |
| 2641 | assert(m_d3dtex != NULL); |
| 2642 | |
| 2643 | // first remember the original render target and set the new one |
| 2644 | result = (*d3dintf->device.get_render_target)(m_renderer->get_device(), 0, &backbuffer); |
| 2645 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 2646 | result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, scale_surface); |
| 2647 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 1\n", (int)result); |
| 2648 | m_renderer->reset_render_states(); |
| 2649 | |
| 2650 | // start the scene |
| 2651 | result = (*d3dintf->device.begin_scene)(m_renderer->get_device()); |
| 2652 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result); |
| 2653 | |
| 2654 | // configure the rendering pipeline |
| 2655 | m_renderer->set_filter(FALSE); |
| 2656 | m_renderer->set_blendmode(BLENDMODE_NONE); |
| 2657 | result = (*d3dintf->device.set_texture)(m_renderer->get_device(), 0, m_d3dtex); |
| 2658 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result); |
| 2659 | |
| 2660 | // lock the vertex buffer |
| 2661 | result = (*d3dintf->vertexbuf.lock)(m_renderer->get_vertex_buffer(), 0, 0, m_renderer->get_locked_buffer_ptr(), D3DLOCK_DISCARD); |
| 2662 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer lock call\n", (int)result); |
| 2663 | |
| 2664 | // configure the X/Y coordinates on the target surface |
| 2665 | vertex *lockedbuf = m_renderer->get_locked_buffer(); |
| 2666 | lockedbuf[0].x = -0.5f; |
| 2667 | lockedbuf[0].y = -0.5f; |
| 2668 | lockedbuf[1].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; |
| 2669 | lockedbuf[1].y = -0.5f; |
| 2670 | lockedbuf[2].x = -0.5f; |
| 2671 | lockedbuf[2].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; |
| 2672 | lockedbuf[3].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; |
| 2673 | lockedbuf[3].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; |
| 2674 | |
| 2675 | // configure the U/V coordintes on the source texture |
| 2676 | lockedbuf[0].u0 = 0.0f; |
| 2677 | lockedbuf[0].v0 = 0.0f; |
| 2678 | lockedbuf[1].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; |
| 2679 | lockedbuf[1].v0 = 0.0f; |
| 2680 | lockedbuf[2].u0 = 0.0f; |
| 2681 | lockedbuf[2].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; |
| 2682 | lockedbuf[3].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; |
| 2683 | lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; |
| 2684 | |
| 2685 | // reset the remaining vertex parameters |
| 2686 | for (i = 0; i < 4; i++) |
| 2687 | { |
| 2688 | lockedbuf[i].z = 0.0f; |
| 2689 | lockedbuf[i].rhw = 1.0f; |
| 2690 | lockedbuf[i].color = D3DCOLOR_ARGB(0xff,0xff,0xff,0xff); |
| 2691 | } |
| 2692 | |
| 2693 | // unlock the vertex buffer |
| 2694 | result = (*d3dintf->vertexbuf.unlock)(m_renderer->get_vertex_buffer()); |
| 2695 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result); |
| 2696 | m_renderer->set_locked_buffer(NULL); |
| 2697 | |
| 2698 | // set the stream and draw the triangle strip |
| 2699 | result = (*d3dintf->device.set_stream_source)(m_renderer->get_device(), 0, m_renderer->get_vertex_buffer(), sizeof(vertex)); |
| 2700 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result); |
| 2701 | result = (*d3dintf->device.draw_primitive)(m_renderer->get_device(), D3DPT_TRIANGLESTRIP, 0, 2); |
| 2702 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 2703 | |
| 2704 | // end the scene |
| 2705 | result = (*d3dintf->device.end_scene)(m_renderer->get_device()); |
| 2706 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result); |
| 2707 | |
| 2708 | // reset the render target and release our reference to the backbuffer |
| 2709 | result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, backbuffer); |
| 2710 | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 2\n", (int)result); |
| 2711 | (*d3dintf->surface.release)(backbuffer); |
| 2712 | m_renderer->reset_render_states(); |
| 2713 | } |
| 2714 | |
| 2715 | // release our reference to the target surface |
| 2716 | (*d3dintf->surface.release)(scale_surface); |
| 2717 | } |
| 2718 | |
| 2719 | |
| 2720 | //============================================================ |
| 2721 | // cache_target::~cache_target |
| 2722 | //============================================================ |
| 2723 | |
| 2724 | cache_target::~cache_target() |
| 2725 | { |
| 2726 | for (int index = 0; index < 11; index++) |
| 2727 | { |
| 2728 | if (bloom_texture[index] != NULL) |
| 2729 | { |
| 2730 | (*d3dintf->texture.release)(bloom_texture[index]); |
| 2731 | bloom_texture[index] = NULL; |
| 2732 | } |
| 2733 | if (bloom_target[index] != NULL) |
| 2734 | { |
| 2735 | (*d3dintf->surface.release)(bloom_target[index]); |
| 2736 | bloom_target[index] = NULL; |
| 2737 | } |
| 2738 | } |
| 2739 | |
| 2740 | if (last_texture != NULL) |
| 2741 | { |
| 2742 | (*d3dintf->texture.release)(last_texture); |
| 2743 | last_texture = NULL; |
| 2744 | } |
| 2745 | if (last_target != NULL) |
| 2746 | { |
| 2747 | (*d3dintf->surface.release)(last_target); |
| 2748 | last_target = NULL; |
| 2749 | } |
| 2750 | } |
| 2751 | |
| 2752 | |
| 2753 | //============================================================ |
| 2754 | // cache_target::init - initializes a target cache |
| 2755 | //============================================================ |
| 2756 | |
| 2757 | bool cache_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) |
| 2758 | { |
| 2759 | int bloom_size = (width < height) ? width : height; |
| 2760 | int bloom_index = 0; |
| 2761 | int bloom_width = width; |
| 2762 | int bloom_height = height; |
| 2763 | for (; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1) |
| 2764 | { |
| 2765 | bloom_width >>= 1; |
| 2766 | bloom_height >>= 1; |
| 2767 | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), bloom_width, bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]); |
| 2768 | if (result != D3D_OK) |
| 2769 | { |
| 2770 | return false; |
| 2771 | } |
| 2772 | (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); |
| 2773 | bloom_index++; |
| 2774 | } |
| 2775 | |
| 2776 | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture); |
| 2777 | if (result != D3D_OK) |
| 2778 | return false; |
| 2779 | (*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target); |
| 2780 | |
| 2781 | target_width = width * prescale_x; |
| 2782 | target_height = height * prescale_y; |
| 2783 | |
| 2784 | return true; |
| 2785 | } |
| 2786 | |
| 2787 | //============================================================ |
| 2788 | // render_target::~render_target |
| 2789 | //============================================================ |
| 2790 | |
| 2791 | render_target::~render_target() |
| 2792 | { |
| 2793 | for (int index = 0; index < 11; index++) |
| 2794 | { |
| 2795 | if (bloom_texture[index] != NULL) |
| 2796 | { |
| 2797 | (*d3dintf->texture.release)(bloom_texture[index]); |
| 2798 | bloom_texture[index] = NULL; |
| 2799 | } |
| 2800 | if (bloom_target[index] != NULL) |
| 2801 | { |
| 2802 | (*d3dintf->surface.release)(bloom_target[index]); |
| 2803 | bloom_target[index] = NULL; |
| 2804 | } |
| 2805 | } |
| 2806 | |
| 2807 | for (int index = 0; index < 5; index++) |
| 2808 | { |
| 2809 | if (render_texture[index] != NULL) |
| 2810 | { |
| 2811 | (*d3dintf->texture.release)(render_texture[index]); |
| 2812 | render_texture[index] = NULL; |
| 2813 | } |
| 2814 | if (target[index] != NULL) |
| 2815 | { |
| 2816 | (*d3dintf->surface.release)(target[index]); |
| 2817 | target[index] = NULL; |
| 2818 | } |
| 2819 | } |
| 2820 | |
| 2821 | if (prescaletexture != NULL) |
| 2822 | { |
| 2823 | (*d3dintf->texture.release)(prescaletexture); |
| 2824 | prescaletexture = NULL; |
| 2825 | } |
| 2826 | if (prescaletarget != NULL) |
| 2827 | { |
| 2828 | (*d3dintf->surface.release)(prescaletarget); |
| 2829 | prescaletarget = NULL; |
| 2830 | } |
| 2831 | |
| 2832 | if (smalltexture != NULL) |
| 2833 | { |
| 2834 | (*d3dintf->texture.release)(smalltexture); |
| 2835 | smalltexture = NULL; |
| 2836 | } |
| 2837 | if (smalltarget != NULL) |
| 2838 | { |
| 2839 | (*d3dintf->surface.release)(smalltarget); |
| 2840 | smalltarget = NULL; |
| 2841 | } |
| 2842 | } |
| 2843 | |
| 2844 | |
| 2845 | //============================================================ |
| 2846 | // render_target::init - initializes a render target |
| 2847 | //============================================================ |
| 2848 | |
| 2849 | bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) |
| 2850 | { |
| 2851 | D3DFORMAT format = D3DFMT_A8R8G8B8; |
| 2852 | |
| 2853 | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[0]); |
| 2854 | if (result != D3D_OK) |
| 2855 | return false; |
| 2856 | (*d3dintf->texture.get_surface_level)(render_texture[0], 0, &target[0]); |
| 2857 | |
| 2858 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[1]); |
| 2859 | if (result != D3D_OK) |
| 2860 | return false; |
| 2861 | (*d3dintf->texture.get_surface_level)(render_texture[1], 0, &target[1]); |
| 2862 | |
| 2863 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[2]); |
| 2864 | if (result != D3D_OK) |
| 2865 | return false; |
| 2866 | (*d3dintf->texture.get_surface_level)(render_texture[2], 0, &target[2]); |
| 2867 | |
| 2868 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[3]); |
| 2869 | if (result != D3D_OK) |
| 2870 | return false; |
| 2871 | (*d3dintf->texture.get_surface_level)(render_texture[3], 0, &target[3]); |
| 2872 | |
| 2873 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[4]); |
| 2874 | if (result != D3D_OK) |
| 2875 | return false; |
| 2876 | (*d3dintf->texture.get_surface_level)(render_texture[4], 0, &target[4]); |
| 2877 | |
| 2878 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &smalltexture); |
| 2879 | if (result != D3D_OK) |
| 2880 | return false; |
| 2881 | (*d3dintf->texture.get_surface_level)(smalltexture, 0, &smalltarget); |
| 2882 | |
| 2883 | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &prescaletexture); |
| 2884 | if (result != D3D_OK) |
| 2885 | return false; |
| 2886 | (*d3dintf->texture.get_surface_level)(prescaletexture, 0, &prescaletarget); |
| 2887 | |
| 2888 | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 2889 | int bloom_index = 0; |
| 2890 | float bloom_width = d3d->get_width(); |
| 2891 | float bloom_height = d3d->get_height(); |
| 2892 | for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 2893 | { |
| 2894 | bloom_width *= 0.5f; |
| 2895 | bloom_height *= 0.5f; |
| 2896 | 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]); |
| 2897 | if (result != D3D_OK) |
| 2898 | return false; |
| 2899 | (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); |
| 2900 | bloom_index++; |
| 2901 | } |
| 2902 | |
| 2903 | this->width = width; |
| 2904 | this->height = height; |
| 2905 | |
| 2906 | target_width = width * prescale_x; |
| 2907 | target_height = height * prescale_y; |
| 2908 | |
| 2909 | return true; |
| 2910 | } |
| 2911 | |
| 2912 | }; |
trunk/src/osd/modules/render/drawdd.c
| r0 | r244652 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Aaron Giles |
| 3 | //============================================================ |
| 4 | // |
| 5 | // drawdd.c - Win32 DirectDraw implementation |
| 6 | // |
| 7 | //============================================================ |
| 8 | |
| 9 | // standard windows headers |
| 10 | #define WIN32_LEAN_AND_MEAN |
| 11 | #include <windows.h> |
| 12 | #include <mmsystem.h> |
| 13 | #include <ddraw.h> |
| 14 | #undef interface |
| 15 | |
| 16 | // MAME headers |
| 17 | #include "emu.h" |
| 18 | #include "render.h" |
| 19 | #include "rendutil.h" |
| 20 | #include "options.h" |
| 21 | #include "rendersw.inc" |
| 22 | |
| 23 | // MAMEOS headers |
| 24 | #include "winmain.h" |
| 25 | #include "window.h" |
| 26 | #include "config.h" |
| 27 | |
| 28 | |
| 29 | |
| 30 | //============================================================ |
| 31 | // TYPE DEFINITIONS |
| 32 | //============================================================ |
| 33 | |
| 34 | typedef HRESULT (WINAPI *directdrawcreateex_ptr)(GUID FAR *lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); |
| 35 | typedef HRESULT (WINAPI *directdrawenumerateex_ptr)(LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); |
| 36 | |
| 37 | |
| 38 | /* dd_info is the information about DirectDraw for the current screen */ |
| 39 | class renderer_dd : public osd_renderer |
| 40 | { |
| 41 | public: |
| 42 | renderer_dd(osd_window *window) |
| 43 | : osd_renderer(window, FLAG_NONE), |
| 44 | //adapter(0), |
| 45 | adapter_ptr(NULL), |
| 46 | clearouter(0), |
| 47 | blitwidth(0), blitheight(0), |
| 48 | //lastdest |
| 49 | ddraw(NULL), |
| 50 | primary(NULL), |
| 51 | back(NULL), |
| 52 | blit(NULL), |
| 53 | clipper(NULL), |
| 54 | gamma(NULL), |
| 55 | //DDSURFACEDESC2 primarydesc; |
| 56 | //DDSURFACEDESC2 blitdesc; |
| 57 | //DDSURFACEDESC2 origmode; |
| 58 | //ddcaps(0), |
| 59 | //helcaps(0), |
| 60 | membuffer(NULL), |
| 61 | membuffersize(0) |
| 62 | { } |
| 63 | |
| 64 | virtual ~renderer_dd() { } |
| 65 | |
| 66 | virtual int create(); |
| 67 | virtual render_primitive_list *get_primitives(); |
| 68 | virtual int draw(const int update); |
| 69 | virtual void save() {}; |
| 70 | virtual void record() {}; |
| 71 | virtual void toggle_fsfx() {}; |
| 72 | virtual void destroy(); |
| 73 | |
| 74 | int width, height; // current width, height |
| 75 | int refresh; // current refresh rate |
| 76 | |
| 77 | private: |
| 78 | |
| 79 | inline void update_outer_rects(); |
| 80 | |
| 81 | // surface management |
| 82 | int ddraw_create(); |
| 83 | int ddraw_create_surfaces(); |
| 84 | void ddraw_delete(); |
| 85 | void ddraw_delete_surfaces(); |
| 86 | int ddraw_verify_caps(); |
| 87 | int ddraw_test_cooperative(); |
| 88 | HRESULT create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type); |
| 89 | int create_clipper(); |
| 90 | |
| 91 | // drawing helpers |
| 92 | void compute_blit_surface_size(); |
| 93 | void blit_to_primary(int srcwidth, int srcheight); |
| 94 | |
| 95 | // video modes |
| 96 | int config_adapter_mode(); |
| 97 | void get_adapter_for_monitor(win_monitor_info *monitor); |
| 98 | void pick_best_mode(); |
| 99 | |
| 100 | // various |
| 101 | void calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins); |
| 102 | |
| 103 | |
| 104 | GUID adapter; // current display adapter |
| 105 | GUID * adapter_ptr; // pointer to current display adapter |
| 106 | int clearouter; // clear the outer areas? |
| 107 | |
| 108 | INT32 blitwidth, blitheight; // current blit width/height values |
| 109 | RECT lastdest; // last destination rectangle |
| 110 | |
| 111 | IDirectDraw7 * ddraw; // pointer to the DirectDraw object |
| 112 | IDirectDrawSurface7 * primary; // pointer to the primary surface object |
| 113 | IDirectDrawSurface7 * back; // pointer to the back buffer surface object |
| 114 | IDirectDrawSurface7 * blit; // pointer to the blit surface object |
| 115 | IDirectDrawClipper * clipper; // pointer to the clipper object |
| 116 | IDirectDrawGammaControl *gamma; // pointer to the gamma control object |
| 117 | |
| 118 | DDSURFACEDESC2 primarydesc; // description of the primary surface |
| 119 | DDSURFACEDESC2 blitdesc; // description of the blitting surface |
| 120 | DDSURFACEDESC2 origmode; // original video mode |
| 121 | |
| 122 | DDCAPS ddcaps; // capabilities of the device |
| 123 | DDCAPS helcaps; // capabilities of the hardware |
| 124 | |
| 125 | UINT8 * membuffer; // memory buffer for complex rendering |
| 126 | UINT32 membuffersize; // current size of the memory buffer |
| 127 | }; |
| 128 | |
| 129 | |
| 130 | /* monitor_enum_info holds information during a monitor enumeration */ |
| 131 | struct monitor_enum_info |
| 132 | { |
| 133 | win_monitor_info * monitor; // pointer to monitor we want |
| 134 | GUID guid; // GUID of the one we found |
| 135 | GUID * guid_ptr; // pointer to our GUID |
| 136 | int foundit; // TRUE if we found what we wanted |
| 137 | }; |
| 138 | |
| 139 | |
| 140 | /* mode_enum_info holds information during a display mode enumeration */ |
| 141 | struct mode_enum_info |
| 142 | { |
| 143 | renderer_dd * renderer; |
| 144 | osd_window * window; |
| 145 | INT32 minimum_width, minimum_height; |
| 146 | INT32 target_width, target_height; |
| 147 | double target_refresh; |
| 148 | float best_score; |
| 149 | }; |
| 150 | |
| 151 | |
| 152 | |
| 153 | //============================================================ |
| 154 | // GLOBALS |
| 155 | //============================================================ |
| 156 | |
| 157 | static HINSTANCE dllhandle; |
| 158 | static directdrawcreateex_ptr directdrawcreateex; |
| 159 | static directdrawenumerateex_ptr directdrawenumerateex; |
| 160 | |
| 161 | |
| 162 | |
| 163 | //============================================================ |
| 164 | // INLINES |
| 165 | //============================================================ |
| 166 | |
| 167 | inline void renderer_dd::update_outer_rects() |
| 168 | { |
| 169 | clearouter = (back != NULL) ? 3 : 1; |
| 170 | } |
| 171 | |
| 172 | |
| 173 | INLINE int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) |
| 174 | { |
| 175 | float aspect0 = (float)width0 / (float)height0; |
| 176 | float aspect1 = (float)width1 / (float)height1; |
| 177 | return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; |
| 178 | } |
| 179 | |
| 180 | |
| 181 | |
| 182 | //============================================================ |
| 183 | // PROTOTYPES |
| 184 | //============================================================ |
| 185 | |
| 186 | // core functions |
| 187 | static void drawdd_exit(void); |
| 188 | |
| 189 | |
| 190 | |
| 191 | //============================================================ |
| 192 | // drawnone_create |
| 193 | //============================================================ |
| 194 | |
| 195 | static osd_renderer *drawdd_create(osd_window *window) |
| 196 | { |
| 197 | return global_alloc(renderer_dd(window)); |
| 198 | } |
| 199 | |
| 200 | |
| 201 | //============================================================ |
| 202 | // drawdd_init |
| 203 | //============================================================ |
| 204 | |
| 205 | int drawdd_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 206 | { |
| 207 | // dynamically grab the create function from ddraw.dll |
| 208 | dllhandle = LoadLibrary(TEXT("ddraw.dll")); |
| 209 | if (dllhandle == NULL) |
| 210 | { |
| 211 | osd_printf_verbose("DirectDraw: Unable to access ddraw.dll\n"); |
| 212 | return 1; |
| 213 | } |
| 214 | |
| 215 | // import the create function |
| 216 | directdrawcreateex = (directdrawcreateex_ptr)GetProcAddress(dllhandle, "DirectDrawCreateEx"); |
| 217 | if (directdrawcreateex == NULL) |
| 218 | { |
| 219 | osd_printf_verbose("DirectDraw: Unable to find DirectDrawCreateEx\n"); |
| 220 | FreeLibrary(dllhandle); |
| 221 | dllhandle = NULL; |
| 222 | return 1; |
| 223 | } |
| 224 | |
| 225 | // import the enumerate function |
| 226 | directdrawenumerateex = (directdrawenumerateex_ptr)GetProcAddress(dllhandle, "DirectDrawEnumerateExA"); |
| 227 | if (directdrawenumerateex == NULL) |
| 228 | { |
| 229 | osd_printf_verbose("DirectDraw: Unable to find DirectDrawEnumerateExA\n"); |
| 230 | FreeLibrary(dllhandle); |
| 231 | dllhandle = NULL; |
| 232 | return 1; |
| 233 | } |
| 234 | |
| 235 | // fill in the callbacks |
| 236 | memset(callbacks, 0, sizeof(*callbacks)); |
| 237 | callbacks->exit = drawdd_exit; |
| 238 | callbacks->create = drawdd_create; |
| 239 | |
| 240 | osd_printf_verbose("DirectDraw: Using DirectDraw 7\n"); |
| 241 | return 0; |
| 242 | } |
| 243 | |
| 244 | |
| 245 | |
| 246 | //============================================================ |
| 247 | // drawdd_exit |
| 248 | //============================================================ |
| 249 | |
| 250 | static void drawdd_exit(void) |
| 251 | { |
| 252 | if (dllhandle != NULL) |
| 253 | FreeLibrary(dllhandle); |
| 254 | } |
| 255 | |
| 256 | |
| 257 | |
| 258 | //============================================================ |
| 259 | // drawdd_window_init |
| 260 | //============================================================ |
| 261 | |
| 262 | int renderer_dd::create() |
| 263 | { |
| 264 | // configure the adapter for the mode we want |
| 265 | if (config_adapter_mode()) |
| 266 | goto error; |
| 267 | |
| 268 | // create the ddraw object |
| 269 | if (ddraw_create()) |
| 270 | goto error; |
| 271 | |
| 272 | return 0; |
| 273 | |
| 274 | error: |
| 275 | destroy(); |
| 276 | osd_printf_error("Unable to initialize DirectDraw.\n"); |
| 277 | return 1; |
| 278 | } |
| 279 | |
| 280 | |
| 281 | |
| 282 | //============================================================ |
| 283 | // drawdd_window_destroy |
| 284 | //============================================================ |
| 285 | |
| 286 | void renderer_dd::destroy() |
| 287 | { |
| 288 | // delete the ddraw object |
| 289 | ddraw_delete(); |
| 290 | } |
| 291 | |
| 292 | |
| 293 | |
| 294 | //============================================================ |
| 295 | // drawdd_window_get_primitives |
| 296 | //============================================================ |
| 297 | |
| 298 | render_primitive_list *renderer_dd::get_primitives() |
| 299 | { |
| 300 | compute_blit_surface_size(); |
| 301 | window().target()->set_bounds(blitwidth, blitheight, 0); |
| 302 | window().target()->set_max_update_rate((refresh == 0) ? origmode.dwRefreshRate : refresh); |
| 303 | |
| 304 | return &window().target()->get_primitives(); |
| 305 | } |
| 306 | |
| 307 | |
| 308 | |
| 309 | //============================================================ |
| 310 | // drawdd_window_draw |
| 311 | //============================================================ |
| 312 | |
| 313 | int renderer_dd::draw(const int update) |
| 314 | { |
| 315 | render_primitive *prim; |
| 316 | int usemembuffer = FALSE; |
| 317 | HRESULT result; |
| 318 | |
| 319 | // if we're updating, remember to erase the outer stuff |
| 320 | if (update) |
| 321 | update_outer_rects(); |
| 322 | |
| 323 | // if we have a ddraw object, check the cooperative level |
| 324 | if (ddraw_test_cooperative()) |
| 325 | return 1; |
| 326 | |
| 327 | // get the size; if we're too small, delete the existing surfaces |
| 328 | if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight) |
| 329 | ddraw_delete_surfaces(); |
| 330 | |
| 331 | // if we need to create surfaces, do it now |
| 332 | if (blit == NULL && ddraw_create_surfaces() != 0) |
| 333 | return 1; |
| 334 | |
| 335 | // select our surface and lock it |
| 336 | result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL); |
| 337 | if (result == DDERR_SURFACELOST) |
| 338 | { |
| 339 | osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); |
| 340 | ddraw_delete_surfaces(); |
| 341 | return 1; |
| 342 | } |
| 343 | if (result != DD_OK) |
| 344 | { |
| 345 | osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); |
| 346 | return 1; |
| 347 | } |
| 348 | |
| 349 | // render to it |
| 350 | window().m_primlist->acquire_lock(); |
| 351 | |
| 352 | // scan the list of primitives for tricky stuff |
| 353 | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 354 | if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || |
| 355 | (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) |
| 356 | { |
| 357 | usemembuffer = TRUE; |
| 358 | break; |
| 359 | } |
| 360 | |
| 361 | // if we're using the memory buffer, draw offscreen first and then copy |
| 362 | if (usemembuffer) |
| 363 | { |
| 364 | int x, y; |
| 365 | |
| 366 | // based on the target format, use one of our standard renderers |
| 367 | switch (blitdesc.ddpfPixelFormat.dwRBitMask) |
| 368 | { |
| 369 | case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 370 | case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 371 | case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 372 | case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 373 | default: |
| 374 | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); |
| 375 | break; |
| 376 | } |
| 377 | |
| 378 | // handle copying to both 16bpp and 32bpp destinations |
| 379 | for (y = 0; y < blitheight; y++) |
| 380 | { |
| 381 | if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) |
| 382 | { |
| 383 | UINT32 *src = (UINT32 *)membuffer + y * blitwidth; |
| 384 | UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); |
| 385 | for (x = 0; x < blitwidth; x++) |
| 386 | *dst++ = *src++; |
| 387 | } |
| 388 | else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) |
| 389 | { |
| 390 | UINT16 *src = (UINT16 *)membuffer + y * blitwidth; |
| 391 | UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); |
| 392 | for (x = 0; x < blitwidth; x++) |
| 393 | *dst++ = *src++; |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | } |
| 398 | |
| 399 | // otherwise, draw directly |
| 400 | else |
| 401 | { |
| 402 | // based on the target format, use one of our standard renderers |
| 403 | switch (blitdesc.ddpfPixelFormat.dwRBitMask) |
| 404 | { |
| 405 | case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; |
| 406 | case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; |
| 407 | case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; |
| 408 | case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; |
| 409 | default: |
| 410 | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); |
| 411 | break; |
| 412 | } |
| 413 | } |
| 414 | window().m_primlist->release_lock(); |
| 415 | |
| 416 | // unlock and blit |
| 417 | result = IDirectDrawSurface7_Unlock(blit, NULL); |
| 418 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); |
| 419 | |
| 420 | // sync to VBLANK |
| 421 | if ((video_config.waitvsync || video_config.syncrefresh) && window().machine().video().throttled() && (!window().fullscreen() || back == NULL)) |
| 422 | { |
| 423 | result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL); |
| 424 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); |
| 425 | } |
| 426 | |
| 427 | // complete the blitting |
| 428 | blit_to_primary(blitwidth, blitheight); |
| 429 | return 0; |
| 430 | } |
| 431 | |
| 432 | |
| 433 | |
| 434 | //============================================================ |
| 435 | // ddraw_create |
| 436 | //============================================================ |
| 437 | |
| 438 | int renderer_dd::ddraw_create() |
| 439 | { |
| 440 | HRESULT result; |
| 441 | int verify; |
| 442 | |
| 443 | // if a device exists, free it |
| 444 | if (ddraw != NULL) |
| 445 | ddraw_delete(); |
| 446 | |
| 447 | // create the DirectDraw object |
| 448 | result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); |
| 449 | if (result != DD_OK) |
| 450 | { |
| 451 | osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); |
| 452 | goto error; |
| 453 | } |
| 454 | |
| 455 | // verify the caps |
| 456 | verify = ddraw_verify_caps(); |
| 457 | if (verify == 2) |
| 458 | { |
| 459 | osd_printf_error("DirectDraw: Error - Device does not meet minimum requirements for DirectDraw rendering\n"); |
| 460 | goto error; |
| 461 | } |
| 462 | if (verify == 1) |
| 463 | osd_printf_verbose("DirectDraw: Warning - Device may not perform well for DirectDraw rendering\n"); |
| 464 | |
| 465 | // set the cooperative level |
| 466 | // for non-window modes, we will use full screen here |
| 467 | result = IDirectDraw7_SetCooperativeLevel(ddraw, win_window_list->m_hwnd, DDSCL_SETFOCUSWINDOW); |
| 468 | if (result != DD_OK) |
| 469 | { |
| 470 | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(FOCUSWINDOW) call\n", (int)result); |
| 471 | goto error; |
| 472 | } |
| 473 | result = IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_SETDEVICEWINDOW | (window().fullscreen() ? DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE : DDSCL_NORMAL)); |
| 474 | if (result != DD_OK) |
| 475 | { |
| 476 | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(DEVICEWINDOW) call\n", (int)result); |
| 477 | goto error; |
| 478 | } |
| 479 | |
| 480 | // full screen mode: set the resolution |
| 481 | if (window().fullscreen() && video_config.switchres) |
| 482 | { |
| 483 | result = IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, refresh, 0); |
| 484 | if (result != DD_OK) |
| 485 | { |
| 486 | osd_printf_verbose("DirectDraw: Error %08X attempting to set video mode %dx%d@%d call\n", (int)result, width, height, refresh); |
| 487 | goto error; |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | return ddraw_create_surfaces(); |
| 492 | |
| 493 | error: |
| 494 | ddraw_delete(); |
| 495 | return 1; |
| 496 | } |
| 497 | |
| 498 | |
| 499 | |
| 500 | //============================================================ |
| 501 | // ddraw_create_surfaces |
| 502 | //============================================================ |
| 503 | |
| 504 | int renderer_dd::ddraw_create_surfaces() |
| 505 | { |
| 506 | HRESULT result; |
| 507 | |
| 508 | // make a description of the primary surface |
| 509 | memset(&primarydesc, 0, sizeof(primarydesc)); |
| 510 | primarydesc.dwSize = sizeof(primarydesc); |
| 511 | primarydesc.dwFlags = DDSD_CAPS; |
| 512 | primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; |
| 513 | |
| 514 | // for triple-buffered full screen mode, allocate flipping surfaces |
| 515 | if (window().fullscreen() && video_config.triplebuf) |
| 516 | { |
| 517 | primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; |
| 518 | primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; |
| 519 | primarydesc.dwBackBufferCount = 2; |
| 520 | } |
| 521 | |
| 522 | // create the primary surface and report errors |
| 523 | result = create_surface(&primarydesc, &primary, "primary"); |
| 524 | if (result != DD_OK) goto error; |
| 525 | |
| 526 | // full screen mode: get the back surface |
| 527 | back = NULL; |
| 528 | if (window().fullscreen() && video_config.triplebuf) |
| 529 | { |
| 530 | DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; |
| 531 | result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back); |
| 532 | if (result != DD_OK) |
| 533 | { |
| 534 | osd_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result); |
| 535 | goto error; |
| 536 | } |
| 537 | } |
| 538 | |
| 539 | // now make a description of our blit surface, based on the primary surface |
| 540 | if (blitwidth == 0 || blitheight == 0) |
| 541 | compute_blit_surface_size(); |
| 542 | blitdesc = primarydesc; |
| 543 | blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; |
| 544 | blitdesc.dwWidth = blitwidth; |
| 545 | blitdesc.dwHeight = blitheight; |
| 546 | blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; |
| 547 | |
| 548 | // then create the blit surface, fall back to system memory if video mem doesn't work |
| 549 | result = create_surface(&blitdesc, &blit, "blit"); |
| 550 | if (result != DD_OK) |
| 551 | { |
| 552 | blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; |
| 553 | result = create_surface(&blitdesc, &blit, "blit"); |
| 554 | } |
| 555 | if (result != DD_OK) goto error; |
| 556 | |
| 557 | // create a memory buffer for offscreen drawing |
| 558 | if (membuffersize < blitwidth * blitheight * 4) |
| 559 | { |
| 560 | membuffersize = blitwidth * blitheight * 4; |
| 561 | global_free_array(membuffer); |
| 562 | membuffer = global_alloc_array(UINT8, membuffersize); |
| 563 | } |
| 564 | if (membuffer == NULL) |
| 565 | goto error; |
| 566 | |
| 567 | // create a clipper for windowed mode |
| 568 | if (!window().fullscreen() && create_clipper()) |
| 569 | goto error; |
| 570 | |
| 571 | // full screen mode: set the gamma |
| 572 | if (window().fullscreen()) |
| 573 | { |
| 574 | // only set the gamma if it's not 1.0f |
| 575 | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 576 | float brightness = options.full_screen_brightness(); |
| 577 | float contrast = options.full_screen_contrast(); |
| 578 | float fgamma = options.full_screen_gamma(); |
| 579 | if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f) |
| 580 | { |
| 581 | // see if we can get a GammaControl object |
| 582 | result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma); |
| 583 | if (result != DD_OK) |
| 584 | { |
| 585 | osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); |
| 586 | this->gamma = NULL; |
| 587 | } |
| 588 | |
| 589 | // proceed if we can |
| 590 | if (this->gamma != NULL) |
| 591 | { |
| 592 | DDGAMMARAMP ramp; |
| 593 | int i; |
| 594 | |
| 595 | // create a standard ramp and set it |
| 596 | for (i = 0; i < 256; i++) |
| 597 | ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, fgamma) << 8; |
| 598 | |
| 599 | // attempt to set it |
| 600 | result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp); |
| 601 | if (result != DD_OK) |
| 602 | osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); |
| 603 | } |
| 604 | } |
| 605 | } |
| 606 | |
| 607 | // force some updates |
| 608 | update_outer_rects(); |
| 609 | return 0; |
| 610 | |
| 611 | error: |
| 612 | ddraw_delete_surfaces(); |
| 613 | return 1; |
| 614 | } |
| 615 | |
| 616 | |
| 617 | |
| 618 | //============================================================ |
| 619 | // ddraw_delete |
| 620 | //============================================================ |
| 621 | |
| 622 | void renderer_dd::ddraw_delete() |
| 623 | { |
| 624 | // free surfaces |
| 625 | ddraw_delete_surfaces(); |
| 626 | |
| 627 | // restore resolutions |
| 628 | if (ddraw != NULL) |
| 629 | IDirectDraw7_RestoreDisplayMode(ddraw); |
| 630 | |
| 631 | // reset cooperative level |
| 632 | if (ddraw != NULL && window().m_hwnd != NULL) |
| 633 | IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_NORMAL); |
| 634 | |
| 635 | // release the DirectDraw object itself |
| 636 | if (ddraw != NULL) |
| 637 | IDirectDraw7_Release(ddraw); |
| 638 | ddraw = NULL; |
| 639 | } |
| 640 | |
| 641 | |
| 642 | |
| 643 | //============================================================ |
| 644 | // ddraw_delete_surfaces |
| 645 | //============================================================ |
| 646 | |
| 647 | void renderer_dd::ddraw_delete_surfaces() |
| 648 | { |
| 649 | // release the gamma control |
| 650 | if (gamma != NULL) |
| 651 | IDirectDrawGammaControl_Release(gamma); |
| 652 | gamma = NULL; |
| 653 | |
| 654 | // release the clipper |
| 655 | if (clipper != NULL) |
| 656 | IDirectDrawClipper_Release(clipper); |
| 657 | clipper = NULL; |
| 658 | |
| 659 | // free the memory buffer |
| 660 | global_free_array(membuffer); |
| 661 | membuffer = NULL; |
| 662 | membuffersize = 0; |
| 663 | |
| 664 | // release the blit surface |
| 665 | if (blit != NULL) |
| 666 | IDirectDrawSurface7_Release(blit); |
| 667 | blit = NULL; |
| 668 | |
| 669 | // release the back surface |
| 670 | if (back != NULL) |
| 671 | IDirectDrawSurface7_Release(back); |
| 672 | back = NULL; |
| 673 | |
| 674 | // release the primary surface |
| 675 | if (primary != NULL) |
| 676 | IDirectDrawSurface7_Release(primary); |
| 677 | primary = NULL; |
| 678 | } |
| 679 | |
| 680 | |
| 681 | |
| 682 | //============================================================ |
| 683 | // ddraw_verify_caps |
| 684 | //============================================================ |
| 685 | |
| 686 | int renderer_dd::ddraw_verify_caps() |
| 687 | { |
| 688 | int retval = 0; |
| 689 | HRESULT result; |
| 690 | |
| 691 | // get the capabilities |
| 692 | ddcaps.dwSize = sizeof(ddcaps); |
| 693 | helcaps.dwSize = sizeof(helcaps); |
| 694 | result = IDirectDraw7_GetCaps(ddraw, &ddcaps, &helcaps); |
| 695 | if (result != DD_OK) |
| 696 | { |
| 697 | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_GetCaps call\n", (int)result); |
| 698 | return 1; |
| 699 | } |
| 700 | |
| 701 | // determine if hardware stretching is available |
| 702 | if ((ddcaps.dwCaps & DDCAPS_BLTSTRETCH) == 0) |
| 703 | { |
| 704 | osd_printf_verbose("DirectDraw: Warning - Device does not support hardware stretching\n"); |
| 705 | retval = 1; |
| 706 | } |
| 707 | |
| 708 | return retval; |
| 709 | } |
| 710 | |
| 711 | |
| 712 | |
| 713 | //============================================================ |
| 714 | // ddraw_test_cooperative |
| 715 | //============================================================ |
| 716 | |
| 717 | int renderer_dd::ddraw_test_cooperative() |
| 718 | { |
| 719 | HRESULT result; |
| 720 | |
| 721 | // check our current status; if we lost the device, punt to GDI |
| 722 | result = IDirectDraw7_TestCooperativeLevel(ddraw); |
| 723 | switch (result) |
| 724 | { |
| 725 | // punt to GDI if someone else has exclusive mode |
| 726 | case DDERR_NOEXCLUSIVEMODE: |
| 727 | case DDERR_EXCLUSIVEMODEALREADYSET: |
| 728 | ddraw_delete_surfaces(); |
| 729 | return 1; |
| 730 | |
| 731 | // if we're ok, but we don't have a primary surface, create one |
| 732 | default: |
| 733 | case DD_OK: |
| 734 | if (primary == NULL) |
| 735 | return ddraw_create_surfaces(); |
| 736 | return 0; |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | |
| 741 | |
| 742 | //============================================================ |
| 743 | // create_surface |
| 744 | //============================================================ |
| 745 | |
| 746 | HRESULT renderer_dd::create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type) |
| 747 | { |
| 748 | HRESULT result; |
| 749 | |
| 750 | // create the surface as requested |
| 751 | result = IDirectDraw7_CreateSurface(ddraw, desc, surface, NULL); |
| 752 | if (result != DD_OK) |
| 753 | { |
| 754 | osd_printf_verbose("DirectDraw: Error %08X creating %s surface\n", (int)result, type); |
| 755 | return result; |
| 756 | } |
| 757 | |
| 758 | // get a description of the primary surface |
| 759 | result = IDirectDrawSurface7_GetSurfaceDesc(*surface, desc); |
| 760 | if (result != DD_OK) |
| 761 | { |
| 762 | osd_printf_verbose("DirectDraw: Error %08X getting %s surface desciption\n", (int)result, type); |
| 763 | IDirectDrawSurface7_Release(*surface); |
| 764 | *surface = NULL; |
| 765 | return result; |
| 766 | } |
| 767 | |
| 768 | // print out the good stuff |
| 769 | osd_printf_verbose("DirectDraw: %s surface created: %dx%dx%d (R=%08X G=%08X B=%08X)\n", |
| 770 | type, |
| 771 | (int)desc->dwWidth, |
| 772 | (int)desc->dwHeight, |
| 773 | (int)desc->ddpfPixelFormat.dwRGBBitCount, |
| 774 | (UINT32)desc->ddpfPixelFormat.dwRBitMask, |
| 775 | (UINT32)desc->ddpfPixelFormat.dwGBitMask, |
| 776 | (UINT32)desc->ddpfPixelFormat.dwBBitMask); |
| 777 | return result; |
| 778 | } |
| 779 | |
| 780 | |
| 781 | |
| 782 | //============================================================ |
| 783 | // create_clipper |
| 784 | //============================================================ |
| 785 | |
| 786 | int renderer_dd::create_clipper() |
| 787 | { |
| 788 | HRESULT result; |
| 789 | |
| 790 | // create a clipper for the primary surface |
| 791 | result = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL); |
| 792 | if (result != DD_OK) |
| 793 | { |
| 794 | osd_printf_verbose("DirectDraw: Error %08X creating clipper\n", (int)result); |
| 795 | return 1; |
| 796 | } |
| 797 | |
| 798 | // set the clipper's hwnd |
| 799 | result = IDirectDrawClipper_SetHWnd(clipper, 0, window().m_hwnd); |
| 800 | if (result != DD_OK) |
| 801 | { |
| 802 | osd_printf_verbose("DirectDraw: Error %08X setting clipper hwnd\n", (int)result); |
| 803 | return 1; |
| 804 | } |
| 805 | |
| 806 | // set the clipper on the primary surface |
| 807 | result = IDirectDrawSurface7_SetClipper(primary, clipper); |
| 808 | if (result != DD_OK) |
| 809 | { |
| 810 | osd_printf_verbose("DirectDraw: Error %08X setting clipper on primary surface\n", (int)result); |
| 811 | return 1; |
| 812 | } |
| 813 | return 0; |
| 814 | } |
| 815 | |
| 816 | |
| 817 | |
| 818 | //============================================================ |
| 819 | // compute_blit_surface_size |
| 820 | //============================================================ |
| 821 | |
| 822 | void renderer_dd::compute_blit_surface_size() |
| 823 | { |
| 824 | INT32 newwidth, newheight; |
| 825 | int xscale, yscale; |
| 826 | RECT client; |
| 827 | |
| 828 | // start with the minimum size |
| 829 | window().target()->compute_minimum_size(newwidth, newheight); |
| 830 | |
| 831 | // get the window's client rectangle |
| 832 | GetClientRect(window().m_hwnd, &client); |
| 833 | |
| 834 | // hardware stretch case: apply prescale |
| 835 | if (video_config.hwstretch) |
| 836 | { |
| 837 | int prescale = (window().prescale() < 1) ? 1 : window().prescale(); |
| 838 | |
| 839 | // clamp the prescale to something smaller than the target bounds |
| 840 | xscale = prescale; |
| 841 | while (xscale > 1 && newwidth * xscale > rect_width(&client)) |
| 842 | xscale--; |
| 843 | yscale = prescale; |
| 844 | while (yscale > 1 && newheight * yscale > rect_height(&client)) |
| 845 | yscale--; |
| 846 | } |
| 847 | |
| 848 | // non stretch case |
| 849 | else |
| 850 | { |
| 851 | INT32 target_width = rect_width(&client); |
| 852 | INT32 target_height = rect_height(&client); |
| 853 | float desired_aspect = 1.0f; |
| 854 | |
| 855 | // compute the appropriate visible area if we're trying to keepaspect |
| 856 | if (video_config.keepaspect) |
| 857 | { |
| 858 | win_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); |
| 859 | window().target()->compute_visible_area(target_width, target_height, monitor->aspect(), window().target()->orientation(), target_width, target_height); |
| 860 | desired_aspect = (float)target_width / (float)target_height; |
| 861 | } |
| 862 | |
| 863 | // compute maximum integral scaling to fit the window |
| 864 | xscale = (target_width + 2) / newwidth; |
| 865 | yscale = (target_height + 2) / newheight; |
| 866 | |
| 867 | // try a little harder to keep the aspect ratio if desired |
| 868 | if (video_config.keepaspect) |
| 869 | { |
| 870 | // if we could stretch more in the X direction, and that makes a better fit, bump the xscale |
| 871 | while (newwidth * (xscale + 1) <= rect_width(&client) && |
| 872 | better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) |
| 873 | xscale++; |
| 874 | |
| 875 | // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale |
| 876 | while (newheight * (yscale + 1) <= rect_height(&client) && |
| 877 | better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) |
| 878 | yscale++; |
| 879 | |
| 880 | // now that we've maxed out, see if backing off the maximally stretched one makes a better fit |
| 881 | if (rect_width(&client) - newwidth * xscale < rect_height(&client) - newheight * yscale) |
| 882 | { |
| 883 | while (xscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect)) |
| 884 | xscale--; |
| 885 | } |
| 886 | else |
| 887 | { |
| 888 | while (yscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect)) |
| 889 | yscale--; |
| 890 | } |
| 891 | } |
| 892 | } |
| 893 | |
| 894 | // ensure at least a scale factor of 1 |
| 895 | if (xscale == 0) xscale = 1; |
| 896 | if (yscale == 0) yscale = 1; |
| 897 | |
| 898 | // apply the final scale |
| 899 | newwidth *= xscale; |
| 900 | newheight *= yscale; |
| 901 | if (newwidth != blitwidth || newheight != blitheight) |
| 902 | { |
| 903 | // force some updates |
| 904 | update_outer_rects(); |
| 905 | osd_printf_verbose("DirectDraw: New blit size = %dx%d\n", newwidth, newheight); |
| 906 | } |
| 907 | blitwidth = newwidth; |
| 908 | blitheight = newheight; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | |
| 913 | //============================================================ |
| 914 | // calc_fullscreen_margins |
| 915 | //============================================================ |
| 916 | |
| 917 | void renderer_dd::calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins) |
| 918 | { |
| 919 | margins->left = 0; |
| 920 | margins->top = 0; |
| 921 | margins->right = desc_width; |
| 922 | margins->bottom = desc_height; |
| 923 | |
| 924 | if (window().win_has_menu()) |
| 925 | { |
| 926 | static int height_with_menubar = 0; |
| 927 | if (height_with_menubar == 0) |
| 928 | { |
| 929 | RECT with_menu = { 100, 100, 200, 200 }; |
| 930 | RECT without_menu = { 100, 100, 200, 200 }; |
| 931 | AdjustWindowRect(&with_menu, WS_OVERLAPPED, TRUE); |
| 932 | AdjustWindowRect(&without_menu, WS_OVERLAPPED, FALSE); |
| 933 | height_with_menubar = (with_menu.bottom - with_menu.top) - (without_menu.bottom - without_menu.top); |
| 934 | } |
| 935 | margins->top = height_with_menubar; |
| 936 | } |
| 937 | } |
| 938 | |
| 939 | |
| 940 | |
| 941 | //============================================================ |
| 942 | // blit_to_primary |
| 943 | //============================================================ |
| 944 | |
| 945 | void renderer_dd::blit_to_primary(int srcwidth, int srcheight) |
| 946 | { |
| 947 | IDirectDrawSurface7 *target = (back != NULL) ? back : primary; |
| 948 | win_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); |
| 949 | DDBLTFX blitfx = { sizeof(DDBLTFX) }; |
| 950 | RECT clear, outer, dest, source; |
| 951 | INT32 dstwidth, dstheight; |
| 952 | HRESULT result; |
| 953 | |
| 954 | // compute source rect |
| 955 | source.left = source.top = 0; |
| 956 | source.right = srcwidth; |
| 957 | source.bottom = srcheight; |
| 958 | |
| 959 | // compute outer rect -- windowed version |
| 960 | if (!window().fullscreen()) |
| 961 | { |
| 962 | GetClientRect(window().m_hwnd, &outer); |
| 963 | ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[0]); |
| 964 | ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[1]); |
| 965 | |
| 966 | // adjust to be relative to the monitor |
| 967 | osd_rect pos = monitor->position_size(); |
| 968 | outer.left -= pos.left(); |
| 969 | outer.right -= pos.left(); |
| 970 | outer.top -= pos.top(); |
| 971 | outer.bottom -= pos.top(); |
| 972 | } |
| 973 | |
| 974 | // compute outer rect -- full screen version |
| 975 | else |
| 976 | { |
| 977 | calc_fullscreen_margins(primarydesc.dwWidth, primarydesc.dwHeight, &outer); |
| 978 | } |
| 979 | |
| 980 | // if we're respecting the aspect ratio, we need to adjust to fit |
| 981 | dstwidth = rect_width(&outer); |
| 982 | dstheight = rect_height(&outer); |
| 983 | if (!video_config.hwstretch) |
| 984 | { |
| 985 | // trim the source if necessary |
| 986 | if (rect_width(&outer) < srcwidth) |
| 987 | { |
| 988 | source.left += (srcwidth - rect_width(&outer)) / 2; |
| 989 | source.right = source.left + rect_width(&outer); |
| 990 | } |
| 991 | if (rect_height(&outer) < srcheight) |
| 992 | { |
| 993 | source.top += (srcheight - rect_height(&outer)) / 2; |
| 994 | source.bottom = source.top + rect_height(&outer); |
| 995 | } |
| 996 | |
| 997 | // match the destination and source sizes |
| 998 | dstwidth = srcwidth = source.right - source.left; |
| 999 | dstheight = srcheight = source.bottom - source.top; |
| 1000 | } |
| 1001 | else if (video_config.keepaspect) |
| 1002 | { |
| 1003 | // compute the appropriate visible area |
| 1004 | window().target()->compute_visible_area(rect_width(&outer), rect_height(&outer), monitor->aspect(), window().target()->orientation(), dstwidth, dstheight); |
| 1005 | } |
| 1006 | |
| 1007 | // center within |
| 1008 | dest.left = outer.left + (rect_width(&outer) - dstwidth) / 2; |
| 1009 | dest.right = dest.left + dstwidth; |
| 1010 | dest.top = outer.top + (rect_height(&outer) - dstheight) / 2; |
| 1011 | dest.bottom = dest.top + dstheight; |
| 1012 | |
| 1013 | // compare against last destination; if different, force a redraw |
| 1014 | if (dest.left != lastdest.left || dest.right != lastdest.right || dest.top != lastdest.top || dest.bottom != lastdest.bottom) |
| 1015 | { |
| 1016 | lastdest = dest; |
| 1017 | update_outer_rects(); |
| 1018 | } |
| 1019 | |
| 1020 | // clear outer rects if we need to |
| 1021 | if (clearouter != 0) |
| 1022 | { |
| 1023 | clearouter--; |
| 1024 | |
| 1025 | // clear the left edge |
| 1026 | if (dest.left > outer.left) |
| 1027 | { |
| 1028 | clear = outer; |
| 1029 | clear.right = dest.left; |
| 1030 | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1031 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1032 | } |
| 1033 | |
| 1034 | // clear the right edge |
| 1035 | if (dest.right < outer.right) |
| 1036 | { |
| 1037 | clear = outer; |
| 1038 | clear.left = dest.right; |
| 1039 | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1040 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1041 | } |
| 1042 | |
| 1043 | // clear the top edge |
| 1044 | if (dest.top > outer.top) |
| 1045 | { |
| 1046 | clear = outer; |
| 1047 | clear.bottom = dest.top; |
| 1048 | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1049 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1050 | } |
| 1051 | |
| 1052 | // clear the bottom edge |
| 1053 | if (dest.bottom < outer.bottom) |
| 1054 | { |
| 1055 | clear = outer; |
| 1056 | clear.top = dest.bottom; |
| 1057 | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1058 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1059 | } |
| 1060 | } |
| 1061 | |
| 1062 | // do the blit |
| 1063 | result = IDirectDrawSurface7_Blt(target, &dest, blit, &source, DDBLT_WAIT, NULL); |
| 1064 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X blitting to the screen\n", (int)result); |
| 1065 | |
| 1066 | // page flip if triple buffered |
| 1067 | if (window().fullscreen() && back != NULL) |
| 1068 | { |
| 1069 | result = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT); |
| 1070 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); |
| 1071 | } |
| 1072 | } |
| 1073 | |
| 1074 | |
| 1075 | |
| 1076 | //============================================================ |
| 1077 | // config_adapter_mode |
| 1078 | //============================================================ |
| 1079 | |
| 1080 | int renderer_dd::config_adapter_mode() |
| 1081 | { |
| 1082 | DDDEVICEIDENTIFIER2 identifier; |
| 1083 | HRESULT result; |
| 1084 | |
| 1085 | // choose the monitor number |
| 1086 | get_adapter_for_monitor(window().monitor()); |
| 1087 | |
| 1088 | // create a temporary DirectDraw object |
| 1089 | result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); |
| 1090 | if (result != DD_OK) |
| 1091 | { |
| 1092 | osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); |
| 1093 | return 1; |
| 1094 | } |
| 1095 | |
| 1096 | // get the identifier |
| 1097 | result = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0); |
| 1098 | if (result != DD_OK) |
| 1099 | { |
| 1100 | osd_printf_error("Error getting identifier for device\n"); |
| 1101 | return 1; |
| 1102 | } |
| 1103 | osd_printf_verbose("DirectDraw: Configuring device %s\n", identifier.szDescription); |
| 1104 | |
| 1105 | // get the current display mode |
| 1106 | memset(&origmode, 0, sizeof(origmode)); |
| 1107 | origmode.dwSize = sizeof(origmode); |
| 1108 | result = IDirectDraw7_GetDisplayMode(ddraw, &origmode); |
| 1109 | if (result != DD_OK) |
| 1110 | { |
| 1111 | osd_printf_verbose("DirectDraw: Error %08X getting current display mode\n", (int)result); |
| 1112 | IDirectDraw7_Release(ddraw); |
| 1113 | return 1; |
| 1114 | } |
| 1115 | |
| 1116 | // choose a resolution: full screen mode case |
| 1117 | if (window().fullscreen()) |
| 1118 | { |
| 1119 | // default to the current mode exactly |
| 1120 | width = origmode.dwWidth; |
| 1121 | height = origmode.dwHeight; |
| 1122 | refresh = origmode.dwRefreshRate; |
| 1123 | |
| 1124 | // if we're allowed to switch resolutions, override with something better |
| 1125 | if (video_config.switchres) |
| 1126 | pick_best_mode(); |
| 1127 | } |
| 1128 | |
| 1129 | // release the DirectDraw object |
| 1130 | IDirectDraw7_Release(ddraw); |
| 1131 | ddraw = NULL; |
| 1132 | |
| 1133 | // if we're not changing resolutions, make sure we have a resolution we can handle |
| 1134 | if (!window().fullscreen() || !video_config.switchres) |
| 1135 | { |
| 1136 | switch (origmode.ddpfPixelFormat.dwRBitMask) |
| 1137 | { |
| 1138 | case 0x00ff0000: |
| 1139 | case 0x000000ff: |
| 1140 | case 0xf800: |
| 1141 | case 0x7c00: |
| 1142 | break; |
| 1143 | |
| 1144 | default: |
| 1145 | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)origmode.ddpfPixelFormat.dwRBitMask, (int)origmode.ddpfPixelFormat.dwGBitMask, (int)origmode.ddpfPixelFormat.dwBBitMask); |
| 1146 | return 1; |
| 1147 | } |
| 1148 | } |
| 1149 | |
| 1150 | return 0; |
| 1151 | } |
| 1152 | |
| 1153 | |
| 1154 | |
| 1155 | //============================================================ |
| 1156 | // monitor_enum_callback |
| 1157 | //============================================================ |
| 1158 | |
| 1159 | static BOOL WINAPI monitor_enum_callback(GUID FAR *guid, LPSTR description, LPSTR name, LPVOID context, HMONITOR hmonitor) |
| 1160 | { |
| 1161 | monitor_enum_info *einfo = (monitor_enum_info *)context; |
| 1162 | |
| 1163 | // do we match the desired monitor? |
| 1164 | if (hmonitor == einfo->monitor->handle() || (hmonitor == NULL && einfo->monitor->is_primary())) |
| 1165 | { |
| 1166 | einfo->guid_ptr = (guid != NULL) ? &einfo->guid : NULL; |
| 1167 | if (guid != NULL) |
| 1168 | einfo->guid = *guid; |
| 1169 | einfo->foundit = TRUE; |
| 1170 | } |
| 1171 | return 1; |
| 1172 | } |
| 1173 | |
| 1174 | |
| 1175 | |
| 1176 | //============================================================ |
| 1177 | // get_adapter_for_monitor |
| 1178 | //============================================================ |
| 1179 | |
| 1180 | void renderer_dd::get_adapter_for_monitor(win_monitor_info *monitor) |
| 1181 | { |
| 1182 | monitor_enum_info einfo; |
| 1183 | HRESULT result; |
| 1184 | |
| 1185 | // try to find our monitor |
| 1186 | memset(&einfo, 0, sizeof(einfo)); |
| 1187 | einfo.monitor = monitor; |
| 1188 | result = (*directdrawenumerateex)(monitor_enum_callback, &einfo, DDENUM_ATTACHEDSECONDARYDEVICES); |
| 1189 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during DirectDrawEnumerateEx call\n", (int)result); |
| 1190 | |
| 1191 | // set up the adapter |
| 1192 | if (einfo.foundit && einfo.guid_ptr != NULL) |
| 1193 | { |
| 1194 | adapter = einfo.guid; |
| 1195 | adapter_ptr = &adapter; |
| 1196 | } |
| 1197 | else |
| 1198 | adapter_ptr = NULL; |
| 1199 | } |
| 1200 | |
| 1201 | |
| 1202 | |
| 1203 | //============================================================ |
| 1204 | // enum_modes_callback |
| 1205 | //============================================================ |
| 1206 | |
| 1207 | static HRESULT WINAPI enum_modes_callback(LPDDSURFACEDESC2 desc, LPVOID context) |
| 1208 | { |
| 1209 | float size_score, refresh_score, final_score; |
| 1210 | mode_enum_info *einfo = (mode_enum_info *)context; |
| 1211 | renderer_dd *dd = einfo->renderer; |
| 1212 | |
| 1213 | // skip non-32 bit modes |
| 1214 | if (desc->ddpfPixelFormat.dwRGBBitCount != 32) |
| 1215 | return DDENUMRET_OK; |
| 1216 | |
| 1217 | // compute initial score based on difference between target and current |
| 1218 | size_score = 1.0f / (1.0f + fabs((float)((INT32)desc->dwWidth - einfo->target_width)) + fabs((float)((INT32)desc->dwHeight - einfo->target_height))); |
| 1219 | |
| 1220 | // if the mode is too small, give a big penalty |
| 1221 | if (desc->dwWidth < einfo->minimum_width || desc->dwHeight < einfo->minimum_height) |
| 1222 | size_score *= 0.01f; |
| 1223 | |
| 1224 | // if mode is smaller than we'd like, it only scores up to 0.1 |
| 1225 | if (desc->dwWidth < einfo->target_width || desc->dwHeight < einfo->target_height) |
| 1226 | size_score *= 0.1f; |
| 1227 | |
| 1228 | // if we're looking for a particular mode, that's a winner |
| 1229 | if (desc->dwWidth == einfo->window->m_win_config.width && desc->dwHeight == einfo->window->m_win_config.height) |
| 1230 | size_score = 2.0f; |
| 1231 | |
| 1232 | // compute refresh score |
| 1233 | refresh_score = 1.0f / (1.0f + fabs((double)desc->dwRefreshRate - einfo->target_refresh)); |
| 1234 | |
| 1235 | // if refresh is smaller than we'd like, it only scores up to 0.1 |
| 1236 | if ((double)desc->dwRefreshRate < einfo->target_refresh) |
| 1237 | refresh_score *= 0.1f; |
| 1238 | |
| 1239 | // if we're looking for a particular refresh, make sure it matches |
| 1240 | if (desc->dwRefreshRate == einfo->window->m_win_config.refresh) |
| 1241 | refresh_score = 2.0f; |
| 1242 | |
| 1243 | // weight size and refresh equally |
| 1244 | final_score = size_score + refresh_score; |
| 1245 | |
| 1246 | // best so far? |
| 1247 | osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", (int)desc->dwWidth, (int)desc->dwHeight, (int)desc->dwRefreshRate, final_score * 1000.0f); |
| 1248 | if (final_score > einfo->best_score) |
| 1249 | { |
| 1250 | einfo->best_score = final_score; |
| 1251 | dd->width = desc->dwWidth; |
| 1252 | dd->height = desc->dwHeight; |
| 1253 | dd->refresh = desc->dwRefreshRate; |
| 1254 | } |
| 1255 | return DDENUMRET_OK; |
| 1256 | } |
| 1257 | |
| 1258 | |
| 1259 | |
| 1260 | //============================================================ |
| 1261 | // pick_best_mode |
| 1262 | //============================================================ |
| 1263 | |
| 1264 | void renderer_dd::pick_best_mode() |
| 1265 | { |
| 1266 | mode_enum_info einfo; |
| 1267 | HRESULT result; |
| 1268 | |
| 1269 | // determine the minimum width/height for the selected target |
| 1270 | // note: technically we should not be calling this from an alternate window |
| 1271 | // thread; however, it is only done during init time, and the init code on |
| 1272 | // the main thread is waiting for us to finish, so it is safe to do so here |
| 1273 | window().target()->compute_minimum_size(einfo.minimum_width, einfo.minimum_height); |
| 1274 | |
| 1275 | // use those as the target for now |
| 1276 | einfo.target_width = einfo.minimum_width * MAX(1, window().prescale()); |
| 1277 | einfo.target_height = einfo.minimum_height * MAX(1, window().prescale()); |
| 1278 | |
| 1279 | // determine the refresh rate of the primary screen |
| 1280 | einfo.target_refresh = 60.0; |
| 1281 | const screen_device *primary_screen = window().machine().config().first_screen(); |
| 1282 | if (primary_screen != NULL) |
| 1283 | einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); |
| 1284 | printf("Target refresh = %f\n", einfo.target_refresh); |
| 1285 | |
| 1286 | // if we're not stretching, allow some slop on the minimum since we can handle it |
| 1287 | if (!video_config.hwstretch) |
| 1288 | { |
| 1289 | einfo.minimum_width -= 4; |
| 1290 | einfo.minimum_height -= 4; |
| 1291 | } |
| 1292 | |
| 1293 | // if we are stretching, aim for a mode approximately 2x the game's resolution |
| 1294 | else if (window().prescale() <= 1) |
| 1295 | { |
| 1296 | einfo.target_width *= 2; |
| 1297 | einfo.target_height *= 2; |
| 1298 | } |
| 1299 | |
| 1300 | // fill in the rest of the data |
| 1301 | einfo.window = &window(); |
| 1302 | einfo.renderer = this; |
| 1303 | einfo.best_score = 0.0f; |
| 1304 | |
| 1305 | // enumerate the modes |
| 1306 | osd_printf_verbose("DirectDraw: Selecting video mode...\n"); |
| 1307 | result = IDirectDraw7_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &einfo, enum_modes_callback); |
| 1308 | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during EnumDisplayModes call\n", (int)result); |
| 1309 | osd_printf_verbose("DirectDraw: Mode selected = %4dx%4d@%3dHz\n", width, height, refresh); |
| 1310 | } |
trunk/src/osd/modules/render/drawogl.c
| r0 | r244652 | |
| 1 | //============================================================ |
| 2 | // |
| 3 | // drawogl.c - SDL software and OpenGL implementation |
| 4 | // |
| 5 | // Copyright (c) 1996-2014, Nicola Salmoria and the MAME Team. |
| 6 | // Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | // |
| 8 | // SDLMAME by Olivier Galibert and R. Belmont |
| 9 | // |
| 10 | // Note: D3D9 goes to a lot of trouble to fiddle with MODULATE |
| 11 | // mode on textures. That is the default in OpenGL so we |
| 12 | // don't have to touch it. |
| 13 | // |
| 14 | //============================================================ |
| 15 | |
| 16 | // standard C headers |
| 17 | #include <math.h> |
| 18 | #include <stdio.h> |
| 19 | |
| 20 | // MAME headers |
| 21 | #include "osdcomm.h" |
| 22 | #include "emu.h" |
| 23 | #include "options.h" |
| 24 | #include "emuopts.h" |
| 25 | |
| 26 | #ifndef OSD_WINDOWS |
| 27 | // standard SDL headers |
| 28 | #define TOBEMIGRATED 1 |
| 29 | #include "sdlinc.h" |
| 30 | #endif |
| 31 | |
| 32 | // OpenGL headers |
| 33 | #include "modules/opengl/osd_opengl.h" |
| 34 | |
| 35 | #ifdef OSD_WINDOWS |
| 36 | #define SDLMAME_SDL2 1 |
| 37 | #ifndef USE_DISPATCH_GL |
| 38 | #include "GL/wglext.h" |
| 39 | #endif |
| 40 | #endif |
| 41 | |
| 42 | #include "modules/lib/osdlib.h" |
| 43 | #include "modules/lib/osdobj_common.h" |
| 44 | |
| 45 | |
| 46 | #include "modules/opengl/gl_shader_tool.h" |
| 47 | #include "modules/opengl/gl_shader_mgr.h" |
| 48 | |
| 49 | #if defined(SDLMAME_MACOSX) |
| 50 | #ifndef APIENTRY |
| 51 | #define APIENTRY |
| 52 | #endif |
| 53 | #ifndef APIENTRYP |
| 54 | #define APIENTRYP APIENTRY * |
| 55 | #endif |
| 56 | |
| 57 | typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); |
| 58 | typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum, GLuint); |
| 59 | typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum, GLsizeiptr, const GLvoid *, GLenum); |
| 60 | typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum, GLintptr, GLsizeiptr, const GLvoid *); |
| 61 | typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum, GLenum); |
| 62 | typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum); |
| 63 | typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei, const GLuint *); |
| 64 | typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); |
| 65 | typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); |
| 66 | typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum m_target, GLuint framebuffer); |
| 67 | typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); |
| 68 | typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); |
| 69 | typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum m_target); |
| 70 | typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum m_target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); |
| 71 | typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); |
| 72 | typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint renderbuffer); |
| 73 | typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height); |
| 74 | typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); |
| 75 | typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); |
| 76 | #endif |
| 77 | |
| 78 | // make sure the extensions compile OK everywhere |
| 79 | #ifndef GL_TEXTURE_STORAGE_HINT_APPLE |
| 80 | #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85bc |
| 81 | #endif |
| 82 | |
| 83 | #ifndef GL_STORAGE_CACHED_APPLE |
| 84 | #define GL_STORAGE_CACHED_APPLE 0x85be |
| 85 | #endif |
| 86 | |
| 87 | #ifndef GL_UNPACK_CLIENT_STORAGE_APPLE |
| 88 | #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85b2 |
| 89 | #endif |
| 90 | |
| 91 | #ifndef GL_TEXTURE_RECTANGLE_ARB |
| 92 | #define GL_TEXTURE_RECTANGLE_ARB 0x84F5 |
| 93 | #endif |
| 94 | |
| 95 | #ifndef GL_PIXEL_UNPACK_BUFFER_ARB |
| 96 | #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC |
| 97 | #endif |
| 98 | |
| 99 | #ifndef GL_STREAM_DRAW |
| 100 | #define GL_STREAM_DRAW 0x88E0 |
| 101 | #endif |
| 102 | |
| 103 | #ifndef GL_WRITE_ONLY |
| 104 | #define GL_WRITE_ONLY 0x88B9 |
| 105 | #endif |
| 106 | |
| 107 | #ifndef GL_ARRAY_BUFFER_ARB |
| 108 | #define GL_ARRAY_BUFFER_ARB 0x8892 |
| 109 | #endif |
| 110 | |
| 111 | #ifndef GL_PIXEL_UNPACK_BUFFER_ARB |
| 112 | #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC |
| 113 | #endif |
| 114 | |
| 115 | #ifndef GL_FRAMEBUFFER_EXT |
| 116 | #define GL_FRAMEBUFFER_EXT 0x8D40 |
| 117 | #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 |
| 118 | #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 |
| 119 | #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 |
| 120 | #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 |
| 121 | #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 |
| 122 | #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA |
| 123 | #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB |
| 124 | #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC |
| 125 | #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD |
| 126 | #define GL_RENDERBUFFER_EXT 0x8D41 |
| 127 | #define GL_DEPTH_COMPONENT16 0x81A5 |
| 128 | #define GL_DEPTH_COMPONENT24 0x81A6 |
| 129 | #define GL_DEPTH_COMPONENT32 0x81A7 |
| 130 | #endif |
| 131 | |
| 132 | #define HASH_SIZE ((1<<10)+1) |
| 133 | #define OVERFLOW_SIZE (1<<10) |
| 134 | |
| 135 | // OSD headers |
| 136 | #ifndef OSD_WINDOWS |
| 137 | #include "osdsdl.h" |
| 138 | #include "window.h" |
| 139 | #else |
| 140 | #include "../windows/window.h" |
| 141 | typedef UINT64 HashT; |
| 142 | #endif |
| 143 | |
| 144 | //============================================================ |
| 145 | // DEBUGGING |
| 146 | //============================================================ |
| 147 | |
| 148 | #define DEBUG_MODE_SCORES 0 |
| 149 | #define USE_WIN32_STYLE_LINES 0 // use the same method baseline does - yields somewhat nicer vectors but a little buggy |
| 150 | |
| 151 | //============================================================ |
| 152 | // CONSTANTS |
| 153 | //============================================================ |
| 154 | |
| 155 | enum |
| 156 | { |
| 157 | TEXTURE_TYPE_NONE, |
| 158 | TEXTURE_TYPE_PLAIN, |
| 159 | TEXTURE_TYPE_DYNAMIC, |
| 160 | TEXTURE_TYPE_SHADER, |
| 161 | TEXTURE_TYPE_SURFACE |
| 162 | }; |
| 163 | |
| 164 | |
| 165 | //============================================================ |
| 166 | // MACROS |
| 167 | //============================================================ |
| 168 | |
| 169 | #ifdef OSD_WINDOWS |
| 170 | // texture formats |
| 171 | // This used to be an enum, but these are now defines so we can use them as |
| 172 | // preprocessor conditionals |
| 173 | #define SDL_TEXFORMAT_ARGB32 (0) // non-16-bit textures or specials |
| 174 | #define SDL_TEXFORMAT_RGB32 (1) |
| 175 | #define SDL_TEXFORMAT_RGB32_PALETTED (2) |
| 176 | #define SDL_TEXFORMAT_YUY16 (3) |
| 177 | #define SDL_TEXFORMAT_YUY16_PALETTED (4) |
| 178 | #define SDL_TEXFORMAT_PALETTE16 (5) |
| 179 | #define SDL_TEXFORMAT_RGB15 (6) |
| 180 | #define SDL_TEXFORMAT_RGB15_PALETTED (7) |
| 181 | #define SDL_TEXFORMAT_PALETTE16A (8) |
| 182 | // special texture formats for 16bpp texture destination support, do not use |
| 183 | // to address the tex properties / tex functions arrays! |
| 184 | #define SDL_TEXFORMAT_PALETTE16_ARGB1555 (16) |
| 185 | #define SDL_TEXFORMAT_RGB15_ARGB1555 (17) |
| 186 | #define SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 (18) |
| 187 | #endif |
| 188 | |
| 189 | #define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0) |
| 190 | #define GL_NO_PRIMITIVE -1 |
| 191 | |
| 192 | //============================================================ |
| 193 | // TYPES |
| 194 | //============================================================ |
| 195 | |
| 196 | #if (SDLMAME_SDL2) |
| 197 | |
| 198 | #ifdef OSD_WINDOWS |
| 199 | class win_gl_context : public osd_gl_context |
| 200 | { |
| 201 | public: |
| 202 | win_gl_context(HWND window) : osd_gl_context(), m_context(0), m_window(NULL), m_hdc(0) |
| 203 | { |
| 204 | m_error[0] = 0; |
| 205 | |
| 206 | this->wglGetProcAddress = (PROC WINAPI (*)(LPCSTR lpszProc)) GetProcAddress(m_module, "wglGetProcAddress"); |
| 207 | this->wglCreateContext = (HGLRC WINAPI (*)(HDC hdc)) GetProcAddress(m_module, "wglCreateContext"); |
| 208 | this->wglDeleteContext = (BOOL WINAPI (*)(HGLRC hglrc)) GetProcAddress(m_module, "wglDeleteContext"); |
| 209 | this->wglMakeCurrent = (BOOL WINAPI (*)(HDC hdc, HGLRC hglrc)) GetProcAddress(m_module, "wglMakeCurrent"); |
| 210 | |
| 211 | m_hdc = GetDC(window); |
| 212 | if (!setupPixelFormat(m_hdc)) |
| 213 | { |
| 214 | m_context = wglCreateContext(m_hdc); |
| 215 | if (!m_context) |
| 216 | { |
| 217 | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, m_error, 255, NULL); |
| 218 | return; |
| 219 | } |
| 220 | wglMakeCurrent(m_hdc, m_context); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | virtual ~win_gl_context() |
| 225 | { |
| 226 | wglDeleteContext(m_context); |
| 227 | ReleaseDC(m_window, m_hdc); |
| 228 | } |
| 229 | |
| 230 | virtual void MakeCurrent() |
| 231 | { |
| 232 | wglMakeCurrent(m_hdc, m_context); |
| 233 | } |
| 234 | |
| 235 | virtual const char *LastErrorMsg() |
| 236 | { |
| 237 | if (m_error[0] == 0) |
| 238 | return NULL; |
| 239 | else |
| 240 | return m_error; |
| 241 | } |
| 242 | |
| 243 | virtual void *getProcAddress(const char *proc) |
| 244 | { |
| 245 | void *ret = (void *) GetProcAddress(m_module, proc); |
| 246 | if (ret == NULL) |
| 247 | ret = (void *) wglGetProcAddress(proc); |
| 248 | return ret; |
| 249 | } |
| 250 | |
| 251 | virtual int SetSwapInterval(const int swap) |
| 252 | { |
| 253 | // FIXME: Missing! |
| 254 | return 0; |
| 255 | } |
| 256 | |
| 257 | virtual void SwapBuffer() |
| 258 | { |
| 259 | SwapBuffers(m_hdc); |
| 260 | //wglSwapLayerBuffers(GetDC(window().m_hwnd), WGL_SWAP_MAIN_PLANE); |
| 261 | } |
| 262 | |
| 263 | static void load_library() |
| 264 | { |
| 265 | m_module = LoadLibraryA("opengl32.dll"); |
| 266 | } |
| 267 | |
| 268 | private: |
| 269 | |
| 270 | int setupPixelFormat(HDC hDC) |
| 271 | { |
| 272 | PIXELFORMATDESCRIPTOR pfd = { |
| 273 | sizeof(PIXELFORMATDESCRIPTOR), /* size */ |
| 274 | 1, /* version */ |
| 275 | PFD_SUPPORT_OPENGL | |
| 276 | PFD_DRAW_TO_WINDOW | |
| 277 | PFD_DOUBLEBUFFER, /* support double-buffering */ |
| 278 | PFD_TYPE_RGBA, /* color type */ |
| 279 | 32, /* prefered color depth */ |
| 280 | 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ |
| 281 | 0, /* no alpha buffer */ |
| 282 | 0, /* alpha bits (ignored) */ |
| 283 | 0, /* no accumulation buffer */ |
| 284 | 0, 0, 0, 0, /* accum bits (ignored) */ |
| 285 | 16, /* depth buffer */ |
| 286 | 0, /* no stencil buffer */ |
| 287 | 0, /* no auxiliary buffers */ |
| 288 | PFD_MAIN_PLANE, /* main layer */ |
| 289 | 0, /* reserved */ |
| 290 | 0, 0, 0, /* no layer, visible, damage masks */ |
| 291 | }; |
| 292 | int pixelFormat; |
| 293 | |
| 294 | pixelFormat = ChoosePixelFormat(hDC, &pfd); |
| 295 | if (pixelFormat == 0) { |
| 296 | strcpy(m_error, "ChoosePixelFormat failed"); |
| 297 | return 1; |
| 298 | } |
| 299 | |
| 300 | if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { |
| 301 | strcpy(m_error, "SetPixelFormat failed."); |
| 302 | return 1; |
| 303 | } |
| 304 | return 0; |
| 305 | } |
| 306 | |
| 307 | |
| 308 | HGLRC m_context; |
| 309 | HWND m_window; |
| 310 | HDC m_hdc; |
| 311 | char m_error[256]; |
| 312 | |
| 313 | PROC WINAPI (*wglGetProcAddress)(LPCSTR lpszProc); |
| 314 | HGLRC WINAPI (*wglCreateContext)(HDC hdc); |
| 315 | BOOL WINAPI (*wglDeleteContext)(HGLRC hglrc); |
| 316 | BOOL WINAPI (*wglMakeCurrent)(HDC hdc, HGLRC hglrc); |
| 317 | |
| 318 | static HMODULE m_module; |
| 319 | }; |
| 320 | |
| 321 | HMODULE win_gl_context::m_module; |
| 322 | |
| 323 | |
| 324 | #else |
| 325 | class sdl_gl_context : public osd_gl_context |
| 326 | { |
| 327 | public: |
| 328 | sdl_gl_context(SDL_Window *window) : osd_gl_context(), m_context(0), m_window(window) |
| 329 | { |
| 330 | m_error[0] = 0; |
| 331 | m_context = SDL_GL_CreateContext(window); |
| 332 | if (!m_context) |
| 333 | { |
| 334 | snprintf(m_error,255, "OpenGL not supported on this driver: %s", SDL_GetError()); |
| 335 | } |
| 336 | } |
| 337 | virtual ~sdl_gl_context() |
| 338 | { |
| 339 | SDL_GL_DeleteContext(m_context); |
| 340 | } |
| 341 | virtual void MakeCurrent() |
| 342 | { |
| 343 | SDL_GL_MakeCurrent(m_window, m_context); |
| 344 | } |
| 345 | |
| 346 | virtual int SetSwapInterval(const int swap) |
| 347 | { |
| 348 | return SDL_GL_SetSwapInterval(swap); |
| 349 | } |
| 350 | |
| 351 | virtual const char *LastErrorMsg() |
| 352 | { |
| 353 | if (m_error[0] == 0) |
| 354 | return NULL; |
| 355 | else |
| 356 | return m_error; |
| 357 | } |
| 358 | virtual void *getProcAddress(const char *proc) |
| 359 | { |
| 360 | return SDL_GL_GetProcAddress(proc); |
| 361 | } |
| 362 | |
| 363 | virtual void SwapBuffer() |
| 364 | { |
| 365 | SDL_GL_SwapWindow(m_window); |
| 366 | } |
| 367 | |
| 368 | private: |
| 369 | SDL_GLContext m_context; |
| 370 | SDL_Window *m_window; |
| 371 | char m_error[256]; |
| 372 | }; |
| 373 | #endif |
| 374 | #else |
| 375 | // SDL 1.2 |
| 376 | class sdl12_gl_context : public osd_gl_context |
| 377 | { |
| 378 | public: |
| 379 | sdl12_gl_context(SDL_Surface *window) : osd_gl_context(), m_window(window) |
| 380 | { |
| 381 | m_error[0] = 0; |
| 382 | } |
| 383 | virtual ~sdl12_gl_context() |
| 384 | { |
| 385 | } |
| 386 | virtual void MakeCurrent() |
| 387 | { |
| 388 | } |
| 389 | |
| 390 | virtual int SetSwapInterval(const int swap) |
| 391 | { |
| 392 | // Not supported on 1.2 |
| 393 | return 0; |
| 394 | } |
| 395 | |
| 396 | virtual const char *LastErrorMsg() |
| 397 | { |
| 398 | if (m_error[0] == 0) |
| 399 | return NULL; |
| 400 | else |
| 401 | return m_error; |
| 402 | } |
| 403 | |
| 404 | virtual void *getProcAddress(const char *proc) |
| 405 | { |
| 406 | return SDL_GL_GetProcAddress(proc); |
| 407 | } |
| 408 | |
| 409 | virtual void SwapBuffer() |
| 410 | { |
| 411 | SDL_GL_SwapBuffers(); |
| 412 | } |
| 413 | |
| 414 | private: |
| 415 | SDL_Surface *m_window; |
| 416 | char m_error[256]; |
| 417 | }; |
| 418 | |
| 419 | |
| 420 | #endif |
| 421 | |
| 422 | //============================================================ |
| 423 | // Textures |
| 424 | //============================================================ |
| 425 | |
| 426 | /* texture_info holds information about a texture */ |
| 427 | class texture_info |
| 428 | { |
| 429 | public: |
| 430 | texture_info() |
| 431 | : hash(0), flags(0), rawwidth(0), rawheight(0), |
| 432 | rawwidth_create(0), rawheight_create(0), |
| 433 | type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0), |
| 434 | texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(NULL), |
| 435 | data_own(0), texCoordBufferName(0) |
| 436 | { |
| 437 | for (int i=0; i<2; i++) |
| 438 | { |
| 439 | mpass_textureunit[i] = 0; |
| 440 | mpass_texture_mamebm[i] = 0; |
| 441 | mpass_fbo_mamebm[i] = 0; |
| 442 | mpass_texture_scrn[i] = 0; |
| 443 | mpass_fbo_scrn[i] = 0; |
| 444 | } |
| 445 | for (int i=0; i<8; i++) |
| 446 | texCoord[i] = 0.0f; |
| 447 | } |
| 448 | |
| 449 | HashT hash; // hash value for the texture (must be >= pointer size) |
| 450 | UINT32 flags; // rendering flags |
| 451 | render_texinfo texinfo; // copy of the texture info |
| 452 | int rawwidth, rawheight; // raw width/height of the texture |
| 453 | int rawwidth_create; // raw width/height, pow2 compatible, if needed |
| 454 | int rawheight_create; // (create and initial set the texture, not for copy!) |
| 455 | int type; // what type of texture are we? |
| 456 | int format; // texture format |
| 457 | int borderpix; // do we have a 1 pixel border? |
| 458 | int xprescale; // what is our X prescale factor? |
| 459 | int yprescale; // what is our Y prescale factor? |
| 460 | int nocopy; // must the texture date be copied? |
| 461 | |
| 462 | UINT32 texture; // OpenGL texture "name"/ID |
| 463 | |
| 464 | GLenum texTarget; // OpenGL texture target |
| 465 | int texpow2; // Is this texture pow2 |
| 466 | |
| 467 | UINT32 mpass_dest_idx; // Multipass dest idx [0..1] |
| 468 | UINT32 mpass_textureunit[2]; // texture unit names for GLSL |
| 469 | |
| 470 | UINT32 mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader |
| 471 | UINT32 mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass |
| 472 | UINT32 mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader |
| 473 | UINT32 mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass |
| 474 | |
| 475 | UINT32 pbo; // pixel buffer object for this texture (DYNAMIC only!) |
| 476 | UINT32 *data; // pixels for the texture |
| 477 | int data_own; // do we own / allocated it ? |
| 478 | GLfloat texCoord[8]; |
| 479 | GLuint texCoordBufferName; |
| 480 | |
| 481 | }; |
| 482 | |
| 483 | /* sdl_info is the information about SDL for the current screen */ |
| 484 | class sdl_info_ogl : public osd_renderer |
| 485 | { |
| 486 | public: |
| 487 | sdl_info_ogl(osd_window *window) |
| 488 | : osd_renderer(window, FLAG_NEEDS_OPENGL), m_blittimer(0), |
| 489 | m_width(0), m_height(0), |
| 490 | m_blit_dim(0, 0), |
| 491 | m_gl_context(NULL), |
| 492 | m_initialized(0), |
| 493 | m_last_blendmode(0), |
| 494 | m_texture_max_width(0), |
| 495 | m_texture_max_height(0), |
| 496 | m_texpoweroftwo(0), |
| 497 | m_usevbo(0), m_usepbo(0), m_usefbo(0), m_useglsl(0), m_glsl(NULL), |
| 498 | m_glsl_program_num(0), |
| 499 | m_glsl_program_mb2sc(0), |
| 500 | m_usetexturerect(0), |
| 501 | m_init_context(0), |
| 502 | m_last_hofs(0.0f), |
| 503 | m_last_vofs(0.0f), |
| 504 | m_surf_w(0), |
| 505 | m_surf_h(0) |
| 506 | { |
| 507 | for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) |
| 508 | m_texhash[i] = NULL; |
| 509 | for (int i=0; i < 2*GLSL_SHADER_MAX; i++) |
| 510 | m_glsl_program[i] = 0; |
| 511 | for (int i=0; i < 8; i++) |
| 512 | m_texVerticex[i] = 0.0f; |
| 513 | } |
| 514 | |
| 515 | /* virtual */ int create(); |
| 516 | /* virtual */ int draw(const int update); |
| 517 | |
| 518 | /* virtual */ int xy_to_render_target(const int x, const int y, int *xt, int *yt); |
| 519 | /* virtual */ void destroy(); |
| 520 | /* virtual */ render_primitive_list *get_primitives() |
| 521 | { |
| 522 | #ifdef OSD_WINDOWS |
| 523 | osd_dim nd = window().get_size(); |
| 524 | #else |
| 525 | osd_dim nd = window().blit_surface_size(); |
| 526 | #endif |
| 527 | if (nd != m_blit_dim) |
| 528 | { |
| 529 | m_blit_dim = nd; |
| 530 | notify_changed(); |
| 531 | } |
| 532 | window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); |
| 533 | return &window().target()->get_primitives(); |
| 534 | } |
| 535 | |
| 536 | /* virtual */ void save() { } |
| 537 | /* virtual */ void record() { } |
| 538 | /* virtual */ void toggle_fsfx() { } |
| 539 | |
| 540 | private: |
| 541 | void destroy_all_textures(); |
| 542 | |
| 543 | void loadGLExtensions(); |
| 544 | void initialize_gl(); |
| 545 | void set_blendmode(int blendmode); |
| 546 | void texture_compute_type_subroutine(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 547 | void texture_compute_size_subroutine(texture_info *texture, UINT32 flags, |
| 548 | UINT32 width, UINT32 height, |
| 549 | int* p_width, int* p_height, int* p_width_create, int* p_height_create); |
| 550 | void texture_compute_size_type(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 551 | texture_info *texture_create(const render_texinfo *texsource, UINT32 flags); |
| 552 | int texture_shader_create(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 553 | texture_info *texture_find(const render_primitive *prim); |
| 554 | void texture_coord_update(texture_info *texture, const render_primitive *prim, int shaderIdx); |
| 555 | void texture_mpass_flip(texture_info *texture, int shaderIdx); |
| 556 | void texture_shader_update(texture_info *texture, render_container *container, int shaderIdx); |
| 557 | texture_info * texture_update(const render_primitive *prim, int shaderIdx); |
| 558 | void texture_disable(texture_info * texture); |
| 559 | void texture_all_disable(); |
| 560 | |
| 561 | INT32 m_blittimer; |
| 562 | int m_width; |
| 563 | int m_height; |
| 564 | osd_dim m_blit_dim; |
| 565 | |
| 566 | osd_gl_context *m_gl_context; |
| 567 | |
| 568 | int m_initialized; // is everything well initialized, i.e. all GL stuff etc. |
| 569 | // 3D info (GL mode only) |
| 570 | texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; |
| 571 | int m_last_blendmode; // previous blendmode |
| 572 | INT32 m_texture_max_width; // texture maximum width |
| 573 | INT32 m_texture_max_height; // texture maximum height |
| 574 | int m_texpoweroftwo; // must textures be power-of-2 sized? |
| 575 | int m_usevbo; // runtime check if VBO is available |
| 576 | int m_usepbo; // runtime check if PBO is available |
| 577 | int m_usefbo; // runtime check if FBO is available |
| 578 | int m_useglsl; // runtime check if GLSL is available |
| 579 | |
| 580 | glsl_shader_info *m_glsl; // glsl_shader_info |
| 581 | |
| 582 | GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 |
| 583 | int m_glsl_program_num; // number of GLSL programs |
| 584 | int m_glsl_program_mb2sc; // GLSL program idx, which transforms |
| 585 | // the mame-bitmap. screen-bitmap (size/rotation/..) |
| 586 | // All progs <= glsl_program_mb2sc using the mame bitmap |
| 587 | // as input, otherwise the screen bitmap. |
| 588 | // All progs >= glsl_program_mb2sc using the screen bitmap |
| 589 | // as output, otherwise the mame bitmap. |
| 590 | int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use |
| 591 | |
| 592 | int m_init_context; // initialize context before next draw |
| 593 | |
| 594 | float m_last_hofs; |
| 595 | float m_last_vofs; |
| 596 | |
| 597 | // Static vars from draogl_window_dra |
| 598 | INT32 m_surf_w; |
| 599 | INT32 m_surf_h; |
| 600 | GLfloat m_texVerticex[8]; |
| 601 | }; |
| 602 | |
| 603 | /* line_aa_step is used for drawing antialiased lines */ |
| 604 | struct line_aa_step |
| 605 | { |
| 606 | float xoffs, yoffs; // X/Y deltas |
| 607 | float weight; // weight contribution |
| 608 | }; |
| 609 | |
| 610 | #if 0 |
| 611 | static const line_aa_step line_aa_1step[] = |
| 612 | { |
| 613 | { 0.00f, 0.00f, 1.00f }, |
| 614 | { 0 } |
| 615 | }; |
| 616 | |
| 617 | static const line_aa_step line_aa_4step[] = |
| 618 | { |
| 619 | { -0.25f, 0.00f, 0.25f }, |
| 620 | { 0.25f, 0.00f, 0.25f }, |
| 621 | { 0.00f, -0.25f, 0.25f }, |
| 622 | { 0.00f, 0.25f, 0.25f }, |
| 623 | { 0 } |
| 624 | }; |
| 625 | #endif |
| 626 | |
| 627 | //============================================================ |
| 628 | // INLINES |
| 629 | //============================================================ |
| 630 | |
| 631 | INLINE HashT texture_compute_hash(const render_texinfo *texture, UINT32 flags) |
| 632 | { |
| 633 | HashT h = (HashT)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 634 | //printf("hash %d\n", (int) h % HASH_SIZE); |
| 635 | return (h >> 8) % HASH_SIZE; |
| 636 | } |
| 637 | |
| 638 | void sdl_info_ogl::set_blendmode(int blendmode) |
| 639 | { |
| 640 | // try to minimize texture state changes |
| 641 | if (blendmode != m_last_blendmode) |
| 642 | { |
| 643 | switch (blendmode) |
| 644 | { |
| 645 | case BLENDMODE_NONE: |
| 646 | glDisable(GL_BLEND); |
| 647 | break; |
| 648 | case BLENDMODE_ALPHA: |
| 649 | glEnable(GL_BLEND); |
| 650 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 651 | break; |
| 652 | case BLENDMODE_RGB_MULTIPLY: |
| 653 | glEnable(GL_BLEND); |
| 654 | glBlendFunc(GL_DST_COLOR, GL_ZERO); |
| 655 | break; |
| 656 | case BLENDMODE_ADD: |
| 657 | glEnable(GL_BLEND); |
| 658 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); |
| 659 | break; |
| 660 | } |
| 661 | |
| 662 | m_last_blendmode = blendmode; |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | //============================================================ |
| 667 | // PROTOTYPES |
| 668 | //============================================================ |
| 669 | |
| 670 | // core functions |
| 671 | |
| 672 | //============================================================ |
| 673 | // STATIC VARIABLES |
| 674 | //============================================================ |
| 675 | |
| 676 | static void drawogl_exit(void); |
| 677 | static void load_gl_lib(running_machine &machine); |
| 678 | |
| 679 | |
| 680 | |
| 681 | // OGL 1.3 |
| 682 | #ifdef GL_ARB_multitexture |
| 683 | static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = NULL; |
| 684 | #else |
| 685 | static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = NULL; |
| 686 | #endif |
| 687 | |
| 688 | // VBO |
| 689 | static PFNGLGENBUFFERSPROC pfn_glGenBuffers = NULL; |
| 690 | static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers = NULL; |
| 691 | static PFNGLBINDBUFFERPROC pfn_glBindBuffer = NULL; |
| 692 | static PFNGLBUFFERDATAPROC pfn_glBufferData = NULL; |
| 693 | static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData = NULL; |
| 694 | |
| 695 | // PBO |
| 696 | static PFNGLMAPBUFFERPROC pfn_glMapBuffer = NULL; |
| 697 | static PFNGLUNMAPBUFFERPROC pfn_glUnmapBuffer = NULL; |
| 698 | |
| 699 | // FBO |
| 700 | static PFNGLISFRAMEBUFFEREXTPROC pfn_glIsFramebuffer = NULL; |
| 701 | static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer = NULL; |
| 702 | static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers = NULL; |
| 703 | static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers = NULL; |
| 704 | static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus = NULL; |
| 705 | static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D = NULL; |
| 706 | |
| 707 | static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; |
| 708 | |
| 709 | //============================================================ |
| 710 | // Textures |
| 711 | //============================================================ |
| 712 | |
| 713 | static void texture_set_data(texture_info *texture, const render_texinfo *texsource, UINT32 flags); |
| 714 | |
| 715 | //============================================================ |
| 716 | // Static Variables |
| 717 | //============================================================ |
| 718 | |
| 719 | static int shown_video_info = 0; |
| 720 | static int dll_loaded = 0; |
| 721 | |
| 722 | //============================================================ |
| 723 | // drawsdl_init |
| 724 | //============================================================ |
| 725 | |
| 726 | static osd_renderer *drawogl_create(osd_window *window) |
| 727 | { |
| 728 | return global_alloc(sdl_info_ogl(window)); |
| 729 | } |
| 730 | |
| 731 | int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 732 | { |
| 733 | // fill in the callbacks |
| 734 | callbacks->exit = drawogl_exit; |
| 735 | callbacks->create = drawogl_create; |
| 736 | |
| 737 | dll_loaded = 0; |
| 738 | |
| 739 | load_gl_lib(machine); |
| 740 | if (SDLMAME_SDL2) |
| 741 | { |
| 742 | osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); |
| 743 | } |
| 744 | else |
| 745 | osd_printf_verbose("Using SDL single-window OpenGL driver (SDL 1.2)\n"); |
| 746 | |
| 747 | return 0; |
| 748 | } |
| 749 | |
| 750 | //============================================================ |
| 751 | // Load the OGL function addresses |
| 752 | //============================================================ |
| 753 | |
| 754 | static void loadgl_functions(osd_gl_context *context) |
| 755 | { |
| 756 | #ifdef USE_DISPATCH_GL |
| 757 | |
| 758 | int err_count = 0; |
| 759 | |
| 760 | /* the following is tricky ... #func will be expanded to glBegin |
| 761 | * while func will be expanded to disp_p->glBegin |
| 762 | */ |
| 763 | |
| 764 | #define OSD_GL(ret,func,params) \ |
| 765 | if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \ |
| 766 | { err_count++; osd_printf_error("GL function %s not found!\n", #func ); } |
| 767 | |
| 768 | #define OSD_GL_UNUSED(ret,func,params) |
| 769 | |
| 770 | #define GET_GLFUNC 1 |
| 771 | #include "modules/opengl/osd_opengl.h" |
| 772 | #undef GET_GLFUNC |
| 773 | |
| 774 | if (err_count) |
| 775 | fatalerror("Error loading GL library functions, giving up\n"); |
| 776 | |
| 777 | #endif |
| 778 | } |
| 779 | |
| 780 | //============================================================ |
| 781 | // Load GL library |
| 782 | //============================================================ |
| 783 | |
| 784 | #ifdef USE_DISPATCH_GL |
| 785 | osd_gl_dispatch *gl_dispatch; |
| 786 | #endif |
| 787 | |
| 788 | static void load_gl_lib(running_machine &machine) |
| 789 | { |
| 790 | if (!dll_loaded) |
| 791 | { |
| 792 | #ifdef OSD_WINDOWS |
| 793 | win_gl_context::load_library(); |
| 794 | #else |
| 795 | #ifdef USE_DISPATCH_GL |
| 796 | /* |
| 797 | * directfb and and x11 use this env var |
| 798 | * SDL_VIDEO_GL_DRIVER |
| 799 | */ |
| 800 | const char *stemp; |
| 801 | |
| 802 | stemp = downcast<sdl_options &>(machine.options()).gl_lib(); |
| 803 | if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) == 0) |
| 804 | stemp = NULL; |
| 805 | |
| 806 | if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==NULL |
| 807 | { |
| 808 | fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); |
| 809 | } |
| 810 | osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); |
| 811 | /* FIXME: must be freed as well */ |
| 812 | #endif |
| 813 | #endif |
| 814 | #ifdef USE_DISPATCH_GL |
| 815 | gl_dispatch = (osd_gl_dispatch *) osd_malloc(sizeof(osd_gl_dispatch)); |
| 816 | #endif |
| 817 | dll_loaded=1; |
| 818 | } |
| 819 | } |
| 820 | |
| 821 | void sdl_info_ogl::initialize_gl() |
| 822 | { |
| 823 | int has_and_allow_texturerect = 0; |
| 824 | |
| 825 | char *extstr = (char *)glGetString(GL_EXTENSIONS); |
| 826 | char *vendor = (char *)glGetString(GL_VENDOR); |
| 827 | |
| 828 | //printf("%p\n", extstr); |
| 829 | #ifdef OSD_WINDOWS |
| 830 | if (!extstr) |
| 831 | extstr = (char *)""; |
| 832 | #endif |
| 833 | // print out the driver info for debugging |
| 834 | if (!shown_video_info) |
| 835 | { |
| 836 | osd_printf_verbose("OpenGL: %s\nOpenGL: %s\nOpenGL: %s\n", vendor, (char *)glGetString(GL_RENDERER), (char *)glGetString(GL_VERSION)); |
| 837 | } |
| 838 | |
| 839 | m_usetexturerect = 0; |
| 840 | m_texpoweroftwo = 1; |
| 841 | m_usevbo = 0; |
| 842 | m_usepbo = 0; |
| 843 | m_usefbo = 0; |
| 844 | m_useglsl = 0; |
| 845 | |
| 846 | if ( video_config.allowtexturerect && |
| 847 | ( strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle") ) |
| 848 | ) |
| 849 | { |
| 850 | has_and_allow_texturerect = 1; |
| 851 | if (!shown_video_info) |
| 852 | { |
| 853 | osd_printf_verbose("OpenGL: texture rectangle supported\n"); |
| 854 | } |
| 855 | } |
| 856 | |
| 857 | // does this card support non-power-of-two sized textures? (they're faster, so use them if possible) |
| 858 | if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) |
| 859 | { |
| 860 | if (!shown_video_info) |
| 861 | { |
| 862 | osd_printf_verbose("OpenGL: non-power-of-2 textures supported (new method)\n"); |
| 863 | } |
| 864 | m_texpoweroftwo = 0; |
| 865 | } |
| 866 | else |
| 867 | { |
| 868 | // second chance: GL_ARB_texture_rectangle or GL_EXT_texture_rectangle (old version) |
| 869 | if (has_and_allow_texturerect) |
| 870 | { |
| 871 | if (!shown_video_info) |
| 872 | { |
| 873 | osd_printf_verbose("OpenGL: non-power-of-2 textures supported (old method)\n"); |
| 874 | } |
| 875 | m_usetexturerect = 1; |
| 876 | } |
| 877 | else |
| 878 | { |
| 879 | if (!shown_video_info) |
| 880 | { |
| 881 | osd_printf_verbose("OpenGL: forcing power-of-2 textures (creation, not copy)\n"); |
| 882 | } |
| 883 | } |
| 884 | } |
| 885 | |
| 886 | if (strstr(extstr, "GL_ARB_vertex_buffer_object")) |
| 887 | { |
| 888 | m_usevbo = video_config.vbo; |
| 889 | if (!shown_video_info) |
| 890 | { |
| 891 | if(m_usevbo) |
| 892 | osd_printf_verbose("OpenGL: vertex buffer supported\n"); |
| 893 | else |
| 894 | osd_printf_verbose("OpenGL: vertex buffer supported, but disabled\n"); |
| 895 | } |
| 896 | } |
| 897 | |
| 898 | if (strstr(extstr, "GL_ARB_pixel_buffer_object")) |
| 899 | { |
| 900 | if( m_usevbo ) |
| 901 | { |
| 902 | m_usepbo = video_config.pbo; |
| 903 | if (!shown_video_info) |
| 904 | { |
| 905 | if(m_usepbo) |
| 906 | osd_printf_verbose("OpenGL: pixel buffers supported\n"); |
| 907 | else |
| 908 | osd_printf_verbose("OpenGL: pixel buffers supported, but disabled\n"); |
| 909 | } |
| 910 | } else { |
| 911 | if (!shown_video_info) |
| 912 | { |
| 913 | osd_printf_verbose("OpenGL: pixel buffers supported, but disabled due to disabled vbo\n"); |
| 914 | } |
| 915 | } |
| 916 | } |
| 917 | else |
| 918 | { |
| 919 | if (!shown_video_info) |
| 920 | { |
| 921 | osd_printf_verbose("OpenGL: pixel buffers not supported\n"); |
| 922 | } |
| 923 | } |
| 924 | |
| 925 | if (strstr(extstr, "GL_EXT_framebuffer_object")) |
| 926 | { |
| 927 | m_usefbo = 1; |
| 928 | if (!shown_video_info) |
| 929 | { |
| 930 | if(m_usefbo) |
| 931 | osd_printf_verbose("OpenGL: framebuffer object supported\n"); |
| 932 | else |
| 933 | osd_printf_verbose("OpenGL: framebuffer object not supported\n"); |
| 934 | } |
| 935 | } |
| 936 | |
| 937 | if (strstr(extstr, "GL_ARB_shader_objects") && |
| 938 | strstr(extstr, "GL_ARB_shading_language_100") && |
| 939 | strstr(extstr, "GL_ARB_vertex_shader") && |
| 940 | strstr(extstr, "GL_ARB_fragment_shader") |
| 941 | ) |
| 942 | { |
| 943 | m_useglsl = video_config.glsl; |
| 944 | if (!shown_video_info) |
| 945 | { |
| 946 | if(m_useglsl) |
| 947 | osd_printf_verbose("OpenGL: GLSL supported\n"); |
| 948 | else |
| 949 | osd_printf_verbose("OpenGL: GLSL supported, but disabled\n"); |
| 950 | } |
| 951 | } else { |
| 952 | if (!shown_video_info) |
| 953 | { |
| 954 | osd_printf_verbose("OpenGL: GLSL not supported\n"); |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | #ifdef TOBEMIGRATED |
| 959 | if (osd_getenv(SDLENV_VMWARE) != NULL) |
| 960 | { |
| 961 | m_usetexturerect = 1; |
| 962 | m_texpoweroftwo = 1; |
| 963 | } |
| 964 | #endif |
| 965 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_width); |
| 966 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_height); |
| 967 | if (!shown_video_info) |
| 968 | { |
| 969 | osd_printf_verbose("OpenGL: max texture size %d x %d\n", m_texture_max_width, m_texture_max_height); |
| 970 | } |
| 971 | |
| 972 | shown_video_info = 1; |
| 973 | |
| 974 | } |
| 975 | //============================================================ |
| 976 | // sdl_info::create |
| 977 | // a |
| 978 | // a |
| 979 | // a |
| 980 | // a |
| 981 | // a |
| 982 | // a |
| 983 | // a |
| 984 | // a |
| 985 | // a |
| 986 | // a |
| 987 | // a |
| 988 | // a |
| 989 | // a |
| 990 | // a |
| 991 | // a |
| 992 | // a |
| 993 | // a |
| 994 | // a |
| 995 | // a |
| 996 | // a |
| 997 | // a |
| 998 | // a |
| 999 | // a |
| 1000 | // a |
| 1001 | // a |
| 1002 | // a |
| 1003 | //============================================================ |
| 1004 | |
| 1005 | int sdl_info_ogl::create() |
| 1006 | { |
| 1007 | #if (SDLMAME_SDL2) |
| 1008 | // create renderer |
| 1009 | #ifdef OSD_WINDOWS |
| 1010 | m_gl_context = global_alloc(win_gl_context(window().m_hwnd)); |
| 1011 | #else |
| 1012 | m_gl_context = global_alloc(sdl_gl_context(window().sdl_window())); |
| 1013 | #endif |
| 1014 | #else |
| 1015 | m_gl_context = global_alloc(sdl12_gl_context(window().sdl_surface())); |
| 1016 | #endif |
| 1017 | if (m_gl_context->LastErrorMsg() != NULL) |
| 1018 | { |
| 1019 | osd_printf_error("%s\n", m_gl_context->LastErrorMsg()); |
| 1020 | return 1; |
| 1021 | } |
| 1022 | m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0); |
| 1023 | |
| 1024 | |
| 1025 | m_blittimer = 0; |
| 1026 | m_surf_w = 0; |
| 1027 | m_surf_h = 0; |
| 1028 | |
| 1029 | m_initialized = 0; |
| 1030 | |
| 1031 | // in case any textures try to come up before these are validated, |
| 1032 | // OpenGL guarantees all implementations can handle something this size. |
| 1033 | m_texture_max_width = 64; |
| 1034 | m_texture_max_height = 64; |
| 1035 | |
| 1036 | /* load any GL function addresses |
| 1037 | * this must be done here because we need a context |
| 1038 | */ |
| 1039 | loadgl_functions(m_gl_context); |
| 1040 | initialize_gl(); |
| 1041 | |
| 1042 | |
| 1043 | m_init_context = 0; |
| 1044 | |
| 1045 | osd_printf_verbose("Leave sdl_info_ogl::create\n"); |
| 1046 | return 0; |
| 1047 | } |
| 1048 | |
| 1049 | |
| 1050 | //============================================================ |
| 1051 | // sdl_info::destroy |
| 1052 | //============================================================ |
| 1053 | |
| 1054 | void sdl_info_ogl::destroy() |
| 1055 | { |
| 1056 | // free the memory in the window |
| 1057 | |
| 1058 | destroy_all_textures(); |
| 1059 | |
| 1060 | global_free(m_gl_context); |
| 1061 | m_gl_context = NULL; |
| 1062 | } |
| 1063 | |
| 1064 | |
| 1065 | //============================================================ |
| 1066 | // drawsdl_xy_to_render_target |
| 1067 | //============================================================ |
| 1068 | |
| 1069 | int sdl_info_ogl::xy_to_render_target(int x, int y, int *xt, int *yt) |
| 1070 | { |
| 1071 | *xt = x - m_last_hofs; |
| 1072 | *yt = y - m_last_vofs; |
| 1073 | if (*xt<0 || *xt >= m_blit_dim.width()) |
| 1074 | return 0; |
| 1075 | if (*yt<0 || *yt >= m_blit_dim.height()) |
| 1076 | return 0; |
| 1077 | return 1; |
| 1078 | } |
| 1079 | |
| 1080 | //============================================================ |
| 1081 | // drawsdl_destroy_all_textures |
| 1082 | //============================================================ |
| 1083 | |
| 1084 | void sdl_info_ogl::destroy_all_textures() |
| 1085 | { |
| 1086 | texture_info *texture = NULL; |
| 1087 | int lock=FALSE; |
| 1088 | int i; |
| 1089 | |
| 1090 | if ( !m_initialized ) |
| 1091 | return; |
| 1092 | |
| 1093 | m_gl_context->MakeCurrent(); |
| 1094 | |
| 1095 | if(window().m_primlist) |
| 1096 | { |
| 1097 | lock=TRUE; |
| 1098 | window().m_primlist->acquire_lock(); |
| 1099 | } |
| 1100 | |
| 1101 | glFinish(); |
| 1102 | |
| 1103 | texture_all_disable(); |
| 1104 | glFinish(); |
| 1105 | glDisableClientState(GL_VERTEX_ARRAY); |
| 1106 | |
| 1107 | i=0; |
| 1108 | while (i<HASH_SIZE+OVERFLOW_SIZE) |
| 1109 | { |
| 1110 | texture = m_texhash[i]; |
| 1111 | m_texhash[i] = NULL; |
| 1112 | if (texture != NULL) |
| 1113 | { |
| 1114 | if(m_usevbo) |
| 1115 | { |
| 1116 | pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); |
| 1117 | texture->texCoordBufferName=0; |
| 1118 | } |
| 1119 | |
| 1120 | if(m_usepbo && texture->pbo) |
| 1121 | { |
| 1122 | pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); |
| 1123 | texture->pbo=0; |
| 1124 | } |
| 1125 | |
| 1126 | if( m_glsl_program_num > 1 ) |
| 1127 | { |
| 1128 | assert(m_usefbo); |
| 1129 | pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); |
| 1130 | glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); |
| 1131 | } |
| 1132 | |
| 1133 | if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 ) |
| 1134 | { |
| 1135 | assert(m_usefbo); |
| 1136 | pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); |
| 1137 | glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); |
| 1138 | } |
| 1139 | |
| 1140 | glDeleteTextures(1, (GLuint *)&texture->texture); |
| 1141 | if ( texture->data_own ) |
| 1142 | { |
| 1143 | free(texture->data); |
| 1144 | texture->data=NULL; |
| 1145 | texture->data_own=FALSE; |
| 1146 | } |
| 1147 | global_free(texture); |
| 1148 | } |
| 1149 | i++; |
| 1150 | } |
| 1151 | if ( m_useglsl ) |
| 1152 | { |
| 1153 | glsl_shader_free(m_glsl); |
| 1154 | m_glsl = NULL; |
| 1155 | } |
| 1156 | |
| 1157 | m_initialized = 0; |
| 1158 | |
| 1159 | if (lock) |
| 1160 | window().m_primlist->release_lock(); |
| 1161 | } |
| 1162 | //============================================================ |
| 1163 | // loadGLExtensions |
| 1164 | //============================================================ |
| 1165 | |
| 1166 | void sdl_info_ogl::loadGLExtensions() |
| 1167 | { |
| 1168 | static int _once = 1; |
| 1169 | |
| 1170 | // usevbo=FALSE; // You may want to switch VBO and PBO off, by uncommenting this statement |
| 1171 | // usepbo=FALSE; // You may want to switch PBO off, by uncommenting this statement |
| 1172 | // useglsl=FALSE; // You may want to switch GLSL off, by uncommenting this statement |
| 1173 | |
| 1174 | if (! m_usevbo) |
| 1175 | { |
| 1176 | if(m_usepbo) // should never ever happen ;-) |
| 1177 | { |
| 1178 | if (_once) |
| 1179 | { |
| 1180 | osd_printf_warning("OpenGL: PBO not supported, no VBO support. (sdlmame error)\n"); |
| 1181 | } |
| 1182 | m_usepbo=FALSE; |
| 1183 | } |
| 1184 | if(m_useglsl) // should never ever happen ;-) |
| 1185 | { |
| 1186 | if (_once) |
| 1187 | { |
| 1188 | osd_printf_warning("OpenGL: GLSL not supported, no VBO support. (sdlmame error)\n"); |
| 1189 | } |
| 1190 | m_useglsl=FALSE; |
| 1191 | } |
| 1192 | } |
| 1193 | |
| 1194 | // Get Pointers To The GL Functions |
| 1195 | // VBO: |
| 1196 | if( m_usevbo ) |
| 1197 | { |
| 1198 | pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers"); |
| 1199 | pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers"); |
| 1200 | pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer"); |
| 1201 | pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData"); |
| 1202 | pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData"); |
| 1203 | } |
| 1204 | // PBO: |
| 1205 | if ( m_usepbo ) |
| 1206 | { |
| 1207 | pfn_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer"); |
| 1208 | pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer"); |
| 1209 | } |
| 1210 | // FBO: |
| 1211 | if ( m_usefbo ) |
| 1212 | { |
| 1213 | pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT"); |
| 1214 | pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT"); |
| 1215 | pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT"); |
| 1216 | pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT"); |
| 1217 | pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT"); |
| 1218 | pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT"); |
| 1219 | } |
| 1220 | |
| 1221 | if ( m_usevbo && |
| 1222 | ( !pfn_glGenBuffers || !pfn_glDeleteBuffers || |
| 1223 | !pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData |
| 1224 | ) ) |
| 1225 | { |
| 1226 | m_usepbo=FALSE; |
| 1227 | if (_once) |
| 1228 | { |
| 1229 | osd_printf_warning("OpenGL: VBO not supported, missing: "); |
| 1230 | if (!pfn_glGenBuffers) |
| 1231 | { |
| 1232 | osd_printf_warning("glGenBuffers, "); |
| 1233 | } |
| 1234 | if (!pfn_glDeleteBuffers) |
| 1235 | { |
| 1236 | osd_printf_warning("glDeleteBuffers"); |
| 1237 | } |
| 1238 | if (!pfn_glBindBuffer) |
| 1239 | { |
| 1240 | osd_printf_warning("glBindBuffer, "); |
| 1241 | } |
| 1242 | if (!pfn_glBufferData) |
| 1243 | { |
| 1244 | osd_printf_warning("glBufferData, "); |
| 1245 | } |
| 1246 | if (!pfn_glBufferSubData) |
| 1247 | { |
| 1248 | osd_printf_warning("glBufferSubData, "); |
| 1249 | } |
| 1250 | osd_printf_warning("\n"); |
| 1251 | } |
| 1252 | if ( m_usevbo ) |
| 1253 | { |
| 1254 | if (_once) |
| 1255 | { |
| 1256 | osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n"); |
| 1257 | } |
| 1258 | m_usepbo=FALSE; |
| 1259 | } |
| 1260 | } |
| 1261 | |
| 1262 | if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) ) |
| 1263 | { |
| 1264 | m_usepbo=FALSE; |
| 1265 | if (_once) |
| 1266 | { |
| 1267 | osd_printf_warning("OpenGL: PBO not supported, missing: "); |
| 1268 | if (!pfn_glMapBuffer) |
| 1269 | { |
| 1270 | osd_printf_warning("glMapBuffer, "); |
| 1271 | } |
| 1272 | if (!pfn_glUnmapBuffer) |
| 1273 | { |
| 1274 | osd_printf_warning("glUnmapBuffer, "); |
| 1275 | } |
| 1276 | osd_printf_warning("\n"); |
| 1277 | } |
| 1278 | } |
| 1279 | |
| 1280 | if ( m_usefbo && |
| 1281 | ( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers || |
| 1282 | !pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D |
| 1283 | )) |
| 1284 | { |
| 1285 | m_usefbo=FALSE; |
| 1286 | if (_once) |
| 1287 | { |
| 1288 | osd_printf_warning("OpenGL: FBO not supported, missing: "); |
| 1289 | if (!pfn_glIsFramebuffer) |
| 1290 | { |
| 1291 | osd_printf_warning("pfn_glIsFramebuffer, "); |
| 1292 | } |
| 1293 | if (!pfn_glBindFramebuffer) |
| 1294 | { |
| 1295 | osd_printf_warning("pfn_glBindFramebuffer, "); |
| 1296 | } |
| 1297 | if (!pfn_glDeleteFramebuffers) |
| 1298 | { |
| 1299 | osd_printf_warning("pfn_glDeleteFramebuffers, "); |
| 1300 | } |
| 1301 | if (!pfn_glGenFramebuffers) |
| 1302 | { |
| 1303 | osd_printf_warning("pfn_glGenFramebuffers, "); |
| 1304 | } |
| 1305 | if (!pfn_glCheckFramebufferStatus) |
| 1306 | { |
| 1307 | osd_printf_warning("pfn_glCheckFramebufferStatus, "); |
| 1308 | } |
| 1309 | if (!pfn_glFramebufferTexture2D) |
| 1310 | { |
| 1311 | osd_printf_warning("pfn_glFramebufferTexture2D, "); |
| 1312 | } |
| 1313 | osd_printf_warning("\n"); |
| 1314 | } |
| 1315 | } |
| 1316 | |
| 1317 | if (_once) |
| 1318 | { |
| 1319 | if ( m_usevbo ) |
| 1320 | { |
| 1321 | osd_printf_verbose("OpenGL: VBO supported\n"); |
| 1322 | } |
| 1323 | else |
| 1324 | { |
| 1325 | osd_printf_warning("OpenGL: VBO not supported\n"); |
| 1326 | } |
| 1327 | |
| 1328 | if ( m_usepbo ) |
| 1329 | { |
| 1330 | osd_printf_verbose("OpenGL: PBO supported\n"); |
| 1331 | } |
| 1332 | else |
| 1333 | { |
| 1334 | osd_printf_warning("OpenGL: PBO not supported\n"); |
| 1335 | } |
| 1336 | |
| 1337 | if ( m_usefbo ) |
| 1338 | { |
| 1339 | osd_printf_verbose("OpenGL: FBO supported\n"); |
| 1340 | } |
| 1341 | else |
| 1342 | { |
| 1343 | osd_printf_warning("OpenGL: FBO not supported\n"); |
| 1344 | } |
| 1345 | } |
| 1346 | |
| 1347 | if ( m_useglsl ) |
| 1348 | { |
| 1349 | #ifdef GL_ARB_multitexture |
| 1350 | pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB"); |
| 1351 | #else |
| 1352 | pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture"); |
| 1353 | #endif |
| 1354 | if (!pfn_glActiveTexture) |
| 1355 | { |
| 1356 | if (_once) |
| 1357 | { |
| 1358 | osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n"); |
| 1359 | } |
| 1360 | m_useglsl = 0; |
| 1361 | } |
| 1362 | } |
| 1363 | |
| 1364 | if ( m_useglsl ) |
| 1365 | { |
| 1366 | m_glsl = glsl_shader_init(m_gl_context); |
| 1367 | m_useglsl = (m_glsl != NULL ? 1 : 0); |
| 1368 | |
| 1369 | if ( ! m_useglsl ) |
| 1370 | { |
| 1371 | if (_once) |
| 1372 | { |
| 1373 | osd_printf_warning("OpenGL: GLSL supported, but shader instantiation failed - disabled\n"); |
| 1374 | } |
| 1375 | } |
| 1376 | } |
| 1377 | |
| 1378 | if ( m_useglsl ) |
| 1379 | { |
| 1380 | if ( window().prescale() != 1 ) |
| 1381 | { |
| 1382 | m_useglsl = 0; |
| 1383 | if (_once) |
| 1384 | { |
| 1385 | osd_printf_warning("OpenGL: GLSL supported, but disabled due to: prescale !=1 \n"); |
| 1386 | } |
| 1387 | } |
| 1388 | } |
| 1389 | |
| 1390 | if ( m_useglsl ) |
| 1391 | { |
| 1392 | int i; |
| 1393 | video_config.filter = FALSE; |
| 1394 | glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; |
| 1395 | m_glsl_program_num = 0; |
| 1396 | m_glsl_program_mb2sc = 0; |
| 1397 | |
| 1398 | for(i=0; i<video_config.glsl_shader_mamebm_num; i++) |
| 1399 | { |
| 1400 | if ( !m_usefbo && m_glsl_program_num==1 ) |
| 1401 | { |
| 1402 | if (_once) |
| 1403 | { |
| 1404 | osd_printf_verbose("OpenGL: GLSL multipass not supported, due to unsupported FBO. Skipping followup shader\n"); |
| 1405 | } |
| 1406 | break; |
| 1407 | } |
| 1408 | |
| 1409 | if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) ) |
| 1410 | { |
| 1411 | osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n", |
| 1412 | i, video_config.glsl_shader_mamebm[i]); |
| 1413 | } else { |
| 1414 | glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM; |
| 1415 | if (_once) |
| 1416 | { |
| 1417 | osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n", |
| 1418 | m_glsl_program_num, video_config.glsl_shader_mamebm[i]); |
| 1419 | } |
| 1420 | m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. |
| 1421 | m_glsl_program_num++; |
| 1422 | } |
| 1423 | } |
| 1424 | |
| 1425 | if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) |
| 1426 | { |
| 1427 | osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n"); |
| 1428 | } |
| 1429 | |
| 1430 | for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++) |
| 1431 | { |
| 1432 | if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i], |
| 1433 | m_glsl_program_num-1-m_glsl_program_mb2sc) ) |
| 1434 | { |
| 1435 | osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n", |
| 1436 | i, video_config.glsl_shader_scrn[i]); |
| 1437 | } else { |
| 1438 | if (_once) |
| 1439 | { |
| 1440 | osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n", |
| 1441 | m_glsl_program_num, video_config.glsl_shader_scrn[i]); |
| 1442 | } |
| 1443 | m_glsl_program_num++; |
| 1444 | } |
| 1445 | } |
| 1446 | |
| 1447 | if ( 0==m_glsl_program_num && |
| 1448 | 0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER ) |
| 1449 | { |
| 1450 | m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. |
| 1451 | m_glsl_program_num++; |
| 1452 | glsl_shader_feature = video_config.glsl_filter; |
| 1453 | |
| 1454 | if (_once) |
| 1455 | { |
| 1456 | osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n", |
| 1457 | glsl_shader_get_filter_name_mamebm(glsl_shader_feature), |
| 1458 | glsl_shader_feature, m_glsl_program_num, video_config.filter); |
| 1459 | } |
| 1460 | } |
| 1461 | |
| 1462 | } else { |
| 1463 | if (_once) |
| 1464 | { |
| 1465 | osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter); |
| 1466 | } |
| 1467 | } |
| 1468 | |
| 1469 | _once = 0; |
| 1470 | } |
| 1471 | |
| 1472 | //============================================================ |
| 1473 | // sdl_info::draw |
| 1474 | //============================================================ |
| 1475 | |
| 1476 | int sdl_info_ogl::draw(const int update) |
| 1477 | { |
| 1478 | render_primitive *prim; |
| 1479 | texture_info *texture=NULL; |
| 1480 | float vofs, hofs; |
| 1481 | int pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE; |
| 1482 | |
| 1483 | #ifdef TOBEMIGRATED |
| 1484 | if (video_config.novideo) |
| 1485 | { |
| 1486 | return 0; |
| 1487 | } |
| 1488 | #endif |
| 1489 | |
| 1490 | osd_dim wdim = window().get_size(); |
| 1491 | |
| 1492 | if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) |
| 1493 | { |
| 1494 | destroy_all_textures(); |
| 1495 | m_width = wdim.width(); |
| 1496 | m_height = wdim.height(); |
| 1497 | m_blittimer = 3; |
| 1498 | m_init_context = 1; |
| 1499 | clear_flags(FI_CHANGED); |
| 1500 | } |
| 1501 | |
| 1502 | m_gl_context->MakeCurrent(); |
| 1503 | |
| 1504 | if (m_init_context) |
| 1505 | { |
| 1506 | // do some one-time OpenGL setup |
| 1507 | #if (SDLMAME_SDL2) |
| 1508 | // FIXME: SRGB conversion is working on SDL2, may be of use |
| 1509 | // when we eventually target gamma and monitor profiles. |
| 1510 | //glEnable(GL_FRAMEBUFFER_SRGB); |
| 1511 | #endif |
| 1512 | glShadeModel(GL_SMOOTH); |
| 1513 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 1514 | glClearDepth(1.0f); |
| 1515 | glEnable(GL_DEPTH_TEST); |
| 1516 | glDepthFunc(GL_LEQUAL); |
| 1517 | glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); |
| 1518 | } |
| 1519 | |
| 1520 | // only clear if the geometry changes (and for 2 frames afterward to clear double and triple buffers) |
| 1521 | if ((m_blittimer > 0) || has_flags(FLAG_HAS_VECTOR_SCREEN)) |
| 1522 | { |
| 1523 | glClear(GL_COLOR_BUFFER_BIT); |
| 1524 | m_blittimer--; |
| 1525 | } |
| 1526 | |
| 1527 | // FIXME: remove m_surf_w and m_surf_h |
| 1528 | if ( !m_initialized || |
| 1529 | m_width != m_surf_w || m_height != m_surf_h ) |
| 1530 | { |
| 1531 | // FIXME:: this can be done in create! |
| 1532 | if ( !m_initialized ) |
| 1533 | { |
| 1534 | loadGLExtensions(); |
| 1535 | } |
| 1536 | |
| 1537 | #if (!SDLMAME_SDL2) |
| 1538 | // force all textures to be regenerated |
| 1539 | destroy_all_textures(); |
| 1540 | #endif |
| 1541 | |
| 1542 | m_surf_w = m_width; |
| 1543 | m_surf_h = m_height; |
| 1544 | |
| 1545 | // we're doing nothing 3d, so the Z-buffer is currently not interesting |
| 1546 | glDisable(GL_DEPTH_TEST); |
| 1547 | |
| 1548 | if (window().machine().options().antialias()) |
| 1549 | { |
| 1550 | // enable antialiasing for lines |
| 1551 | glEnable(GL_LINE_SMOOTH); |
| 1552 | // enable antialiasing for points |
| 1553 | glEnable(GL_POINT_SMOOTH); |
| 1554 | |
| 1555 | // prefer quality to speed |
| 1556 | glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); |
| 1557 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 1558 | } |
| 1559 | else |
| 1560 | { |
| 1561 | glDisable(GL_LINE_SMOOTH); |
| 1562 | glDisable(GL_POINT_SMOOTH); |
| 1563 | } |
| 1564 | |
| 1565 | // enable blending |
| 1566 | glEnable(GL_BLEND); |
| 1567 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 1568 | m_last_blendmode = BLENDMODE_ALPHA; |
| 1569 | |
| 1570 | #ifdef TOBEMIGRATED |
| 1571 | // set lines and points just barely above normal size to get proper results |
| 1572 | glLineWidth(video_config.beamwidth); |
| 1573 | glPointSize(video_config.beamwidth); |
| 1574 | #endif |
| 1575 | |
| 1576 | // set up a nice simple 2D coordinate system, so GL behaves exactly how we'd like. |
| 1577 | // |
| 1578 | // (0,0) (w,0) |
| 1579 | // |~~~~~~~~~| |
| 1580 | // | | |
| 1581 | // | | |
| 1582 | // | | |
| 1583 | // |_________| |
| 1584 | // (0,h) (w,h) |
| 1585 | |
| 1586 | glViewport(0.0, 0.0, (GLsizei) m_width, (GLsizei) m_height); |
| 1587 | glMatrixMode(GL_PROJECTION); |
| 1588 | glLoadIdentity(); |
| 1589 | glOrtho(0.0, (GLdouble) m_width, (GLdouble) m_height, 0.0, 0.0, -1.0); |
| 1590 | glMatrixMode(GL_MODELVIEW); |
| 1591 | glLoadIdentity(); |
| 1592 | |
| 1593 | if ( ! m_initialized ) |
| 1594 | { |
| 1595 | glEnableClientState(GL_VERTEX_ARRAY); |
| 1596 | glVertexPointer(2, GL_FLOAT, 0, m_texVerticex); // no VBO, since it's too volatile |
| 1597 | |
| 1598 | m_initialized = 1; |
| 1599 | } |
| 1600 | } |
| 1601 | |
| 1602 | // compute centering parameters |
| 1603 | vofs = hofs = 0.0f; |
| 1604 | |
| 1605 | #ifdef TOBEMIGRATED |
| 1606 | if (video_config.centerv || video_config.centerh) |
| 1607 | { |
| 1608 | int ch, cw; |
| 1609 | |
| 1610 | ch = m_height; |
| 1611 | cw = m_width; |
| 1612 | |
| 1613 | if (video_config.centerv) |
| 1614 | { |
| 1615 | vofs = (ch - m_blit_dim.height()) / 2.0f; |
| 1616 | } |
| 1617 | if (video_config.centerh) |
| 1618 | { |
| 1619 | hofs = (cw - m_blit_dim.width()) / 2.0f; |
| 1620 | } |
| 1621 | } |
| 1622 | #else |
| 1623 | #endif |
| 1624 | |
| 1625 | m_last_hofs = hofs; |
| 1626 | m_last_vofs = vofs; |
| 1627 | |
| 1628 | window().m_primlist->acquire_lock(); |
| 1629 | |
| 1630 | // now draw |
| 1631 | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 1632 | { |
| 1633 | int i; |
| 1634 | |
| 1635 | switch (prim->type) |
| 1636 | { |
| 1637 | /** |
| 1638 | * Try to stay in one Begin/End block as long as possible, |
| 1639 | * since entering and leaving one is most expensive.. |
| 1640 | */ |
| 1641 | case render_primitive::LINE: |
| 1642 | #if !USE_WIN32_STYLE_LINES |
| 1643 | // check if it's really a point |
| 1644 | if (((prim->bounds.x1 - prim->bounds.x0) == 0) && ((prim->bounds.y1 - prim->bounds.y0) == 0)) |
| 1645 | { |
| 1646 | curPrimitive=GL_POINTS; |
| 1647 | } else { |
| 1648 | curPrimitive=GL_LINES; |
| 1649 | } |
| 1650 | |
| 1651 | if(pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) |
| 1652 | { |
| 1653 | glEnd(); |
| 1654 | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1655 | } |
| 1656 | |
| 1657 | if ( pendingPrimitive==GL_NO_PRIMITIVE ) |
| 1658 | { |
| 1659 | set_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1660 | } |
| 1661 | |
| 1662 | glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); |
| 1663 | |
| 1664 | if(pendingPrimitive!=curPrimitive) |
| 1665 | { |
| 1666 | glBegin(curPrimitive); |
| 1667 | pendingPrimitive=curPrimitive; |
| 1668 | } |
| 1669 | |
| 1670 | // check if it's really a point |
| 1671 | if (curPrimitive==GL_POINTS) |
| 1672 | { |
| 1673 | glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); |
| 1674 | } |
| 1675 | else |
| 1676 | { |
| 1677 | glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); |
| 1678 | glVertex2f(prim->bounds.x1+hofs, prim->bounds.y1+vofs); |
| 1679 | } |
| 1680 | #else |
| 1681 | { |
| 1682 | const line_aa_step *step = line_aa_4step; |
| 1683 | render_bounds b0, b1; |
| 1684 | float r, g, b, a; |
| 1685 | float effwidth; |
| 1686 | |
| 1687 | // we're not gonna play fancy here. close anything pending and let's go. |
| 1688 | if (pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) |
| 1689 | { |
| 1690 | glEnd(); |
| 1691 | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1692 | } |
| 1693 | |
| 1694 | set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1695 | |
| 1696 | // compute the effective width based on the direction of the line |
| 1697 | effwidth = prim->width(); |
| 1698 | if (effwidth < 0.5f) |
| 1699 | effwidth = 0.5f; |
| 1700 | |
| 1701 | // determine the bounds of a quad to draw this line |
| 1702 | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1703 | |
| 1704 | // fix window position |
| 1705 | b0.x0 += hofs; |
| 1706 | b0.x1 += hofs; |
| 1707 | b1.x0 += hofs; |
| 1708 | b1.x1 += hofs; |
| 1709 | b0.y0 += vofs; |
| 1710 | b0.y1 += vofs; |
| 1711 | b1.y0 += vofs; |
| 1712 | b1.y1 += vofs; |
| 1713 | |
| 1714 | // iterate over AA steps |
| 1715 | for (step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; step->weight != 0; step++) |
| 1716 | { |
| 1717 | glBegin(GL_TRIANGLE_STRIP); |
| 1718 | |
| 1719 | // rotate the unit vector by 135 degrees and add to point 0 |
| 1720 | glVertex2f(b0.x0 + step->xoffs, b0.y0 + step->yoffs); |
| 1721 | |
| 1722 | // rotate the unit vector by -135 degrees and add to point 0 |
| 1723 | glVertex2f(b0.x1 + step->xoffs, b0.y1 + step->yoffs); |
| 1724 | |
| 1725 | // rotate the unit vector by 45 degrees and add to point 1 |
| 1726 | glVertex2f(b1.x0 + step->xoffs, b1.y0 + step->yoffs); |
| 1727 | |
| 1728 | // rotate the unit vector by -45 degrees and add to point 1 |
| 1729 | glVertex2f(b1.x1 + step->xoffs, b1.y1 + step->yoffs); |
| 1730 | |
| 1731 | // determine the color of the line |
| 1732 | r = (prim->color.r * step->weight); |
| 1733 | g = (prim->color.g * step->weight); |
| 1734 | b = (prim->color.b * step->weight); |
| 1735 | a = (prim->color.a * 255.0f); |
| 1736 | if (r > 1.0) r = 1.0; |
| 1737 | if (g > 1.0) g = 1.0; |
| 1738 | if (b > 1.0) b = 1.0; |
| 1739 | if (a > 1.0) a = 1.0; |
| 1740 | glColor4f(r, g, b, a); |
| 1741 | |
| 1742 | // texture = texture_update(window, prim, 0); |
| 1743 | // if (texture) printf("line has texture!\n"); |
| 1744 | |
| 1745 | // if we have a texture to use for the vectors, use it here |
| 1746 | #if 0 |
| 1747 | if (d3d->vector_texture != NULL) |
| 1748 | { |
| 1749 | printf("SDL: textured lines unsupported\n"); |
| 1750 | vertex[0].u0 = d3d->vector_texture->ustart; |
| 1751 | vertex[0].v0 = d3d->vector_texture->vstart; |
| 1752 | |
| 1753 | vertex[2].u0 = d3d->vector_texture->ustop; |
| 1754 | vertex[2].v0 = d3d->vector_texture->vstart; |
| 1755 | |
| 1756 | vertex[1].u0 = d3d->vector_texture->ustart; |
| 1757 | vertex[1].v0 = d3d->vector_texture->vstop; |
| 1758 | |
| 1759 | vertex[3].u0 = d3d->vector_texture->ustop; |
| 1760 | vertex[3].v0 = d3d->vector_texture->vstop; |
| 1761 | } |
| 1762 | #endif |
| 1763 | glEnd(); |
| 1764 | } |
| 1765 | } |
| 1766 | #endif |
| 1767 | break; |
| 1768 | |
| 1769 | case render_primitive::QUAD: |
| 1770 | |
| 1771 | if(pendingPrimitive!=GL_NO_PRIMITIVE) |
| 1772 | { |
| 1773 | glEnd(); |
| 1774 | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1775 | } |
| 1776 | |
| 1777 | glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); |
| 1778 | |
| 1779 | set_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1780 | |
| 1781 | texture = texture_update(prim, 0); |
| 1782 | |
| 1783 | if ( texture && texture->type==TEXTURE_TYPE_SHADER ) |
| 1784 | { |
| 1785 | for(i=0; i<m_glsl_program_num; i++) |
| 1786 | { |
| 1787 | if ( i==m_glsl_program_mb2sc ) |
| 1788 | { |
| 1789 | // i==glsl_program_mb2sc -> transformation mamebm->scrn |
| 1790 | m_texVerticex[0]=prim->bounds.x0 + hofs; |
| 1791 | m_texVerticex[1]=prim->bounds.y0 + vofs; |
| 1792 | m_texVerticex[2]=prim->bounds.x1 + hofs; |
| 1793 | m_texVerticex[3]=prim->bounds.y0 + vofs; |
| 1794 | m_texVerticex[4]=prim->bounds.x1 + hofs; |
| 1795 | m_texVerticex[5]=prim->bounds.y1 + vofs; |
| 1796 | m_texVerticex[6]=prim->bounds.x0 + hofs; |
| 1797 | m_texVerticex[7]=prim->bounds.y1 + vofs; |
| 1798 | } else { |
| 1799 | // 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1) on texture dimensions |
| 1800 | m_texVerticex[0]=(GLfloat)0.0; |
| 1801 | m_texVerticex[1]=(GLfloat)0.0; |
| 1802 | m_texVerticex[2]=(GLfloat)m_width; |
| 1803 | m_texVerticex[3]=(GLfloat)0.0; |
| 1804 | m_texVerticex[4]=(GLfloat)m_width; |
| 1805 | m_texVerticex[5]=(GLfloat)m_height; |
| 1806 | m_texVerticex[6]=(GLfloat)0.0; |
| 1807 | m_texVerticex[7]=(GLfloat)m_height; |
| 1808 | } |
| 1809 | |
| 1810 | if(i>0) // first fetch already done |
| 1811 | { |
| 1812 | texture = texture_update(prim, i); |
| 1813 | } |
| 1814 | glDrawArrays(GL_QUADS, 0, 4); |
| 1815 | } |
| 1816 | } else { |
| 1817 | m_texVerticex[0]=prim->bounds.x0 + hofs; |
| 1818 | m_texVerticex[1]=prim->bounds.y0 + vofs; |
| 1819 | m_texVerticex[2]=prim->bounds.x1 + hofs; |
| 1820 | m_texVerticex[3]=prim->bounds.y0 + vofs; |
| 1821 | m_texVerticex[4]=prim->bounds.x1 + hofs; |
| 1822 | m_texVerticex[5]=prim->bounds.y1 + vofs; |
| 1823 | m_texVerticex[6]=prim->bounds.x0 + hofs; |
| 1824 | m_texVerticex[7]=prim->bounds.y1 + vofs; |
| 1825 | |
| 1826 | glDrawArrays(GL_QUADS, 0, 4); |
| 1827 | } |
| 1828 | |
| 1829 | if ( texture ) |
| 1830 | { |
| 1831 | texture_disable(texture); |
| 1832 | texture=NULL; |
| 1833 | } |
| 1834 | break; |
| 1835 | |
| 1836 | default: |
| 1837 | throw emu_fatalerror("Unexpected render_primitive type"); |
| 1838 | } |
| 1839 | } |
| 1840 | |
| 1841 | if(pendingPrimitive!=GL_NO_PRIMITIVE) |
| 1842 | { |
| 1843 | glEnd(); |
| 1844 | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1845 | } |
| 1846 | |
| 1847 | window().m_primlist->release_lock(); |
| 1848 | m_init_context = 0; |
| 1849 | |
| 1850 | m_gl_context->SwapBuffer(); |
| 1851 | |
| 1852 | return 0; |
| 1853 | } |
| 1854 | |
| 1855 | //============================================================ |
| 1856 | // texture handling |
| 1857 | //============================================================ |
| 1858 | |
| 1859 | static const char * texfmt_to_string[9] = { |
| 1860 | "ARGB32", |
| 1861 | "RGB32", |
| 1862 | "RGB32_PALETTED", |
| 1863 | "YUV16", |
| 1864 | "YUV16_PALETTED", |
| 1865 | "PALETTE16", |
| 1866 | "RGB15", |
| 1867 | "RGB15_PALETTE", |
| 1868 | "PALETTE16A" |
| 1869 | }; |
| 1870 | |
| 1871 | // |
| 1872 | // Note: if you change the following array order, change the matching defines in texsrc.h |
| 1873 | // |
| 1874 | |
| 1875 | enum { SDL_TEXFORMAT_SRC_EQUALS_DEST, SDL_TEXFORMAT_SRC_HAS_PALETTE }; |
| 1876 | |
| 1877 | static const GLint texture_copy_properties[9][2] = { |
| 1878 | { TRUE, FALSE }, // SDL_TEXFORMAT_ARGB32 |
| 1879 | { TRUE, FALSE }, // SDL_TEXFORMAT_RGB32 |
| 1880 | { TRUE, TRUE }, // SDL_TEXFORMAT_RGB32_PALETTED |
| 1881 | { FALSE, FALSE }, // SDL_TEXFORMAT_YUY16 |
| 1882 | { FALSE, TRUE }, // SDL_TEXFORMAT_YUY16_PALETTED |
| 1883 | { FALSE, TRUE }, // SDL_TEXFORMAT_PALETTE16 |
| 1884 | { TRUE, FALSE }, // SDL_TEXFORMAT_RGB15 |
| 1885 | { TRUE, TRUE }, // SDL_TEXFORMAT_RGB15_PALETTED |
| 1886 | { FALSE, TRUE } // SDL_TEXFORMAT_PALETTE16A |
| 1887 | }; |
| 1888 | |
| 1889 | //============================================================ |
| 1890 | // drawogl_exit |
| 1891 | //============================================================ |
| 1892 | |
| 1893 | static void drawogl_exit(void) |
| 1894 | { |
| 1895 | int i; |
| 1896 | |
| 1897 | for(i=0; i<video_config.glsl_shader_mamebm_num; i++) |
| 1898 | { |
| 1899 | if ( NULL!=video_config.glsl_shader_mamebm[i]) |
| 1900 | { |
| 1901 | free(video_config.glsl_shader_mamebm[i]); |
| 1902 | video_config.glsl_shader_mamebm[i] = NULL; |
| 1903 | } |
| 1904 | } |
| 1905 | for(i=0; i<video_config.glsl_shader_scrn_num; i++) |
| 1906 | { |
| 1907 | if ( NULL!=video_config.glsl_shader_scrn[i]) |
| 1908 | { |
| 1909 | free(video_config.glsl_shader_scrn[i]); |
| 1910 | video_config.glsl_shader_scrn[i] = NULL; |
| 1911 | } |
| 1912 | } |
| 1913 | } |
| 1914 | |
| 1915 | //============================================================ |
| 1916 | // texture_compute_size and type |
| 1917 | //============================================================ |
| 1918 | |
| 1919 | // |
| 1920 | // glBufferData to push a nocopy texture to the GPU is slower than TexSubImage2D, |
| 1921 | // so don't use PBO here |
| 1922 | // |
| 1923 | // we also don't want to use PBO's in the case of nocopy==TRUE, |
| 1924 | // since we now might have GLSL shaders - this decision simplifies out life ;-) |
| 1925 | // |
| 1926 | void sdl_info_ogl::texture_compute_type_subroutine(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 1927 | { |
| 1928 | texture->type = TEXTURE_TYPE_NONE; |
| 1929 | texture->nocopy = FALSE; |
| 1930 | |
| 1931 | if ( texture->type == TEXTURE_TYPE_NONE && |
| 1932 | !PRIMFLAG_GET_SCREENTEX(flags)) |
| 1933 | { |
| 1934 | texture->type = TEXTURE_TYPE_PLAIN; |
| 1935 | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1936 | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1937 | } |
| 1938 | |
| 1939 | if ( texture->type == TEXTURE_TYPE_NONE && m_useglsl && |
| 1940 | texture->xprescale == 1 && texture->yprescale == 1 && |
| 1941 | texsource->rowpixels <= m_texture_max_width ) |
| 1942 | { |
| 1943 | texture->type = TEXTURE_TYPE_SHADER; |
| 1944 | texture->texTarget = GL_TEXTURE_2D; |
| 1945 | texture->texpow2 = m_texpoweroftwo; |
| 1946 | } |
| 1947 | |
| 1948 | // determine if we can skip the copy step |
| 1949 | // if this was not already decided by the shader condition above |
| 1950 | if ( texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST] && |
| 1951 | !texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE] && |
| 1952 | texture->xprescale == 1 && texture->yprescale == 1 && |
| 1953 | !texture->borderpix && !texsource->palette && |
| 1954 | texsource->rowpixels <= m_texture_max_width ) |
| 1955 | { |
| 1956 | texture->nocopy = TRUE; |
| 1957 | } |
| 1958 | |
| 1959 | if( texture->type == TEXTURE_TYPE_NONE && |
| 1960 | m_usepbo && !texture->nocopy ) |
| 1961 | { |
| 1962 | texture->type = TEXTURE_TYPE_DYNAMIC; |
| 1963 | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1964 | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1965 | } |
| 1966 | |
| 1967 | if( texture->type == TEXTURE_TYPE_NONE ) |
| 1968 | { |
| 1969 | texture->type = TEXTURE_TYPE_SURFACE; |
| 1970 | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1971 | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1972 | } |
| 1973 | } |
| 1974 | |
| 1975 | INLINE int get_valid_pow2_value(int v, int needPow2) |
| 1976 | { |
| 1977 | return (needPow2)?gl_round_to_pow2(v):v; |
| 1978 | } |
| 1979 | |
| 1980 | void sdl_info_ogl::texture_compute_size_subroutine(texture_info *texture, UINT32 flags, |
| 1981 | UINT32 width, UINT32 height, |
| 1982 | int* p_width, int* p_height, int* p_width_create, int* p_height_create) |
| 1983 | { |
| 1984 | int width_create; |
| 1985 | int height_create; |
| 1986 | |
| 1987 | if ( texture->texpow2 ) |
| 1988 | { |
| 1989 | width_create = gl_round_to_pow2 (width); |
| 1990 | height_create = gl_round_to_pow2 (height); |
| 1991 | } else if ( texture->type==TEXTURE_TYPE_SHADER ) |
| 1992 | { |
| 1993 | /** |
| 1994 | * at least use a multiple of 8 for shader .. just in case |
| 1995 | */ |
| 1996 | width_create = ( width & ~0x07 ) + ( (width & 0x07)? 8 : 0 ) ; |
| 1997 | height_create = ( height & ~0x07 ) + ( (height & 0x07)? 8 : 0 ) ; |
| 1998 | } else { |
| 1999 | width_create = width ; |
| 2000 | height_create = height ; |
| 2001 | } |
| 2002 | |
| 2003 | // don't prescale above max texture size |
| 2004 | while (texture->xprescale > 1 && width_create * texture->xprescale > m_texture_max_width) |
| 2005 | texture->xprescale--; |
| 2006 | while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height) |
| 2007 | texture->yprescale--; |
| 2008 | if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != window().prescale() || texture->yprescale != window().prescale())) |
| 2009 | osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", window().prescale(), window().prescale(), texture->xprescale, texture->yprescale); |
| 2010 | |
| 2011 | width *= texture->xprescale; |
| 2012 | height *= texture->yprescale; |
| 2013 | width_create *= texture->xprescale; |
| 2014 | height_create *= texture->yprescale; |
| 2015 | |
| 2016 | // adjust the size for the border (must do this *after* the power of 2 clamp to satisfy |
| 2017 | // OpenGL semantics) |
| 2018 | if (texture->borderpix) |
| 2019 | { |
| 2020 | width += 2; |
| 2021 | height += 2; |
| 2022 | width_create += 2; |
| 2023 | height_create += 2; |
| 2024 | } |
| 2025 | *p_width=width; |
| 2026 | *p_height=height; |
| 2027 | *p_width_create=width_create; |
| 2028 | *p_height_create=height_create; |
| 2029 | } |
| 2030 | |
| 2031 | void sdl_info_ogl::texture_compute_size_type(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 2032 | { |
| 2033 | int finalheight, finalwidth; |
| 2034 | int finalheight_create, finalwidth_create; |
| 2035 | |
| 2036 | // if we're not wrapping, add a 1 pixel border on all sides |
| 2037 | texture->borderpix = 0; //!(texture->flags & PRIMFLAG_TEXWRAP_MASK); |
| 2038 | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 2039 | { |
| 2040 | texture->borderpix = 0; // don't border the screen right now, there's a bug |
| 2041 | } |
| 2042 | |
| 2043 | texture_compute_type_subroutine(texsource, texture, flags); |
| 2044 | |
| 2045 | texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height, |
| 2046 | &finalwidth, &finalheight, &finalwidth_create, &finalheight_create); |
| 2047 | |
| 2048 | // if we added pixels for the border, and that just barely pushed us over, take it back |
| 2049 | if (texture->borderpix && |
| 2050 | ((finalwidth > m_texture_max_width && finalwidth - 2 <= m_texture_max_width) || |
| 2051 | (finalheight > m_texture_max_height && finalheight - 2 <= m_texture_max_height))) |
| 2052 | { |
| 2053 | texture->borderpix = FALSE; |
| 2054 | |
| 2055 | texture_compute_type_subroutine(texsource, texture, flags); |
| 2056 | |
| 2057 | texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height, |
| 2058 | &finalwidth, &finalheight, &finalwidth_create, &finalheight_create); |
| 2059 | } |
| 2060 | |
| 2061 | // if we're above the max width/height, do what? |
| 2062 | if (finalwidth_create > m_texture_max_width || finalheight_create > m_texture_max_height) |
| 2063 | { |
| 2064 | static int printed = FALSE; |
| 2065 | if (!printed) |
| 2066 | osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth_create, finalheight_create, m_texture_max_width, m_texture_max_height); |
| 2067 | printed = TRUE; |
| 2068 | } |
| 2069 | |
| 2070 | if(!texture->nocopy || texture->type==TEXTURE_TYPE_DYNAMIC || texture->type==TEXTURE_TYPE_SHADER || |
| 2071 | // any of the mame core's device generated bitmap types: |
| 2072 | texture->format==SDL_TEXFORMAT_RGB32 || |
| 2073 | texture->format==SDL_TEXFORMAT_RGB32_PALETTED || |
| 2074 | texture->format==SDL_TEXFORMAT_RGB15 || |
| 2075 | texture->format==SDL_TEXFORMAT_RGB15_PALETTED || |
| 2076 | texture->format==SDL_TEXFORMAT_PALETTE16 || |
| 2077 | texture->format==SDL_TEXFORMAT_PALETTE16A |
| 2078 | ) |
| 2079 | { |
| 2080 | osd_printf_verbose("GL texture: copy %d, shader %d, dynamic %d, %dx%d %dx%d [%s, Equal: %d, Palette: %d,\n" |
| 2081 | " scale %dx%d, border %d, pitch %d,%d/%d], bytes/pix %d\n", |
| 2082 | !texture->nocopy, texture->type==TEXTURE_TYPE_SHADER, texture->type==TEXTURE_TYPE_DYNAMIC, |
| 2083 | finalwidth, finalheight, finalwidth_create, finalheight_create, |
| 2084 | texfmt_to_string[texture->format], |
| 2085 | (int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST], |
| 2086 | (int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE], |
| 2087 | texture->xprescale, texture->yprescale, |
| 2088 | texture->borderpix, texsource->rowpixels, finalwidth, m_texture_max_width, |
| 2089 | (int)sizeof(UINT32) |
| 2090 | ); |
| 2091 | } |
| 2092 | |
| 2093 | // set the final values |
| 2094 | texture->rawwidth = finalwidth; |
| 2095 | texture->rawheight = finalheight; |
| 2096 | texture->rawwidth_create = finalwidth_create; |
| 2097 | texture->rawheight_create = finalheight_create; |
| 2098 | } |
| 2099 | |
| 2100 | //============================================================ |
| 2101 | // texture_create |
| 2102 | //============================================================ |
| 2103 | |
| 2104 | static int gl_checkFramebufferStatus(void) |
| 2105 | { |
| 2106 | GLenum status; |
| 2107 | status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); |
| 2108 | switch(status) { |
| 2109 | case GL_FRAMEBUFFER_COMPLETE_EXT: |
| 2110 | return 0; |
| 2111 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: |
| 2112 | osd_printf_error("GL FBO: incomplete,incomplete attachment\n"); |
| 2113 | return -1; |
| 2114 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: |
| 2115 | osd_printf_error("GL FBO: Unsupported framebuffer format\n"); |
| 2116 | return -1; |
| 2117 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: |
| 2118 | osd_printf_error("GL FBO: incomplete,missing attachment\n"); |
| 2119 | return -1; |
| 2120 | case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: |
| 2121 | osd_printf_error("GL FBO: incomplete,attached images must have same dimensions\n"); |
| 2122 | return -1; |
| 2123 | case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: |
| 2124 | osd_printf_error("GL FBO: incomplete,attached images must have same format\n"); |
| 2125 | return -1; |
| 2126 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: |
| 2127 | osd_printf_error("GL FBO: incomplete,missing draw buffer\n"); |
| 2128 | return -1; |
| 2129 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: |
| 2130 | osd_printf_error("GL FBO: incomplete,missing read buffer\n"); |
| 2131 | return -1; |
| 2132 | #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT |
| 2133 | case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: |
| 2134 | osd_printf_error("GL FBO: incomplete, duplicate attachment\n"); |
| 2135 | return -1; |
| 2136 | #endif |
| 2137 | case 0: |
| 2138 | osd_printf_error("GL FBO: incomplete, implementation fault\n"); |
| 2139 | return -1; |
| 2140 | default: |
| 2141 | osd_printf_error("GL FBO: incomplete, implementation ERROR\n"); |
| 2142 | /* fall through */ |
| 2143 | } |
| 2144 | return -1; |
| 2145 | } |
| 2146 | |
| 2147 | static int texture_fbo_create(UINT32 text_unit, UINT32 text_name, UINT32 fbo_name, int width, int height) |
| 2148 | { |
| 2149 | pfn_glActiveTexture(text_unit); |
| 2150 | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); |
| 2151 | glBindTexture(GL_TEXTURE_2D, text_name); |
| 2152 | { |
| 2153 | GLint _width, _height; |
| 2154 | if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, |
| 2155 | 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) ) |
| 2156 | { |
| 2157 | osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n", |
| 2158 | width, height, (int)_width, (int)_height); |
| 2159 | return -1; |
| 2160 | } |
| 2161 | |
| 2162 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, |
| 2163 | 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL ); |
| 2164 | } |
| 2165 | // non-screen textures will never be filtered |
| 2166 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2167 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2168 | |
| 2169 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2170 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2171 | |
| 2172 | pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| 2173 | GL_TEXTURE_2D, text_name, 0); |
| 2174 | |
| 2175 | if ( gl_checkFramebufferStatus() ) |
| 2176 | { |
| 2177 | osd_printf_error("FBO error fbo texture - bail out\n"); |
| 2178 | return -1; |
| 2179 | } |
| 2180 | |
| 2181 | return 0; |
| 2182 | } |
| 2183 | |
| 2184 | int sdl_info_ogl::texture_shader_create(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 2185 | { |
| 2186 | int uniform_location; |
| 2187 | int i; |
| 2188 | int surf_w_pow2 = get_valid_pow2_value (m_blit_dim.width(), texture->texpow2); |
| 2189 | int surf_h_pow2 = get_valid_pow2_value (m_blit_dim.height(), texture->texpow2); |
| 2190 | |
| 2191 | assert ( texture->type==TEXTURE_TYPE_SHADER ); |
| 2192 | |
| 2193 | GL_CHECK_ERROR_QUIET(); |
| 2194 | |
| 2195 | if( m_glsl_program_num > 1 ) |
| 2196 | { |
| 2197 | // multipass mode |
| 2198 | assert(m_usefbo); |
| 2199 | |
| 2200 | // GL_TEXTURE3 GLSL Uniforms |
| 2201 | texture->mpass_dest_idx = 0; |
| 2202 | texture->mpass_textureunit[0] = GL_TEXTURE3; |
| 2203 | texture->mpass_textureunit[1] = GL_TEXTURE2; |
| 2204 | } |
| 2205 | |
| 2206 | for(i=0; i<m_glsl_program_num; i++) |
| 2207 | { |
| 2208 | if ( i<=m_glsl_program_mb2sc ) |
| 2209 | { |
| 2210 | m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i); |
| 2211 | } else { |
| 2212 | m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc); |
| 2213 | } |
| 2214 | pfn_glUseProgramObjectARB(m_glsl_program[i]); |
| 2215 | |
| 2216 | if ( i<=m_glsl_program_mb2sc ) |
| 2217 | { |
| 2218 | // GL_TEXTURE0 GLSL Uniforms |
| 2219 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture"); |
| 2220 | pfn_glUniform1iARB(uniform_location, 0); |
| 2221 | GL_CHECK_ERROR_NORMAL(); |
| 2222 | } |
| 2223 | |
| 2224 | { |
| 2225 | GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight }; |
| 2226 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz"); |
| 2227 | pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0])); |
| 2228 | GL_CHECK_ERROR_NORMAL(); |
| 2229 | } |
| 2230 | |
| 2231 | GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create }; |
| 2232 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz"); |
| 2233 | pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0])); |
| 2234 | GL_CHECK_ERROR_NORMAL(); |
| 2235 | |
| 2236 | GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() }; |
| 2237 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz"); |
| 2238 | pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0])); |
| 2239 | GL_CHECK_ERROR_NORMAL(); |
| 2240 | |
| 2241 | GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 }; |
| 2242 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz"); |
| 2243 | pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0])); |
| 2244 | GL_CHECK_ERROR_NORMAL(); |
| 2245 | } |
| 2246 | |
| 2247 | pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader |
| 2248 | |
| 2249 | if( m_glsl_program_num > 1 ) |
| 2250 | { |
| 2251 | // multipass mode |
| 2252 | // GL_TEXTURE2/GL_TEXTURE3 |
| 2253 | pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); |
| 2254 | glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); |
| 2255 | |
| 2256 | for (i=0; i<2; i++) |
| 2257 | { |
| 2258 | if ( texture_fbo_create(texture->mpass_textureunit[i], |
| 2259 | texture->mpass_texture_mamebm[i], |
| 2260 | texture->mpass_fbo_mamebm[i], |
| 2261 | texture->rawwidth_create, texture->rawheight_create) ) |
| 2262 | { |
| 2263 | return -1; |
| 2264 | } |
| 2265 | } |
| 2266 | |
| 2267 | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 2268 | |
| 2269 | osd_printf_verbose("GL texture: mpass mame-bmp 2x %dx%d (pow2 %dx%d)\n", |
| 2270 | texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create); |
| 2271 | } |
| 2272 | |
| 2273 | if( m_glsl_program_num > 1 && m_glsl_program_mb2sc < m_glsl_program_num - 1 ) |
| 2274 | { |
| 2275 | // multipass mode |
| 2276 | // GL_TEXTURE2/GL_TEXTURE3 |
| 2277 | pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); |
| 2278 | glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); |
| 2279 | |
| 2280 | for (i=0; i<2; i++) |
| 2281 | { |
| 2282 | if ( texture_fbo_create(texture->mpass_textureunit[i], |
| 2283 | texture->mpass_texture_scrn[i], |
| 2284 | texture->mpass_fbo_scrn[i], |
| 2285 | surf_w_pow2, surf_h_pow2) ) |
| 2286 | { |
| 2287 | return -1; |
| 2288 | } |
| 2289 | } |
| 2290 | |
| 2291 | osd_printf_verbose("GL texture: mpass screen-bmp 2x %dx%d (pow2 %dx%d)\n", |
| 2292 | m_width, m_height, surf_w_pow2, surf_h_pow2); |
| 2293 | } |
| 2294 | |
| 2295 | // GL_TEXTURE0 |
| 2296 | // get a name for this texture |
| 2297 | glGenTextures(1, (GLuint *)&texture->texture); |
| 2298 | pfn_glActiveTexture(GL_TEXTURE0); |
| 2299 | glBindTexture(GL_TEXTURE_2D, texture->texture); |
| 2300 | |
| 2301 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create); |
| 2302 | |
| 2303 | UINT32 * dummy = NULL; |
| 2304 | GLint _width, _height; |
| 2305 | if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, |
| 2306 | texture->rawwidth_create, texture->rawheight_create, |
| 2307 | 0, |
| 2308 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, |
| 2309 | &_width, &_height, 1) ) |
| 2310 | { |
| 2311 | osd_printf_error("cannot create bitmap texture, req: %dx%d, avail: %dx%d - bail out\n", |
| 2312 | texture->rawwidth_create, texture->rawheight_create, (int)_width, (int)_height); |
| 2313 | return -1; |
| 2314 | } |
| 2315 | |
| 2316 | dummy = (UINT32 *) malloc(texture->rawwidth_create * texture->rawheight_create * sizeof(UINT32)); |
| 2317 | memset(dummy, 0, texture->rawwidth_create * texture->rawheight_create * sizeof(UINT32)); |
| 2318 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, |
| 2319 | texture->rawwidth_create, texture->rawheight_create, |
| 2320 | 0, |
| 2321 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dummy); |
| 2322 | glFinish(); // should not be necessary, .. but make sure we won't access the memory after free |
| 2323 | free(dummy); |
| 2324 | |
| 2325 | if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter) |
| 2326 | { |
| 2327 | assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN ); |
| 2328 | |
| 2329 | // screen textures get the user's choice of filtering |
| 2330 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 2331 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 2332 | } |
| 2333 | else |
| 2334 | { |
| 2335 | // non-screen textures will never be filtered |
| 2336 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2337 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2338 | } |
| 2339 | |
| 2340 | // set wrapping mode appropriately |
| 2341 | if (texture->flags & PRIMFLAG_TEXWRAP_MASK) |
| 2342 | { |
| 2343 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| 2344 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| 2345 | } |
| 2346 | else |
| 2347 | { |
| 2348 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2349 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2350 | } |
| 2351 | |
| 2352 | GL_CHECK_ERROR_NORMAL(); |
| 2353 | |
| 2354 | return 0; |
| 2355 | } |
| 2356 | |
| 2357 | texture_info *sdl_info_ogl::texture_create(const render_texinfo *texsource, UINT32 flags) |
| 2358 | { |
| 2359 | texture_info *texture; |
| 2360 | |
| 2361 | // allocate a new texture |
| 2362 | texture = global_alloc(texture_info); |
| 2363 | |
| 2364 | // fill in the core data |
| 2365 | texture->hash = texture_compute_hash(texsource, flags); |
| 2366 | texture->flags = flags; |
| 2367 | texture->texinfo = *texsource; |
| 2368 | texture->texinfo.seqid = -1; // force set data |
| 2369 | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 2370 | { |
| 2371 | texture->xprescale = window().prescale(); |
| 2372 | texture->yprescale = window().prescale(); |
| 2373 | } |
| 2374 | else |
| 2375 | { |
| 2376 | texture->xprescale = 1; |
| 2377 | texture->yprescale = 1; |
| 2378 | } |
| 2379 | |
| 2380 | // set the texture_format |
| 2381 | // |
| 2382 | // src/emu/validity.c:validate_display() states, |
| 2383 | // an emulated driver can only produce |
| 2384 | // BITMAP_FORMAT_IND16 and BITMAP_FORMAT_RGB32 |
| 2385 | // where only the first original paletted. |
| 2386 | // |
| 2387 | // other paletted formats, i.e.: |
| 2388 | // SDL_TEXFORMAT_RGB32_PALETTED, SDL_TEXFORMAT_RGB15_PALETTED and SDL_TEXFORMAT_YUY16_PALETTED |
| 2389 | // add features like brightness etc by the mame core |
| 2390 | // |
| 2391 | // all palette lookup may be implemented using shaders later on .. |
| 2392 | // that's why we keep the EQUAL flag TRUE, for all original true color bitmaps. |
| 2393 | // |
| 2394 | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2395 | { |
| 2396 | case TEXFORMAT_ARGB32: |
| 2397 | texture->format = SDL_TEXFORMAT_ARGB32; |
| 2398 | break; |
| 2399 | case TEXFORMAT_RGB32: |
| 2400 | if (texsource->palette != NULL) |
| 2401 | texture->format = SDL_TEXFORMAT_RGB32_PALETTED; |
| 2402 | else |
| 2403 | texture->format = SDL_TEXFORMAT_RGB32; |
| 2404 | break; |
| 2405 | case TEXFORMAT_PALETTE16: |
| 2406 | texture->format = SDL_TEXFORMAT_PALETTE16; |
| 2407 | break; |
| 2408 | case TEXFORMAT_PALETTEA16: |
| 2409 | texture->format = SDL_TEXFORMAT_PALETTE16A; |
| 2410 | break; |
| 2411 | case TEXFORMAT_YUY16: |
| 2412 | if (texsource->palette != NULL) |
| 2413 | texture->format = SDL_TEXFORMAT_YUY16_PALETTED; |
| 2414 | else |
| 2415 | texture->format = SDL_TEXFORMAT_YUY16; |
| 2416 | break; |
| 2417 | |
| 2418 | default: |
| 2419 | osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2420 | } |
| 2421 | |
| 2422 | // compute the size |
| 2423 | texture_compute_size_type(texsource, texture, flags); |
| 2424 | |
| 2425 | texture->pbo=0; |
| 2426 | |
| 2427 | if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl) |
| 2428 | { |
| 2429 | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 2430 | } |
| 2431 | |
| 2432 | if ( texture->type==TEXTURE_TYPE_SHADER ) |
| 2433 | { |
| 2434 | if ( texture_shader_create(texsource, texture, flags) ) |
| 2435 | { |
| 2436 | global_free(texture); |
| 2437 | return NULL; |
| 2438 | } |
| 2439 | } |
| 2440 | else |
| 2441 | { |
| 2442 | // get a name for this texture |
| 2443 | glGenTextures(1, (GLuint *)&texture->texture); |
| 2444 | |
| 2445 | glEnable(texture->texTarget); |
| 2446 | |
| 2447 | // make sure we're operating on *this* texture |
| 2448 | glBindTexture(texture->texTarget, texture->texture); |
| 2449 | |
| 2450 | // this doesn't actually upload, it just sets up the PBO's parameters |
| 2451 | glTexImage2D(texture->texTarget, 0, GL_RGBA8, |
| 2452 | texture->rawwidth_create, texture->rawheight_create, |
| 2453 | texture->borderpix ? 1 : 0, |
| 2454 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); |
| 2455 | |
| 2456 | if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter) |
| 2457 | { |
| 2458 | // screen textures get the user's choice of filtering |
| 2459 | glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 2460 | glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 2461 | } |
| 2462 | else |
| 2463 | { |
| 2464 | // non-screen textures will never be filtered |
| 2465 | glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2466 | glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2467 | } |
| 2468 | |
| 2469 | if( texture->texTarget==GL_TEXTURE_RECTANGLE_ARB ) |
| 2470 | { |
| 2471 | // texture rectangles can't wrap |
| 2472 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2473 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2474 | } else { |
| 2475 | // set wrapping mode appropriately |
| 2476 | if (texture->flags & PRIMFLAG_TEXWRAP_MASK) |
| 2477 | { |
| 2478 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| 2479 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| 2480 | } |
| 2481 | else |
| 2482 | { |
| 2483 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2484 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2485 | } |
| 2486 | } |
| 2487 | } |
| 2488 | |
| 2489 | if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2490 | { |
| 2491 | assert(m_usepbo); |
| 2492 | |
| 2493 | // create the PBO |
| 2494 | pfn_glGenBuffers(1, (GLuint *)&texture->pbo); |
| 2495 | |
| 2496 | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); |
| 2497 | |
| 2498 | // set up the PBO dimension, .. |
| 2499 | pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, |
| 2500 | texture->rawwidth * texture->rawheight * sizeof(UINT32), |
| 2501 | NULL, GL_STREAM_DRAW); |
| 2502 | } |
| 2503 | |
| 2504 | if ( !texture->nocopy && texture->type!=TEXTURE_TYPE_DYNAMIC ) |
| 2505 | { |
| 2506 | texture->data = (UINT32 *) malloc(texture->rawwidth* texture->rawheight * sizeof(UINT32)); |
| 2507 | texture->data_own=TRUE; |
| 2508 | } |
| 2509 | |
| 2510 | // add us to the texture list |
| 2511 | if (m_texhash[texture->hash] == NULL) |
| 2512 | m_texhash[texture->hash] = texture; |
| 2513 | else |
| 2514 | { |
| 2515 | int i; |
| 2516 | for (i = HASH_SIZE; i < HASH_SIZE + OVERFLOW_SIZE; i++) |
| 2517 | if (m_texhash[i] == NULL) |
| 2518 | { |
| 2519 | m_texhash[i] = texture; |
| 2520 | break; |
| 2521 | } |
| 2522 | assert_always(i < HASH_SIZE + OVERFLOW_SIZE, "texture hash exhausted ..."); |
| 2523 | } |
| 2524 | |
| 2525 | if(m_usevbo) |
| 2526 | { |
| 2527 | // Generate And Bind The Texture Coordinate Buffer |
| 2528 | pfn_glGenBuffers( 1, &(texture->texCoordBufferName) ); |
| 2529 | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); |
| 2530 | // Load The Data |
| 2531 | pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); |
| 2532 | glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // we are using ARB VBO buffers |
| 2533 | } |
| 2534 | else |
| 2535 | { |
| 2536 | glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord); |
| 2537 | } |
| 2538 | |
| 2539 | return texture; |
| 2540 | } |
| 2541 | |
| 2542 | //============================================================ |
| 2543 | // copyline_palette16 |
| 2544 | //============================================================ |
| 2545 | |
| 2546 | INLINE void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2547 | { |
| 2548 | int x; |
| 2549 | |
| 2550 | assert(xborderpix == 0 || xborderpix == 1); |
| 2551 | if (xborderpix) |
| 2552 | *dst++ = 0xff000000 | palette[*src]; |
| 2553 | for (x = 0; x < width; x++) |
| 2554 | { |
| 2555 | int srcpix = *src++; |
| 2556 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2557 | *dst++ = 0xff000000 | palette[srcpix]; |
| 2558 | } |
| 2559 | if (xborderpix) |
| 2560 | *dst++ = 0xff000000 | palette[*--src]; |
| 2561 | } |
| 2562 | |
| 2563 | |
| 2564 | |
| 2565 | //============================================================ |
| 2566 | // copyline_palettea16 |
| 2567 | //============================================================ |
| 2568 | |
| 2569 | INLINE void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2570 | { |
| 2571 | int x; |
| 2572 | |
| 2573 | assert(xborderpix == 0 || xborderpix == 1); |
| 2574 | if (xborderpix) |
| 2575 | *dst++ = palette[*src]; |
| 2576 | for (x = 0; x < width; x++) |
| 2577 | { |
| 2578 | int srcpix = *src++; |
| 2579 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2580 | *dst++ = palette[srcpix]; |
| 2581 | } |
| 2582 | if (xborderpix) |
| 2583 | *dst++ = palette[*--src]; |
| 2584 | } |
| 2585 | |
| 2586 | |
| 2587 | |
| 2588 | //============================================================ |
| 2589 | // copyline_rgb32 |
| 2590 | //============================================================ |
| 2591 | |
| 2592 | INLINE void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2593 | { |
| 2594 | int x; |
| 2595 | |
| 2596 | assert(xborderpix == 0 || xborderpix == 1); |
| 2597 | |
| 2598 | // palette (really RGB map) case |
| 2599 | if (palette != NULL) |
| 2600 | { |
| 2601 | if (xborderpix) |
| 2602 | { |
| 2603 | rgb_t srcpix = *src; |
| 2604 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2605 | } |
| 2606 | for (x = 0; x < width; x++) |
| 2607 | { |
| 2608 | rgb_t srcpix = *src++; |
| 2609 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2610 | { |
| 2611 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2612 | } |
| 2613 | } |
| 2614 | if (xborderpix) |
| 2615 | { |
| 2616 | rgb_t srcpix = *--src; |
| 2617 | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2618 | } |
| 2619 | } |
| 2620 | |
| 2621 | // direct case |
| 2622 | else |
| 2623 | { |
| 2624 | if (xborderpix) |
| 2625 | *dst++ = 0xff000000 | *src; |
| 2626 | for (x = 0; x < width; x++) |
| 2627 | { |
| 2628 | rgb_t srcpix = *src++; |
| 2629 | |
| 2630 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2631 | { |
| 2632 | *dst++ = 0xff000000 | srcpix; |
| 2633 | } |
| 2634 | } |
| 2635 | if (xborderpix) |
| 2636 | *dst++ = 0xff000000 | *--src; |
| 2637 | } |
| 2638 | } |
| 2639 | |
| 2640 | //============================================================ |
| 2641 | // copyline_argb32 |
| 2642 | //============================================================ |
| 2643 | |
| 2644 | INLINE void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2645 | { |
| 2646 | int x; |
| 2647 | |
| 2648 | assert(xborderpix == 0 || xborderpix == 1); |
| 2649 | |
| 2650 | // palette (really RGB map) case |
| 2651 | if (palette != NULL) |
| 2652 | { |
| 2653 | if (xborderpix) |
| 2654 | { |
| 2655 | rgb_t srcpix = *src; |
| 2656 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2657 | } |
| 2658 | for (x = 0; x < width; x++) |
| 2659 | { |
| 2660 | rgb_t srcpix = *src++; |
| 2661 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2662 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2663 | } |
| 2664 | if (xborderpix) |
| 2665 | { |
| 2666 | rgb_t srcpix = *--src; |
| 2667 | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2668 | } |
| 2669 | } |
| 2670 | |
| 2671 | // direct case |
| 2672 | else |
| 2673 | { |
| 2674 | if (xborderpix) |
| 2675 | *dst++ = *src; |
| 2676 | for (x = 0; x < width; x++) |
| 2677 | { |
| 2678 | rgb_t srcpix = *src++; |
| 2679 | for (int x2 = 0; x2 < xprescale; x2++) |
| 2680 | *dst++ = srcpix; |
| 2681 | } |
| 2682 | if (xborderpix) |
| 2683 | *dst++ = *--src; |
| 2684 | } |
| 2685 | } |
| 2686 | |
| 2687 | INLINE UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) |
| 2688 | { |
| 2689 | /* original equations: |
| 2690 | |
| 2691 | C = Y - 16 |
| 2692 | D = Cb - 128 |
| 2693 | E = Cr - 128 |
| 2694 | |
| 2695 | R = clip(( 298 * C + 409 * E + 128) >> 8) |
| 2696 | G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) |
| 2697 | B = clip(( 298 * C + 516 * D + 128) >> 8) |
| 2698 | |
| 2699 | R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) |
| 2700 | G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) |
| 2701 | B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) |
| 2702 | |
| 2703 | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 2704 | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 2705 | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 2706 | |
| 2707 | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 2708 | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 2709 | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 2710 | */ |
| 2711 | int r, g, b, common; |
| 2712 | |
| 2713 | common = 298 * y - 298 * 16; |
| 2714 | r = (common + 409 * cr - 409 * 128 + 128) >> 8; |
| 2715 | g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; |
| 2716 | b = (common + 516 * cb - 516 * 128 + 128) >> 8; |
| 2717 | |
| 2718 | if (r < 0) r = 0; |
| 2719 | else if (r > 255) r = 255; |
| 2720 | if (g < 0) g = 0; |
| 2721 | else if (g > 255) g = 255; |
| 2722 | if (b < 0) b = 0; |
| 2723 | else if (b > 255) b = 255; |
| 2724 | |
| 2725 | return rgb_t(0xff, r, g, b); |
| 2726 | } |
| 2727 | |
| 2728 | //============================================================ |
| 2729 | // copyline_yuy16_to_argb |
| 2730 | //============================================================ |
| 2731 | |
| 2732 | INLINE void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2733 | { |
| 2734 | int x; |
| 2735 | |
| 2736 | assert(xborderpix == 0 || xborderpix == 2); |
| 2737 | assert(width % 2 == 0); |
| 2738 | |
| 2739 | // palette (really RGB map) case |
| 2740 | if (palette != NULL) |
| 2741 | { |
| 2742 | if (xborderpix) |
| 2743 | { |
| 2744 | UINT16 srcpix0 = src[0]; |
| 2745 | UINT16 srcpix1 = src[1]; |
| 2746 | UINT8 cb = srcpix0 & 0xff; |
| 2747 | UINT8 cr = srcpix1 & 0xff; |
| 2748 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2749 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2750 | } |
| 2751 | for (x = 0; x < width / 2; x++) |
| 2752 | { |
| 2753 | UINT16 srcpix0 = *src++; |
| 2754 | UINT16 srcpix1 = *src++; |
| 2755 | UINT8 cb = srcpix0 & 0xff; |
| 2756 | UINT8 cr = srcpix1 & 0xff; |
| 2757 | for (int x2 = 0; x2 < xprescale/2; x2++) |
| 2758 | { |
| 2759 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2760 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2761 | } |
| 2762 | } |
| 2763 | if (xborderpix) |
| 2764 | { |
| 2765 | UINT16 srcpix1 = *--src; |
| 2766 | UINT16 srcpix0 = *--src; |
| 2767 | UINT8 cb = srcpix0 & 0xff; |
| 2768 | UINT8 cr = srcpix1 & 0xff; |
| 2769 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2770 | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2771 | } |
| 2772 | } |
| 2773 | |
| 2774 | // direct case |
| 2775 | else |
| 2776 | { |
| 2777 | if (xborderpix) |
| 2778 | { |
| 2779 | UINT16 srcpix0 = src[0]; |
| 2780 | UINT16 srcpix1 = src[1]; |
| 2781 | UINT8 cb = srcpix0 & 0xff; |
| 2782 | UINT8 cr = srcpix1 & 0xff; |
| 2783 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2784 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2785 | } |
| 2786 | for (x = 0; x < width; x += 2) |
| 2787 | { |
| 2788 | UINT16 srcpix0 = *src++; |
| 2789 | UINT16 srcpix1 = *src++; |
| 2790 | UINT8 cb = srcpix0 & 0xff; |
| 2791 | UINT8 cr = srcpix1 & 0xff; |
| 2792 | for (int x2 = 0; x2 < xprescale/2; x2++) |
| 2793 | { |
| 2794 | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2795 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2796 | } |
| 2797 | } |
| 2798 | if (xborderpix) |
| 2799 | { |
| 2800 | UINT16 srcpix1 = *--src; |
| 2801 | UINT16 srcpix0 = *--src; |
| 2802 | UINT8 cb = srcpix0 & 0xff; |
| 2803 | UINT8 cr = srcpix1 & 0xff; |
| 2804 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2805 | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2806 | } |
| 2807 | } |
| 2808 | } |
| 2809 | |
| 2810 | //============================================================ |
| 2811 | // texture_set_data |
| 2812 | //============================================================ |
| 2813 | |
| 2814 | static void texture_set_data(texture_info *texture, const render_texinfo *texsource, UINT32 flags) |
| 2815 | { |
| 2816 | if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2817 | { |
| 2818 | assert(texture->pbo); |
| 2819 | assert(!texture->nocopy); |
| 2820 | |
| 2821 | texture->data = (UINT32 *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); |
| 2822 | } |
| 2823 | |
| 2824 | // note that nocopy and borderpix are mutually exclusive, IOW |
| 2825 | // they cannot be both true, thus this cannot lead to the |
| 2826 | // borderpix code below writing to texsource->base . |
| 2827 | if (texture->nocopy) |
| 2828 | { |
| 2829 | texture->data = (UINT32 *) texsource->base; |
| 2830 | } |
| 2831 | |
| 2832 | // always fill non-wrapping textures with an extra pixel on the top |
| 2833 | if (texture->borderpix) |
| 2834 | { |
| 2835 | memset(texture->data, 0, |
| 2836 | (texsource->width * texture->xprescale + 2) * sizeof(UINT32)); |
| 2837 | } |
| 2838 | |
| 2839 | // when nescesarry copy (and convert) the data |
| 2840 | if (!texture->nocopy) |
| 2841 | { |
| 2842 | int y, y2; |
| 2843 | UINT8 *dst; |
| 2844 | |
| 2845 | for (y = 0; y < texsource->height; y++) |
| 2846 | { |
| 2847 | for (y2 = 0; y2 < texture->yprescale; y2++) |
| 2848 | { |
| 2849 | dst = (UINT8 *)(texture->data + (y * texture->yprescale + texture->borderpix + y2) * texture->rawwidth); |
| 2850 | |
| 2851 | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2852 | { |
| 2853 | case TEXFORMAT_PALETTE16: |
| 2854 | copyline_palette16((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2855 | break; |
| 2856 | |
| 2857 | case TEXFORMAT_PALETTEA16: |
| 2858 | copyline_palettea16((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2859 | break; |
| 2860 | |
| 2861 | case TEXFORMAT_RGB32: |
| 2862 | copyline_rgb32((UINT32 *)dst, (UINT32 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2863 | break; |
| 2864 | |
| 2865 | case TEXFORMAT_ARGB32: |
| 2866 | copyline_argb32((UINT32 *)dst, (UINT32 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2867 | break; |
| 2868 | |
| 2869 | case TEXFORMAT_YUY16: |
| 2870 | copyline_yuy16_to_argb((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2871 | break; |
| 2872 | |
| 2873 | default: |
| 2874 | osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2875 | break; |
| 2876 | } |
| 2877 | } |
| 2878 | } |
| 2879 | } |
| 2880 | |
| 2881 | // always fill non-wrapping textures with an extra pixel on the bottom |
| 2882 | if (texture->borderpix) |
| 2883 | { |
| 2884 | memset((UINT8 *)texture->data + |
| 2885 | (texsource->height + 1) * texture->rawwidth * sizeof(UINT32), |
| 2886 | 0, |
| 2887 | (texsource->width * texture->xprescale + 2) * sizeof(UINT32)); |
| 2888 | } |
| 2889 | |
| 2890 | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 2891 | { |
| 2892 | pfn_glActiveTexture(GL_TEXTURE0); |
| 2893 | glBindTexture(texture->texTarget, texture->texture); |
| 2894 | |
| 2895 | if (texture->nocopy) |
| 2896 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels); |
| 2897 | else |
| 2898 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2899 | |
| 2900 | // and upload the image |
| 2901 | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2902 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data); |
| 2903 | } |
| 2904 | else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2905 | { |
| 2906 | glBindTexture(texture->texTarget, texture->texture); |
| 2907 | |
| 2908 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2909 | |
| 2910 | // unmap the buffer from the CPU space so it can DMA |
| 2911 | pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); |
| 2912 | |
| 2913 | // kick off the DMA |
| 2914 | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2915 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); |
| 2916 | } |
| 2917 | else |
| 2918 | { |
| 2919 | glBindTexture(texture->texTarget, texture->texture); |
| 2920 | |
| 2921 | // give the card a hint |
| 2922 | if (texture->nocopy) |
| 2923 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels); |
| 2924 | else |
| 2925 | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2926 | |
| 2927 | // and upload the image |
| 2928 | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2929 | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data); |
| 2930 | } |
| 2931 | } |
| 2932 | |
| 2933 | //============================================================ |
| 2934 | // texture_find |
| 2935 | //============================================================ |
| 2936 | |
| 2937 | static int compare_texture_primitive(const texture_info *texture, const render_primitive *prim) |
| 2938 | { |
| 2939 | if (texture->texinfo.base == prim->texture.base && |
| 2940 | texture->texinfo.width == prim->texture.width && |
| 2941 | texture->texinfo.height == prim->texture.height && |
| 2942 | texture->texinfo.rowpixels == prim->texture.rowpixels && |
| 2943 | /* texture->texinfo.palette == prim->texture.palette && */ |
| 2944 | ((texture->flags ^ prim->flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) |
| 2945 | return 1; |
| 2946 | else |
| 2947 | return 0; |
| 2948 | } |
| 2949 | |
| 2950 | texture_info *sdl_info_ogl::texture_find(const render_primitive *prim) |
| 2951 | { |
| 2952 | HashT texhash = texture_compute_hash(&prim->texture, prim->flags); |
| 2953 | texture_info *texture; |
| 2954 | |
| 2955 | texture = m_texhash[texhash]; |
| 2956 | if (texture != NULL) |
| 2957 | { |
| 2958 | int i; |
| 2959 | if (compare_texture_primitive(texture, prim)) |
| 2960 | return texture; |
| 2961 | for (i=HASH_SIZE; i<HASH_SIZE + OVERFLOW_SIZE; i++) |
| 2962 | { |
| 2963 | texture = m_texhash[i]; |
| 2964 | if (texture != NULL && compare_texture_primitive(texture, prim)) |
| 2965 | return texture; |
| 2966 | } |
| 2967 | } |
| 2968 | return NULL; |
| 2969 | } |
| 2970 | |
| 2971 | //============================================================ |
| 2972 | // texture_update |
| 2973 | //============================================================ |
| 2974 | |
| 2975 | void sdl_info_ogl::texture_coord_update(texture_info *texture, const render_primitive *prim, int shaderIdx) |
| 2976 | { |
| 2977 | float ustart = 0.0f, ustop = 0.0f; // beginning/ending U coordinates |
| 2978 | float vstart = 0.0f, vstop = 0.0f; // beginning/ending V coordinates |
| 2979 | float du, dv; |
| 2980 | |
| 2981 | if ( texture->type != TEXTURE_TYPE_SHADER || |
| 2982 | ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx<=m_glsl_program_mb2sc ) ) |
| 2983 | { |
| 2984 | // compute the U/V scale factors |
| 2985 | if (texture->borderpix) |
| 2986 | { |
| 2987 | int unscaledwidth = (texture->rawwidth_create-2) / texture->xprescale + 2; |
| 2988 | int unscaledheight = (texture->rawheight_create-2) / texture->yprescale + 2; |
| 2989 | ustart = 1.0f / (float)(unscaledwidth); |
| 2990 | ustop = (float)(prim->texture.width + 1) / (float)(unscaledwidth); |
| 2991 | vstart = 1.0f / (float)(unscaledheight); |
| 2992 | vstop = (float)(prim->texture.height + 1) / (float)(unscaledheight); |
| 2993 | } |
| 2994 | else |
| 2995 | { |
| 2996 | ustop = (float)(prim->texture.width*texture->xprescale) / (float)texture->rawwidth_create; |
| 2997 | vstop = (float)(prim->texture.height*texture->yprescale) / (float)texture->rawheight_create; |
| 2998 | } |
| 2999 | } |
| 3000 | else if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx>m_glsl_program_mb2sc ) |
| 3001 | { |
| 3002 | int surf_w_pow2 = get_valid_pow2_value (m_width, texture->texpow2); |
| 3003 | int surf_h_pow2 = get_valid_pow2_value (m_height, texture->texpow2); |
| 3004 | |
| 3005 | ustop = (float)(m_width) / (float)surf_w_pow2; |
| 3006 | vstop = (float)(m_height) / (float)surf_h_pow2; |
| 3007 | |
| 3008 | } |
| 3009 | else |
| 3010 | { |
| 3011 | assert(0); // ?? |
| 3012 | } |
| 3013 | |
| 3014 | du = ustop - ustart; |
| 3015 | dv = vstop - vstart; |
| 3016 | |
| 3017 | if ( texture->texTarget == GL_TEXTURE_RECTANGLE_ARB ) |
| 3018 | { |
| 3019 | // texture coordinates for TEXTURE_RECTANGLE are 0,0 -> w,h |
| 3020 | // rather than 0,0 -> 1,1 as with normal OpenGL texturing |
| 3021 | du *= (float)texture->rawwidth; |
| 3022 | dv *= (float)texture->rawheight; |
| 3023 | } |
| 3024 | |
| 3025 | if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx!=m_glsl_program_mb2sc ) |
| 3026 | { |
| 3027 | // 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1) |
| 3028 | // we must go CW here due to the mame bitmap order |
| 3029 | texture->texCoord[0]=ustart + du * 0.0f; |
| 3030 | texture->texCoord[1]=vstart + dv * 1.0f; |
| 3031 | texture->texCoord[2]=ustart + du * 1.0f; |
| 3032 | texture->texCoord[3]=vstart + dv * 1.0f; |
| 3033 | texture->texCoord[4]=ustart + du * 1.0f; |
| 3034 | texture->texCoord[5]=vstart + dv * 0.0f; |
| 3035 | texture->texCoord[6]=ustart + du * 0.0f; |
| 3036 | texture->texCoord[7]=vstart + dv * 0.0f; |
| 3037 | } |
| 3038 | else |
| 3039 | { |
| 3040 | // transformation: mamebm -> scrn |
| 3041 | texture->texCoord[0]=ustart + du * prim->texcoords.tl.u; |
| 3042 | texture->texCoord[1]=vstart + dv * prim->texcoords.tl.v; |
| 3043 | texture->texCoord[2]=ustart + du * prim->texcoords.tr.u; |
| 3044 | texture->texCoord[3]=vstart + dv * prim->texcoords.tr.v; |
| 3045 | texture->texCoord[4]=ustart + du * prim->texcoords.br.u; |
| 3046 | texture->texCoord[5]=vstart + dv * prim->texcoords.br.v; |
| 3047 | texture->texCoord[6]=ustart + du * prim->texcoords.bl.u; |
| 3048 | texture->texCoord[7]=vstart + dv * prim->texcoords.bl.v; |
| 3049 | } |
| 3050 | } |
| 3051 | |
| 3052 | void sdl_info_ogl::texture_mpass_flip(texture_info *texture, int shaderIdx) |
| 3053 | { |
| 3054 | UINT32 mpass_src_idx = texture->mpass_dest_idx; |
| 3055 | |
| 3056 | texture->mpass_dest_idx = (mpass_src_idx+1) % 2; |
| 3057 | |
| 3058 | if ( shaderIdx>0 ) |
| 3059 | { |
| 3060 | int uniform_location; |
| 3061 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture"); |
| 3062 | pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0); |
| 3063 | GL_CHECK_ERROR_NORMAL(); |
| 3064 | } |
| 3065 | |
| 3066 | pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); |
| 3067 | if ( shaderIdx<=m_glsl_program_mb2sc ) |
| 3068 | { |
| 3069 | glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]); |
| 3070 | } |
| 3071 | else |
| 3072 | { |
| 3073 | glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]); |
| 3074 | } |
| 3075 | pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); |
| 3076 | glBindTexture(texture->texTarget, 0); |
| 3077 | |
| 3078 | pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); |
| 3079 | |
| 3080 | if ( shaderIdx<m_glsl_program_num-1 ) |
| 3081 | { |
| 3082 | if ( shaderIdx>=m_glsl_program_mb2sc ) |
| 3083 | { |
| 3084 | glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]); |
| 3085 | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); |
| 3086 | } |
| 3087 | else |
| 3088 | { |
| 3089 | glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]); |
| 3090 | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); |
| 3091 | } |
| 3092 | |
| 3093 | if ( shaderIdx==0 ) |
| 3094 | { |
| 3095 | glPushAttrib(GL_VIEWPORT_BIT); |
| 3096 | GL_CHECK_ERROR_NORMAL(); |
| 3097 | glViewport(0.0, 0.0, (GLsizei)texture->rawwidth, (GLsizei)texture->rawheight); |
| 3098 | } |
| 3099 | else if ( shaderIdx==m_glsl_program_mb2sc ) |
| 3100 | { |
| 3101 | assert ( m_glsl_program_mb2sc < m_glsl_program_num-1 ); |
| 3102 | glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height) |
| 3103 | GL_CHECK_ERROR_NORMAL(); |
| 3104 | } |
| 3105 | glClear(GL_COLOR_BUFFER_BIT); // make sure the whole texture is redrawn .. |
| 3106 | } |
| 3107 | else |
| 3108 | { |
| 3109 | glBindTexture(texture->texTarget, 0); |
| 3110 | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3111 | |
| 3112 | if ( m_glsl_program_mb2sc == m_glsl_program_num-1 ) |
| 3113 | { |
| 3114 | glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height) |
| 3115 | GL_CHECK_ERROR_NORMAL(); |
| 3116 | } |
| 3117 | |
| 3118 | pfn_glActiveTexture(GL_TEXTURE0); |
| 3119 | glBindTexture(texture->texTarget, 0); |
| 3120 | } |
| 3121 | } |
| 3122 | |
| 3123 | void sdl_info_ogl::texture_shader_update(texture_info *texture, render_container *container, int shaderIdx) |
| 3124 | { |
| 3125 | int uniform_location; |
| 3126 | GLfloat vid_attributes[4]; |
| 3127 | |
| 3128 | if (container!=NULL) |
| 3129 | { |
| 3130 | render_container::user_settings settings; |
| 3131 | container->get_user_settings(settings); |
| 3132 | /* FIXME: the code below is in just for illustration issue on |
| 3133 | * how to set shader variables. gamma, contrast and brightness are |
| 3134 | * handled already by the core |
| 3135 | */ |
| 3136 | vid_attributes[0] = settings.m_gamma; |
| 3137 | vid_attributes[1] = settings.m_contrast; |
| 3138 | vid_attributes[2] = settings.m_brightness; |
| 3139 | vid_attributes[3] = 0.0f; |
| 3140 | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes"); |
| 3141 | pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx])); |
| 3142 | if ( GL_CHECK_ERROR_QUIET() ) { |
| 3143 | osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx); |
| 3144 | } |
| 3145 | } |
| 3146 | } |
| 3147 | |
| 3148 | texture_info * sdl_info_ogl::texture_update(const render_primitive *prim, int shaderIdx) |
| 3149 | { |
| 3150 | texture_info *texture = texture_find(prim); |
| 3151 | int texBound = 0; |
| 3152 | |
| 3153 | // if we didn't find one, create a new texture |
| 3154 | if (texture == NULL && prim->texture.base != NULL) |
| 3155 | { |
| 3156 | texture = texture_create(&prim->texture, prim->flags); |
| 3157 | } |
| 3158 | else if (texture != NULL) |
| 3159 | { |
| 3160 | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3161 | { |
| 3162 | pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader |
| 3163 | } |
| 3164 | else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 3165 | { |
| 3166 | assert ( m_usepbo ) ; |
| 3167 | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); |
| 3168 | glEnable(texture->texTarget); |
| 3169 | } |
| 3170 | else |
| 3171 | { |
| 3172 | glEnable(texture->texTarget); |
| 3173 | } |
| 3174 | } |
| 3175 | |
| 3176 | if (texture != NULL) |
| 3177 | { |
| 3178 | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3179 | { |
| 3180 | texture_shader_update(texture, prim->container, shaderIdx); |
| 3181 | if ( m_glsl_program_num>1 ) |
| 3182 | { |
| 3183 | texture_mpass_flip(texture, shaderIdx); |
| 3184 | } |
| 3185 | } |
| 3186 | |
| 3187 | if ( shaderIdx==0 ) // redundant for subsequent multipass shader |
| 3188 | { |
| 3189 | if (prim->texture.base != NULL && texture->texinfo.seqid != prim->texture.seqid) |
| 3190 | { |
| 3191 | texture->texinfo.seqid = prim->texture.seqid; |
| 3192 | |
| 3193 | // if we found it, but with a different seqid, copy the data |
| 3194 | texture_set_data(texture, &prim->texture, prim->flags); |
| 3195 | texBound=1; |
| 3196 | } |
| 3197 | } |
| 3198 | |
| 3199 | if (!texBound) { |
| 3200 | glBindTexture(texture->texTarget, texture->texture); |
| 3201 | } |
| 3202 | texture_coord_update(texture, prim, shaderIdx); |
| 3203 | |
| 3204 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| 3205 | if(m_usevbo) |
| 3206 | { |
| 3207 | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); |
| 3208 | // Load The Data |
| 3209 | pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); |
| 3210 | glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // we are using ARB VBO buffers |
| 3211 | } |
| 3212 | else |
| 3213 | { |
| 3214 | glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord); |
| 3215 | } |
| 3216 | } |
| 3217 | |
| 3218 | return texture; |
| 3219 | } |
| 3220 | |
| 3221 | void sdl_info_ogl::texture_disable(texture_info * texture) |
| 3222 | { |
| 3223 | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3224 | { |
| 3225 | assert ( m_useglsl ); |
| 3226 | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 3227 | } else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 3228 | { |
| 3229 | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 3230 | glDisable(texture->texTarget); |
| 3231 | } else { |
| 3232 | glDisable(texture->texTarget); |
| 3233 | } |
| 3234 | } |
| 3235 | |
| 3236 | void sdl_info_ogl::texture_all_disable() |
| 3237 | { |
| 3238 | if ( m_useglsl ) |
| 3239 | { |
| 3240 | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 3241 | |
| 3242 | pfn_glActiveTexture(GL_TEXTURE3); |
| 3243 | glBindTexture(GL_TEXTURE_2D, 0); |
| 3244 | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3245 | pfn_glActiveTexture(GL_TEXTURE2); |
| 3246 | glBindTexture(GL_TEXTURE_2D, 0); |
| 3247 | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3248 | pfn_glActiveTexture(GL_TEXTURE1); |
| 3249 | glBindTexture(GL_TEXTURE_2D, 0); |
| 3250 | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3251 | pfn_glActiveTexture(GL_TEXTURE0); |
| 3252 | glBindTexture(GL_TEXTURE_2D, 0); |
| 3253 | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3254 | } |
| 3255 | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); |
| 3256 | |
| 3257 | if(m_usetexturerect) |
| 3258 | { |
| 3259 | glDisable(GL_TEXTURE_RECTANGLE_ARB); |
| 3260 | } |
| 3261 | glDisable(GL_TEXTURE_2D); |
| 3262 | |
| 3263 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| 3264 | if(m_usevbo) |
| 3265 | { |
| 3266 | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. |
| 3267 | } |
| 3268 | if ( m_usepbo ) |
| 3269 | { |
| 3270 | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 3271 | } |
| 3272 | } |
trunk/src/osd/sdl/draw13.c
| r244651 | r244652 | |
| 1 | | //============================================================ |
| 2 | | // |
| 3 | | // draw13.c - SDL 2.0 drawing implementation |
| 4 | | // |
| 5 | | // Copyright (c) 1996-2014, Nicola Salmoria and the MAME Team. |
| 6 | | // Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | | // |
| 8 | | // SDLMAME by Olivier Galibert and R. Belmont |
| 9 | | // |
| 10 | | //============================================================ |
| 11 | | |
| 12 | | // standard C headers |
| 13 | | #include <math.h> |
| 14 | | #include <stdio.h> |
| 15 | | |
| 16 | | // MAME headers |
| 17 | | #include "emu.h" |
| 18 | | #include "options.h" |
| 19 | | |
| 20 | | // standard SDL headers |
| 21 | | #include "sdlinc.h" |
| 22 | | |
| 23 | | // OSD headers |
| 24 | | #include "osdsdl.h" |
| 25 | | #include "window.h" |
| 26 | | |
| 27 | | |
| 28 | | //============================================================ |
| 29 | | // DEBUGGING |
| 30 | | //============================================================ |
| 31 | | |
| 32 | | //============================================================ |
| 33 | | // CONSTANTS |
| 34 | | //============================================================ |
| 35 | | |
| 36 | | #define STAT_PIXEL_THRESHOLD (150*150) |
| 37 | | |
| 38 | | enum |
| 39 | | { |
| 40 | | TEXTURE_TYPE_NONE, |
| 41 | | TEXTURE_TYPE_PLAIN, |
| 42 | | TEXTURE_TYPE_SURFACE |
| 43 | | }; |
| 44 | | |
| 45 | | |
| 46 | | //============================================================ |
| 47 | | // Inline functions |
| 48 | | //============================================================ |
| 49 | | |
| 50 | | static inline bool is_opaque(const float &a) |
| 51 | | { |
| 52 | | return (a >= 1.0f); |
| 53 | | } |
| 54 | | |
| 55 | | static inline bool is_transparent(const float &a) |
| 56 | | { |
| 57 | | return (a < 0.0001f); |
| 58 | | } |
| 59 | | |
| 60 | | //============================================================ |
| 61 | | // TYPES |
| 62 | | //============================================================ |
| 63 | | |
| 64 | | |
| 65 | | struct quad_setup_data |
| 66 | | { |
| 67 | | quad_setup_data() |
| 68 | | : dudx(0), dvdx(0), dudy(0), dvdy(0), startu(0), startv(0), |
| 69 | | rotwidth(0), rotheight(0) |
| 70 | | {} |
| 71 | | void compute(const render_primitive &prim, const int prescale); |
| 72 | | |
| 73 | | INT32 dudx, dvdx, dudy, dvdy; |
| 74 | | INT32 startu, startv; |
| 75 | | INT32 rotwidth, rotheight; |
| 76 | | }; |
| 77 | | |
| 78 | | //============================================================ |
| 79 | | // Textures |
| 80 | | //============================================================ |
| 81 | | |
| 82 | | class sdl_info13; |
| 83 | | struct copy_info_t; |
| 84 | | |
| 85 | | /* texture_info holds information about a texture */ |
| 86 | | class texture_info |
| 87 | | { |
| 88 | | friend class simple_list<texture_info>; |
| 89 | | public: |
| 90 | | texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const UINT32 flags); |
| 91 | | ~texture_info(); |
| 92 | | |
| 93 | | void set_data(const render_texinfo &texsource, const UINT32 flags); |
| 94 | | void render_quad(const render_primitive *prim, const int x, const int y); |
| 95 | | bool matches(const render_primitive &prim, const quad_setup_data &setup); |
| 96 | | |
| 97 | | copy_info_t *compute_size_type(); |
| 98 | | |
| 99 | | void *m_pixels; // pixels for the texture |
| 100 | | int m_pitch; |
| 101 | | |
| 102 | | copy_info_t *m_copyinfo; |
| 103 | | quad_setup_data m_setup; |
| 104 | | |
| 105 | | osd_ticks_t m_last_access; |
| 106 | | |
| 107 | | int raw_width() const { return m_texinfo.width; } |
| 108 | | int raw_height() const { return m_texinfo.height; } |
| 109 | | |
| 110 | | texture_info *next() { return m_next; } |
| 111 | | const render_texinfo &texinfo() const { return m_texinfo; } |
| 112 | | render_texinfo &texinfo() { return m_texinfo; } |
| 113 | | |
| 114 | | const HashT hash() const { return m_hash; } |
| 115 | | const UINT32 flags() const { return m_flags; } |
| 116 | | // FIXME: |
| 117 | | const bool is_pixels_owned() const; |
| 118 | | |
| 119 | | private: |
| 120 | | Uint32 m_sdl_access; |
| 121 | | SDL_Renderer * m_sdl_renderer; |
| 122 | | render_texinfo m_texinfo; // copy of the texture info |
| 123 | | HashT m_hash; // hash value for the texture (must be >= pointer size) |
| 124 | | UINT32 m_flags; // rendering flags |
| 125 | | |
| 126 | | SDL_Texture * m_texture_id; |
| 127 | | bool m_is_rotated; |
| 128 | | |
| 129 | | int m_format; // texture format |
| 130 | | SDL_BlendMode m_sdl_blendmode; |
| 131 | | |
| 132 | | texture_info * m_next; // next texture in the list |
| 133 | | }; |
| 134 | | |
| 135 | | //============================================================ |
| 136 | | // TEXCOPY FUNCS |
| 137 | | //============================================================ |
| 138 | | |
| 139 | | #include "blit13.h" |
| 140 | | |
| 141 | | /* sdl_info is the information about SDL for the current screen */ |
| 142 | | class sdl_info13 : public osd_renderer |
| 143 | | { |
| 144 | | public: |
| 145 | | sdl_info13(osd_window *w) |
| 146 | | : osd_renderer(w, FLAG_NONE), m_blittimer(0), m_sdl_renderer(NULL), |
| 147 | | m_last_hofs(0), m_last_vofs(0), |
| 148 | | m_width(0), m_height(0), |
| 149 | | m_blit_dim(0,0), |
| 150 | | m_last_blit_time(0), m_last_blit_pixels(0) |
| 151 | | {} |
| 152 | | |
| 153 | | /* virtual */ int create(); |
| 154 | | /* virtual */ int draw(const int update); |
| 155 | | /* virtual */ int xy_to_render_target(const int x, const int y, int *xt, int *yt); |
| 156 | | /* virtual */ void destroy(); |
| 157 | | /* virtual */ render_primitive_list *get_primitives() |
| 158 | | { |
| 159 | | osd_dim nd = window().blit_surface_size(); |
| 160 | | if (nd != m_blit_dim) |
| 161 | | { |
| 162 | | m_blit_dim = nd; |
| 163 | | notify_changed(); |
| 164 | | } |
| 165 | | window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); |
| 166 | | return &window().target()->get_primitives(); |
| 167 | | } |
| 168 | | |
| 169 | | private: |
| 170 | | void render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y); |
| 171 | | |
| 172 | | texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); |
| 173 | | texture_info *texture_update(const render_primitive &prim); |
| 174 | | |
| 175 | | void destroy_all_textures(); |
| 176 | | |
| 177 | | INT32 m_blittimer; |
| 178 | | |
| 179 | | #if (SDLMAME_SDL2) |
| 180 | | //SDL_GLContext m_gl_context_id; |
| 181 | | #else |
| 182 | | // SDL surface |
| 183 | | SDL_Surface *m_sdlsurf; |
| 184 | | #endif |
| 185 | | |
| 186 | | SDL_Renderer * m_sdl_renderer; |
| 187 | | simple_list<texture_info> m_texlist; // list of active textures |
| 188 | | |
| 189 | | float m_last_hofs; |
| 190 | | float m_last_vofs; |
| 191 | | |
| 192 | | int m_width; |
| 193 | | int m_height; |
| 194 | | |
| 195 | | osd_dim m_blit_dim; |
| 196 | | |
| 197 | | // Stats |
| 198 | | INT64 m_last_blit_time; |
| 199 | | INT64 m_last_blit_pixels; |
| 200 | | }; |
| 201 | | |
| 202 | | struct copy_info_t { |
| 203 | | int src_fmt; |
| 204 | | Uint32 dst_fmt; |
| 205 | | const blit_base *blitter; |
| 206 | | Uint32 bm_mask; |
| 207 | | const char *srcname; |
| 208 | | const char *dstname; |
| 209 | | /* Statistics */ |
| 210 | | UINT64 pixel_count; |
| 211 | | INT64 time; |
| 212 | | int samples; |
| 213 | | int perf; |
| 214 | | /* list */ |
| 215 | | copy_info_t *next; |
| 216 | | }; |
| 217 | | |
| 218 | | |
| 219 | | //============================================================ |
| 220 | | // PROTOTYPES |
| 221 | | //============================================================ |
| 222 | | |
| 223 | | // core functions |
| 224 | | |
| 225 | | static void drawsdl2_exit(void); |
| 226 | | |
| 227 | | //============================================================ |
| 228 | | // STATIC VARIABLES |
| 229 | | //============================================================ |
| 230 | | |
| 231 | | #define SDL_TEXFORMAT_LAST SDL_TEXFORMAT_PALETTE16A |
| 232 | | #define BM_ALL (-1) |
| 233 | | //( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD) |
| 234 | | |
| 235 | | #define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} |
| 236 | | #define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} |
| 237 | | #define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} |
| 238 | | |
| 239 | | static copy_info_t blit_info_default[] = |
| 240 | | { |
| 241 | | /* no rotation */ |
| 242 | | ENTRY(ARGB32, ARGB8888, argb32_argb32), |
| 243 | | ENTRY_LR(ARGB32, RGB888, argb32_rgb32), |
| 244 | | /* Entry primarily for directfb */ |
| 245 | | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), |
| 246 | | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), |
| 247 | | ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), |
| 248 | | |
| 249 | | ENTRY(RGB32, ARGB8888, rgb32_argb32), |
| 250 | | ENTRY(RGB32, RGB888, rgb32_rgb32), |
| 251 | | |
| 252 | | ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), |
| 253 | | ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), |
| 254 | | |
| 255 | | ENTRY(YUY16, UYVY, yuv16_uyvy), |
| 256 | | ENTRY(YUY16, YUY2, yuv16_yuy2), |
| 257 | | ENTRY(YUY16, YVYU, yuv16_yvyu), |
| 258 | | ENTRY(YUY16, ARGB8888, yuv16_argb32), |
| 259 | | ENTRY(YUY16, RGB888, yuv16_argb32), |
| 260 | | |
| 261 | | ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), |
| 262 | | ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), |
| 263 | | ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), |
| 264 | | ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), |
| 265 | | ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), |
| 266 | | |
| 267 | | ENTRY(PALETTE16, ARGB8888, pal16_argb32), |
| 268 | | ENTRY(PALETTE16, RGB888, pal16_argb32), |
| 269 | | |
| 270 | | ENTRY(RGB15, RGB555, rgb15_rgb555), |
| 271 | | ENTRY(RGB15, ARGB1555, rgb15_argb1555), |
| 272 | | ENTRY(RGB15, ARGB8888, rgb15_argb32), |
| 273 | | ENTRY(RGB15, RGB888, rgb15_argb32), |
| 274 | | |
| 275 | | ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), |
| 276 | | ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), |
| 277 | | |
| 278 | | ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), |
| 279 | | ENTRY(PALETTE16A, RGB888, pal16a_rgb32), |
| 280 | | |
| 281 | | /* rotation */ |
| 282 | | ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), |
| 283 | | ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), |
| 284 | | /* Entry primarily for directfb */ |
| 285 | | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), |
| 286 | | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), |
| 287 | | ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), |
| 288 | | |
| 289 | | ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), |
| 290 | | ENTRY(RGB32, RGB888, rot_argb32_argb32), |
| 291 | | |
| 292 | | ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), |
| 293 | | ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), |
| 294 | | |
| 295 | | ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), |
| 296 | | ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), |
| 297 | | |
| 298 | | ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), |
| 299 | | ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), |
| 300 | | |
| 301 | | ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), |
| 302 | | ENTRY(PALETTE16, RGB888, rot_pal16_argb32), |
| 303 | | |
| 304 | | ENTRY(RGB15, RGB555, rot_rgb15_argb1555), |
| 305 | | ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), |
| 306 | | ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), |
| 307 | | ENTRY(RGB15, RGB888, rot_rgb15_argb32), |
| 308 | | |
| 309 | | ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), |
| 310 | | ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), |
| 311 | | |
| 312 | | ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), |
| 313 | | ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), |
| 314 | | |
| 315 | | { -1 }, |
| 316 | | }; |
| 317 | | |
| 318 | | static copy_info_t *blit_info[SDL_TEXFORMAT_LAST+1]; |
| 319 | | |
| 320 | | static struct |
| 321 | | { |
| 322 | | Uint32 format; |
| 323 | | int status; |
| 324 | | } fmt_support[30] = { { 0, 0 } }; |
| 325 | | |
| 326 | | |
| 327 | | //============================================================ |
| 328 | | // INLINES |
| 329 | | //============================================================ |
| 330 | | |
| 331 | | |
| 332 | | INLINE float round_nearest(float f) |
| 333 | | { |
| 334 | | return floor(f + 0.5f); |
| 335 | | } |
| 336 | | |
| 337 | | INLINE HashT texture_compute_hash(const render_texinfo &texture, const UINT32 flags) |
| 338 | | { |
| 339 | | return (HashT)texture.base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 340 | | } |
| 341 | | |
| 342 | | INLINE SDL_BlendMode map_blendmode(const int blendmode) |
| 343 | | { |
| 344 | | switch (blendmode) |
| 345 | | { |
| 346 | | case BLENDMODE_NONE: |
| 347 | | return SDL_BLENDMODE_NONE; |
| 348 | | case BLENDMODE_ALPHA: |
| 349 | | return SDL_BLENDMODE_BLEND; |
| 350 | | case BLENDMODE_RGB_MULTIPLY: |
| 351 | | return SDL_BLENDMODE_MOD; |
| 352 | | case BLENDMODE_ADD: |
| 353 | | return SDL_BLENDMODE_ADD; |
| 354 | | default: |
| 355 | | osd_printf_warning("Unknown Blendmode %d", blendmode); |
| 356 | | } |
| 357 | | return SDL_BLENDMODE_NONE; |
| 358 | | } |
| 359 | | |
| 360 | | INLINE void set_coloralphamode(SDL_Texture *texture_id, const render_color *color) |
| 361 | | { |
| 362 | | UINT32 sr = (UINT32)(255.0f * color->r); |
| 363 | | UINT32 sg = (UINT32)(255.0f * color->g); |
| 364 | | UINT32 sb = (UINT32)(255.0f * color->b); |
| 365 | | UINT32 sa = (UINT32)(255.0f * color->a); |
| 366 | | |
| 367 | | |
| 368 | | if (color->r >= 1.0f && color->g >= 1.0f && color->b >= 1.0f && is_opaque(color->a)) |
| 369 | | { |
| 370 | | SDL_SetTextureColorMod(texture_id, 0xFF, 0xFF, 0xFF); |
| 371 | | SDL_SetTextureAlphaMod(texture_id, 0xFF); |
| 372 | | } |
| 373 | | /* coloring-only case */ |
| 374 | | else if (is_opaque(color->a)) |
| 375 | | { |
| 376 | | SDL_SetTextureColorMod(texture_id, sr, sg, sb); |
| 377 | | SDL_SetTextureAlphaMod(texture_id, 0xFF); |
| 378 | | } |
| 379 | | /* alpha and/or coloring case */ |
| 380 | | else if (!is_transparent(color->a)) |
| 381 | | { |
| 382 | | SDL_SetTextureColorMod(texture_id, sr, sg, sb); |
| 383 | | SDL_SetTextureAlphaMod(texture_id, sa); |
| 384 | | } |
| 385 | | else |
| 386 | | { |
| 387 | | SDL_SetTextureColorMod(texture_id, 0xFF, 0xFF, 0xFF); |
| 388 | | SDL_SetTextureAlphaMod(texture_id, 0x00); |
| 389 | | } |
| 390 | | } |
| 391 | | |
| 392 | | void texture_info::render_quad(const render_primitive *prim, const int x, const int y) |
| 393 | | { |
| 394 | | SDL_Rect target_rect; |
| 395 | | |
| 396 | | target_rect.x = x; |
| 397 | | target_rect.y = y; |
| 398 | | target_rect.w = round_nearest(prim->bounds.x1 - prim->bounds.x0); |
| 399 | | target_rect.h = round_nearest(prim->bounds.y1 - prim->bounds.y0); |
| 400 | | |
| 401 | | SDL_SetTextureBlendMode(m_texture_id, m_sdl_blendmode); |
| 402 | | set_coloralphamode(m_texture_id, &prim->color); |
| 403 | | SDL_RenderCopy(m_sdl_renderer, m_texture_id, NULL, &target_rect); |
| 404 | | } |
| 405 | | |
| 406 | | void sdl_info13::render_quad(texture_info *texture, const render_primitive *prim, const int x, const int y) |
| 407 | | { |
| 408 | | SDL_Rect target_rect; |
| 409 | | |
| 410 | | target_rect.x = x; |
| 411 | | target_rect.y = y; |
| 412 | | target_rect.w = round_nearest(prim->bounds.x1 - prim->bounds.x0); |
| 413 | | target_rect.h = round_nearest(prim->bounds.y1 - prim->bounds.y0); |
| 414 | | |
| 415 | | if (texture) |
| 416 | | { |
| 417 | | copy_info_t *copyinfo = texture->m_copyinfo; |
| 418 | | copyinfo->time -= osd_ticks(); |
| 419 | | texture->render_quad(prim, x, y); |
| 420 | | copyinfo->time += osd_ticks(); |
| 421 | | |
| 422 | | copyinfo->pixel_count += MAX(STAT_PIXEL_THRESHOLD , (texture->raw_width() * texture->raw_height())); |
| 423 | | if (m_last_blit_pixels) |
| 424 | | { |
| 425 | | copyinfo->time += (m_last_blit_time * (INT64) (texture->raw_width() * texture->raw_height())) / (INT64) m_last_blit_pixels; |
| 426 | | } |
| 427 | | copyinfo->samples++; |
| 428 | | copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time; |
| 429 | | } |
| 430 | | else |
| 431 | | { |
| 432 | | UINT32 sr = (UINT32)(255.0f * prim->color.r); |
| 433 | | UINT32 sg = (UINT32)(255.0f * prim->color.g); |
| 434 | | UINT32 sb = (UINT32)(255.0f * prim->color.b); |
| 435 | | UINT32 sa = (UINT32)(255.0f * prim->color.a); |
| 436 | | |
| 437 | | SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
| 438 | | SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa); |
| 439 | | SDL_RenderFillRect(m_sdl_renderer, &target_rect); |
| 440 | | } |
| 441 | | } |
| 442 | | |
| 443 | | static int RendererSupportsFormat(SDL_Renderer *renderer, Uint32 format, Uint32 access, const char *sformat) |
| 444 | | { |
| 445 | | int i; |
| 446 | | SDL_Texture *texid; |
| 447 | | for (i=0; fmt_support[i].format != 0; i++) |
| 448 | | { |
| 449 | | if (format == fmt_support[i].format) |
| 450 | | { |
| 451 | | return fmt_support[i].status; |
| 452 | | } |
| 453 | | } |
| 454 | | /* not tested yet */ |
| 455 | | fmt_support[i].format = format; |
| 456 | | fmt_support[i + 1].format = 0; |
| 457 | | texid = SDL_CreateTexture(renderer, format, access, 16, 16); |
| 458 | | if (texid) |
| 459 | | { |
| 460 | | fmt_support[i].status = 1; |
| 461 | | SDL_DestroyTexture(texid); |
| 462 | | return 1; |
| 463 | | } |
| 464 | | osd_printf_verbose("Pixelformat <%s> error %s \n", sformat, SDL_GetError()); |
| 465 | | osd_printf_verbose("Pixelformat <%s> not supported\n", sformat); |
| 466 | | fmt_support[i].status = 0; |
| 467 | | return 0; |
| 468 | | } |
| 469 | | |
| 470 | | //============================================================ |
| 471 | | // drawsdl_init |
| 472 | | //============================================================ |
| 473 | | |
| 474 | | static void add_list(copy_info_t **head, copy_info_t *element, Uint32 bm) |
| 475 | | { |
| 476 | | copy_info_t *newci = global_alloc(copy_info_t); |
| 477 | | *newci = *element; |
| 478 | | |
| 479 | | newci->bm_mask = bm; |
| 480 | | newci->next = *head; |
| 481 | | *head = newci; |
| 482 | | } |
| 483 | | |
| 484 | | static void expand_copy_info(copy_info_t *list) |
| 485 | | { |
| 486 | | copy_info_t *bi; |
| 487 | | |
| 488 | | for (bi = list; bi->src_fmt != -1; bi++) |
| 489 | | { |
| 490 | | if (bi->bm_mask == BM_ALL) |
| 491 | | { |
| 492 | | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE); |
| 493 | | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD); |
| 494 | | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD); |
| 495 | | add_list(&blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND); |
| 496 | | } |
| 497 | | else |
| 498 | | add_list(&blit_info[bi->src_fmt], bi, bi->bm_mask); |
| 499 | | } |
| 500 | | } |
| 501 | | |
| 502 | | static osd_renderer *drawsdl2_create(osd_window *window) |
| 503 | | { |
| 504 | | return global_alloc(sdl_info13(window)); |
| 505 | | } |
| 506 | | |
| 507 | | // FIXME: machine only used to access options. |
| 508 | | int drawsdl2_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 509 | | { |
| 510 | | const char *stemp; |
| 511 | | |
| 512 | | // fill in the callbacks |
| 513 | | callbacks->exit = drawsdl2_exit; |
| 514 | | callbacks->create = drawsdl2_create; |
| 515 | | |
| 516 | | osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); |
| 517 | | |
| 518 | | expand_copy_info(blit_info_default); |
| 519 | | |
| 520 | | #if USE_OPENGL |
| 521 | | // Load the GL library now - else MT will fail |
| 522 | | stemp = downcast<sdl_options &>(machine.options()).gl_lib(); |
| 523 | | #else |
| 524 | | stemp = NULL; |
| 525 | | #endif |
| 526 | | if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) == 0) |
| 527 | | stemp = NULL; |
| 528 | | |
| 529 | | // No fatalerror here since not all video drivers support GL ! |
| 530 | | if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==NULL |
| 531 | | osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); |
| 532 | | else |
| 533 | | osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); |
| 534 | | |
| 535 | | return 0; |
| 536 | | } |
| 537 | | |
| 538 | | |
| 539 | | //============================================================ |
| 540 | | // drawsdl_exit |
| 541 | | //============================================================ |
| 542 | | |
| 543 | | static void drawsdl2_exit(void) |
| 544 | | { |
| 545 | | int i; |
| 546 | | copy_info_t *bi, *freeme; |
| 547 | | for (i = 0; i <= SDL_TEXFORMAT_LAST; i++) |
| 548 | | for (bi = blit_info[i]; bi != NULL; ) |
| 549 | | { |
| 550 | | if (bi->pixel_count) |
| 551 | | osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname, |
| 552 | | bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples, |
| 553 | | (int) bi->perf); |
| 554 | | freeme = bi; |
| 555 | | bi = bi->next; |
| 556 | | global_free(freeme); |
| 557 | | } |
| 558 | | } |
| 559 | | |
| 560 | | //============================================================ |
| 561 | | // sdl_info::create |
| 562 | | // a |
| 563 | | // a |
| 564 | | // a |
| 565 | | // a |
| 566 | | // a |
| 567 | | // a |
| 568 | | // a |
| 569 | | // a |
| 570 | | // a |
| 571 | | // a |
| 572 | | // a |
| 573 | | // a |
| 574 | | // a |
| 575 | | // a |
| 576 | | // a |
| 577 | | // a |
| 578 | | // a |
| 579 | | // a |
| 580 | | // a |
| 581 | | // a |
| 582 | | // a |
| 583 | | // a |
| 584 | | // a |
| 585 | | // a |
| 586 | | // a |
| 587 | | // a |
| 588 | | //============================================================ |
| 589 | | |
| 590 | | int sdl_info13::create() |
| 591 | | { |
| 592 | | #if (SDLMAME_SDL2) |
| 593 | | // create renderer |
| 594 | | |
| 595 | | /* Enable bilinear filtering in case it is supported. |
| 596 | | * This applies to all texture operations. However, artwort is pre-scaled |
| 597 | | * and thus shouldn't be affected. |
| 598 | | */ |
| 599 | | if (video_config.filter) |
| 600 | | { |
| 601 | | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); |
| 602 | | } |
| 603 | | else |
| 604 | | { |
| 605 | | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); |
| 606 | | } |
| 607 | | |
| 608 | | if (video_config.waitvsync) |
| 609 | | m_sdl_renderer = SDL_CreateRenderer(window().sdl_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); |
| 610 | | else |
| 611 | | m_sdl_renderer = SDL_CreateRenderer(window().sdl_window(), -1, SDL_RENDERER_ACCELERATED); |
| 612 | | |
| 613 | | if (!m_sdl_renderer) |
| 614 | | { |
| 615 | | fatalerror("Error on creating renderer: %s\n", SDL_GetError()); |
| 616 | | } |
| 617 | | |
| 618 | | //SDL_SelectRenderer(window().sdl_window); |
| 619 | | |
| 620 | | m_blittimer = 3; |
| 621 | | |
| 622 | | SDL_RenderPresent(m_sdl_renderer); |
| 623 | | osd_printf_verbose("Leave sdl_info13::create\n"); |
| 624 | | |
| 625 | | #else |
| 626 | | |
| 627 | | #endif |
| 628 | | return 0; |
| 629 | | } |
| 630 | | |
| 631 | | |
| 632 | | //============================================================ |
| 633 | | // sdl_info::destroy |
| 634 | | //============================================================ |
| 635 | | |
| 636 | | void sdl_info13::destroy() |
| 637 | | { |
| 638 | | destroy_all_textures(); |
| 639 | | } |
| 640 | | |
| 641 | | |
| 642 | | //============================================================ |
| 643 | | // drawsdl_xy_to_render_target |
| 644 | | //============================================================ |
| 645 | | |
| 646 | | int sdl_info13::xy_to_render_target(int x, int y, int *xt, int *yt) |
| 647 | | { |
| 648 | | *xt = x - m_last_hofs; |
| 649 | | *yt = y - m_last_vofs; |
| 650 | | if (*xt<0 || *xt >= m_blit_dim.width()) |
| 651 | | return 0; |
| 652 | | if (*yt<0 || *yt >= m_blit_dim.height()) |
| 653 | | return 0; |
| 654 | | return 1; |
| 655 | | } |
| 656 | | |
| 657 | | //============================================================ |
| 658 | | // drawsdl_destroy_all_textures |
| 659 | | //============================================================ |
| 660 | | |
| 661 | | void sdl_info13::destroy_all_textures() |
| 662 | | { |
| 663 | | if(window().m_primlist) |
| 664 | | { |
| 665 | | window().m_primlist->acquire_lock(); |
| 666 | | m_texlist.reset(); |
| 667 | | window().m_primlist->release_lock(); |
| 668 | | } |
| 669 | | else |
| 670 | | m_texlist.reset(); |
| 671 | | } |
| 672 | | |
| 673 | | //============================================================ |
| 674 | | // sdl_info::draw |
| 675 | | //============================================================ |
| 676 | | |
| 677 | | int sdl_info13::draw(int update) |
| 678 | | { |
| 679 | | render_primitive *prim; |
| 680 | | texture_info *texture=NULL; |
| 681 | | float vofs, hofs; |
| 682 | | int blit_pixels = 0; |
| 683 | | |
| 684 | | if (video_config.novideo) |
| 685 | | { |
| 686 | | return 0; |
| 687 | | } |
| 688 | | |
| 689 | | osd_dim wdim = window().get_size(); |
| 690 | | |
| 691 | | if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) |
| 692 | | { |
| 693 | | destroy_all_textures(); |
| 694 | | m_width = wdim.width(); |
| 695 | | m_height = wdim.height(); |
| 696 | | SDL_RenderSetViewport(m_sdl_renderer, NULL); |
| 697 | | m_blittimer = 3; |
| 698 | | clear_flags(FI_CHANGED); |
| 699 | | } |
| 700 | | |
| 701 | | //SDL_SelectRenderer(window().sdl_window); |
| 702 | | |
| 703 | | if (m_blittimer > 0) |
| 704 | | { |
| 705 | | /* SDL Underlays need alpha = 0 ! */ |
| 706 | | SDL_SetRenderDrawBlendMode(m_sdl_renderer, SDL_BLENDMODE_NONE); |
| 707 | | //SDL_SetRenderDrawColor(0,0,0,255); |
| 708 | | SDL_SetRenderDrawColor(m_sdl_renderer, 0,0,0,0); |
| 709 | | SDL_RenderFillRect(m_sdl_renderer, NULL); |
| 710 | | m_blittimer--; |
| 711 | | } |
| 712 | | |
| 713 | | // compute centering parameters |
| 714 | | vofs = hofs = 0.0f; |
| 715 | | |
| 716 | | if (video_config.centerv || video_config.centerh) |
| 717 | | { |
| 718 | | int ch, cw; |
| 719 | | |
| 720 | | ch = wdim.height(); |
| 721 | | cw = wdim.width(); |
| 722 | | |
| 723 | | if (video_config.centerv) |
| 724 | | { |
| 725 | | vofs = (ch - m_blit_dim.height()) / 2.0f; |
| 726 | | } |
| 727 | | if (video_config.centerh) |
| 728 | | { |
| 729 | | hofs = (cw - m_blit_dim.width()) / 2.0f; |
| 730 | | } |
| 731 | | } |
| 732 | | |
| 733 | | m_last_hofs = hofs; |
| 734 | | m_last_vofs = vofs; |
| 735 | | |
| 736 | | window().m_primlist->acquire_lock(); |
| 737 | | |
| 738 | | // now draw |
| 739 | | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 740 | | { |
| 741 | | Uint8 sr, sg, sb, sa; |
| 742 | | |
| 743 | | switch (prim->type) |
| 744 | | { |
| 745 | | case render_primitive::LINE: |
| 746 | | sr = (int)(255.0f * prim->color.r); |
| 747 | | sg = (int)(255.0f * prim->color.g); |
| 748 | | sb = (int)(255.0f * prim->color.b); |
| 749 | | sa = (int)(255.0f * prim->color.a); |
| 750 | | |
| 751 | | SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
| 752 | | SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa); |
| 753 | | SDL_RenderDrawLine(m_sdl_renderer, prim->bounds.x0 + hofs, prim->bounds.y0 + vofs, |
| 754 | | prim->bounds.x1 + hofs, prim->bounds.y1 + vofs); |
| 755 | | break; |
| 756 | | case render_primitive::QUAD: |
| 757 | | texture = texture_update(*prim); |
| 758 | | if (texture) |
| 759 | | blit_pixels += (texture->raw_height() * texture->raw_width()); |
| 760 | | render_quad(texture, prim, |
| 761 | | round_nearest(hofs + prim->bounds.x0), |
| 762 | | round_nearest(vofs + prim->bounds.y0)); |
| 763 | | break; |
| 764 | | default: |
| 765 | | throw emu_fatalerror("Unexpected render_primitive type\n"); |
| 766 | | } |
| 767 | | } |
| 768 | | |
| 769 | | window().m_primlist->release_lock(); |
| 770 | | |
| 771 | | m_last_blit_pixels = blit_pixels; |
| 772 | | m_last_blit_time = -osd_ticks(); |
| 773 | | SDL_RenderPresent(m_sdl_renderer); |
| 774 | | m_last_blit_time += osd_ticks(); |
| 775 | | |
| 776 | | return 0; |
| 777 | | } |
| 778 | | |
| 779 | | |
| 780 | | //============================================================ |
| 781 | | // texture handling |
| 782 | | //============================================================ |
| 783 | | |
| 784 | | //============================================================ |
| 785 | | // texture_compute_size and type |
| 786 | | //============================================================ |
| 787 | | |
| 788 | | copy_info_t *texture_info::compute_size_type() |
| 789 | | { |
| 790 | | copy_info_t *bi; |
| 791 | | copy_info_t *result = NULL; |
| 792 | | int maxperf = 0; |
| 793 | | |
| 794 | | for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) |
| 795 | | { |
| 796 | | if ((m_is_rotated == bi->blitter->m_is_rot) |
| 797 | | && (m_sdl_blendmode == bi->bm_mask)) |
| 798 | | { |
| 799 | | if (RendererSupportsFormat(m_sdl_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) |
| 800 | | { |
| 801 | | int perf = bi->perf; |
| 802 | | if (perf == 0) |
| 803 | | return bi; |
| 804 | | else if (perf > (maxperf * 102) / 100) |
| 805 | | { |
| 806 | | result = bi; |
| 807 | | maxperf = perf; |
| 808 | | } |
| 809 | | } |
| 810 | | } |
| 811 | | } |
| 812 | | if (result) |
| 813 | | return result; |
| 814 | | /* try last resort handlers */ |
| 815 | | for (bi = blit_info[m_format]; bi != NULL; bi = bi->next) |
| 816 | | { |
| 817 | | if ((m_is_rotated == bi->blitter->m_is_rot) |
| 818 | | && (m_sdl_blendmode == bi->bm_mask)) |
| 819 | | if (RendererSupportsFormat(m_sdl_renderer, bi->dst_fmt, m_sdl_access, bi->dstname)) |
| 820 | | return bi; |
| 821 | | } |
| 822 | | //FIXME: crash implement a -do nothing handler */ |
| 823 | | return NULL; |
| 824 | | } |
| 825 | | |
| 826 | | // FIXME: |
| 827 | | const bool texture_info::is_pixels_owned() const |
| 828 | | { // do we own / allocated it ? |
| 829 | | return ((m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 830 | | && (m_copyinfo->blitter->m_is_passthrough)); |
| 831 | | } |
| 832 | | |
| 833 | | //============================================================ |
| 834 | | // texture_info::matches |
| 835 | | //============================================================ |
| 836 | | |
| 837 | | bool texture_info::matches(const render_primitive &prim, const quad_setup_data &setup) |
| 838 | | { |
| 839 | | return texinfo().base == prim.texture.base && |
| 840 | | texinfo().width == prim.texture.width && |
| 841 | | texinfo().height == prim.texture.height && |
| 842 | | texinfo().rowpixels == prim.texture.rowpixels && |
| 843 | | m_setup.dudx == setup.dudx && |
| 844 | | m_setup.dvdx == setup.dvdx && |
| 845 | | m_setup.dudy == setup.dudy && |
| 846 | | m_setup.dvdy == setup.dvdy && |
| 847 | | ((flags() ^ prim.flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0; |
| 848 | | } |
| 849 | | |
| 850 | | //============================================================ |
| 851 | | // texture_create |
| 852 | | //============================================================ |
| 853 | | |
| 854 | | texture_info::texture_info(SDL_Renderer *renderer, const render_texinfo &texsource, const quad_setup_data &setup, UINT32 flags) |
| 855 | | { |
| 856 | | // fill in the core data |
| 857 | | m_sdl_renderer = renderer; |
| 858 | | m_hash = texture_compute_hash(texsource, flags); |
| 859 | | m_flags = flags; |
| 860 | | m_texinfo = texsource; |
| 861 | | m_texinfo.seqid = -1; // force set data |
| 862 | | m_is_rotated = false; |
| 863 | | m_setup = setup; |
| 864 | | m_sdl_blendmode = map_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); |
| 865 | | m_pitch = 0; |
| 866 | | |
| 867 | | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 868 | | { |
| 869 | | case TEXFORMAT_ARGB32: |
| 870 | | m_format = SDL_TEXFORMAT_ARGB32; |
| 871 | | break; |
| 872 | | case TEXFORMAT_RGB32: |
| 873 | | m_format = texsource.palette ? SDL_TEXFORMAT_RGB32_PALETTED : SDL_TEXFORMAT_RGB32; |
| 874 | | break; |
| 875 | | case TEXFORMAT_PALETTE16: |
| 876 | | m_format = SDL_TEXFORMAT_PALETTE16; |
| 877 | | break; |
| 878 | | case TEXFORMAT_PALETTEA16: |
| 879 | | m_format = SDL_TEXFORMAT_PALETTE16A; |
| 880 | | break; |
| 881 | | case TEXFORMAT_YUY16: |
| 882 | | m_format = texsource.palette ? SDL_TEXFORMAT_YUY16_PALETTED : SDL_TEXFORMAT_YUY16; |
| 883 | | break; |
| 884 | | |
| 885 | | default: |
| 886 | | osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags)); |
| 887 | | } |
| 888 | | |
| 889 | | if (setup.rotwidth != m_texinfo.width || setup.rotheight != m_texinfo.height |
| 890 | | || setup.dudx < 0 || setup.dvdy < 0) |
| 891 | | m_is_rotated = true; |
| 892 | | else |
| 893 | | m_is_rotated = false; |
| 894 | | |
| 895 | | //m_sdl_access = SDL_TEXTUREACCESS_STATIC; |
| 896 | | m_sdl_access = SDL_TEXTUREACCESS_STREAMING; |
| 897 | | |
| 898 | | // Watch out for 0x0 textures ... |
| 899 | | if (!m_setup.rotwidth || !m_setup.rotheight) |
| 900 | | osd_printf_warning("Trying to create texture with zero dim\n"); |
| 901 | | |
| 902 | | // set copy_info |
| 903 | | |
| 904 | | m_copyinfo = compute_size_type(); |
| 905 | | |
| 906 | | m_texture_id = SDL_CreateTexture(m_sdl_renderer, m_copyinfo->dst_fmt, m_sdl_access, |
| 907 | | m_setup.rotwidth, m_setup.rotheight); |
| 908 | | |
| 909 | | if (!m_texture_id) |
| 910 | | osd_printf_error("Error creating texture: %d x %d, pixelformat %s error: %s\n", m_setup.rotwidth, m_setup.rotheight, |
| 911 | | m_copyinfo->dstname, SDL_GetError()); |
| 912 | | |
| 913 | | if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 914 | | { |
| 915 | | if (m_copyinfo->blitter->m_is_passthrough) |
| 916 | | m_pixels = NULL; |
| 917 | | else |
| 918 | | m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->blitter->m_dest_bpp); |
| 919 | | } |
| 920 | | m_last_access = osd_ticks(); |
| 921 | | |
| 922 | | } |
| 923 | | |
| 924 | | texture_info::~texture_info() |
| 925 | | { |
| 926 | | if ( is_pixels_owned() && (m_pixels != NULL) ) |
| 927 | | free(m_pixels); |
| 928 | | SDL_DestroyTexture(m_texture_id); |
| 929 | | } |
| 930 | | |
| 931 | | //============================================================ |
| 932 | | // texture_set_data |
| 933 | | //============================================================ |
| 934 | | |
| 935 | | void texture_info::set_data(const render_texinfo &texsource, const UINT32 flags) |
| 936 | | { |
| 937 | | m_copyinfo->time -= osd_ticks(); |
| 938 | | if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) |
| 939 | | { |
| 940 | | if ( m_copyinfo->blitter->m_is_passthrough ) |
| 941 | | { |
| 942 | | m_pixels = texsource.base; |
| 943 | | m_pitch = m_texinfo.rowpixels * m_copyinfo->blitter->m_dest_bpp; |
| 944 | | } |
| 945 | | else |
| 946 | | { |
| 947 | | m_pitch = m_setup.rotwidth * m_copyinfo->blitter->m_dest_bpp; |
| 948 | | m_copyinfo->blitter->texop(this, &texsource); |
| 949 | | } |
| 950 | | SDL_UpdateTexture(m_texture_id, NULL, m_pixels, m_pitch); |
| 951 | | } |
| 952 | | else |
| 953 | | { |
| 954 | | SDL_LockTexture(m_texture_id, NULL, (void **) &m_pixels, &m_pitch); |
| 955 | | if ( m_copyinfo->blitter->m_is_passthrough ) |
| 956 | | { |
| 957 | | UINT8 *src = (UINT8 *) texsource.base; |
| 958 | | UINT8 *dst = (UINT8 *) m_pixels; |
| 959 | | int spitch = texsource.rowpixels * m_copyinfo->blitter->m_dest_bpp; |
| 960 | | int num = texsource.width * m_copyinfo->blitter->m_dest_bpp; |
| 961 | | int h = texsource.height; |
| 962 | | while (h--) { |
| 963 | | memcpy(dst, src, num); |
| 964 | | src += spitch; |
| 965 | | dst += m_pitch; |
| 966 | | } |
| 967 | | } |
| 968 | | else |
| 969 | | m_copyinfo->blitter->texop(this, &texsource); |
| 970 | | SDL_UnlockTexture(m_texture_id); |
| 971 | | } |
| 972 | | m_copyinfo->time += osd_ticks(); |
| 973 | | } |
| 974 | | |
| 975 | | //============================================================ |
| 976 | | // compute rotation setup |
| 977 | | //============================================================ |
| 978 | | |
| 979 | | void quad_setup_data::compute(const render_primitive &prim, const int prescale) |
| 980 | | { |
| 981 | | const render_quad_texuv *texcoords = &prim.texcoords; |
| 982 | | int texwidth = prim.texture.width; |
| 983 | | int texheight = prim.texture.height; |
| 984 | | float fdudx, fdvdx, fdudy, fdvdy; |
| 985 | | float width, height; |
| 986 | | float fscale; |
| 987 | | /* determine U/V deltas */ |
| 988 | | if ((PRIMFLAG_GET_SCREENTEX(prim.flags))) |
| 989 | | fscale = (float) prescale; |
| 990 | | else |
| 991 | | fscale = 1.0f; |
| 992 | | |
| 993 | | fdudx = (texcoords->tr.u - texcoords->tl.u) / fscale; // a a11 |
| 994 | | fdvdx = (texcoords->tr.v - texcoords->tl.v) / fscale; // c a21 |
| 995 | | fdudy = (texcoords->bl.u - texcoords->tl.u) / fscale; // b a12 |
| 996 | | fdvdy = (texcoords->bl.v - texcoords->tl.v) / fscale; // d a22 |
| 997 | | |
| 998 | | #if 0 |
| 999 | | printf("tl.u %f tl.v %f\n", texcoords->tl.u, texcoords->tl.v); |
| 1000 | | printf("tr.u %f tr.v %f\n", texcoords->tr.u, texcoords->tr.v); |
| 1001 | | printf("bl.u %f bl.v %f\n", texcoords->bl.u, texcoords->bl.v); |
| 1002 | | printf("br.u %f br.v %f\n", texcoords->br.u, texcoords->br.v); |
| 1003 | | /* compute start and delta U,V coordinates now */ |
| 1004 | | #endif |
| 1005 | | |
| 1006 | | dudx = round_nearest(65536.0f * fdudx); |
| 1007 | | dvdx = round_nearest(65536.0f * fdvdx); |
| 1008 | | dudy = round_nearest(65536.0f * fdudy); |
| 1009 | | dvdy = round_nearest(65536.0f * fdvdy); |
| 1010 | | startu = round_nearest(65536.0f * (float) texwidth * texcoords->tl.u); |
| 1011 | | startv = round_nearest(65536.0f * (float) texheight * texcoords->tl.v); |
| 1012 | | |
| 1013 | | /* clamp to integers */ |
| 1014 | | |
| 1015 | | width = fabs((fdudx * (float) (texwidth) + fdvdx * (float) (texheight)) * fscale * fscale); |
| 1016 | | height = fabs((fdudy * (float)(texwidth) + fdvdy * (float) (texheight)) * fscale * fscale); |
| 1017 | | |
| 1018 | | rotwidth = width; |
| 1019 | | rotheight = height; |
| 1020 | | |
| 1021 | | startu += (dudx + dudy) / 2; |
| 1022 | | startv += (dvdx + dvdy) / 2; |
| 1023 | | |
| 1024 | | } |
| 1025 | | |
| 1026 | | //============================================================ |
| 1027 | | // texture_find |
| 1028 | | //============================================================ |
| 1029 | | |
| 1030 | | texture_info *sdl_info13::texture_find(const render_primitive &prim, const quad_setup_data &setup) |
| 1031 | | { |
| 1032 | | HashT texhash = texture_compute_hash(prim.texture, prim.flags); |
| 1033 | | texture_info *texture; |
| 1034 | | osd_ticks_t now = osd_ticks(); |
| 1035 | | |
| 1036 | | // find a match |
| 1037 | | for (texture = m_texlist.first(); texture != NULL; ) |
| 1038 | | if (texture->hash() == texhash && |
| 1039 | | texture->matches(prim, setup)) |
| 1040 | | { |
| 1041 | | /* would we choose another blitter based on performance ? */ |
| 1042 | | if ((texture->m_copyinfo->samples & 0x7f) == 0x7f) |
| 1043 | | { |
| 1044 | | if (texture->m_copyinfo != texture->compute_size_type()) |
| 1045 | | return NULL; |
| 1046 | | } |
| 1047 | | texture->m_last_access = now; |
| 1048 | | return texture; |
| 1049 | | } |
| 1050 | | else |
| 1051 | | { |
| 1052 | | /* free resources not needed any longer? */ |
| 1053 | | texture_info *expire = texture; |
| 1054 | | texture = texture->next(); |
| 1055 | | if (now - expire->m_last_access > osd_ticks_per_second()) |
| 1056 | | m_texlist.remove(*expire); |
| 1057 | | } |
| 1058 | | |
| 1059 | | // nothing found |
| 1060 | | return NULL; |
| 1061 | | } |
| 1062 | | |
| 1063 | | //============================================================ |
| 1064 | | // texture_update |
| 1065 | | //============================================================ |
| 1066 | | |
| 1067 | | texture_info * sdl_info13::texture_update(const render_primitive &prim) |
| 1068 | | { |
| 1069 | | quad_setup_data setup; |
| 1070 | | texture_info *texture; |
| 1071 | | |
| 1072 | | setup.compute(prim, window().prescale()); |
| 1073 | | |
| 1074 | | texture = texture_find(prim, setup); |
| 1075 | | |
| 1076 | | // if we didn't find one, create a new texture |
| 1077 | | if (texture == NULL && prim.texture.base != NULL) |
| 1078 | | { |
| 1079 | | texture = global_alloc(texture_info(m_sdl_renderer, prim.texture, setup, prim.flags)); |
| 1080 | | /* add us to the texture list */ |
| 1081 | | m_texlist.prepend(*texture); |
| 1082 | | |
| 1083 | | } |
| 1084 | | |
| 1085 | | if (texture != NULL) |
| 1086 | | { |
| 1087 | | if (prim.texture.base != NULL && texture->texinfo().seqid != prim.texture.seqid) |
| 1088 | | { |
| 1089 | | texture->texinfo().seqid = prim.texture.seqid; |
| 1090 | | // if we found it, but with a different seqid, copy the data |
| 1091 | | texture->set_data(prim.texture, prim.flags); |
| 1092 | | } |
| 1093 | | |
| 1094 | | } |
| 1095 | | return texture; |
| 1096 | | } |
trunk/src/osd/sdl/drawogl.c
| r244651 | r244652 | |
| 1 | | //============================================================ |
| 2 | | // |
| 3 | | // drawogl.c - SDL software and OpenGL implementation |
| 4 | | // |
| 5 | | // Copyright (c) 1996-2014, Nicola Salmoria and the MAME Team. |
| 6 | | // Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | | // |
| 8 | | // SDLMAME by Olivier Galibert and R. Belmont |
| 9 | | // |
| 10 | | // Note: D3D9 goes to a lot of trouble to fiddle with MODULATE |
| 11 | | // mode on textures. That is the default in OpenGL so we |
| 12 | | // don't have to touch it. |
| 13 | | // |
| 14 | | //============================================================ |
| 15 | | |
| 16 | | // standard C headers |
| 17 | | #include <math.h> |
| 18 | | #include <stdio.h> |
| 19 | | |
| 20 | | // MAME headers |
| 21 | | #include "osdcomm.h" |
| 22 | | #include "emu.h" |
| 23 | | #include "options.h" |
| 24 | | #include "emuopts.h" |
| 25 | | |
| 26 | | #ifndef OSD_WINDOWS |
| 27 | | // standard SDL headers |
| 28 | | #define TOBEMIGRATED 1 |
| 29 | | #include "sdlinc.h" |
| 30 | | #endif |
| 31 | | |
| 32 | | // OpenGL headers |
| 33 | | #include "modules/opengl/osd_opengl.h" |
| 34 | | |
| 35 | | #ifdef OSD_WINDOWS |
| 36 | | #define SDLMAME_SDL2 1 |
| 37 | | #ifndef USE_DISPATCH_GL |
| 38 | | #include "GL/wglext.h" |
| 39 | | #endif |
| 40 | | #endif |
| 41 | | |
| 42 | | #include "modules/lib/osdlib.h" |
| 43 | | #include "modules/lib/osdobj_common.h" |
| 44 | | |
| 45 | | |
| 46 | | #include "modules/opengl/gl_shader_tool.h" |
| 47 | | #include "modules/opengl/gl_shader_mgr.h" |
| 48 | | |
| 49 | | #if defined(SDLMAME_MACOSX) |
| 50 | | #ifndef APIENTRY |
| 51 | | #define APIENTRY |
| 52 | | #endif |
| 53 | | #ifndef APIENTRYP |
| 54 | | #define APIENTRYP APIENTRY * |
| 55 | | #endif |
| 56 | | |
| 57 | | typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); |
| 58 | | typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum, GLuint); |
| 59 | | typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum, GLsizeiptr, const GLvoid *, GLenum); |
| 60 | | typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum, GLintptr, GLsizeiptr, const GLvoid *); |
| 61 | | typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum, GLenum); |
| 62 | | typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum); |
| 63 | | typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei, const GLuint *); |
| 64 | | typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); |
| 65 | | typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); |
| 66 | | typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum m_target, GLuint framebuffer); |
| 67 | | typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); |
| 68 | | typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); |
| 69 | | typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum m_target); |
| 70 | | typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum m_target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); |
| 71 | | typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); |
| 72 | | typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint renderbuffer); |
| 73 | | typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height); |
| 74 | | typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); |
| 75 | | typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); |
| 76 | | #endif |
| 77 | | |
| 78 | | // make sure the extensions compile OK everywhere |
| 79 | | #ifndef GL_TEXTURE_STORAGE_HINT_APPLE |
| 80 | | #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85bc |
| 81 | | #endif |
| 82 | | |
| 83 | | #ifndef GL_STORAGE_CACHED_APPLE |
| 84 | | #define GL_STORAGE_CACHED_APPLE 0x85be |
| 85 | | #endif |
| 86 | | |
| 87 | | #ifndef GL_UNPACK_CLIENT_STORAGE_APPLE |
| 88 | | #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85b2 |
| 89 | | #endif |
| 90 | | |
| 91 | | #ifndef GL_TEXTURE_RECTANGLE_ARB |
| 92 | | #define GL_TEXTURE_RECTANGLE_ARB 0x84F5 |
| 93 | | #endif |
| 94 | | |
| 95 | | #ifndef GL_PIXEL_UNPACK_BUFFER_ARB |
| 96 | | #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC |
| 97 | | #endif |
| 98 | | |
| 99 | | #ifndef GL_STREAM_DRAW |
| 100 | | #define GL_STREAM_DRAW 0x88E0 |
| 101 | | #endif |
| 102 | | |
| 103 | | #ifndef GL_WRITE_ONLY |
| 104 | | #define GL_WRITE_ONLY 0x88B9 |
| 105 | | #endif |
| 106 | | |
| 107 | | #ifndef GL_ARRAY_BUFFER_ARB |
| 108 | | #define GL_ARRAY_BUFFER_ARB 0x8892 |
| 109 | | #endif |
| 110 | | |
| 111 | | #ifndef GL_PIXEL_UNPACK_BUFFER_ARB |
| 112 | | #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC |
| 113 | | #endif |
| 114 | | |
| 115 | | #ifndef GL_FRAMEBUFFER_EXT |
| 116 | | #define GL_FRAMEBUFFER_EXT 0x8D40 |
| 117 | | #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 |
| 118 | | #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 |
| 119 | | #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 |
| 120 | | #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 |
| 121 | | #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 |
| 122 | | #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA |
| 123 | | #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB |
| 124 | | #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC |
| 125 | | #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD |
| 126 | | #define GL_RENDERBUFFER_EXT 0x8D41 |
| 127 | | #define GL_DEPTH_COMPONENT16 0x81A5 |
| 128 | | #define GL_DEPTH_COMPONENT24 0x81A6 |
| 129 | | #define GL_DEPTH_COMPONENT32 0x81A7 |
| 130 | | #endif |
| 131 | | |
| 132 | | #define HASH_SIZE ((1<<10)+1) |
| 133 | | #define OVERFLOW_SIZE (1<<10) |
| 134 | | |
| 135 | | // OSD headers |
| 136 | | #ifndef OSD_WINDOWS |
| 137 | | #include "osdsdl.h" |
| 138 | | #include "window.h" |
| 139 | | #else |
| 140 | | #include "../windows/window.h" |
| 141 | | typedef UINT64 HashT; |
| 142 | | #endif |
| 143 | | |
| 144 | | //============================================================ |
| 145 | | // DEBUGGING |
| 146 | | //============================================================ |
| 147 | | |
| 148 | | #define DEBUG_MODE_SCORES 0 |
| 149 | | #define USE_WIN32_STYLE_LINES 0 // use the same method baseline does - yields somewhat nicer vectors but a little buggy |
| 150 | | |
| 151 | | //============================================================ |
| 152 | | // CONSTANTS |
| 153 | | //============================================================ |
| 154 | | |
| 155 | | enum |
| 156 | | { |
| 157 | | TEXTURE_TYPE_NONE, |
| 158 | | TEXTURE_TYPE_PLAIN, |
| 159 | | TEXTURE_TYPE_DYNAMIC, |
| 160 | | TEXTURE_TYPE_SHADER, |
| 161 | | TEXTURE_TYPE_SURFACE |
| 162 | | }; |
| 163 | | |
| 164 | | |
| 165 | | //============================================================ |
| 166 | | // MACROS |
| 167 | | //============================================================ |
| 168 | | |
| 169 | | #ifdef OSD_WINDOWS |
| 170 | | // texture formats |
| 171 | | // This used to be an enum, but these are now defines so we can use them as |
| 172 | | // preprocessor conditionals |
| 173 | | #define SDL_TEXFORMAT_ARGB32 (0) // non-16-bit textures or specials |
| 174 | | #define SDL_TEXFORMAT_RGB32 (1) |
| 175 | | #define SDL_TEXFORMAT_RGB32_PALETTED (2) |
| 176 | | #define SDL_TEXFORMAT_YUY16 (3) |
| 177 | | #define SDL_TEXFORMAT_YUY16_PALETTED (4) |
| 178 | | #define SDL_TEXFORMAT_PALETTE16 (5) |
| 179 | | #define SDL_TEXFORMAT_RGB15 (6) |
| 180 | | #define SDL_TEXFORMAT_RGB15_PALETTED (7) |
| 181 | | #define SDL_TEXFORMAT_PALETTE16A (8) |
| 182 | | // special texture formats for 16bpp texture destination support, do not use |
| 183 | | // to address the tex properties / tex functions arrays! |
| 184 | | #define SDL_TEXFORMAT_PALETTE16_ARGB1555 (16) |
| 185 | | #define SDL_TEXFORMAT_RGB15_ARGB1555 (17) |
| 186 | | #define SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 (18) |
| 187 | | #endif |
| 188 | | |
| 189 | | #define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0) |
| 190 | | #define GL_NO_PRIMITIVE -1 |
| 191 | | |
| 192 | | //============================================================ |
| 193 | | // TYPES |
| 194 | | //============================================================ |
| 195 | | |
| 196 | | #if (SDLMAME_SDL2) |
| 197 | | |
| 198 | | #ifdef OSD_WINDOWS |
| 199 | | class win_gl_context : public osd_gl_context |
| 200 | | { |
| 201 | | public: |
| 202 | | win_gl_context(HWND window) : osd_gl_context(), m_context(0), m_window(NULL), m_hdc(0) |
| 203 | | { |
| 204 | | m_error[0] = 0; |
| 205 | | |
| 206 | | this->wglGetProcAddress = (PROC WINAPI (*)(LPCSTR lpszProc)) GetProcAddress(m_module, "wglGetProcAddress"); |
| 207 | | this->wglCreateContext = (HGLRC WINAPI (*)(HDC hdc)) GetProcAddress(m_module, "wglCreateContext"); |
| 208 | | this->wglDeleteContext = (BOOL WINAPI (*)(HGLRC hglrc)) GetProcAddress(m_module, "wglDeleteContext"); |
| 209 | | this->wglMakeCurrent = (BOOL WINAPI (*)(HDC hdc, HGLRC hglrc)) GetProcAddress(m_module, "wglMakeCurrent"); |
| 210 | | |
| 211 | | m_hdc = GetDC(window); |
| 212 | | if (!setupPixelFormat(m_hdc)) |
| 213 | | { |
| 214 | | m_context = wglCreateContext(m_hdc); |
| 215 | | if (!m_context) |
| 216 | | { |
| 217 | | FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, m_error, 255, NULL); |
| 218 | | return; |
| 219 | | } |
| 220 | | wglMakeCurrent(m_hdc, m_context); |
| 221 | | } |
| 222 | | } |
| 223 | | |
| 224 | | virtual ~win_gl_context() |
| 225 | | { |
| 226 | | wglDeleteContext(m_context); |
| 227 | | ReleaseDC(m_window, m_hdc); |
| 228 | | } |
| 229 | | |
| 230 | | virtual void MakeCurrent() |
| 231 | | { |
| 232 | | wglMakeCurrent(m_hdc, m_context); |
| 233 | | } |
| 234 | | |
| 235 | | virtual const char *LastErrorMsg() |
| 236 | | { |
| 237 | | if (m_error[0] == 0) |
| 238 | | return NULL; |
| 239 | | else |
| 240 | | return m_error; |
| 241 | | } |
| 242 | | |
| 243 | | virtual void *getProcAddress(const char *proc) |
| 244 | | { |
| 245 | | void *ret = (void *) GetProcAddress(m_module, proc); |
| 246 | | if (ret == NULL) |
| 247 | | ret = (void *) wglGetProcAddress(proc); |
| 248 | | return ret; |
| 249 | | } |
| 250 | | |
| 251 | | virtual int SetSwapInterval(const int swap) |
| 252 | | { |
| 253 | | // FIXME: Missing! |
| 254 | | return 0; |
| 255 | | } |
| 256 | | |
| 257 | | virtual void SwapBuffer() |
| 258 | | { |
| 259 | | SwapBuffers(m_hdc); |
| 260 | | //wglSwapLayerBuffers(GetDC(window().m_hwnd), WGL_SWAP_MAIN_PLANE); |
| 261 | | } |
| 262 | | |
| 263 | | static void load_library() |
| 264 | | { |
| 265 | | m_module = LoadLibraryA("opengl32.dll"); |
| 266 | | } |
| 267 | | |
| 268 | | private: |
| 269 | | |
| 270 | | int setupPixelFormat(HDC hDC) |
| 271 | | { |
| 272 | | PIXELFORMATDESCRIPTOR pfd = { |
| 273 | | sizeof(PIXELFORMATDESCRIPTOR), /* size */ |
| 274 | | 1, /* version */ |
| 275 | | PFD_SUPPORT_OPENGL | |
| 276 | | PFD_DRAW_TO_WINDOW | |
| 277 | | PFD_DOUBLEBUFFER, /* support double-buffering */ |
| 278 | | PFD_TYPE_RGBA, /* color type */ |
| 279 | | 32, /* prefered color depth */ |
| 280 | | 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ |
| 281 | | 0, /* no alpha buffer */ |
| 282 | | 0, /* alpha bits (ignored) */ |
| 283 | | 0, /* no accumulation buffer */ |
| 284 | | 0, 0, 0, 0, /* accum bits (ignored) */ |
| 285 | | 16, /* depth buffer */ |
| 286 | | 0, /* no stencil buffer */ |
| 287 | | 0, /* no auxiliary buffers */ |
| 288 | | PFD_MAIN_PLANE, /* main layer */ |
| 289 | | 0, /* reserved */ |
| 290 | | 0, 0, 0, /* no layer, visible, damage masks */ |
| 291 | | }; |
| 292 | | int pixelFormat; |
| 293 | | |
| 294 | | pixelFormat = ChoosePixelFormat(hDC, &pfd); |
| 295 | | if (pixelFormat == 0) { |
| 296 | | strcpy(m_error, "ChoosePixelFormat failed"); |
| 297 | | return 1; |
| 298 | | } |
| 299 | | |
| 300 | | if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { |
| 301 | | strcpy(m_error, "SetPixelFormat failed."); |
| 302 | | return 1; |
| 303 | | } |
| 304 | | return 0; |
| 305 | | } |
| 306 | | |
| 307 | | |
| 308 | | HGLRC m_context; |
| 309 | | HWND m_window; |
| 310 | | HDC m_hdc; |
| 311 | | char m_error[256]; |
| 312 | | |
| 313 | | PROC WINAPI (*wglGetProcAddress)(LPCSTR lpszProc); |
| 314 | | HGLRC WINAPI (*wglCreateContext)(HDC hdc); |
| 315 | | BOOL WINAPI (*wglDeleteContext)(HGLRC hglrc); |
| 316 | | BOOL WINAPI (*wglMakeCurrent)(HDC hdc, HGLRC hglrc); |
| 317 | | |
| 318 | | static HMODULE m_module; |
| 319 | | }; |
| 320 | | |
| 321 | | HMODULE win_gl_context::m_module; |
| 322 | | |
| 323 | | |
| 324 | | #else |
| 325 | | class sdl_gl_context : public osd_gl_context |
| 326 | | { |
| 327 | | public: |
| 328 | | sdl_gl_context(SDL_Window *window) : osd_gl_context(), m_context(0), m_window(window) |
| 329 | | { |
| 330 | | m_error[0] = 0; |
| 331 | | m_context = SDL_GL_CreateContext(window); |
| 332 | | if (!m_context) |
| 333 | | { |
| 334 | | snprintf(m_error,255, "OpenGL not supported on this driver: %s", SDL_GetError()); |
| 335 | | } |
| 336 | | } |
| 337 | | virtual ~sdl_gl_context() |
| 338 | | { |
| 339 | | SDL_GL_DeleteContext(m_context); |
| 340 | | } |
| 341 | | virtual void MakeCurrent() |
| 342 | | { |
| 343 | | SDL_GL_MakeCurrent(m_window, m_context); |
| 344 | | } |
| 345 | | |
| 346 | | virtual int SetSwapInterval(const int swap) |
| 347 | | { |
| 348 | | return SDL_GL_SetSwapInterval(swap); |
| 349 | | } |
| 350 | | |
| 351 | | virtual const char *LastErrorMsg() |
| 352 | | { |
| 353 | | if (m_error[0] == 0) |
| 354 | | return NULL; |
| 355 | | else |
| 356 | | return m_error; |
| 357 | | } |
| 358 | | virtual void *getProcAddress(const char *proc) |
| 359 | | { |
| 360 | | return SDL_GL_GetProcAddress(proc); |
| 361 | | } |
| 362 | | |
| 363 | | virtual void SwapBuffer() |
| 364 | | { |
| 365 | | SDL_GL_SwapWindow(m_window); |
| 366 | | } |
| 367 | | |
| 368 | | private: |
| 369 | | SDL_GLContext m_context; |
| 370 | | SDL_Window *m_window; |
| 371 | | char m_error[256]; |
| 372 | | }; |
| 373 | | #endif |
| 374 | | #else |
| 375 | | // SDL 1.2 |
| 376 | | class sdl12_gl_context : public osd_gl_context |
| 377 | | { |
| 378 | | public: |
| 379 | | sdl12_gl_context(SDL_Surface *window) : osd_gl_context(), m_window(window) |
| 380 | | { |
| 381 | | m_error[0] = 0; |
| 382 | | } |
| 383 | | virtual ~sdl12_gl_context() |
| 384 | | { |
| 385 | | } |
| 386 | | virtual void MakeCurrent() |
| 387 | | { |
| 388 | | } |
| 389 | | |
| 390 | | virtual int SetSwapInterval(const int swap) |
| 391 | | { |
| 392 | | // Not supported on 1.2 |
| 393 | | return 0; |
| 394 | | } |
| 395 | | |
| 396 | | virtual const char *LastErrorMsg() |
| 397 | | { |
| 398 | | if (m_error[0] == 0) |
| 399 | | return NULL; |
| 400 | | else |
| 401 | | return m_error; |
| 402 | | } |
| 403 | | |
| 404 | | virtual void *getProcAddress(const char *proc) |
| 405 | | { |
| 406 | | return SDL_GL_GetProcAddress(proc); |
| 407 | | } |
| 408 | | |
| 409 | | virtual void SwapBuffer() |
| 410 | | { |
| 411 | | SDL_GL_SwapBuffers(); |
| 412 | | } |
| 413 | | |
| 414 | | private: |
| 415 | | SDL_Surface *m_window; |
| 416 | | char m_error[256]; |
| 417 | | }; |
| 418 | | |
| 419 | | |
| 420 | | #endif |
| 421 | | |
| 422 | | //============================================================ |
| 423 | | // Textures |
| 424 | | //============================================================ |
| 425 | | |
| 426 | | /* texture_info holds information about a texture */ |
| 427 | | class texture_info |
| 428 | | { |
| 429 | | public: |
| 430 | | texture_info() |
| 431 | | : hash(0), flags(0), rawwidth(0), rawheight(0), |
| 432 | | rawwidth_create(0), rawheight_create(0), |
| 433 | | type(0), format(0), borderpix(0), xprescale(0), yprescale(0), nocopy(0), |
| 434 | | texture(0), texTarget(0), texpow2(0), mpass_dest_idx(0), pbo(0), data(NULL), |
| 435 | | data_own(0), texCoordBufferName(0) |
| 436 | | { |
| 437 | | for (int i=0; i<2; i++) |
| 438 | | { |
| 439 | | mpass_textureunit[i] = 0; |
| 440 | | mpass_texture_mamebm[i] = 0; |
| 441 | | mpass_fbo_mamebm[i] = 0; |
| 442 | | mpass_texture_scrn[i] = 0; |
| 443 | | mpass_fbo_scrn[i] = 0; |
| 444 | | } |
| 445 | | for (int i=0; i<8; i++) |
| 446 | | texCoord[i] = 0.0f; |
| 447 | | } |
| 448 | | |
| 449 | | HashT hash; // hash value for the texture (must be >= pointer size) |
| 450 | | UINT32 flags; // rendering flags |
| 451 | | render_texinfo texinfo; // copy of the texture info |
| 452 | | int rawwidth, rawheight; // raw width/height of the texture |
| 453 | | int rawwidth_create; // raw width/height, pow2 compatible, if needed |
| 454 | | int rawheight_create; // (create and initial set the texture, not for copy!) |
| 455 | | int type; // what type of texture are we? |
| 456 | | int format; // texture format |
| 457 | | int borderpix; // do we have a 1 pixel border? |
| 458 | | int xprescale; // what is our X prescale factor? |
| 459 | | int yprescale; // what is our Y prescale factor? |
| 460 | | int nocopy; // must the texture date be copied? |
| 461 | | |
| 462 | | UINT32 texture; // OpenGL texture "name"/ID |
| 463 | | |
| 464 | | GLenum texTarget; // OpenGL texture target |
| 465 | | int texpow2; // Is this texture pow2 |
| 466 | | |
| 467 | | UINT32 mpass_dest_idx; // Multipass dest idx [0..1] |
| 468 | | UINT32 mpass_textureunit[2]; // texture unit names for GLSL |
| 469 | | |
| 470 | | UINT32 mpass_texture_mamebm[2];// Multipass OpenGL texture "name"/ID for the shader |
| 471 | | UINT32 mpass_fbo_mamebm[2]; // framebuffer object for this texture, multipass |
| 472 | | UINT32 mpass_texture_scrn[2]; // Multipass OpenGL texture "name"/ID for the shader |
| 473 | | UINT32 mpass_fbo_scrn[2]; // framebuffer object for this texture, multipass |
| 474 | | |
| 475 | | UINT32 pbo; // pixel buffer object for this texture (DYNAMIC only!) |
| 476 | | UINT32 *data; // pixels for the texture |
| 477 | | int data_own; // do we own / allocated it ? |
| 478 | | GLfloat texCoord[8]; |
| 479 | | GLuint texCoordBufferName; |
| 480 | | |
| 481 | | }; |
| 482 | | |
| 483 | | /* sdl_info is the information about SDL for the current screen */ |
| 484 | | class sdl_info_ogl : public osd_renderer |
| 485 | | { |
| 486 | | public: |
| 487 | | sdl_info_ogl(osd_window *window) |
| 488 | | : osd_renderer(window, FLAG_NEEDS_OPENGL), m_blittimer(0), |
| 489 | | m_width(0), m_height(0), |
| 490 | | m_blit_dim(0, 0), |
| 491 | | m_gl_context(NULL), |
| 492 | | m_initialized(0), |
| 493 | | m_last_blendmode(0), |
| 494 | | m_texture_max_width(0), |
| 495 | | m_texture_max_height(0), |
| 496 | | m_texpoweroftwo(0), |
| 497 | | m_usevbo(0), m_usepbo(0), m_usefbo(0), m_useglsl(0), m_glsl(NULL), |
| 498 | | m_glsl_program_num(0), |
| 499 | | m_glsl_program_mb2sc(0), |
| 500 | | m_usetexturerect(0), |
| 501 | | m_init_context(0), |
| 502 | | m_last_hofs(0.0f), |
| 503 | | m_last_vofs(0.0f), |
| 504 | | m_surf_w(0), |
| 505 | | m_surf_h(0) |
| 506 | | { |
| 507 | | for (int i=0; i < HASH_SIZE + OVERFLOW_SIZE; i++) |
| 508 | | m_texhash[i] = NULL; |
| 509 | | for (int i=0; i < 2*GLSL_SHADER_MAX; i++) |
| 510 | | m_glsl_program[i] = 0; |
| 511 | | for (int i=0; i < 8; i++) |
| 512 | | m_texVerticex[i] = 0.0f; |
| 513 | | } |
| 514 | | |
| 515 | | /* virtual */ int create(); |
| 516 | | /* virtual */ int draw(const int update); |
| 517 | | |
| 518 | | /* virtual */ int xy_to_render_target(const int x, const int y, int *xt, int *yt); |
| 519 | | /* virtual */ void destroy(); |
| 520 | | /* virtual */ render_primitive_list *get_primitives() |
| 521 | | { |
| 522 | | #ifdef OSD_WINDOWS |
| 523 | | osd_dim nd = window().get_size(); |
| 524 | | #else |
| 525 | | osd_dim nd = window().blit_surface_size(); |
| 526 | | #endif |
| 527 | | if (nd != m_blit_dim) |
| 528 | | { |
| 529 | | m_blit_dim = nd; |
| 530 | | notify_changed(); |
| 531 | | } |
| 532 | | window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); |
| 533 | | return &window().target()->get_primitives(); |
| 534 | | } |
| 535 | | |
| 536 | | /* virtual */ void save() { } |
| 537 | | /* virtual */ void record() { } |
| 538 | | /* virtual */ void toggle_fsfx() { } |
| 539 | | |
| 540 | | private: |
| 541 | | void destroy_all_textures(); |
| 542 | | |
| 543 | | void loadGLExtensions(); |
| 544 | | void initialize_gl(); |
| 545 | | void set_blendmode(int blendmode); |
| 546 | | void texture_compute_type_subroutine(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 547 | | void texture_compute_size_subroutine(texture_info *texture, UINT32 flags, |
| 548 | | UINT32 width, UINT32 height, |
| 549 | | int* p_width, int* p_height, int* p_width_create, int* p_height_create); |
| 550 | | void texture_compute_size_type(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 551 | | texture_info *texture_create(const render_texinfo *texsource, UINT32 flags); |
| 552 | | int texture_shader_create(const render_texinfo *texsource, texture_info *texture, UINT32 flags); |
| 553 | | texture_info *texture_find(const render_primitive *prim); |
| 554 | | void texture_coord_update(texture_info *texture, const render_primitive *prim, int shaderIdx); |
| 555 | | void texture_mpass_flip(texture_info *texture, int shaderIdx); |
| 556 | | void texture_shader_update(texture_info *texture, render_container *container, int shaderIdx); |
| 557 | | texture_info * texture_update(const render_primitive *prim, int shaderIdx); |
| 558 | | void texture_disable(texture_info * texture); |
| 559 | | void texture_all_disable(); |
| 560 | | |
| 561 | | INT32 m_blittimer; |
| 562 | | int m_width; |
| 563 | | int m_height; |
| 564 | | osd_dim m_blit_dim; |
| 565 | | |
| 566 | | osd_gl_context *m_gl_context; |
| 567 | | |
| 568 | | int m_initialized; // is everything well initialized, i.e. all GL stuff etc. |
| 569 | | // 3D info (GL mode only) |
| 570 | | texture_info * m_texhash[HASH_SIZE + OVERFLOW_SIZE]; |
| 571 | | int m_last_blendmode; // previous blendmode |
| 572 | | INT32 m_texture_max_width; // texture maximum width |
| 573 | | INT32 m_texture_max_height; // texture maximum height |
| 574 | | int m_texpoweroftwo; // must textures be power-of-2 sized? |
| 575 | | int m_usevbo; // runtime check if VBO is available |
| 576 | | int m_usepbo; // runtime check if PBO is available |
| 577 | | int m_usefbo; // runtime check if FBO is available |
| 578 | | int m_useglsl; // runtime check if GLSL is available |
| 579 | | |
| 580 | | glsl_shader_info *m_glsl; // glsl_shader_info |
| 581 | | |
| 582 | | GLhandleARB m_glsl_program[2*GLSL_SHADER_MAX]; // GLSL programs, or 0 |
| 583 | | int m_glsl_program_num; // number of GLSL programs |
| 584 | | int m_glsl_program_mb2sc; // GLSL program idx, which transforms |
| 585 | | // the mame-bitmap. screen-bitmap (size/rotation/..) |
| 586 | | // All progs <= glsl_program_mb2sc using the mame bitmap |
| 587 | | // as input, otherwise the screen bitmap. |
| 588 | | // All progs >= glsl_program_mb2sc using the screen bitmap |
| 589 | | // as output, otherwise the mame bitmap. |
| 590 | | int m_usetexturerect; // use ARB_texture_rectangle for non-power-of-2, general use |
| 591 | | |
| 592 | | int m_init_context; // initialize context before next draw |
| 593 | | |
| 594 | | float m_last_hofs; |
| 595 | | float m_last_vofs; |
| 596 | | |
| 597 | | // Static vars from draogl_window_dra |
| 598 | | INT32 m_surf_w; |
| 599 | | INT32 m_surf_h; |
| 600 | | GLfloat m_texVerticex[8]; |
| 601 | | }; |
| 602 | | |
| 603 | | /* line_aa_step is used for drawing antialiased lines */ |
| 604 | | struct line_aa_step |
| 605 | | { |
| 606 | | float xoffs, yoffs; // X/Y deltas |
| 607 | | float weight; // weight contribution |
| 608 | | }; |
| 609 | | |
| 610 | | #if 0 |
| 611 | | static const line_aa_step line_aa_1step[] = |
| 612 | | { |
| 613 | | { 0.00f, 0.00f, 1.00f }, |
| 614 | | { 0 } |
| 615 | | }; |
| 616 | | |
| 617 | | static const line_aa_step line_aa_4step[] = |
| 618 | | { |
| 619 | | { -0.25f, 0.00f, 0.25f }, |
| 620 | | { 0.25f, 0.00f, 0.25f }, |
| 621 | | { 0.00f, -0.25f, 0.25f }, |
| 622 | | { 0.00f, 0.25f, 0.25f }, |
| 623 | | { 0 } |
| 624 | | }; |
| 625 | | #endif |
| 626 | | |
| 627 | | //============================================================ |
| 628 | | // INLINES |
| 629 | | //============================================================ |
| 630 | | |
| 631 | | INLINE HashT texture_compute_hash(const render_texinfo *texture, UINT32 flags) |
| 632 | | { |
| 633 | | HashT h = (HashT)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 634 | | //printf("hash %d\n", (int) h % HASH_SIZE); |
| 635 | | return (h >> 8) % HASH_SIZE; |
| 636 | | } |
| 637 | | |
| 638 | | void sdl_info_ogl::set_blendmode(int blendmode) |
| 639 | | { |
| 640 | | // try to minimize texture state changes |
| 641 | | if (blendmode != m_last_blendmode) |
| 642 | | { |
| 643 | | switch (blendmode) |
| 644 | | { |
| 645 | | case BLENDMODE_NONE: |
| 646 | | glDisable(GL_BLEND); |
| 647 | | break; |
| 648 | | case BLENDMODE_ALPHA: |
| 649 | | glEnable(GL_BLEND); |
| 650 | | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 651 | | break; |
| 652 | | case BLENDMODE_RGB_MULTIPLY: |
| 653 | | glEnable(GL_BLEND); |
| 654 | | glBlendFunc(GL_DST_COLOR, GL_ZERO); |
| 655 | | break; |
| 656 | | case BLENDMODE_ADD: |
| 657 | | glEnable(GL_BLEND); |
| 658 | | glBlendFunc(GL_SRC_ALPHA, GL_ONE); |
| 659 | | break; |
| 660 | | } |
| 661 | | |
| 662 | | m_last_blendmode = blendmode; |
| 663 | | } |
| 664 | | } |
| 665 | | |
| 666 | | //============================================================ |
| 667 | | // PROTOTYPES |
| 668 | | //============================================================ |
| 669 | | |
| 670 | | // core functions |
| 671 | | |
| 672 | | //============================================================ |
| 673 | | // STATIC VARIABLES |
| 674 | | //============================================================ |
| 675 | | |
| 676 | | static void drawogl_exit(void); |
| 677 | | static void load_gl_lib(running_machine &machine); |
| 678 | | |
| 679 | | |
| 680 | | |
| 681 | | // OGL 1.3 |
| 682 | | #ifdef GL_ARB_multitexture |
| 683 | | static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = NULL; |
| 684 | | #else |
| 685 | | static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = NULL; |
| 686 | | #endif |
| 687 | | |
| 688 | | // VBO |
| 689 | | static PFNGLGENBUFFERSPROC pfn_glGenBuffers = NULL; |
| 690 | | static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers = NULL; |
| 691 | | static PFNGLBINDBUFFERPROC pfn_glBindBuffer = NULL; |
| 692 | | static PFNGLBUFFERDATAPROC pfn_glBufferData = NULL; |
| 693 | | static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData = NULL; |
| 694 | | |
| 695 | | // PBO |
| 696 | | static PFNGLMAPBUFFERPROC pfn_glMapBuffer = NULL; |
| 697 | | static PFNGLUNMAPBUFFERPROC pfn_glUnmapBuffer = NULL; |
| 698 | | |
| 699 | | // FBO |
| 700 | | static PFNGLISFRAMEBUFFEREXTPROC pfn_glIsFramebuffer = NULL; |
| 701 | | static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer = NULL; |
| 702 | | static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers = NULL; |
| 703 | | static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers = NULL; |
| 704 | | static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus = NULL; |
| 705 | | static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D = NULL; |
| 706 | | |
| 707 | | static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; |
| 708 | | |
| 709 | | //============================================================ |
| 710 | | // Textures |
| 711 | | //============================================================ |
| 712 | | |
| 713 | | static void texture_set_data(texture_info *texture, const render_texinfo *texsource, UINT32 flags); |
| 714 | | |
| 715 | | //============================================================ |
| 716 | | // Static Variables |
| 717 | | //============================================================ |
| 718 | | |
| 719 | | static int shown_video_info = 0; |
| 720 | | static int dll_loaded = 0; |
| 721 | | |
| 722 | | //============================================================ |
| 723 | | // drawsdl_init |
| 724 | | //============================================================ |
| 725 | | |
| 726 | | static osd_renderer *drawogl_create(osd_window *window) |
| 727 | | { |
| 728 | | return global_alloc(sdl_info_ogl(window)); |
| 729 | | } |
| 730 | | |
| 731 | | int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 732 | | { |
| 733 | | // fill in the callbacks |
| 734 | | callbacks->exit = drawogl_exit; |
| 735 | | callbacks->create = drawogl_create; |
| 736 | | |
| 737 | | dll_loaded = 0; |
| 738 | | |
| 739 | | load_gl_lib(machine); |
| 740 | | if (SDLMAME_SDL2) |
| 741 | | { |
| 742 | | osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); |
| 743 | | } |
| 744 | | else |
| 745 | | osd_printf_verbose("Using SDL single-window OpenGL driver (SDL 1.2)\n"); |
| 746 | | |
| 747 | | return 0; |
| 748 | | } |
| 749 | | |
| 750 | | //============================================================ |
| 751 | | // Load the OGL function addresses |
| 752 | | //============================================================ |
| 753 | | |
| 754 | | static void loadgl_functions(osd_gl_context *context) |
| 755 | | { |
| 756 | | #ifdef USE_DISPATCH_GL |
| 757 | | |
| 758 | | int err_count = 0; |
| 759 | | |
| 760 | | /* the following is tricky ... #func will be expanded to glBegin |
| 761 | | * while func will be expanded to disp_p->glBegin |
| 762 | | */ |
| 763 | | |
| 764 | | #define OSD_GL(ret,func,params) \ |
| 765 | | if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \ |
| 766 | | { err_count++; osd_printf_error("GL function %s not found!\n", #func ); } |
| 767 | | |
| 768 | | #define OSD_GL_UNUSED(ret,func,params) |
| 769 | | |
| 770 | | #define GET_GLFUNC 1 |
| 771 | | #include "modules/opengl/osd_opengl.h" |
| 772 | | #undef GET_GLFUNC |
| 773 | | |
| 774 | | if (err_count) |
| 775 | | fatalerror("Error loading GL library functions, giving up\n"); |
| 776 | | |
| 777 | | #endif |
| 778 | | } |
| 779 | | |
| 780 | | //============================================================ |
| 781 | | // Load GL library |
| 782 | | //============================================================ |
| 783 | | |
| 784 | | #ifdef USE_DISPATCH_GL |
| 785 | | osd_gl_dispatch *gl_dispatch; |
| 786 | | #endif |
| 787 | | |
| 788 | | static void load_gl_lib(running_machine &machine) |
| 789 | | { |
| 790 | | if (!dll_loaded) |
| 791 | | { |
| 792 | | #ifdef OSD_WINDOWS |
| 793 | | win_gl_context::load_library(); |
| 794 | | #else |
| 795 | | #ifdef USE_DISPATCH_GL |
| 796 | | /* |
| 797 | | * directfb and and x11 use this env var |
| 798 | | * SDL_VIDEO_GL_DRIVER |
| 799 | | */ |
| 800 | | const char *stemp; |
| 801 | | |
| 802 | | stemp = downcast<sdl_options &>(machine.options()).gl_lib(); |
| 803 | | if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) == 0) |
| 804 | | stemp = NULL; |
| 805 | | |
| 806 | | if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==NULL |
| 807 | | { |
| 808 | | fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); |
| 809 | | } |
| 810 | | osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); |
| 811 | | /* FIXME: must be freed as well */ |
| 812 | | #endif |
| 813 | | #endif |
| 814 | | gl_dispatch = (osd_gl_dispatch *) osd_malloc(sizeof(osd_gl_dispatch)); |
| 815 | | dll_loaded=1; |
| 816 | | } |
| 817 | | } |
| 818 | | |
| 819 | | void sdl_info_ogl::initialize_gl() |
| 820 | | { |
| 821 | | int has_and_allow_texturerect = 0; |
| 822 | | |
| 823 | | char *extstr = (char *)glGetString(GL_EXTENSIONS); |
| 824 | | char *vendor = (char *)glGetString(GL_VENDOR); |
| 825 | | |
| 826 | | //printf("%p\n", extstr); |
| 827 | | #ifdef OSD_WINDOWS |
| 828 | | if (!extstr) |
| 829 | | extstr = (char *)""; |
| 830 | | #endif |
| 831 | | // print out the driver info for debugging |
| 832 | | if (!shown_video_info) |
| 833 | | { |
| 834 | | osd_printf_verbose("OpenGL: %s\nOpenGL: %s\nOpenGL: %s\n", vendor, (char *)glGetString(GL_RENDERER), (char *)glGetString(GL_VERSION)); |
| 835 | | } |
| 836 | | |
| 837 | | m_usetexturerect = 0; |
| 838 | | m_texpoweroftwo = 1; |
| 839 | | m_usevbo = 0; |
| 840 | | m_usepbo = 0; |
| 841 | | m_usefbo = 0; |
| 842 | | m_useglsl = 0; |
| 843 | | |
| 844 | | if ( video_config.allowtexturerect && |
| 845 | | ( strstr(extstr, "GL_ARB_texture_rectangle") || strstr(extstr, "GL_EXT_texture_rectangle") ) |
| 846 | | ) |
| 847 | | { |
| 848 | | has_and_allow_texturerect = 1; |
| 849 | | if (!shown_video_info) |
| 850 | | { |
| 851 | | osd_printf_verbose("OpenGL: texture rectangle supported\n"); |
| 852 | | } |
| 853 | | } |
| 854 | | |
| 855 | | // does this card support non-power-of-two sized textures? (they're faster, so use them if possible) |
| 856 | | if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two")) |
| 857 | | { |
| 858 | | if (!shown_video_info) |
| 859 | | { |
| 860 | | osd_printf_verbose("OpenGL: non-power-of-2 textures supported (new method)\n"); |
| 861 | | } |
| 862 | | m_texpoweroftwo = 0; |
| 863 | | } |
| 864 | | else |
| 865 | | { |
| 866 | | // second chance: GL_ARB_texture_rectangle or GL_EXT_texture_rectangle (old version) |
| 867 | | if (has_and_allow_texturerect) |
| 868 | | { |
| 869 | | if (!shown_video_info) |
| 870 | | { |
| 871 | | osd_printf_verbose("OpenGL: non-power-of-2 textures supported (old method)\n"); |
| 872 | | } |
| 873 | | m_usetexturerect = 1; |
| 874 | | } |
| 875 | | else |
| 876 | | { |
| 877 | | if (!shown_video_info) |
| 878 | | { |
| 879 | | osd_printf_verbose("OpenGL: forcing power-of-2 textures (creation, not copy)\n"); |
| 880 | | } |
| 881 | | } |
| 882 | | } |
| 883 | | |
| 884 | | if (strstr(extstr, "GL_ARB_vertex_buffer_object")) |
| 885 | | { |
| 886 | | m_usevbo = video_config.vbo; |
| 887 | | if (!shown_video_info) |
| 888 | | { |
| 889 | | if(m_usevbo) |
| 890 | | osd_printf_verbose("OpenGL: vertex buffer supported\n"); |
| 891 | | else |
| 892 | | osd_printf_verbose("OpenGL: vertex buffer supported, but disabled\n"); |
| 893 | | } |
| 894 | | } |
| 895 | | |
| 896 | | if (strstr(extstr, "GL_ARB_pixel_buffer_object")) |
| 897 | | { |
| 898 | | if( m_usevbo ) |
| 899 | | { |
| 900 | | m_usepbo = video_config.pbo; |
| 901 | | if (!shown_video_info) |
| 902 | | { |
| 903 | | if(m_usepbo) |
| 904 | | osd_printf_verbose("OpenGL: pixel buffers supported\n"); |
| 905 | | else |
| 906 | | osd_printf_verbose("OpenGL: pixel buffers supported, but disabled\n"); |
| 907 | | } |
| 908 | | } else { |
| 909 | | if (!shown_video_info) |
| 910 | | { |
| 911 | | osd_printf_verbose("OpenGL: pixel buffers supported, but disabled due to disabled vbo\n"); |
| 912 | | } |
| 913 | | } |
| 914 | | } |
| 915 | | else |
| 916 | | { |
| 917 | | if (!shown_video_info) |
| 918 | | { |
| 919 | | osd_printf_verbose("OpenGL: pixel buffers not supported\n"); |
| 920 | | } |
| 921 | | } |
| 922 | | |
| 923 | | if (strstr(extstr, "GL_EXT_framebuffer_object")) |
| 924 | | { |
| 925 | | m_usefbo = 1; |
| 926 | | if (!shown_video_info) |
| 927 | | { |
| 928 | | if(m_usefbo) |
| 929 | | osd_printf_verbose("OpenGL: framebuffer object supported\n"); |
| 930 | | else |
| 931 | | osd_printf_verbose("OpenGL: framebuffer object not supported\n"); |
| 932 | | } |
| 933 | | } |
| 934 | | |
| 935 | | if (strstr(extstr, "GL_ARB_shader_objects") && |
| 936 | | strstr(extstr, "GL_ARB_shading_language_100") && |
| 937 | | strstr(extstr, "GL_ARB_vertex_shader") && |
| 938 | | strstr(extstr, "GL_ARB_fragment_shader") |
| 939 | | ) |
| 940 | | { |
| 941 | | m_useglsl = video_config.glsl; |
| 942 | | if (!shown_video_info) |
| 943 | | { |
| 944 | | if(m_useglsl) |
| 945 | | osd_printf_verbose("OpenGL: GLSL supported\n"); |
| 946 | | else |
| 947 | | osd_printf_verbose("OpenGL: GLSL supported, but disabled\n"); |
| 948 | | } |
| 949 | | } else { |
| 950 | | if (!shown_video_info) |
| 951 | | { |
| 952 | | osd_printf_verbose("OpenGL: GLSL not supported\n"); |
| 953 | | } |
| 954 | | } |
| 955 | | |
| 956 | | #ifdef TOBEMIGRATED |
| 957 | | if (osd_getenv(SDLENV_VMWARE) != NULL) |
| 958 | | { |
| 959 | | m_usetexturerect = 1; |
| 960 | | m_texpoweroftwo = 1; |
| 961 | | } |
| 962 | | #endif |
| 963 | | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_width); |
| 964 | | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_height); |
| 965 | | if (!shown_video_info) |
| 966 | | { |
| 967 | | osd_printf_verbose("OpenGL: max texture size %d x %d\n", m_texture_max_width, m_texture_max_height); |
| 968 | | } |
| 969 | | |
| 970 | | shown_video_info = 1; |
| 971 | | |
| 972 | | } |
| 973 | | //============================================================ |
| 974 | | // sdl_info::create |
| 975 | | // a |
| 976 | | // a |
| 977 | | // a |
| 978 | | // a |
| 979 | | // a |
| 980 | | // a |
| 981 | | // a |
| 982 | | // a |
| 983 | | // a |
| 984 | | // a |
| 985 | | // a |
| 986 | | // a |
| 987 | | // a |
| 988 | | // a |
| 989 | | // a |
| 990 | | // a |
| 991 | | // a |
| 992 | | // a |
| 993 | | // a |
| 994 | | // a |
| 995 | | // a |
| 996 | | // a |
| 997 | | // a |
| 998 | | // a |
| 999 | | // a |
| 1000 | | // a |
| 1001 | | //============================================================ |
| 1002 | | |
| 1003 | | int sdl_info_ogl::create() |
| 1004 | | { |
| 1005 | | #if (SDLMAME_SDL2) |
| 1006 | | // create renderer |
| 1007 | | #ifdef OSD_WINDOWS |
| 1008 | | m_gl_context = global_alloc(win_gl_context(window().m_hwnd)); |
| 1009 | | #else |
| 1010 | | m_gl_context = global_alloc(sdl_gl_context(window().sdl_window())); |
| 1011 | | #endif |
| 1012 | | #else |
| 1013 | | m_gl_context = global_alloc(sdl12_gl_context(window().sdl_surface())); |
| 1014 | | #endif |
| 1015 | | if (m_gl_context->LastErrorMsg() != NULL) |
| 1016 | | { |
| 1017 | | osd_printf_error("%s\n", m_gl_context->LastErrorMsg()); |
| 1018 | | return 1; |
| 1019 | | } |
| 1020 | | m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0); |
| 1021 | | |
| 1022 | | |
| 1023 | | m_blittimer = 0; |
| 1024 | | m_surf_w = 0; |
| 1025 | | m_surf_h = 0; |
| 1026 | | |
| 1027 | | m_initialized = 0; |
| 1028 | | |
| 1029 | | // in case any textures try to come up before these are validated, |
| 1030 | | // OpenGL guarantees all implementations can handle something this size. |
| 1031 | | m_texture_max_width = 64; |
| 1032 | | m_texture_max_height = 64; |
| 1033 | | |
| 1034 | | /* load any GL function addresses |
| 1035 | | * this must be done here because we need a context |
| 1036 | | */ |
| 1037 | | loadgl_functions(m_gl_context); |
| 1038 | | initialize_gl(); |
| 1039 | | |
| 1040 | | |
| 1041 | | m_init_context = 0; |
| 1042 | | |
| 1043 | | osd_printf_verbose("Leave sdl_info_ogl::create\n"); |
| 1044 | | return 0; |
| 1045 | | } |
| 1046 | | |
| 1047 | | |
| 1048 | | //============================================================ |
| 1049 | | // sdl_info::destroy |
| 1050 | | //============================================================ |
| 1051 | | |
| 1052 | | void sdl_info_ogl::destroy() |
| 1053 | | { |
| 1054 | | // free the memory in the window |
| 1055 | | |
| 1056 | | destroy_all_textures(); |
| 1057 | | |
| 1058 | | global_free(m_gl_context); |
| 1059 | | m_gl_context = NULL; |
| 1060 | | } |
| 1061 | | |
| 1062 | | |
| 1063 | | //============================================================ |
| 1064 | | // drawsdl_xy_to_render_target |
| 1065 | | //============================================================ |
| 1066 | | |
| 1067 | | int sdl_info_ogl::xy_to_render_target(int x, int y, int *xt, int *yt) |
| 1068 | | { |
| 1069 | | *xt = x - m_last_hofs; |
| 1070 | | *yt = y - m_last_vofs; |
| 1071 | | if (*xt<0 || *xt >= m_blit_dim.width()) |
| 1072 | | return 0; |
| 1073 | | if (*yt<0 || *yt >= m_blit_dim.height()) |
| 1074 | | return 0; |
| 1075 | | return 1; |
| 1076 | | } |
| 1077 | | |
| 1078 | | //============================================================ |
| 1079 | | // drawsdl_destroy_all_textures |
| 1080 | | //============================================================ |
| 1081 | | |
| 1082 | | void sdl_info_ogl::destroy_all_textures() |
| 1083 | | { |
| 1084 | | texture_info *texture = NULL; |
| 1085 | | int lock=FALSE; |
| 1086 | | int i; |
| 1087 | | |
| 1088 | | if ( !m_initialized ) |
| 1089 | | return; |
| 1090 | | |
| 1091 | | m_gl_context->MakeCurrent(); |
| 1092 | | |
| 1093 | | if(window().m_primlist) |
| 1094 | | { |
| 1095 | | lock=TRUE; |
| 1096 | | window().m_primlist->acquire_lock(); |
| 1097 | | } |
| 1098 | | |
| 1099 | | glFinish(); |
| 1100 | | |
| 1101 | | texture_all_disable(); |
| 1102 | | glFinish(); |
| 1103 | | glDisableClientState(GL_VERTEX_ARRAY); |
| 1104 | | |
| 1105 | | i=0; |
| 1106 | | while (i<HASH_SIZE+OVERFLOW_SIZE) |
| 1107 | | { |
| 1108 | | texture = m_texhash[i]; |
| 1109 | | m_texhash[i] = NULL; |
| 1110 | | if (texture != NULL) |
| 1111 | | { |
| 1112 | | if(m_usevbo) |
| 1113 | | { |
| 1114 | | pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) ); |
| 1115 | | texture->texCoordBufferName=0; |
| 1116 | | } |
| 1117 | | |
| 1118 | | if(m_usepbo && texture->pbo) |
| 1119 | | { |
| 1120 | | pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) ); |
| 1121 | | texture->pbo=0; |
| 1122 | | } |
| 1123 | | |
| 1124 | | if( m_glsl_program_num > 1 ) |
| 1125 | | { |
| 1126 | | assert(m_usefbo); |
| 1127 | | pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); |
| 1128 | | glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); |
| 1129 | | } |
| 1130 | | |
| 1131 | | if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 ) |
| 1132 | | { |
| 1133 | | assert(m_usefbo); |
| 1134 | | pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); |
| 1135 | | glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); |
| 1136 | | } |
| 1137 | | |
| 1138 | | glDeleteTextures(1, (GLuint *)&texture->texture); |
| 1139 | | if ( texture->data_own ) |
| 1140 | | { |
| 1141 | | free(texture->data); |
| 1142 | | texture->data=NULL; |
| 1143 | | texture->data_own=FALSE; |
| 1144 | | } |
| 1145 | | global_free(texture); |
| 1146 | | } |
| 1147 | | i++; |
| 1148 | | } |
| 1149 | | if ( m_useglsl ) |
| 1150 | | { |
| 1151 | | glsl_shader_free(m_glsl); |
| 1152 | | m_glsl = NULL; |
| 1153 | | } |
| 1154 | | |
| 1155 | | m_initialized = 0; |
| 1156 | | |
| 1157 | | if (lock) |
| 1158 | | window().m_primlist->release_lock(); |
| 1159 | | } |
| 1160 | | //============================================================ |
| 1161 | | // loadGLExtensions |
| 1162 | | //============================================================ |
| 1163 | | |
| 1164 | | void sdl_info_ogl::loadGLExtensions() |
| 1165 | | { |
| 1166 | | static int _once = 1; |
| 1167 | | |
| 1168 | | // usevbo=FALSE; // You may want to switch VBO and PBO off, by uncommenting this statement |
| 1169 | | // usepbo=FALSE; // You may want to switch PBO off, by uncommenting this statement |
| 1170 | | // useglsl=FALSE; // You may want to switch GLSL off, by uncommenting this statement |
| 1171 | | |
| 1172 | | if (! m_usevbo) |
| 1173 | | { |
| 1174 | | if(m_usepbo) // should never ever happen ;-) |
| 1175 | | { |
| 1176 | | if (_once) |
| 1177 | | { |
| 1178 | | osd_printf_warning("OpenGL: PBO not supported, no VBO support. (sdlmame error)\n"); |
| 1179 | | } |
| 1180 | | m_usepbo=FALSE; |
| 1181 | | } |
| 1182 | | if(m_useglsl) // should never ever happen ;-) |
| 1183 | | { |
| 1184 | | if (_once) |
| 1185 | | { |
| 1186 | | osd_printf_warning("OpenGL: GLSL not supported, no VBO support. (sdlmame error)\n"); |
| 1187 | | } |
| 1188 | | m_useglsl=FALSE; |
| 1189 | | } |
| 1190 | | } |
| 1191 | | |
| 1192 | | // Get Pointers To The GL Functions |
| 1193 | | // VBO: |
| 1194 | | if( m_usevbo ) |
| 1195 | | { |
| 1196 | | pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers"); |
| 1197 | | pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers"); |
| 1198 | | pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer"); |
| 1199 | | pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData"); |
| 1200 | | pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData"); |
| 1201 | | } |
| 1202 | | // PBO: |
| 1203 | | if ( m_usepbo ) |
| 1204 | | { |
| 1205 | | pfn_glMapBuffer = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer"); |
| 1206 | | pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer"); |
| 1207 | | } |
| 1208 | | // FBO: |
| 1209 | | if ( m_usefbo ) |
| 1210 | | { |
| 1211 | | pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT"); |
| 1212 | | pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT"); |
| 1213 | | pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT"); |
| 1214 | | pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT"); |
| 1215 | | pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT"); |
| 1216 | | pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT"); |
| 1217 | | } |
| 1218 | | |
| 1219 | | if ( m_usevbo && |
| 1220 | | ( !pfn_glGenBuffers || !pfn_glDeleteBuffers || |
| 1221 | | !pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData |
| 1222 | | ) ) |
| 1223 | | { |
| 1224 | | m_usepbo=FALSE; |
| 1225 | | if (_once) |
| 1226 | | { |
| 1227 | | osd_printf_warning("OpenGL: VBO not supported, missing: "); |
| 1228 | | if (!pfn_glGenBuffers) |
| 1229 | | { |
| 1230 | | osd_printf_warning("glGenBuffers, "); |
| 1231 | | } |
| 1232 | | if (!pfn_glDeleteBuffers) |
| 1233 | | { |
| 1234 | | osd_printf_warning("glDeleteBuffers"); |
| 1235 | | } |
| 1236 | | if (!pfn_glBindBuffer) |
| 1237 | | { |
| 1238 | | osd_printf_warning("glBindBuffer, "); |
| 1239 | | } |
| 1240 | | if (!pfn_glBufferData) |
| 1241 | | { |
| 1242 | | osd_printf_warning("glBufferData, "); |
| 1243 | | } |
| 1244 | | if (!pfn_glBufferSubData) |
| 1245 | | { |
| 1246 | | osd_printf_warning("glBufferSubData, "); |
| 1247 | | } |
| 1248 | | osd_printf_warning("\n"); |
| 1249 | | } |
| 1250 | | if ( m_usevbo ) |
| 1251 | | { |
| 1252 | | if (_once) |
| 1253 | | { |
| 1254 | | osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n"); |
| 1255 | | } |
| 1256 | | m_usepbo=FALSE; |
| 1257 | | } |
| 1258 | | } |
| 1259 | | |
| 1260 | | if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) ) |
| 1261 | | { |
| 1262 | | m_usepbo=FALSE; |
| 1263 | | if (_once) |
| 1264 | | { |
| 1265 | | osd_printf_warning("OpenGL: PBO not supported, missing: "); |
| 1266 | | if (!pfn_glMapBuffer) |
| 1267 | | { |
| 1268 | | osd_printf_warning("glMapBuffer, "); |
| 1269 | | } |
| 1270 | | if (!pfn_glUnmapBuffer) |
| 1271 | | { |
| 1272 | | osd_printf_warning("glUnmapBuffer, "); |
| 1273 | | } |
| 1274 | | osd_printf_warning("\n"); |
| 1275 | | } |
| 1276 | | } |
| 1277 | | |
| 1278 | | if ( m_usefbo && |
| 1279 | | ( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers || |
| 1280 | | !pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D |
| 1281 | | )) |
| 1282 | | { |
| 1283 | | m_usefbo=FALSE; |
| 1284 | | if (_once) |
| 1285 | | { |
| 1286 | | osd_printf_warning("OpenGL: FBO not supported, missing: "); |
| 1287 | | if (!pfn_glIsFramebuffer) |
| 1288 | | { |
| 1289 | | osd_printf_warning("pfn_glIsFramebuffer, "); |
| 1290 | | } |
| 1291 | | if (!pfn_glBindFramebuffer) |
| 1292 | | { |
| 1293 | | osd_printf_warning("pfn_glBindFramebuffer, "); |
| 1294 | | } |
| 1295 | | if (!pfn_glDeleteFramebuffers) |
| 1296 | | { |
| 1297 | | osd_printf_warning("pfn_glDeleteFramebuffers, "); |
| 1298 | | } |
| 1299 | | if (!pfn_glGenFramebuffers) |
| 1300 | | { |
| 1301 | | osd_printf_warning("pfn_glGenFramebuffers, "); |
| 1302 | | } |
| 1303 | | if (!pfn_glCheckFramebufferStatus) |
| 1304 | | { |
| 1305 | | osd_printf_warning("pfn_glCheckFramebufferStatus, "); |
| 1306 | | } |
| 1307 | | if (!pfn_glFramebufferTexture2D) |
| 1308 | | { |
| 1309 | | osd_printf_warning("pfn_glFramebufferTexture2D, "); |
| 1310 | | } |
| 1311 | | osd_printf_warning("\n"); |
| 1312 | | } |
| 1313 | | } |
| 1314 | | |
| 1315 | | if (_once) |
| 1316 | | { |
| 1317 | | if ( m_usevbo ) |
| 1318 | | { |
| 1319 | | osd_printf_verbose("OpenGL: VBO supported\n"); |
| 1320 | | } |
| 1321 | | else |
| 1322 | | { |
| 1323 | | osd_printf_warning("OpenGL: VBO not supported\n"); |
| 1324 | | } |
| 1325 | | |
| 1326 | | if ( m_usepbo ) |
| 1327 | | { |
| 1328 | | osd_printf_verbose("OpenGL: PBO supported\n"); |
| 1329 | | } |
| 1330 | | else |
| 1331 | | { |
| 1332 | | osd_printf_warning("OpenGL: PBO not supported\n"); |
| 1333 | | } |
| 1334 | | |
| 1335 | | if ( m_usefbo ) |
| 1336 | | { |
| 1337 | | osd_printf_verbose("OpenGL: FBO supported\n"); |
| 1338 | | } |
| 1339 | | else |
| 1340 | | { |
| 1341 | | osd_printf_warning("OpenGL: FBO not supported\n"); |
| 1342 | | } |
| 1343 | | } |
| 1344 | | |
| 1345 | | if ( m_useglsl ) |
| 1346 | | { |
| 1347 | | #ifdef GL_ARB_multitexture |
| 1348 | | pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB"); |
| 1349 | | #else |
| 1350 | | pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture"); |
| 1351 | | #endif |
| 1352 | | if (!pfn_glActiveTexture) |
| 1353 | | { |
| 1354 | | if (_once) |
| 1355 | | { |
| 1356 | | osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n"); |
| 1357 | | } |
| 1358 | | m_useglsl = 0; |
| 1359 | | } |
| 1360 | | } |
| 1361 | | |
| 1362 | | if ( m_useglsl ) |
| 1363 | | { |
| 1364 | | m_glsl = glsl_shader_init(m_gl_context); |
| 1365 | | m_useglsl = (m_glsl != NULL ? 1 : 0); |
| 1366 | | |
| 1367 | | if ( ! m_useglsl ) |
| 1368 | | { |
| 1369 | | if (_once) |
| 1370 | | { |
| 1371 | | osd_printf_warning("OpenGL: GLSL supported, but shader instantiation failed - disabled\n"); |
| 1372 | | } |
| 1373 | | } |
| 1374 | | } |
| 1375 | | |
| 1376 | | if ( m_useglsl ) |
| 1377 | | { |
| 1378 | | if ( window().prescale() != 1 ) |
| 1379 | | { |
| 1380 | | m_useglsl = 0; |
| 1381 | | if (_once) |
| 1382 | | { |
| 1383 | | osd_printf_warning("OpenGL: GLSL supported, but disabled due to: prescale !=1 \n"); |
| 1384 | | } |
| 1385 | | } |
| 1386 | | } |
| 1387 | | |
| 1388 | | if ( m_useglsl ) |
| 1389 | | { |
| 1390 | | int i; |
| 1391 | | video_config.filter = FALSE; |
| 1392 | | glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN; |
| 1393 | | m_glsl_program_num = 0; |
| 1394 | | m_glsl_program_mb2sc = 0; |
| 1395 | | |
| 1396 | | for(i=0; i<video_config.glsl_shader_mamebm_num; i++) |
| 1397 | | { |
| 1398 | | if ( !m_usefbo && m_glsl_program_num==1 ) |
| 1399 | | { |
| 1400 | | if (_once) |
| 1401 | | { |
| 1402 | | osd_printf_verbose("OpenGL: GLSL multipass not supported, due to unsupported FBO. Skipping followup shader\n"); |
| 1403 | | } |
| 1404 | | break; |
| 1405 | | } |
| 1406 | | |
| 1407 | | if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) ) |
| 1408 | | { |
| 1409 | | osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n", |
| 1410 | | i, video_config.glsl_shader_mamebm[i]); |
| 1411 | | } else { |
| 1412 | | glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM; |
| 1413 | | if (_once) |
| 1414 | | { |
| 1415 | | osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n", |
| 1416 | | m_glsl_program_num, video_config.glsl_shader_mamebm[i]); |
| 1417 | | } |
| 1418 | | m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. |
| 1419 | | m_glsl_program_num++; |
| 1420 | | } |
| 1421 | | } |
| 1422 | | |
| 1423 | | if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 ) |
| 1424 | | { |
| 1425 | | osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n"); |
| 1426 | | } |
| 1427 | | |
| 1428 | | for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++) |
| 1429 | | { |
| 1430 | | if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i], |
| 1431 | | m_glsl_program_num-1-m_glsl_program_mb2sc) ) |
| 1432 | | { |
| 1433 | | osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n", |
| 1434 | | i, video_config.glsl_shader_scrn[i]); |
| 1435 | | } else { |
| 1436 | | if (_once) |
| 1437 | | { |
| 1438 | | osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n", |
| 1439 | | m_glsl_program_num, video_config.glsl_shader_scrn[i]); |
| 1440 | | } |
| 1441 | | m_glsl_program_num++; |
| 1442 | | } |
| 1443 | | } |
| 1444 | | |
| 1445 | | if ( 0==m_glsl_program_num && |
| 1446 | | 0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER ) |
| 1447 | | { |
| 1448 | | m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it. |
| 1449 | | m_glsl_program_num++; |
| 1450 | | glsl_shader_feature = video_config.glsl_filter; |
| 1451 | | |
| 1452 | | if (_once) |
| 1453 | | { |
| 1454 | | osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n", |
| 1455 | | glsl_shader_get_filter_name_mamebm(glsl_shader_feature), |
| 1456 | | glsl_shader_feature, m_glsl_program_num, video_config.filter); |
| 1457 | | } |
| 1458 | | } |
| 1459 | | |
| 1460 | | } else { |
| 1461 | | if (_once) |
| 1462 | | { |
| 1463 | | osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter); |
| 1464 | | } |
| 1465 | | } |
| 1466 | | |
| 1467 | | _once = 0; |
| 1468 | | } |
| 1469 | | |
| 1470 | | //============================================================ |
| 1471 | | // sdl_info::draw |
| 1472 | | //============================================================ |
| 1473 | | |
| 1474 | | int sdl_info_ogl::draw(const int update) |
| 1475 | | { |
| 1476 | | render_primitive *prim; |
| 1477 | | texture_info *texture=NULL; |
| 1478 | | float vofs, hofs; |
| 1479 | | int pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE; |
| 1480 | | |
| 1481 | | #ifdef TOBEMIGRATED |
| 1482 | | if (video_config.novideo) |
| 1483 | | { |
| 1484 | | return 0; |
| 1485 | | } |
| 1486 | | #endif |
| 1487 | | |
| 1488 | | osd_dim wdim = window().get_size(); |
| 1489 | | |
| 1490 | | if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) |
| 1491 | | { |
| 1492 | | destroy_all_textures(); |
| 1493 | | m_width = wdim.width(); |
| 1494 | | m_height = wdim.height(); |
| 1495 | | m_blittimer = 3; |
| 1496 | | m_init_context = 1; |
| 1497 | | clear_flags(FI_CHANGED); |
| 1498 | | } |
| 1499 | | |
| 1500 | | m_gl_context->MakeCurrent(); |
| 1501 | | |
| 1502 | | if (m_init_context) |
| 1503 | | { |
| 1504 | | // do some one-time OpenGL setup |
| 1505 | | #if (SDLMAME_SDL2) |
| 1506 | | // FIXME: SRGB conversion is working on SDL2, may be of use |
| 1507 | | // when we eventually target gamma and monitor profiles. |
| 1508 | | //glEnable(GL_FRAMEBUFFER_SRGB); |
| 1509 | | #endif |
| 1510 | | glShadeModel(GL_SMOOTH); |
| 1511 | | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 1512 | | glClearDepth(1.0f); |
| 1513 | | glEnable(GL_DEPTH_TEST); |
| 1514 | | glDepthFunc(GL_LEQUAL); |
| 1515 | | glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); |
| 1516 | | } |
| 1517 | | |
| 1518 | | // only clear if the geometry changes (and for 2 frames afterward to clear double and triple buffers) |
| 1519 | | if ((m_blittimer > 0) || has_flags(FLAG_HAS_VECTOR_SCREEN)) |
| 1520 | | { |
| 1521 | | glClear(GL_COLOR_BUFFER_BIT); |
| 1522 | | m_blittimer--; |
| 1523 | | } |
| 1524 | | |
| 1525 | | // FIXME: remove m_surf_w and m_surf_h |
| 1526 | | if ( !m_initialized || |
| 1527 | | m_width != m_surf_w || m_height != m_surf_h ) |
| 1528 | | { |
| 1529 | | // FIXME:: this can be done in create! |
| 1530 | | if ( !m_initialized ) |
| 1531 | | { |
| 1532 | | loadGLExtensions(); |
| 1533 | | } |
| 1534 | | |
| 1535 | | #if (!SDLMAME_SDL2) |
| 1536 | | // force all textures to be regenerated |
| 1537 | | destroy_all_textures(); |
| 1538 | | #endif |
| 1539 | | |
| 1540 | | m_surf_w = m_width; |
| 1541 | | m_surf_h = m_height; |
| 1542 | | |
| 1543 | | // we're doing nothing 3d, so the Z-buffer is currently not interesting |
| 1544 | | glDisable(GL_DEPTH_TEST); |
| 1545 | | |
| 1546 | | if (window().machine().options().antialias()) |
| 1547 | | { |
| 1548 | | // enable antialiasing for lines |
| 1549 | | glEnable(GL_LINE_SMOOTH); |
| 1550 | | // enable antialiasing for points |
| 1551 | | glEnable(GL_POINT_SMOOTH); |
| 1552 | | |
| 1553 | | // prefer quality to speed |
| 1554 | | glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); |
| 1555 | | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 1556 | | } |
| 1557 | | else |
| 1558 | | { |
| 1559 | | glDisable(GL_LINE_SMOOTH); |
| 1560 | | glDisable(GL_POINT_SMOOTH); |
| 1561 | | } |
| 1562 | | |
| 1563 | | // enable blending |
| 1564 | | glEnable(GL_BLEND); |
| 1565 | | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 1566 | | m_last_blendmode = BLENDMODE_ALPHA; |
| 1567 | | |
| 1568 | | #ifdef TOBEMIGRATED |
| 1569 | | // set lines and points just barely above normal size to get proper results |
| 1570 | | glLineWidth(video_config.beamwidth); |
| 1571 | | glPointSize(video_config.beamwidth); |
| 1572 | | #endif |
| 1573 | | |
| 1574 | | // set up a nice simple 2D coordinate system, so GL behaves exactly how we'd like. |
| 1575 | | // |
| 1576 | | // (0,0) (w,0) |
| 1577 | | // |~~~~~~~~~| |
| 1578 | | // | | |
| 1579 | | // | | |
| 1580 | | // | | |
| 1581 | | // |_________| |
| 1582 | | // (0,h) (w,h) |
| 1583 | | |
| 1584 | | glViewport(0.0, 0.0, (GLsizei) m_width, (GLsizei) m_height); |
| 1585 | | glMatrixMode(GL_PROJECTION); |
| 1586 | | glLoadIdentity(); |
| 1587 | | glOrtho(0.0, (GLdouble) m_width, (GLdouble) m_height, 0.0, 0.0, -1.0); |
| 1588 | | glMatrixMode(GL_MODELVIEW); |
| 1589 | | glLoadIdentity(); |
| 1590 | | |
| 1591 | | if ( ! m_initialized ) |
| 1592 | | { |
| 1593 | | glEnableClientState(GL_VERTEX_ARRAY); |
| 1594 | | glVertexPointer(2, GL_FLOAT, 0, m_texVerticex); // no VBO, since it's too volatile |
| 1595 | | |
| 1596 | | m_initialized = 1; |
| 1597 | | } |
| 1598 | | } |
| 1599 | | |
| 1600 | | // compute centering parameters |
| 1601 | | vofs = hofs = 0.0f; |
| 1602 | | |
| 1603 | | #ifdef TOBEMIGRATED |
| 1604 | | if (video_config.centerv || video_config.centerh) |
| 1605 | | { |
| 1606 | | int ch, cw; |
| 1607 | | |
| 1608 | | ch = m_height; |
| 1609 | | cw = m_width; |
| 1610 | | |
| 1611 | | if (video_config.centerv) |
| 1612 | | { |
| 1613 | | vofs = (ch - m_blit_dim.height()) / 2.0f; |
| 1614 | | } |
| 1615 | | if (video_config.centerh) |
| 1616 | | { |
| 1617 | | hofs = (cw - m_blit_dim.width()) / 2.0f; |
| 1618 | | } |
| 1619 | | } |
| 1620 | | #else |
| 1621 | | #endif |
| 1622 | | |
| 1623 | | m_last_hofs = hofs; |
| 1624 | | m_last_vofs = vofs; |
| 1625 | | |
| 1626 | | window().m_primlist->acquire_lock(); |
| 1627 | | |
| 1628 | | // now draw |
| 1629 | | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 1630 | | { |
| 1631 | | int i; |
| 1632 | | |
| 1633 | | switch (prim->type) |
| 1634 | | { |
| 1635 | | /** |
| 1636 | | * Try to stay in one Begin/End block as long as possible, |
| 1637 | | * since entering and leaving one is most expensive.. |
| 1638 | | */ |
| 1639 | | case render_primitive::LINE: |
| 1640 | | #if !USE_WIN32_STYLE_LINES |
| 1641 | | // check if it's really a point |
| 1642 | | if (((prim->bounds.x1 - prim->bounds.x0) == 0) && ((prim->bounds.y1 - prim->bounds.y0) == 0)) |
| 1643 | | { |
| 1644 | | curPrimitive=GL_POINTS; |
| 1645 | | } else { |
| 1646 | | curPrimitive=GL_LINES; |
| 1647 | | } |
| 1648 | | |
| 1649 | | if(pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) |
| 1650 | | { |
| 1651 | | glEnd(); |
| 1652 | | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1653 | | } |
| 1654 | | |
| 1655 | | if ( pendingPrimitive==GL_NO_PRIMITIVE ) |
| 1656 | | { |
| 1657 | | set_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1658 | | } |
| 1659 | | |
| 1660 | | glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); |
| 1661 | | |
| 1662 | | if(pendingPrimitive!=curPrimitive) |
| 1663 | | { |
| 1664 | | glBegin(curPrimitive); |
| 1665 | | pendingPrimitive=curPrimitive; |
| 1666 | | } |
| 1667 | | |
| 1668 | | // check if it's really a point |
| 1669 | | if (curPrimitive==GL_POINTS) |
| 1670 | | { |
| 1671 | | glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); |
| 1672 | | } |
| 1673 | | else |
| 1674 | | { |
| 1675 | | glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); |
| 1676 | | glVertex2f(prim->bounds.x1+hofs, prim->bounds.y1+vofs); |
| 1677 | | } |
| 1678 | | #else |
| 1679 | | { |
| 1680 | | const line_aa_step *step = line_aa_4step; |
| 1681 | | render_bounds b0, b1; |
| 1682 | | float r, g, b, a; |
| 1683 | | float effwidth; |
| 1684 | | |
| 1685 | | // we're not gonna play fancy here. close anything pending and let's go. |
| 1686 | | if (pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) |
| 1687 | | { |
| 1688 | | glEnd(); |
| 1689 | | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1690 | | } |
| 1691 | | |
| 1692 | | set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1693 | | |
| 1694 | | // compute the effective width based on the direction of the line |
| 1695 | | effwidth = prim->width(); |
| 1696 | | if (effwidth < 0.5f) |
| 1697 | | effwidth = 0.5f; |
| 1698 | | |
| 1699 | | // determine the bounds of a quad to draw this line |
| 1700 | | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1701 | | |
| 1702 | | // fix window position |
| 1703 | | b0.x0 += hofs; |
| 1704 | | b0.x1 += hofs; |
| 1705 | | b1.x0 += hofs; |
| 1706 | | b1.x1 += hofs; |
| 1707 | | b0.y0 += vofs; |
| 1708 | | b0.y1 += vofs; |
| 1709 | | b1.y0 += vofs; |
| 1710 | | b1.y1 += vofs; |
| 1711 | | |
| 1712 | | // iterate over AA steps |
| 1713 | | for (step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; step->weight != 0; step++) |
| 1714 | | { |
| 1715 | | glBegin(GL_TRIANGLE_STRIP); |
| 1716 | | |
| 1717 | | // rotate the unit vector by 135 degrees and add to point 0 |
| 1718 | | glVertex2f(b0.x0 + step->xoffs, b0.y0 + step->yoffs); |
| 1719 | | |
| 1720 | | // rotate the unit vector by -135 degrees and add to point 0 |
| 1721 | | glVertex2f(b0.x1 + step->xoffs, b0.y1 + step->yoffs); |
| 1722 | | |
| 1723 | | // rotate the unit vector by 45 degrees and add to point 1 |
| 1724 | | glVertex2f(b1.x0 + step->xoffs, b1.y0 + step->yoffs); |
| 1725 | | |
| 1726 | | // rotate the unit vector by -45 degrees and add to point 1 |
| 1727 | | glVertex2f(b1.x1 + step->xoffs, b1.y1 + step->yoffs); |
| 1728 | | |
| 1729 | | // determine the color of the line |
| 1730 | | r = (prim->color.r * step->weight); |
| 1731 | | g = (prim->color.g * step->weight); |
| 1732 | | b = (prim->color.b * step->weight); |
| 1733 | | a = (prim->color.a * 255.0f); |
| 1734 | | if (r > 1.0) r = 1.0; |
| 1735 | | if (g > 1.0) g = 1.0; |
| 1736 | | if (b > 1.0) b = 1.0; |
| 1737 | | if (a > 1.0) a = 1.0; |
| 1738 | | glColor4f(r, g, b, a); |
| 1739 | | |
| 1740 | | // texture = texture_update(window, prim, 0); |
| 1741 | | // if (texture) printf("line has texture!\n"); |
| 1742 | | |
| 1743 | | // if we have a texture to use for the vectors, use it here |
| 1744 | | #if 0 |
| 1745 | | if (d3d->vector_texture != NULL) |
| 1746 | | { |
| 1747 | | printf("SDL: textured lines unsupported\n"); |
| 1748 | | vertex[0].u0 = d3d->vector_texture->ustart; |
| 1749 | | vertex[0].v0 = d3d->vector_texture->vstart; |
| 1750 | | |
| 1751 | | vertex[2].u0 = d3d->vector_texture->ustop; |
| 1752 | | vertex[2].v0 = d3d->vector_texture->vstart; |
| 1753 | | |
| 1754 | | vertex[1].u0 = d3d->vector_texture->ustart; |
| 1755 | | vertex[1].v0 = d3d->vector_texture->vstop; |
| 1756 | | |
| 1757 | | vertex[3].u0 = d3d->vector_texture->ustop; |
| 1758 | | vertex[3].v0 = d3d->vector_texture->vstop; |
| 1759 | | } |
| 1760 | | #endif |
| 1761 | | glEnd(); |
| 1762 | | } |
| 1763 | | } |
| 1764 | | #endif |
| 1765 | | break; |
| 1766 | | |
| 1767 | | case render_primitive::QUAD: |
| 1768 | | |
| 1769 | | if(pendingPrimitive!=GL_NO_PRIMITIVE) |
| 1770 | | { |
| 1771 | | glEnd(); |
| 1772 | | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1773 | | } |
| 1774 | | |
| 1775 | | glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); |
| 1776 | | |
| 1777 | | set_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags)); |
| 1778 | | |
| 1779 | | texture = texture_update(prim, 0); |
| 1780 | | |
| 1781 | | if ( texture && texture->type==TEXTURE_TYPE_SHADER ) |
| 1782 | | { |
| 1783 | | for(i=0; i<m_glsl_program_num; i++) |
| 1784 | | { |
| 1785 | | if ( i==m_glsl_program_mb2sc ) |
| 1786 | | { |
| 1787 | | // i==glsl_program_mb2sc -> transformation mamebm->scrn |
| 1788 | | m_texVerticex[0]=prim->bounds.x0 + hofs; |
| 1789 | | m_texVerticex[1]=prim->bounds.y0 + vofs; |
| 1790 | | m_texVerticex[2]=prim->bounds.x1 + hofs; |
| 1791 | | m_texVerticex[3]=prim->bounds.y0 + vofs; |
| 1792 | | m_texVerticex[4]=prim->bounds.x1 + hofs; |
| 1793 | | m_texVerticex[5]=prim->bounds.y1 + vofs; |
| 1794 | | m_texVerticex[6]=prim->bounds.x0 + hofs; |
| 1795 | | m_texVerticex[7]=prim->bounds.y1 + vofs; |
| 1796 | | } else { |
| 1797 | | // 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1) on texture dimensions |
| 1798 | | m_texVerticex[0]=(GLfloat)0.0; |
| 1799 | | m_texVerticex[1]=(GLfloat)0.0; |
| 1800 | | m_texVerticex[2]=(GLfloat)m_width; |
| 1801 | | m_texVerticex[3]=(GLfloat)0.0; |
| 1802 | | m_texVerticex[4]=(GLfloat)m_width; |
| 1803 | | m_texVerticex[5]=(GLfloat)m_height; |
| 1804 | | m_texVerticex[6]=(GLfloat)0.0; |
| 1805 | | m_texVerticex[7]=(GLfloat)m_height; |
| 1806 | | } |
| 1807 | | |
| 1808 | | if(i>0) // first fetch already done |
| 1809 | | { |
| 1810 | | texture = texture_update(prim, i); |
| 1811 | | } |
| 1812 | | glDrawArrays(GL_QUADS, 0, 4); |
| 1813 | | } |
| 1814 | | } else { |
| 1815 | | m_texVerticex[0]=prim->bounds.x0 + hofs; |
| 1816 | | m_texVerticex[1]=prim->bounds.y0 + vofs; |
| 1817 | | m_texVerticex[2]=prim->bounds.x1 + hofs; |
| 1818 | | m_texVerticex[3]=prim->bounds.y0 + vofs; |
| 1819 | | m_texVerticex[4]=prim->bounds.x1 + hofs; |
| 1820 | | m_texVerticex[5]=prim->bounds.y1 + vofs; |
| 1821 | | m_texVerticex[6]=prim->bounds.x0 + hofs; |
| 1822 | | m_texVerticex[7]=prim->bounds.y1 + vofs; |
| 1823 | | |
| 1824 | | glDrawArrays(GL_QUADS, 0, 4); |
| 1825 | | } |
| 1826 | | |
| 1827 | | if ( texture ) |
| 1828 | | { |
| 1829 | | texture_disable(texture); |
| 1830 | | texture=NULL; |
| 1831 | | } |
| 1832 | | break; |
| 1833 | | |
| 1834 | | default: |
| 1835 | | throw emu_fatalerror("Unexpected render_primitive type"); |
| 1836 | | } |
| 1837 | | } |
| 1838 | | |
| 1839 | | if(pendingPrimitive!=GL_NO_PRIMITIVE) |
| 1840 | | { |
| 1841 | | glEnd(); |
| 1842 | | pendingPrimitive=GL_NO_PRIMITIVE; |
| 1843 | | } |
| 1844 | | |
| 1845 | | window().m_primlist->release_lock(); |
| 1846 | | m_init_context = 0; |
| 1847 | | |
| 1848 | | m_gl_context->SwapBuffer(); |
| 1849 | | |
| 1850 | | return 0; |
| 1851 | | } |
| 1852 | | |
| 1853 | | //============================================================ |
| 1854 | | // texture handling |
| 1855 | | //============================================================ |
| 1856 | | |
| 1857 | | static const char * texfmt_to_string[9] = { |
| 1858 | | "ARGB32", |
| 1859 | | "RGB32", |
| 1860 | | "RGB32_PALETTED", |
| 1861 | | "YUV16", |
| 1862 | | "YUV16_PALETTED", |
| 1863 | | "PALETTE16", |
| 1864 | | "RGB15", |
| 1865 | | "RGB15_PALETTE", |
| 1866 | | "PALETTE16A" |
| 1867 | | }; |
| 1868 | | |
| 1869 | | // |
| 1870 | | // Note: if you change the following array order, change the matching defines in texsrc.h |
| 1871 | | // |
| 1872 | | |
| 1873 | | enum { SDL_TEXFORMAT_SRC_EQUALS_DEST, SDL_TEXFORMAT_SRC_HAS_PALETTE }; |
| 1874 | | |
| 1875 | | static const GLint texture_copy_properties[9][2] = { |
| 1876 | | { TRUE, FALSE }, // SDL_TEXFORMAT_ARGB32 |
| 1877 | | { TRUE, FALSE }, // SDL_TEXFORMAT_RGB32 |
| 1878 | | { TRUE, TRUE }, // SDL_TEXFORMAT_RGB32_PALETTED |
| 1879 | | { FALSE, FALSE }, // SDL_TEXFORMAT_YUY16 |
| 1880 | | { FALSE, TRUE }, // SDL_TEXFORMAT_YUY16_PALETTED |
| 1881 | | { FALSE, TRUE }, // SDL_TEXFORMAT_PALETTE16 |
| 1882 | | { TRUE, FALSE }, // SDL_TEXFORMAT_RGB15 |
| 1883 | | { TRUE, TRUE }, // SDL_TEXFORMAT_RGB15_PALETTED |
| 1884 | | { FALSE, TRUE } // SDL_TEXFORMAT_PALETTE16A |
| 1885 | | }; |
| 1886 | | |
| 1887 | | //============================================================ |
| 1888 | | // drawogl_exit |
| 1889 | | //============================================================ |
| 1890 | | |
| 1891 | | static void drawogl_exit(void) |
| 1892 | | { |
| 1893 | | int i; |
| 1894 | | |
| 1895 | | for(i=0; i<video_config.glsl_shader_mamebm_num; i++) |
| 1896 | | { |
| 1897 | | if ( NULL!=video_config.glsl_shader_mamebm[i]) |
| 1898 | | { |
| 1899 | | free(video_config.glsl_shader_mamebm[i]); |
| 1900 | | video_config.glsl_shader_mamebm[i] = NULL; |
| 1901 | | } |
| 1902 | | } |
| 1903 | | for(i=0; i<video_config.glsl_shader_scrn_num; i++) |
| 1904 | | { |
| 1905 | | if ( NULL!=video_config.glsl_shader_scrn[i]) |
| 1906 | | { |
| 1907 | | free(video_config.glsl_shader_scrn[i]); |
| 1908 | | video_config.glsl_shader_scrn[i] = NULL; |
| 1909 | | } |
| 1910 | | } |
| 1911 | | } |
| 1912 | | |
| 1913 | | //============================================================ |
| 1914 | | // texture_compute_size and type |
| 1915 | | //============================================================ |
| 1916 | | |
| 1917 | | // |
| 1918 | | // glBufferData to push a nocopy texture to the GPU is slower than TexSubImage2D, |
| 1919 | | // so don't use PBO here |
| 1920 | | // |
| 1921 | | // we also don't want to use PBO's in the case of nocopy==TRUE, |
| 1922 | | // since we now might have GLSL shaders - this decision simplifies out life ;-) |
| 1923 | | // |
| 1924 | | void sdl_info_ogl::texture_compute_type_subroutine(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 1925 | | { |
| 1926 | | texture->type = TEXTURE_TYPE_NONE; |
| 1927 | | texture->nocopy = FALSE; |
| 1928 | | |
| 1929 | | if ( texture->type == TEXTURE_TYPE_NONE && |
| 1930 | | !PRIMFLAG_GET_SCREENTEX(flags)) |
| 1931 | | { |
| 1932 | | texture->type = TEXTURE_TYPE_PLAIN; |
| 1933 | | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1934 | | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1935 | | } |
| 1936 | | |
| 1937 | | if ( texture->type == TEXTURE_TYPE_NONE && m_useglsl && |
| 1938 | | texture->xprescale == 1 && texture->yprescale == 1 && |
| 1939 | | texsource->rowpixels <= m_texture_max_width ) |
| 1940 | | { |
| 1941 | | texture->type = TEXTURE_TYPE_SHADER; |
| 1942 | | texture->texTarget = GL_TEXTURE_2D; |
| 1943 | | texture->texpow2 = m_texpoweroftwo; |
| 1944 | | } |
| 1945 | | |
| 1946 | | // determine if we can skip the copy step |
| 1947 | | // if this was not already decided by the shader condition above |
| 1948 | | if ( texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST] && |
| 1949 | | !texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE] && |
| 1950 | | texture->xprescale == 1 && texture->yprescale == 1 && |
| 1951 | | !texture->borderpix && !texsource->palette && |
| 1952 | | texsource->rowpixels <= m_texture_max_width ) |
| 1953 | | { |
| 1954 | | texture->nocopy = TRUE; |
| 1955 | | } |
| 1956 | | |
| 1957 | | if( texture->type == TEXTURE_TYPE_NONE && |
| 1958 | | m_usepbo && !texture->nocopy ) |
| 1959 | | { |
| 1960 | | texture->type = TEXTURE_TYPE_DYNAMIC; |
| 1961 | | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1962 | | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1963 | | } |
| 1964 | | |
| 1965 | | if( texture->type == TEXTURE_TYPE_NONE ) |
| 1966 | | { |
| 1967 | | texture->type = TEXTURE_TYPE_SURFACE; |
| 1968 | | texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D; |
| 1969 | | texture->texpow2 = (m_usetexturerect)?0:m_texpoweroftwo; |
| 1970 | | } |
| 1971 | | } |
| 1972 | | |
| 1973 | | INLINE int get_valid_pow2_value(int v, int needPow2) |
| 1974 | | { |
| 1975 | | return (needPow2)?gl_round_to_pow2(v):v; |
| 1976 | | } |
| 1977 | | |
| 1978 | | void sdl_info_ogl::texture_compute_size_subroutine(texture_info *texture, UINT32 flags, |
| 1979 | | UINT32 width, UINT32 height, |
| 1980 | | int* p_width, int* p_height, int* p_width_create, int* p_height_create) |
| 1981 | | { |
| 1982 | | int width_create; |
| 1983 | | int height_create; |
| 1984 | | |
| 1985 | | if ( texture->texpow2 ) |
| 1986 | | { |
| 1987 | | width_create = gl_round_to_pow2 (width); |
| 1988 | | height_create = gl_round_to_pow2 (height); |
| 1989 | | } else if ( texture->type==TEXTURE_TYPE_SHADER ) |
| 1990 | | { |
| 1991 | | /** |
| 1992 | | * at least use a multiple of 8 for shader .. just in case |
| 1993 | | */ |
| 1994 | | width_create = ( width & ~0x07 ) + ( (width & 0x07)? 8 : 0 ) ; |
| 1995 | | height_create = ( height & ~0x07 ) + ( (height & 0x07)? 8 : 0 ) ; |
| 1996 | | } else { |
| 1997 | | width_create = width ; |
| 1998 | | height_create = height ; |
| 1999 | | } |
| 2000 | | |
| 2001 | | // don't prescale above max texture size |
| 2002 | | while (texture->xprescale > 1 && width_create * texture->xprescale > m_texture_max_width) |
| 2003 | | texture->xprescale--; |
| 2004 | | while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height) |
| 2005 | | texture->yprescale--; |
| 2006 | | if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != window().prescale() || texture->yprescale != window().prescale())) |
| 2007 | | osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", window().prescale(), window().prescale(), texture->xprescale, texture->yprescale); |
| 2008 | | |
| 2009 | | width *= texture->xprescale; |
| 2010 | | height *= texture->yprescale; |
| 2011 | | width_create *= texture->xprescale; |
| 2012 | | height_create *= texture->yprescale; |
| 2013 | | |
| 2014 | | // adjust the size for the border (must do this *after* the power of 2 clamp to satisfy |
| 2015 | | // OpenGL semantics) |
| 2016 | | if (texture->borderpix) |
| 2017 | | { |
| 2018 | | width += 2; |
| 2019 | | height += 2; |
| 2020 | | width_create += 2; |
| 2021 | | height_create += 2; |
| 2022 | | } |
| 2023 | | *p_width=width; |
| 2024 | | *p_height=height; |
| 2025 | | *p_width_create=width_create; |
| 2026 | | *p_height_create=height_create; |
| 2027 | | } |
| 2028 | | |
| 2029 | | void sdl_info_ogl::texture_compute_size_type(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 2030 | | { |
| 2031 | | int finalheight, finalwidth; |
| 2032 | | int finalheight_create, finalwidth_create; |
| 2033 | | |
| 2034 | | // if we're not wrapping, add a 1 pixel border on all sides |
| 2035 | | texture->borderpix = 0; //!(texture->flags & PRIMFLAG_TEXWRAP_MASK); |
| 2036 | | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 2037 | | { |
| 2038 | | texture->borderpix = 0; // don't border the screen right now, there's a bug |
| 2039 | | } |
| 2040 | | |
| 2041 | | texture_compute_type_subroutine(texsource, texture, flags); |
| 2042 | | |
| 2043 | | texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height, |
| 2044 | | &finalwidth, &finalheight, &finalwidth_create, &finalheight_create); |
| 2045 | | |
| 2046 | | // if we added pixels for the border, and that just barely pushed us over, take it back |
| 2047 | | if (texture->borderpix && |
| 2048 | | ((finalwidth > m_texture_max_width && finalwidth - 2 <= m_texture_max_width) || |
| 2049 | | (finalheight > m_texture_max_height && finalheight - 2 <= m_texture_max_height))) |
| 2050 | | { |
| 2051 | | texture->borderpix = FALSE; |
| 2052 | | |
| 2053 | | texture_compute_type_subroutine(texsource, texture, flags); |
| 2054 | | |
| 2055 | | texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height, |
| 2056 | | &finalwidth, &finalheight, &finalwidth_create, &finalheight_create); |
| 2057 | | } |
| 2058 | | |
| 2059 | | // if we're above the max width/height, do what? |
| 2060 | | if (finalwidth_create > m_texture_max_width || finalheight_create > m_texture_max_height) |
| 2061 | | { |
| 2062 | | static int printed = FALSE; |
| 2063 | | if (!printed) |
| 2064 | | osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth_create, finalheight_create, m_texture_max_width, m_texture_max_height); |
| 2065 | | printed = TRUE; |
| 2066 | | } |
| 2067 | | |
| 2068 | | if(!texture->nocopy || texture->type==TEXTURE_TYPE_DYNAMIC || texture->type==TEXTURE_TYPE_SHADER || |
| 2069 | | // any of the mame core's device generated bitmap types: |
| 2070 | | texture->format==SDL_TEXFORMAT_RGB32 || |
| 2071 | | texture->format==SDL_TEXFORMAT_RGB32_PALETTED || |
| 2072 | | texture->format==SDL_TEXFORMAT_RGB15 || |
| 2073 | | texture->format==SDL_TEXFORMAT_RGB15_PALETTED || |
| 2074 | | texture->format==SDL_TEXFORMAT_PALETTE16 || |
| 2075 | | texture->format==SDL_TEXFORMAT_PALETTE16A |
| 2076 | | ) |
| 2077 | | { |
| 2078 | | osd_printf_verbose("GL texture: copy %d, shader %d, dynamic %d, %dx%d %dx%d [%s, Equal: %d, Palette: %d,\n" |
| 2079 | | " scale %dx%d, border %d, pitch %d,%d/%d], bytes/pix %d\n", |
| 2080 | | !texture->nocopy, texture->type==TEXTURE_TYPE_SHADER, texture->type==TEXTURE_TYPE_DYNAMIC, |
| 2081 | | finalwidth, finalheight, finalwidth_create, finalheight_create, |
| 2082 | | texfmt_to_string[texture->format], |
| 2083 | | (int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST], |
| 2084 | | (int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE], |
| 2085 | | texture->xprescale, texture->yprescale, |
| 2086 | | texture->borderpix, texsource->rowpixels, finalwidth, m_texture_max_width, |
| 2087 | | (int)sizeof(UINT32) |
| 2088 | | ); |
| 2089 | | } |
| 2090 | | |
| 2091 | | // set the final values |
| 2092 | | texture->rawwidth = finalwidth; |
| 2093 | | texture->rawheight = finalheight; |
| 2094 | | texture->rawwidth_create = finalwidth_create; |
| 2095 | | texture->rawheight_create = finalheight_create; |
| 2096 | | } |
| 2097 | | |
| 2098 | | //============================================================ |
| 2099 | | // texture_create |
| 2100 | | //============================================================ |
| 2101 | | |
| 2102 | | static int gl_checkFramebufferStatus(void) |
| 2103 | | { |
| 2104 | | GLenum status; |
| 2105 | | status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); |
| 2106 | | switch(status) { |
| 2107 | | case GL_FRAMEBUFFER_COMPLETE_EXT: |
| 2108 | | return 0; |
| 2109 | | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: |
| 2110 | | osd_printf_error("GL FBO: incomplete,incomplete attachment\n"); |
| 2111 | | return -1; |
| 2112 | | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: |
| 2113 | | osd_printf_error("GL FBO: Unsupported framebuffer format\n"); |
| 2114 | | return -1; |
| 2115 | | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: |
| 2116 | | osd_printf_error("GL FBO: incomplete,missing attachment\n"); |
| 2117 | | return -1; |
| 2118 | | case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: |
| 2119 | | osd_printf_error("GL FBO: incomplete,attached images must have same dimensions\n"); |
| 2120 | | return -1; |
| 2121 | | case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: |
| 2122 | | osd_printf_error("GL FBO: incomplete,attached images must have same format\n"); |
| 2123 | | return -1; |
| 2124 | | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: |
| 2125 | | osd_printf_error("GL FBO: incomplete,missing draw buffer\n"); |
| 2126 | | return -1; |
| 2127 | | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: |
| 2128 | | osd_printf_error("GL FBO: incomplete,missing read buffer\n"); |
| 2129 | | return -1; |
| 2130 | | #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT |
| 2131 | | case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: |
| 2132 | | osd_printf_error("GL FBO: incomplete, duplicate attachment\n"); |
| 2133 | | return -1; |
| 2134 | | #endif |
| 2135 | | case 0: |
| 2136 | | osd_printf_error("GL FBO: incomplete, implementation fault\n"); |
| 2137 | | return -1; |
| 2138 | | default: |
| 2139 | | osd_printf_error("GL FBO: incomplete, implementation ERROR\n"); |
| 2140 | | /* fall through */ |
| 2141 | | } |
| 2142 | | return -1; |
| 2143 | | } |
| 2144 | | |
| 2145 | | static int texture_fbo_create(UINT32 text_unit, UINT32 text_name, UINT32 fbo_name, int width, int height) |
| 2146 | | { |
| 2147 | | pfn_glActiveTexture(text_unit); |
| 2148 | | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name); |
| 2149 | | glBindTexture(GL_TEXTURE_2D, text_name); |
| 2150 | | { |
| 2151 | | GLint _width, _height; |
| 2152 | | if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, |
| 2153 | | 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) ) |
| 2154 | | { |
| 2155 | | osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n", |
| 2156 | | width, height, (int)_width, (int)_height); |
| 2157 | | return -1; |
| 2158 | | } |
| 2159 | | |
| 2160 | | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, |
| 2161 | | 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL ); |
| 2162 | | } |
| 2163 | | // non-screen textures will never be filtered |
| 2164 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2165 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2166 | | |
| 2167 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2168 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2169 | | |
| 2170 | | pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| 2171 | | GL_TEXTURE_2D, text_name, 0); |
| 2172 | | |
| 2173 | | if ( gl_checkFramebufferStatus() ) |
| 2174 | | { |
| 2175 | | osd_printf_error("FBO error fbo texture - bail out\n"); |
| 2176 | | return -1; |
| 2177 | | } |
| 2178 | | |
| 2179 | | return 0; |
| 2180 | | } |
| 2181 | | |
| 2182 | | int sdl_info_ogl::texture_shader_create(const render_texinfo *texsource, texture_info *texture, UINT32 flags) |
| 2183 | | { |
| 2184 | | int uniform_location; |
| 2185 | | int i; |
| 2186 | | int surf_w_pow2 = get_valid_pow2_value (m_blit_dim.width(), texture->texpow2); |
| 2187 | | int surf_h_pow2 = get_valid_pow2_value (m_blit_dim.height(), texture->texpow2); |
| 2188 | | |
| 2189 | | assert ( texture->type==TEXTURE_TYPE_SHADER ); |
| 2190 | | |
| 2191 | | GL_CHECK_ERROR_QUIET(); |
| 2192 | | |
| 2193 | | if( m_glsl_program_num > 1 ) |
| 2194 | | { |
| 2195 | | // multipass mode |
| 2196 | | assert(m_usefbo); |
| 2197 | | |
| 2198 | | // GL_TEXTURE3 GLSL Uniforms |
| 2199 | | texture->mpass_dest_idx = 0; |
| 2200 | | texture->mpass_textureunit[0] = GL_TEXTURE3; |
| 2201 | | texture->mpass_textureunit[1] = GL_TEXTURE2; |
| 2202 | | } |
| 2203 | | |
| 2204 | | for(i=0; i<m_glsl_program_num; i++) |
| 2205 | | { |
| 2206 | | if ( i<=m_glsl_program_mb2sc ) |
| 2207 | | { |
| 2208 | | m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i); |
| 2209 | | } else { |
| 2210 | | m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc); |
| 2211 | | } |
| 2212 | | pfn_glUseProgramObjectARB(m_glsl_program[i]); |
| 2213 | | |
| 2214 | | if ( i<=m_glsl_program_mb2sc ) |
| 2215 | | { |
| 2216 | | // GL_TEXTURE0 GLSL Uniforms |
| 2217 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture"); |
| 2218 | | pfn_glUniform1iARB(uniform_location, 0); |
| 2219 | | GL_CHECK_ERROR_NORMAL(); |
| 2220 | | } |
| 2221 | | |
| 2222 | | { |
| 2223 | | GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight }; |
| 2224 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz"); |
| 2225 | | pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0])); |
| 2226 | | GL_CHECK_ERROR_NORMAL(); |
| 2227 | | } |
| 2228 | | |
| 2229 | | GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create }; |
| 2230 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz"); |
| 2231 | | pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0])); |
| 2232 | | GL_CHECK_ERROR_NORMAL(); |
| 2233 | | |
| 2234 | | GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() }; |
| 2235 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz"); |
| 2236 | | pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0])); |
| 2237 | | GL_CHECK_ERROR_NORMAL(); |
| 2238 | | |
| 2239 | | GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 }; |
| 2240 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz"); |
| 2241 | | pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0])); |
| 2242 | | GL_CHECK_ERROR_NORMAL(); |
| 2243 | | } |
| 2244 | | |
| 2245 | | pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader |
| 2246 | | |
| 2247 | | if( m_glsl_program_num > 1 ) |
| 2248 | | { |
| 2249 | | // multipass mode |
| 2250 | | // GL_TEXTURE2/GL_TEXTURE3 |
| 2251 | | pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]); |
| 2252 | | glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]); |
| 2253 | | |
| 2254 | | for (i=0; i<2; i++) |
| 2255 | | { |
| 2256 | | if ( texture_fbo_create(texture->mpass_textureunit[i], |
| 2257 | | texture->mpass_texture_mamebm[i], |
| 2258 | | texture->mpass_fbo_mamebm[i], |
| 2259 | | texture->rawwidth_create, texture->rawheight_create) ) |
| 2260 | | { |
| 2261 | | return -1; |
| 2262 | | } |
| 2263 | | } |
| 2264 | | |
| 2265 | | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 2266 | | |
| 2267 | | osd_printf_verbose("GL texture: mpass mame-bmp 2x %dx%d (pow2 %dx%d)\n", |
| 2268 | | texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create); |
| 2269 | | } |
| 2270 | | |
| 2271 | | if( m_glsl_program_num > 1 && m_glsl_program_mb2sc < m_glsl_program_num - 1 ) |
| 2272 | | { |
| 2273 | | // multipass mode |
| 2274 | | // GL_TEXTURE2/GL_TEXTURE3 |
| 2275 | | pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]); |
| 2276 | | glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]); |
| 2277 | | |
| 2278 | | for (i=0; i<2; i++) |
| 2279 | | { |
| 2280 | | if ( texture_fbo_create(texture->mpass_textureunit[i], |
| 2281 | | texture->mpass_texture_scrn[i], |
| 2282 | | texture->mpass_fbo_scrn[i], |
| 2283 | | surf_w_pow2, surf_h_pow2) ) |
| 2284 | | { |
| 2285 | | return -1; |
| 2286 | | } |
| 2287 | | } |
| 2288 | | |
| 2289 | | osd_printf_verbose("GL texture: mpass screen-bmp 2x %dx%d (pow2 %dx%d)\n", |
| 2290 | | m_width, m_height, surf_w_pow2, surf_h_pow2); |
| 2291 | | } |
| 2292 | | |
| 2293 | | // GL_TEXTURE0 |
| 2294 | | // get a name for this texture |
| 2295 | | glGenTextures(1, (GLuint *)&texture->texture); |
| 2296 | | pfn_glActiveTexture(GL_TEXTURE0); |
| 2297 | | glBindTexture(GL_TEXTURE_2D, texture->texture); |
| 2298 | | |
| 2299 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create); |
| 2300 | | |
| 2301 | | UINT32 * dummy = NULL; |
| 2302 | | GLint _width, _height; |
| 2303 | | if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, |
| 2304 | | texture->rawwidth_create, texture->rawheight_create, |
| 2305 | | 0, |
| 2306 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, |
| 2307 | | &_width, &_height, 1) ) |
| 2308 | | { |
| 2309 | | osd_printf_error("cannot create bitmap texture, req: %dx%d, avail: %dx%d - bail out\n", |
| 2310 | | texture->rawwidth_create, texture->rawheight_create, (int)_width, (int)_height); |
| 2311 | | return -1; |
| 2312 | | } |
| 2313 | | |
| 2314 | | dummy = (UINT32 *) malloc(texture->rawwidth_create * texture->rawheight_create * sizeof(UINT32)); |
| 2315 | | memset(dummy, 0, texture->rawwidth_create * texture->rawheight_create * sizeof(UINT32)); |
| 2316 | | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, |
| 2317 | | texture->rawwidth_create, texture->rawheight_create, |
| 2318 | | 0, |
| 2319 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dummy); |
| 2320 | | glFinish(); // should not be necessary, .. but make sure we won't access the memory after free |
| 2321 | | free(dummy); |
| 2322 | | |
| 2323 | | if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter) |
| 2324 | | { |
| 2325 | | assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN ); |
| 2326 | | |
| 2327 | | // screen textures get the user's choice of filtering |
| 2328 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 2329 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 2330 | | } |
| 2331 | | else |
| 2332 | | { |
| 2333 | | // non-screen textures will never be filtered |
| 2334 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2335 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2336 | | } |
| 2337 | | |
| 2338 | | // set wrapping mode appropriately |
| 2339 | | if (texture->flags & PRIMFLAG_TEXWRAP_MASK) |
| 2340 | | { |
| 2341 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| 2342 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| 2343 | | } |
| 2344 | | else |
| 2345 | | { |
| 2346 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2347 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2348 | | } |
| 2349 | | |
| 2350 | | GL_CHECK_ERROR_NORMAL(); |
| 2351 | | |
| 2352 | | return 0; |
| 2353 | | } |
| 2354 | | |
| 2355 | | texture_info *sdl_info_ogl::texture_create(const render_texinfo *texsource, UINT32 flags) |
| 2356 | | { |
| 2357 | | texture_info *texture; |
| 2358 | | |
| 2359 | | // allocate a new texture |
| 2360 | | texture = global_alloc(texture_info); |
| 2361 | | |
| 2362 | | // fill in the core data |
| 2363 | | texture->hash = texture_compute_hash(texsource, flags); |
| 2364 | | texture->flags = flags; |
| 2365 | | texture->texinfo = *texsource; |
| 2366 | | texture->texinfo.seqid = -1; // force set data |
| 2367 | | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 2368 | | { |
| 2369 | | texture->xprescale = window().prescale(); |
| 2370 | | texture->yprescale = window().prescale(); |
| 2371 | | } |
| 2372 | | else |
| 2373 | | { |
| 2374 | | texture->xprescale = 1; |
| 2375 | | texture->yprescale = 1; |
| 2376 | | } |
| 2377 | | |
| 2378 | | // set the texture_format |
| 2379 | | // |
| 2380 | | // src/emu/validity.c:validate_display() states, |
| 2381 | | // an emulated driver can only produce |
| 2382 | | // BITMAP_FORMAT_IND16 and BITMAP_FORMAT_RGB32 |
| 2383 | | // where only the first original paletted. |
| 2384 | | // |
| 2385 | | // other paletted formats, i.e.: |
| 2386 | | // SDL_TEXFORMAT_RGB32_PALETTED, SDL_TEXFORMAT_RGB15_PALETTED and SDL_TEXFORMAT_YUY16_PALETTED |
| 2387 | | // add features like brightness etc by the mame core |
| 2388 | | // |
| 2389 | | // all palette lookup may be implemented using shaders later on .. |
| 2390 | | // that's why we keep the EQUAL flag TRUE, for all original true color bitmaps. |
| 2391 | | // |
| 2392 | | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2393 | | { |
| 2394 | | case TEXFORMAT_ARGB32: |
| 2395 | | texture->format = SDL_TEXFORMAT_ARGB32; |
| 2396 | | break; |
| 2397 | | case TEXFORMAT_RGB32: |
| 2398 | | if (texsource->palette != NULL) |
| 2399 | | texture->format = SDL_TEXFORMAT_RGB32_PALETTED; |
| 2400 | | else |
| 2401 | | texture->format = SDL_TEXFORMAT_RGB32; |
| 2402 | | break; |
| 2403 | | case TEXFORMAT_PALETTE16: |
| 2404 | | texture->format = SDL_TEXFORMAT_PALETTE16; |
| 2405 | | break; |
| 2406 | | case TEXFORMAT_PALETTEA16: |
| 2407 | | texture->format = SDL_TEXFORMAT_PALETTE16A; |
| 2408 | | break; |
| 2409 | | case TEXFORMAT_YUY16: |
| 2410 | | if (texsource->palette != NULL) |
| 2411 | | texture->format = SDL_TEXFORMAT_YUY16_PALETTED; |
| 2412 | | else |
| 2413 | | texture->format = SDL_TEXFORMAT_YUY16; |
| 2414 | | break; |
| 2415 | | |
| 2416 | | default: |
| 2417 | | osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2418 | | } |
| 2419 | | |
| 2420 | | // compute the size |
| 2421 | | texture_compute_size_type(texsource, texture, flags); |
| 2422 | | |
| 2423 | | texture->pbo=0; |
| 2424 | | |
| 2425 | | if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl) |
| 2426 | | { |
| 2427 | | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 2428 | | } |
| 2429 | | |
| 2430 | | if ( texture->type==TEXTURE_TYPE_SHADER ) |
| 2431 | | { |
| 2432 | | if ( texture_shader_create(texsource, texture, flags) ) |
| 2433 | | { |
| 2434 | | global_free(texture); |
| 2435 | | return NULL; |
| 2436 | | } |
| 2437 | | } |
| 2438 | | else |
| 2439 | | { |
| 2440 | | // get a name for this texture |
| 2441 | | glGenTextures(1, (GLuint *)&texture->texture); |
| 2442 | | |
| 2443 | | glEnable(texture->texTarget); |
| 2444 | | |
| 2445 | | // make sure we're operating on *this* texture |
| 2446 | | glBindTexture(texture->texTarget, texture->texture); |
| 2447 | | |
| 2448 | | // this doesn't actually upload, it just sets up the PBO's parameters |
| 2449 | | glTexImage2D(texture->texTarget, 0, GL_RGBA8, |
| 2450 | | texture->rawwidth_create, texture->rawheight_create, |
| 2451 | | texture->borderpix ? 1 : 0, |
| 2452 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); |
| 2453 | | |
| 2454 | | if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter) |
| 2455 | | { |
| 2456 | | // screen textures get the user's choice of filtering |
| 2457 | | glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 2458 | | glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 2459 | | } |
| 2460 | | else |
| 2461 | | { |
| 2462 | | // non-screen textures will never be filtered |
| 2463 | | glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 2464 | | glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 2465 | | } |
| 2466 | | |
| 2467 | | if( texture->texTarget==GL_TEXTURE_RECTANGLE_ARB ) |
| 2468 | | { |
| 2469 | | // texture rectangles can't wrap |
| 2470 | | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2471 | | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2472 | | } else { |
| 2473 | | // set wrapping mode appropriately |
| 2474 | | if (texture->flags & PRIMFLAG_TEXWRAP_MASK) |
| 2475 | | { |
| 2476 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| 2477 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| 2478 | | } |
| 2479 | | else |
| 2480 | | { |
| 2481 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); |
| 2482 | | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); |
| 2483 | | } |
| 2484 | | } |
| 2485 | | } |
| 2486 | | |
| 2487 | | if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2488 | | { |
| 2489 | | assert(m_usepbo); |
| 2490 | | |
| 2491 | | // create the PBO |
| 2492 | | pfn_glGenBuffers(1, (GLuint *)&texture->pbo); |
| 2493 | | |
| 2494 | | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); |
| 2495 | | |
| 2496 | | // set up the PBO dimension, .. |
| 2497 | | pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, |
| 2498 | | texture->rawwidth * texture->rawheight * sizeof(UINT32), |
| 2499 | | NULL, GL_STREAM_DRAW); |
| 2500 | | } |
| 2501 | | |
| 2502 | | if ( !texture->nocopy && texture->type!=TEXTURE_TYPE_DYNAMIC ) |
| 2503 | | { |
| 2504 | | texture->data = (UINT32 *) malloc(texture->rawwidth* texture->rawheight * sizeof(UINT32)); |
| 2505 | | texture->data_own=TRUE; |
| 2506 | | } |
| 2507 | | |
| 2508 | | // add us to the texture list |
| 2509 | | if (m_texhash[texture->hash] == NULL) |
| 2510 | | m_texhash[texture->hash] = texture; |
| 2511 | | else |
| 2512 | | { |
| 2513 | | int i; |
| 2514 | | for (i = HASH_SIZE; i < HASH_SIZE + OVERFLOW_SIZE; i++) |
| 2515 | | if (m_texhash[i] == NULL) |
| 2516 | | { |
| 2517 | | m_texhash[i] = texture; |
| 2518 | | break; |
| 2519 | | } |
| 2520 | | assert_always(i < HASH_SIZE + OVERFLOW_SIZE, "texture hash exhausted ..."); |
| 2521 | | } |
| 2522 | | |
| 2523 | | if(m_usevbo) |
| 2524 | | { |
| 2525 | | // Generate And Bind The Texture Coordinate Buffer |
| 2526 | | pfn_glGenBuffers( 1, &(texture->texCoordBufferName) ); |
| 2527 | | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); |
| 2528 | | // Load The Data |
| 2529 | | pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW ); |
| 2530 | | glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // we are using ARB VBO buffers |
| 2531 | | } |
| 2532 | | else |
| 2533 | | { |
| 2534 | | glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord); |
| 2535 | | } |
| 2536 | | |
| 2537 | | return texture; |
| 2538 | | } |
| 2539 | | |
| 2540 | | //============================================================ |
| 2541 | | // copyline_palette16 |
| 2542 | | //============================================================ |
| 2543 | | |
| 2544 | | INLINE void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2545 | | { |
| 2546 | | int x; |
| 2547 | | |
| 2548 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2549 | | if (xborderpix) |
| 2550 | | *dst++ = 0xff000000 | palette[*src]; |
| 2551 | | for (x = 0; x < width; x++) |
| 2552 | | { |
| 2553 | | int srcpix = *src++; |
| 2554 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2555 | | *dst++ = 0xff000000 | palette[srcpix]; |
| 2556 | | } |
| 2557 | | if (xborderpix) |
| 2558 | | *dst++ = 0xff000000 | palette[*--src]; |
| 2559 | | } |
| 2560 | | |
| 2561 | | |
| 2562 | | |
| 2563 | | //============================================================ |
| 2564 | | // copyline_palettea16 |
| 2565 | | //============================================================ |
| 2566 | | |
| 2567 | | INLINE void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2568 | | { |
| 2569 | | int x; |
| 2570 | | |
| 2571 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2572 | | if (xborderpix) |
| 2573 | | *dst++ = palette[*src]; |
| 2574 | | for (x = 0; x < width; x++) |
| 2575 | | { |
| 2576 | | int srcpix = *src++; |
| 2577 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2578 | | *dst++ = palette[srcpix]; |
| 2579 | | } |
| 2580 | | if (xborderpix) |
| 2581 | | *dst++ = palette[*--src]; |
| 2582 | | } |
| 2583 | | |
| 2584 | | |
| 2585 | | |
| 2586 | | //============================================================ |
| 2587 | | // copyline_rgb32 |
| 2588 | | //============================================================ |
| 2589 | | |
| 2590 | | INLINE void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2591 | | { |
| 2592 | | int x; |
| 2593 | | |
| 2594 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2595 | | |
| 2596 | | // palette (really RGB map) case |
| 2597 | | if (palette != NULL) |
| 2598 | | { |
| 2599 | | if (xborderpix) |
| 2600 | | { |
| 2601 | | rgb_t srcpix = *src; |
| 2602 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2603 | | } |
| 2604 | | for (x = 0; x < width; x++) |
| 2605 | | { |
| 2606 | | rgb_t srcpix = *src++; |
| 2607 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2608 | | { |
| 2609 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2610 | | } |
| 2611 | | } |
| 2612 | | if (xborderpix) |
| 2613 | | { |
| 2614 | | rgb_t srcpix = *--src; |
| 2615 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2616 | | } |
| 2617 | | } |
| 2618 | | |
| 2619 | | // direct case |
| 2620 | | else |
| 2621 | | { |
| 2622 | | if (xborderpix) |
| 2623 | | *dst++ = 0xff000000 | *src; |
| 2624 | | for (x = 0; x < width; x++) |
| 2625 | | { |
| 2626 | | rgb_t srcpix = *src++; |
| 2627 | | |
| 2628 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2629 | | { |
| 2630 | | *dst++ = 0xff000000 | srcpix; |
| 2631 | | } |
| 2632 | | } |
| 2633 | | if (xborderpix) |
| 2634 | | *dst++ = 0xff000000 | *--src; |
| 2635 | | } |
| 2636 | | } |
| 2637 | | |
| 2638 | | //============================================================ |
| 2639 | | // copyline_argb32 |
| 2640 | | //============================================================ |
| 2641 | | |
| 2642 | | INLINE void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2643 | | { |
| 2644 | | int x; |
| 2645 | | |
| 2646 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2647 | | |
| 2648 | | // palette (really RGB map) case |
| 2649 | | if (palette != NULL) |
| 2650 | | { |
| 2651 | | if (xborderpix) |
| 2652 | | { |
| 2653 | | rgb_t srcpix = *src; |
| 2654 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2655 | | } |
| 2656 | | for (x = 0; x < width; x++) |
| 2657 | | { |
| 2658 | | rgb_t srcpix = *src++; |
| 2659 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2660 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2661 | | } |
| 2662 | | if (xborderpix) |
| 2663 | | { |
| 2664 | | rgb_t srcpix = *--src; |
| 2665 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2666 | | } |
| 2667 | | } |
| 2668 | | |
| 2669 | | // direct case |
| 2670 | | else |
| 2671 | | { |
| 2672 | | if (xborderpix) |
| 2673 | | *dst++ = *src; |
| 2674 | | for (x = 0; x < width; x++) |
| 2675 | | { |
| 2676 | | rgb_t srcpix = *src++; |
| 2677 | | for (int x2 = 0; x2 < xprescale; x2++) |
| 2678 | | *dst++ = srcpix; |
| 2679 | | } |
| 2680 | | if (xborderpix) |
| 2681 | | *dst++ = *--src; |
| 2682 | | } |
| 2683 | | } |
| 2684 | | |
| 2685 | | INLINE UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) |
| 2686 | | { |
| 2687 | | /* original equations: |
| 2688 | | |
| 2689 | | C = Y - 16 |
| 2690 | | D = Cb - 128 |
| 2691 | | E = Cr - 128 |
| 2692 | | |
| 2693 | | R = clip(( 298 * C + 409 * E + 128) >> 8) |
| 2694 | | G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) |
| 2695 | | B = clip(( 298 * C + 516 * D + 128) >> 8) |
| 2696 | | |
| 2697 | | R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) |
| 2698 | | G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) |
| 2699 | | B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) |
| 2700 | | |
| 2701 | | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 2702 | | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 2703 | | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 2704 | | |
| 2705 | | R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) |
| 2706 | | G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) |
| 2707 | | B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) |
| 2708 | | */ |
| 2709 | | int r, g, b, common; |
| 2710 | | |
| 2711 | | common = 298 * y - 298 * 16; |
| 2712 | | r = (common + 409 * cr - 409 * 128 + 128) >> 8; |
| 2713 | | g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; |
| 2714 | | b = (common + 516 * cb - 516 * 128 + 128) >> 8; |
| 2715 | | |
| 2716 | | if (r < 0) r = 0; |
| 2717 | | else if (r > 255) r = 255; |
| 2718 | | if (g < 0) g = 0; |
| 2719 | | else if (g > 255) g = 255; |
| 2720 | | if (b < 0) b = 0; |
| 2721 | | else if (b > 255) b = 255; |
| 2722 | | |
| 2723 | | return rgb_t(0xff, r, g, b); |
| 2724 | | } |
| 2725 | | |
| 2726 | | //============================================================ |
| 2727 | | // copyline_yuy16_to_argb |
| 2728 | | //============================================================ |
| 2729 | | |
| 2730 | | INLINE void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix, int xprescale) |
| 2731 | | { |
| 2732 | | int x; |
| 2733 | | |
| 2734 | | assert(xborderpix == 0 || xborderpix == 2); |
| 2735 | | assert(width % 2 == 0); |
| 2736 | | |
| 2737 | | // palette (really RGB map) case |
| 2738 | | if (palette != NULL) |
| 2739 | | { |
| 2740 | | if (xborderpix) |
| 2741 | | { |
| 2742 | | UINT16 srcpix0 = src[0]; |
| 2743 | | UINT16 srcpix1 = src[1]; |
| 2744 | | UINT8 cb = srcpix0 & 0xff; |
| 2745 | | UINT8 cr = srcpix1 & 0xff; |
| 2746 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2747 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2748 | | } |
| 2749 | | for (x = 0; x < width / 2; x++) |
| 2750 | | { |
| 2751 | | UINT16 srcpix0 = *src++; |
| 2752 | | UINT16 srcpix1 = *src++; |
| 2753 | | UINT8 cb = srcpix0 & 0xff; |
| 2754 | | UINT8 cr = srcpix1 & 0xff; |
| 2755 | | for (int x2 = 0; x2 < xprescale/2; x2++) |
| 2756 | | { |
| 2757 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2758 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2759 | | } |
| 2760 | | } |
| 2761 | | if (xborderpix) |
| 2762 | | { |
| 2763 | | UINT16 srcpix1 = *--src; |
| 2764 | | UINT16 srcpix0 = *--src; |
| 2765 | | UINT8 cb = srcpix0 & 0xff; |
| 2766 | | UINT8 cr = srcpix1 & 0xff; |
| 2767 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2768 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2769 | | } |
| 2770 | | } |
| 2771 | | |
| 2772 | | // direct case |
| 2773 | | else |
| 2774 | | { |
| 2775 | | if (xborderpix) |
| 2776 | | { |
| 2777 | | UINT16 srcpix0 = src[0]; |
| 2778 | | UINT16 srcpix1 = src[1]; |
| 2779 | | UINT8 cb = srcpix0 & 0xff; |
| 2780 | | UINT8 cr = srcpix1 & 0xff; |
| 2781 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2782 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2783 | | } |
| 2784 | | for (x = 0; x < width; x += 2) |
| 2785 | | { |
| 2786 | | UINT16 srcpix0 = *src++; |
| 2787 | | UINT16 srcpix1 = *src++; |
| 2788 | | UINT8 cb = srcpix0 & 0xff; |
| 2789 | | UINT8 cr = srcpix1 & 0xff; |
| 2790 | | for (int x2 = 0; x2 < xprescale/2; x2++) |
| 2791 | | { |
| 2792 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2793 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2794 | | } |
| 2795 | | } |
| 2796 | | if (xborderpix) |
| 2797 | | { |
| 2798 | | UINT16 srcpix1 = *--src; |
| 2799 | | UINT16 srcpix0 = *--src; |
| 2800 | | UINT8 cb = srcpix0 & 0xff; |
| 2801 | | UINT8 cr = srcpix1 & 0xff; |
| 2802 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2803 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2804 | | } |
| 2805 | | } |
| 2806 | | } |
| 2807 | | |
| 2808 | | //============================================================ |
| 2809 | | // texture_set_data |
| 2810 | | //============================================================ |
| 2811 | | |
| 2812 | | static void texture_set_data(texture_info *texture, const render_texinfo *texsource, UINT32 flags) |
| 2813 | | { |
| 2814 | | if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2815 | | { |
| 2816 | | assert(texture->pbo); |
| 2817 | | assert(!texture->nocopy); |
| 2818 | | |
| 2819 | | texture->data = (UINT32 *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); |
| 2820 | | } |
| 2821 | | |
| 2822 | | // note that nocopy and borderpix are mutually exclusive, IOW |
| 2823 | | // they cannot be both true, thus this cannot lead to the |
| 2824 | | // borderpix code below writing to texsource->base . |
| 2825 | | if (texture->nocopy) |
| 2826 | | { |
| 2827 | | texture->data = (UINT32 *) texsource->base; |
| 2828 | | } |
| 2829 | | |
| 2830 | | // always fill non-wrapping textures with an extra pixel on the top |
| 2831 | | if (texture->borderpix) |
| 2832 | | { |
| 2833 | | memset(texture->data, 0, |
| 2834 | | (texsource->width * texture->xprescale + 2) * sizeof(UINT32)); |
| 2835 | | } |
| 2836 | | |
| 2837 | | // when nescesarry copy (and convert) the data |
| 2838 | | if (!texture->nocopy) |
| 2839 | | { |
| 2840 | | int y, y2; |
| 2841 | | UINT8 *dst; |
| 2842 | | |
| 2843 | | for (y = 0; y < texsource->height; y++) |
| 2844 | | { |
| 2845 | | for (y2 = 0; y2 < texture->yprescale; y2++) |
| 2846 | | { |
| 2847 | | dst = (UINT8 *)(texture->data + (y * texture->yprescale + texture->borderpix + y2) * texture->rawwidth); |
| 2848 | | |
| 2849 | | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2850 | | { |
| 2851 | | case TEXFORMAT_PALETTE16: |
| 2852 | | copyline_palette16((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2853 | | break; |
| 2854 | | |
| 2855 | | case TEXFORMAT_PALETTEA16: |
| 2856 | | copyline_palettea16((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2857 | | break; |
| 2858 | | |
| 2859 | | case TEXFORMAT_RGB32: |
| 2860 | | copyline_rgb32((UINT32 *)dst, (UINT32 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2861 | | break; |
| 2862 | | |
| 2863 | | case TEXFORMAT_ARGB32: |
| 2864 | | copyline_argb32((UINT32 *)dst, (UINT32 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2865 | | break; |
| 2866 | | |
| 2867 | | case TEXFORMAT_YUY16: |
| 2868 | | copyline_yuy16_to_argb((UINT32 *)dst, (UINT16 *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale); |
| 2869 | | break; |
| 2870 | | |
| 2871 | | default: |
| 2872 | | osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2873 | | break; |
| 2874 | | } |
| 2875 | | } |
| 2876 | | } |
| 2877 | | } |
| 2878 | | |
| 2879 | | // always fill non-wrapping textures with an extra pixel on the bottom |
| 2880 | | if (texture->borderpix) |
| 2881 | | { |
| 2882 | | memset((UINT8 *)texture->data + |
| 2883 | | (texsource->height + 1) * texture->rawwidth * sizeof(UINT32), |
| 2884 | | 0, |
| 2885 | | (texsource->width * texture->xprescale + 2) * sizeof(UINT32)); |
| 2886 | | } |
| 2887 | | |
| 2888 | | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 2889 | | { |
| 2890 | | pfn_glActiveTexture(GL_TEXTURE0); |
| 2891 | | glBindTexture(texture->texTarget, texture->texture); |
| 2892 | | |
| 2893 | | if (texture->nocopy) |
| 2894 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels); |
| 2895 | | else |
| 2896 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2897 | | |
| 2898 | | // and upload the image |
| 2899 | | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2900 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data); |
| 2901 | | } |
| 2902 | | else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 2903 | | { |
| 2904 | | glBindTexture(texture->texTarget, texture->texture); |
| 2905 | | |
| 2906 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2907 | | |
| 2908 | | // unmap the buffer from the CPU space so it can DMA |
| 2909 | | pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); |
| 2910 | | |
| 2911 | | // kick off the DMA |
| 2912 | | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2913 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); |
| 2914 | | } |
| 2915 | | else |
| 2916 | | { |
| 2917 | | glBindTexture(texture->texTarget, texture->texture); |
| 2918 | | |
| 2919 | | // give the card a hint |
| 2920 | | if (texture->nocopy) |
| 2921 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels); |
| 2922 | | else |
| 2923 | | glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth); |
| 2924 | | |
| 2925 | | // and upload the image |
| 2926 | | glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight, |
| 2927 | | GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data); |
| 2928 | | } |
| 2929 | | } |
| 2930 | | |
| 2931 | | //============================================================ |
| 2932 | | // texture_find |
| 2933 | | //============================================================ |
| 2934 | | |
| 2935 | | static int compare_texture_primitive(const texture_info *texture, const render_primitive *prim) |
| 2936 | | { |
| 2937 | | if (texture->texinfo.base == prim->texture.base && |
| 2938 | | texture->texinfo.width == prim->texture.width && |
| 2939 | | texture->texinfo.height == prim->texture.height && |
| 2940 | | texture->texinfo.rowpixels == prim->texture.rowpixels && |
| 2941 | | /* texture->texinfo.palette == prim->texture.palette && */ |
| 2942 | | ((texture->flags ^ prim->flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) |
| 2943 | | return 1; |
| 2944 | | else |
| 2945 | | return 0; |
| 2946 | | } |
| 2947 | | |
| 2948 | | texture_info *sdl_info_ogl::texture_find(const render_primitive *prim) |
| 2949 | | { |
| 2950 | | HashT texhash = texture_compute_hash(&prim->texture, prim->flags); |
| 2951 | | texture_info *texture; |
| 2952 | | |
| 2953 | | texture = m_texhash[texhash]; |
| 2954 | | if (texture != NULL) |
| 2955 | | { |
| 2956 | | int i; |
| 2957 | | if (compare_texture_primitive(texture, prim)) |
| 2958 | | return texture; |
| 2959 | | for (i=HASH_SIZE; i<HASH_SIZE + OVERFLOW_SIZE; i++) |
| 2960 | | { |
| 2961 | | texture = m_texhash[i]; |
| 2962 | | if (texture != NULL && compare_texture_primitive(texture, prim)) |
| 2963 | | return texture; |
| 2964 | | } |
| 2965 | | } |
| 2966 | | return NULL; |
| 2967 | | } |
| 2968 | | |
| 2969 | | //============================================================ |
| 2970 | | // texture_update |
| 2971 | | //============================================================ |
| 2972 | | |
| 2973 | | void sdl_info_ogl::texture_coord_update(texture_info *texture, const render_primitive *prim, int shaderIdx) |
| 2974 | | { |
| 2975 | | float ustart = 0.0f, ustop = 0.0f; // beginning/ending U coordinates |
| 2976 | | float vstart = 0.0f, vstop = 0.0f; // beginning/ending V coordinates |
| 2977 | | float du, dv; |
| 2978 | | |
| 2979 | | if ( texture->type != TEXTURE_TYPE_SHADER || |
| 2980 | | ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx<=m_glsl_program_mb2sc ) ) |
| 2981 | | { |
| 2982 | | // compute the U/V scale factors |
| 2983 | | if (texture->borderpix) |
| 2984 | | { |
| 2985 | | int unscaledwidth = (texture->rawwidth_create-2) / texture->xprescale + 2; |
| 2986 | | int unscaledheight = (texture->rawheight_create-2) / texture->yprescale + 2; |
| 2987 | | ustart = 1.0f / (float)(unscaledwidth); |
| 2988 | | ustop = (float)(prim->texture.width + 1) / (float)(unscaledwidth); |
| 2989 | | vstart = 1.0f / (float)(unscaledheight); |
| 2990 | | vstop = (float)(prim->texture.height + 1) / (float)(unscaledheight); |
| 2991 | | } |
| 2992 | | else |
| 2993 | | { |
| 2994 | | ustop = (float)(prim->texture.width*texture->xprescale) / (float)texture->rawwidth_create; |
| 2995 | | vstop = (float)(prim->texture.height*texture->yprescale) / (float)texture->rawheight_create; |
| 2996 | | } |
| 2997 | | } |
| 2998 | | else if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx>m_glsl_program_mb2sc ) |
| 2999 | | { |
| 3000 | | int surf_w_pow2 = get_valid_pow2_value (m_width, texture->texpow2); |
| 3001 | | int surf_h_pow2 = get_valid_pow2_value (m_height, texture->texpow2); |
| 3002 | | |
| 3003 | | ustop = (float)(m_width) / (float)surf_w_pow2; |
| 3004 | | vstop = (float)(m_height) / (float)surf_h_pow2; |
| 3005 | | |
| 3006 | | } |
| 3007 | | else |
| 3008 | | { |
| 3009 | | assert(0); // ?? |
| 3010 | | } |
| 3011 | | |
| 3012 | | du = ustop - ustart; |
| 3013 | | dv = vstop - vstart; |
| 3014 | | |
| 3015 | | if ( texture->texTarget == GL_TEXTURE_RECTANGLE_ARB ) |
| 3016 | | { |
| 3017 | | // texture coordinates for TEXTURE_RECTANGLE are 0,0 -> w,h |
| 3018 | | // rather than 0,0 -> 1,1 as with normal OpenGL texturing |
| 3019 | | du *= (float)texture->rawwidth; |
| 3020 | | dv *= (float)texture->rawheight; |
| 3021 | | } |
| 3022 | | |
| 3023 | | if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx!=m_glsl_program_mb2sc ) |
| 3024 | | { |
| 3025 | | // 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1) |
| 3026 | | // we must go CW here due to the mame bitmap order |
| 3027 | | texture->texCoord[0]=ustart + du * 0.0f; |
| 3028 | | texture->texCoord[1]=vstart + dv * 1.0f; |
| 3029 | | texture->texCoord[2]=ustart + du * 1.0f; |
| 3030 | | texture->texCoord[3]=vstart + dv * 1.0f; |
| 3031 | | texture->texCoord[4]=ustart + du * 1.0f; |
| 3032 | | texture->texCoord[5]=vstart + dv * 0.0f; |
| 3033 | | texture->texCoord[6]=ustart + du * 0.0f; |
| 3034 | | texture->texCoord[7]=vstart + dv * 0.0f; |
| 3035 | | } |
| 3036 | | else |
| 3037 | | { |
| 3038 | | // transformation: mamebm -> scrn |
| 3039 | | texture->texCoord[0]=ustart + du * prim->texcoords.tl.u; |
| 3040 | | texture->texCoord[1]=vstart + dv * prim->texcoords.tl.v; |
| 3041 | | texture->texCoord[2]=ustart + du * prim->texcoords.tr.u; |
| 3042 | | texture->texCoord[3]=vstart + dv * prim->texcoords.tr.v; |
| 3043 | | texture->texCoord[4]=ustart + du * prim->texcoords.br.u; |
| 3044 | | texture->texCoord[5]=vstart + dv * prim->texcoords.br.v; |
| 3045 | | texture->texCoord[6]=ustart + du * prim->texcoords.bl.u; |
| 3046 | | texture->texCoord[7]=vstart + dv * prim->texcoords.bl.v; |
| 3047 | | } |
| 3048 | | } |
| 3049 | | |
| 3050 | | void sdl_info_ogl::texture_mpass_flip(texture_info *texture, int shaderIdx) |
| 3051 | | { |
| 3052 | | UINT32 mpass_src_idx = texture->mpass_dest_idx; |
| 3053 | | |
| 3054 | | texture->mpass_dest_idx = (mpass_src_idx+1) % 2; |
| 3055 | | |
| 3056 | | if ( shaderIdx>0 ) |
| 3057 | | { |
| 3058 | | int uniform_location; |
| 3059 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture"); |
| 3060 | | pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0); |
| 3061 | | GL_CHECK_ERROR_NORMAL(); |
| 3062 | | } |
| 3063 | | |
| 3064 | | pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]); |
| 3065 | | if ( shaderIdx<=m_glsl_program_mb2sc ) |
| 3066 | | { |
| 3067 | | glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]); |
| 3068 | | } |
| 3069 | | else |
| 3070 | | { |
| 3071 | | glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]); |
| 3072 | | } |
| 3073 | | pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); |
| 3074 | | glBindTexture(texture->texTarget, 0); |
| 3075 | | |
| 3076 | | pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]); |
| 3077 | | |
| 3078 | | if ( shaderIdx<m_glsl_program_num-1 ) |
| 3079 | | { |
| 3080 | | if ( shaderIdx>=m_glsl_program_mb2sc ) |
| 3081 | | { |
| 3082 | | glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]); |
| 3083 | | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]); |
| 3084 | | } |
| 3085 | | else |
| 3086 | | { |
| 3087 | | glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]); |
| 3088 | | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]); |
| 3089 | | } |
| 3090 | | |
| 3091 | | if ( shaderIdx==0 ) |
| 3092 | | { |
| 3093 | | glPushAttrib(GL_VIEWPORT_BIT); |
| 3094 | | GL_CHECK_ERROR_NORMAL(); |
| 3095 | | glViewport(0.0, 0.0, (GLsizei)texture->rawwidth, (GLsizei)texture->rawheight); |
| 3096 | | } |
| 3097 | | else if ( shaderIdx==m_glsl_program_mb2sc ) |
| 3098 | | { |
| 3099 | | assert ( m_glsl_program_mb2sc < m_glsl_program_num-1 ); |
| 3100 | | glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height) |
| 3101 | | GL_CHECK_ERROR_NORMAL(); |
| 3102 | | } |
| 3103 | | glClear(GL_COLOR_BUFFER_BIT); // make sure the whole texture is redrawn .. |
| 3104 | | } |
| 3105 | | else |
| 3106 | | { |
| 3107 | | glBindTexture(texture->texTarget, 0); |
| 3108 | | pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3109 | | |
| 3110 | | if ( m_glsl_program_mb2sc == m_glsl_program_num-1 ) |
| 3111 | | { |
| 3112 | | glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height) |
| 3113 | | GL_CHECK_ERROR_NORMAL(); |
| 3114 | | } |
| 3115 | | |
| 3116 | | pfn_glActiveTexture(GL_TEXTURE0); |
| 3117 | | glBindTexture(texture->texTarget, 0); |
| 3118 | | } |
| 3119 | | } |
| 3120 | | |
| 3121 | | void sdl_info_ogl::texture_shader_update(texture_info *texture, render_container *container, int shaderIdx) |
| 3122 | | { |
| 3123 | | int uniform_location; |
| 3124 | | GLfloat vid_attributes[4]; |
| 3125 | | |
| 3126 | | if (container!=NULL) |
| 3127 | | { |
| 3128 | | render_container::user_settings settings; |
| 3129 | | container->get_user_settings(settings); |
| 3130 | | /* FIXME: the code below is in just for illustration issue on |
| 3131 | | * how to set shader variables. gamma, contrast and brightness are |
| 3132 | | * handled already by the core |
| 3133 | | */ |
| 3134 | | vid_attributes[0] = settings.m_gamma; |
| 3135 | | vid_attributes[1] = settings.m_contrast; |
| 3136 | | vid_attributes[2] = settings.m_brightness; |
| 3137 | | vid_attributes[3] = 0.0f; |
| 3138 | | uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes"); |
| 3139 | | pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx])); |
| 3140 | | if ( GL_CHECK_ERROR_QUIET() ) { |
| 3141 | | osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx); |
| 3142 | | } |
| 3143 | | } |
| 3144 | | } |
| 3145 | | |
| 3146 | | texture_info * sdl_info_ogl::texture_update(const render_primitive *prim, int shaderIdx) |
| 3147 | | { |
| 3148 | | texture_info *texture = texture_find(prim); |
| 3149 | | int texBound = 0; |
| 3150 | | |
| 3151 | | // if we didn't find one, create a new texture |
| 3152 | | if (texture == NULL && prim->texture.base != NULL) |
| 3153 | | { |
| 3154 | | texture = texture_create(&prim->texture, prim->flags); |
| 3155 | | } |
| 3156 | | else if (texture != NULL) |
| 3157 | | { |
| 3158 | | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3159 | | { |
| 3160 | | pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader |
| 3161 | | } |
| 3162 | | else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 3163 | | { |
| 3164 | | assert ( m_usepbo ) ; |
| 3165 | | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo); |
| 3166 | | glEnable(texture->texTarget); |
| 3167 | | } |
| 3168 | | else |
| 3169 | | { |
| 3170 | | glEnable(texture->texTarget); |
| 3171 | | } |
| 3172 | | } |
| 3173 | | |
| 3174 | | if (texture != NULL) |
| 3175 | | { |
| 3176 | | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3177 | | { |
| 3178 | | texture_shader_update(texture, prim->container, shaderIdx); |
| 3179 | | if ( m_glsl_program_num>1 ) |
| 3180 | | { |
| 3181 | | texture_mpass_flip(texture, shaderIdx); |
| 3182 | | } |
| 3183 | | } |
| 3184 | | |
| 3185 | | if ( shaderIdx==0 ) // redundant for subsequent multipass shader |
| 3186 | | { |
| 3187 | | if (prim->texture.base != NULL && texture->texinfo.seqid != prim->texture.seqid) |
| 3188 | | { |
| 3189 | | texture->texinfo.seqid = prim->texture.seqid; |
| 3190 | | |
| 3191 | | // if we found it, but with a different seqid, copy the data |
| 3192 | | texture_set_data(texture, &prim->texture, prim->flags); |
| 3193 | | texBound=1; |
| 3194 | | } |
| 3195 | | } |
| 3196 | | |
| 3197 | | if (!texBound) { |
| 3198 | | glBindTexture(texture->texTarget, texture->texture); |
| 3199 | | } |
| 3200 | | texture_coord_update(texture, prim, shaderIdx); |
| 3201 | | |
| 3202 | | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| 3203 | | if(m_usevbo) |
| 3204 | | { |
| 3205 | | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName ); |
| 3206 | | // Load The Data |
| 3207 | | pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord ); |
| 3208 | | glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // we are using ARB VBO buffers |
| 3209 | | } |
| 3210 | | else |
| 3211 | | { |
| 3212 | | glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord); |
| 3213 | | } |
| 3214 | | } |
| 3215 | | |
| 3216 | | return texture; |
| 3217 | | } |
| 3218 | | |
| 3219 | | void sdl_info_ogl::texture_disable(texture_info * texture) |
| 3220 | | { |
| 3221 | | if ( texture->type == TEXTURE_TYPE_SHADER ) |
| 3222 | | { |
| 3223 | | assert ( m_useglsl ); |
| 3224 | | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 3225 | | } else if ( texture->type == TEXTURE_TYPE_DYNAMIC ) |
| 3226 | | { |
| 3227 | | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 3228 | | glDisable(texture->texTarget); |
| 3229 | | } else { |
| 3230 | | glDisable(texture->texTarget); |
| 3231 | | } |
| 3232 | | } |
| 3233 | | |
| 3234 | | void sdl_info_ogl::texture_all_disable() |
| 3235 | | { |
| 3236 | | if ( m_useglsl ) |
| 3237 | | { |
| 3238 | | pfn_glUseProgramObjectARB(0); // back to fixed function pipeline |
| 3239 | | |
| 3240 | | pfn_glActiveTexture(GL_TEXTURE3); |
| 3241 | | glBindTexture(GL_TEXTURE_2D, 0); |
| 3242 | | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3243 | | pfn_glActiveTexture(GL_TEXTURE2); |
| 3244 | | glBindTexture(GL_TEXTURE_2D, 0); |
| 3245 | | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3246 | | pfn_glActiveTexture(GL_TEXTURE1); |
| 3247 | | glBindTexture(GL_TEXTURE_2D, 0); |
| 3248 | | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3249 | | pfn_glActiveTexture(GL_TEXTURE0); |
| 3250 | | glBindTexture(GL_TEXTURE_2D, 0); |
| 3251 | | if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
| 3252 | | } |
| 3253 | | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); |
| 3254 | | |
| 3255 | | if(m_usetexturerect) |
| 3256 | | { |
| 3257 | | glDisable(GL_TEXTURE_RECTANGLE_ARB); |
| 3258 | | } |
| 3259 | | glDisable(GL_TEXTURE_2D); |
| 3260 | | |
| 3261 | | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| 3262 | | if(m_usevbo) |
| 3263 | | { |
| 3264 | | pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind .. |
| 3265 | | } |
| 3266 | | if ( m_usepbo ) |
| 3267 | | { |
| 3268 | | pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 3269 | | } |
| 3270 | | } |
trunk/src/osd/windows/d3dhlsl.c
| r244651 | r244652 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Aaron Giles |
| 3 | | //============================================================ |
| 4 | | // |
| 5 | | // d3dhlsl.c - Win32 Direct3D HLSL 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 | | #include "screen.h" |
| 37 | | |
| 38 | | // MAMEOS headers |
| 39 | | #include "d3dintf.h" |
| 40 | | #include "winmain.h" |
| 41 | | #include "window.h" |
| 42 | | #include "config.h" |
| 43 | | #include "d3dcomm.h" |
| 44 | | #include "drawd3d.h" |
| 45 | | #include "strconv.h" |
| 46 | | |
| 47 | | |
| 48 | | |
| 49 | | //============================================================ |
| 50 | | // GLOBALS |
| 51 | | //============================================================ |
| 52 | | |
| 53 | | static slider_state *g_slider_list; |
| 54 | | static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx); |
| 55 | | |
| 56 | | namespace d3d |
| 57 | | { |
| 58 | | hlsl_options shaders::s_hlsl_presets[4] = |
| 59 | | { |
| 60 | | { // 25% Shadow mask, 50% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 61 | | true, |
| 62 | | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 63 | | 0.03f, 0.03f, |
| 64 | | 0.5f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 65 | | { 0.0f, 0.0f }, |
| 66 | | { 0.0f, 0.0f, 0.0f }, |
| 67 | | { 0.0f, 0.0f, 0.0f }, |
| 68 | | { 0.0f, 0.0f, 0.0f }, |
| 69 | | { 0.0f, 0.0f, 0.0f }, |
| 70 | | { 1.0f, 0.0f, 0.0f }, |
| 71 | | { 0.0f, 1.0f, 0.0f }, |
| 72 | | { 0.0f, 0.0f, 1.0f }, |
| 73 | | { 0.0f, 0.0f, 0.0f }, |
| 74 | | { 1.0f, 1.0f, 1.0f }, |
| 75 | | { 0.9f, 0.9f, 0.9f }, |
| 76 | | { 0.05f,0.05f,0.05f}, |
| 77 | | { 0.25f,0.25f,0.25f}, |
| 78 | | 1.2f, |
| 79 | | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 80 | | 0.9f, 4.0f, |
| 81 | | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 82 | | }, |
| 83 | | { // 25% Shadow mask, 0% Scanlines, 3% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 84 | | true, |
| 85 | | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 86 | | 0.03f, 0.03f, |
| 87 | | 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 88 | | { 0.0f, 0.0f }, |
| 89 | | { 0.0f, 0.0f, 0.0f }, |
| 90 | | { 0.0f, 0.0f, 0.0f }, |
| 91 | | { 0.0f, 0.0f, 0.0f }, |
| 92 | | { 0.0f, 0.0f, 0.0f }, |
| 93 | | { 1.0f, 0.0f, 0.0f }, |
| 94 | | { 0.0f, 1.0f, 0.0f }, |
| 95 | | { 0.0f, 0.0f, 1.0f }, |
| 96 | | { 0.0f, 0.0f, 0.0f }, |
| 97 | | { 1.0f, 1.0f, 1.0f }, |
| 98 | | { 0.9f, 0.9f, 0.9f }, |
| 99 | | { 0.05f,0.05f,0.05f}, |
| 100 | | { 0.25f,0.25f,0.25f}, |
| 101 | | 1.2f, |
| 102 | | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 103 | | 0.9f, 4.0f, |
| 104 | | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 105 | | }, |
| 106 | | { // 25% Shadow mask, 0% Scanlines, 0% Pincushion, 0 defocus, No Tint, 0.9 Exponent, 5% Floor, 25% Phosphor Return, 120% Saturation |
| 107 | | true, |
| 108 | | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 109 | | 0.0f, 0.0f, |
| 110 | | 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.0f, |
| 111 | | { 0.0f, 0.0f }, |
| 112 | | { 0.0f, 0.0f, 0.0f }, |
| 113 | | { 0.0f, 0.0f, 0.0f }, |
| 114 | | { 0.0f, 0.0f, 0.0f }, |
| 115 | | { 0.0f, 0.0f, 0.0f }, |
| 116 | | { 1.0f, 0.0f, 0.0f }, |
| 117 | | { 0.0f, 1.0f, 0.0f }, |
| 118 | | { 0.0f, 0.0f, 1.0f }, |
| 119 | | { 0.0f, 0.0f, 0.0f }, |
| 120 | | { 1.0f, 1.0f, 1.0f }, |
| 121 | | { 0.9f, 0.9f, 0.9f }, |
| 122 | | { 0.05f,0.05f,0.05f}, |
| 123 | | { 0.25f,0.25f,0.25f}, |
| 124 | | 1.2f, |
| 125 | | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 126 | | 0.9f, 4.0f, |
| 127 | | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 128 | | }, |
| 129 | | { // 25% Shadow mask, 100% Scanlines, 15% Pincushion, 3 defocus, 24-degree Tint Out, 1.5 Exponent, 5% Floor, 70% Phosphor Return, 80% Saturation, Bad Convergence |
| 130 | | true, |
| 131 | | 0.25f, { "aperture.png" }, 320, 240, 0.09375f, 0.109375f, |
| 132 | | 0.15f, 0.15f, |
| 133 | | 1.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f, |
| 134 | | { 3.0f, 3.0f }, |
| 135 | | { 0.5f,-0.33f,0.7f }, |
| 136 | | { 0.0f,-1.0f, 0.5f }, |
| 137 | | { 0.0f, 0.2f, 0.3f }, |
| 138 | | { 0.0f, 0.2f, 0.0f }, |
| 139 | | { 0.8f, 0.2f, 0.0f }, |
| 140 | | { 0.0f, 0.8f, 0.2f}, |
| 141 | | { 0.2f, 0.0f, 0.8f}, |
| 142 | | { 0.0f, 0.0f, 0.0f }, |
| 143 | | { 1.0f, 1.0f, 1.0f }, |
| 144 | | { 1.5f, 1.5f, 1.5f }, |
| 145 | | { 0.05f,0.05f,0.05f}, |
| 146 | | { 0.7f, 0.7f, 0.7f}, |
| 147 | | 0.8f, |
| 148 | | false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, |
| 149 | | 0.9f, 4.0f, |
| 150 | | 1.0f, 0.21f, 0.19f, 0.17f, 0.15f, 0.14f, 0.13f, 0.12f, 0.11f, 0.10f, 0.09f |
| 151 | | }, |
| 152 | | }; |
| 153 | | |
| 154 | | //============================================================ |
| 155 | | // PROTOTYPES |
| 156 | | //============================================================ |
| 157 | | |
| 158 | | static void get_vector(const char *data, int count, float *out, int report_error); |
| 159 | | |
| 160 | | |
| 161 | | //============================================================ |
| 162 | | // TYPE DEFINITIONS |
| 163 | | //============================================================ |
| 164 | | |
| 165 | | typedef HRESULT (WINAPI *direct3dx9_loadeffect_ptr)(LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors); |
| 166 | | static direct3dx9_loadeffect_ptr g_load_effect = NULL; |
| 167 | | |
| 168 | | //============================================================ |
| 169 | | // shader manager constructor |
| 170 | | //============================================================ |
| 171 | | |
| 172 | | shaders::shaders() |
| 173 | | { |
| 174 | | master_enable = false; |
| 175 | | vector_enable = true; |
| 176 | | prescale_size_x = 1; |
| 177 | | prescale_size_y = 1; |
| 178 | | prescale_force_x = 0; |
| 179 | | prescale_force_y = 0; |
| 180 | | preset = -1; |
| 181 | | shadow_texture = NULL; |
| 182 | | options = NULL; |
| 183 | | paused = true; |
| 184 | | lastidx = -1; |
| 185 | | targethead = NULL; |
| 186 | | cachehead = NULL; |
| 187 | | initialized = false; |
| 188 | | } |
| 189 | | |
| 190 | | |
| 191 | | |
| 192 | | //============================================================ |
| 193 | | // shaders destructor |
| 194 | | //============================================================ |
| 195 | | |
| 196 | | shaders::~shaders() |
| 197 | | { |
| 198 | | global_free(options); |
| 199 | | cache_target *currcache = cachehead; |
| 200 | | while(cachehead != NULL) |
| 201 | | { |
| 202 | | cachehead = currcache->next; |
| 203 | | global_free(currcache); |
| 204 | | currcache = cachehead; |
| 205 | | } |
| 206 | | |
| 207 | | render_target *currtarget = targethead; |
| 208 | | while(targethead != NULL) |
| 209 | | { |
| 210 | | targethead = currtarget->next; |
| 211 | | global_free(currtarget); |
| 212 | | currtarget = targethead; |
| 213 | | } |
| 214 | | } |
| 215 | | |
| 216 | | |
| 217 | | |
| 218 | | //============================================================ |
| 219 | | // shaders::window_save |
| 220 | | //============================================================ |
| 221 | | |
| 222 | | void shaders::window_save() |
| 223 | | { |
| 224 | | if (!master_enable || !d3dintf->post_fx_available) |
| 225 | | return; |
| 226 | | |
| 227 | | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &snap_copy_texture); |
| 228 | | if (result != D3D_OK) |
| 229 | | { |
| 230 | | osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); |
| 231 | | return; |
| 232 | | } |
| 233 | | (*d3dintf->texture.get_surface_level)(snap_copy_texture, 0, &snap_copy_target); |
| 234 | | |
| 235 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), snap_width, snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &snap_texture); |
| 236 | | if (result != D3D_OK) |
| 237 | | { |
| 238 | | osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL snapshot (%08x), bailing\n", (UINT32)result); |
| 239 | | return; |
| 240 | | } |
| 241 | | (*d3dintf->texture.get_surface_level)(snap_texture, 0, &snap_target); |
| 242 | | |
| 243 | | render_snap = true; |
| 244 | | snap_rendered = false; |
| 245 | | } |
| 246 | | |
| 247 | | |
| 248 | | |
| 249 | | //============================================================ |
| 250 | | // shaders::window_record |
| 251 | | //============================================================ |
| 252 | | |
| 253 | | void shaders::window_record() |
| 254 | | { |
| 255 | | if (!master_enable || !d3dintf->post_fx_available) |
| 256 | | return; |
| 257 | | |
| 258 | | windows_options &options = downcast<windows_options &>(machine->options()); |
| 259 | | const char *filename = options.d3d_hlsl_write(); |
| 260 | | |
| 261 | | if (avi_output_file != NULL) |
| 262 | | end_avi_recording(); |
| 263 | | else if (filename[0] != 0) |
| 264 | | begin_avi_recording(filename); |
| 265 | | } |
| 266 | | |
| 267 | | |
| 268 | | //============================================================ |
| 269 | | // shaders::avi_update_snap |
| 270 | | //============================================================ |
| 271 | | |
| 272 | | void shaders::avi_update_snap(surface *surface) |
| 273 | | { |
| 274 | | if (!master_enable || !d3dintf->post_fx_available) |
| 275 | | return; |
| 276 | | |
| 277 | | D3DLOCKED_RECT rect; |
| 278 | | |
| 279 | | // if we don't have a bitmap, or if it's not the right size, allocate a new one |
| 280 | | if (!avi_snap.valid() || (int)snap_width != avi_snap.width() || (int)snap_height != avi_snap.height()) |
| 281 | | { |
| 282 | | avi_snap.allocate((int)snap_width, (int)snap_height); |
| 283 | | } |
| 284 | | |
| 285 | | // copy the texture |
| 286 | | HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, avi_copy_surface); |
| 287 | | if (result != D3D_OK) |
| 288 | | { |
| 289 | | return; |
| 290 | | } |
| 291 | | |
| 292 | | // lock the texture |
| 293 | | result = (*d3dintf->surface.lock_rect)(avi_copy_surface, &rect, NULL, D3DLOCK_DISCARD); |
| 294 | | if (result != D3D_OK) |
| 295 | | { |
| 296 | | return; |
| 297 | | } |
| 298 | | |
| 299 | | // loop over Y |
| 300 | | for (int srcy = 0; srcy < (int)snap_height; srcy++) |
| 301 | | { |
| 302 | | DWORD *src = (DWORD *)((BYTE *)rect.pBits + srcy * rect.Pitch); |
| 303 | | UINT32 *dst = &avi_snap.pix32(srcy); |
| 304 | | |
| 305 | | for(int x = 0; x < snap_width; x++) |
| 306 | | *dst++ = *src++; |
| 307 | | } |
| 308 | | |
| 309 | | // unlock |
| 310 | | result = (*d3dintf->surface.unlock_rect)(avi_copy_surface); |
| 311 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 312 | | } |
| 313 | | |
| 314 | | |
| 315 | | |
| 316 | | //============================================================ |
| 317 | | // hlsl_render_snapshot |
| 318 | | //============================================================ |
| 319 | | |
| 320 | | void shaders::render_snapshot(surface *surface) |
| 321 | | { |
| 322 | | if (!master_enable || !d3dintf->post_fx_available) |
| 323 | | return; |
| 324 | | |
| 325 | | D3DLOCKED_RECT rect; |
| 326 | | |
| 327 | | render_snap = false; |
| 328 | | |
| 329 | | // if we don't have a bitmap, or if it's not the right size, allocate a new one |
| 330 | | if (!avi_snap.valid() || snap_width != (avi_snap.width() / 2) || snap_height != (avi_snap.height() / 2)) |
| 331 | | { |
| 332 | | avi_snap.allocate(snap_width / 2, snap_height / 2); |
| 333 | | } |
| 334 | | |
| 335 | | // copy the texture |
| 336 | | HRESULT result = (*d3dintf->device.get_render_target_data)(d3d->get_device(), surface, snap_copy_target); |
| 337 | | if (result != D3D_OK) |
| 338 | | { |
| 339 | | return; |
| 340 | | } |
| 341 | | |
| 342 | | // lock the texture |
| 343 | | result = (*d3dintf->surface.lock_rect)(snap_copy_target, &rect, NULL, D3DLOCK_DISCARD); |
| 344 | | if (result != D3D_OK) |
| 345 | | { |
| 346 | | return; |
| 347 | | } |
| 348 | | |
| 349 | | for(int cy = 0; cy < 2; cy++) |
| 350 | | { |
| 351 | | for(int cx = 0; cx < 2; cx++) |
| 352 | | { |
| 353 | | // loop over Y |
| 354 | | for (int srcy = 0; srcy < snap_height / 2; srcy++) |
| 355 | | { |
| 356 | | int toty = (srcy + cy * (snap_height / 2)); |
| 357 | | int totx = cx * (snap_width / 2); |
| 358 | | DWORD *src = (DWORD *)((BYTE *)rect.pBits + toty * rect.Pitch + totx * 4); |
| 359 | | UINT32 *dst = &avi_snap.pix32(srcy); |
| 360 | | |
| 361 | | for(int x = 0; x < snap_width / 2; x++) |
| 362 | | *dst++ = *src++; |
| 363 | | } |
| 364 | | |
| 365 | | int idx = cy * 2 + cx; |
| 366 | | |
| 367 | | emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); |
| 368 | | file_error filerr = open_next(d3d, file, NULL, "png", idx); |
| 369 | | if (filerr != FILERR_NONE) |
| 370 | | return; |
| 371 | | |
| 372 | | // add two text entries describing the image |
| 373 | | astring text1(emulator_info::get_appname(), " ", build_version); |
| 374 | | astring text2(machine->system().manufacturer, " ", machine->system().description); |
| 375 | | png_info pnginfo = { 0 }; |
| 376 | | png_add_text(&pnginfo, "Software", text1); |
| 377 | | png_add_text(&pnginfo, "System", text2); |
| 378 | | |
| 379 | | // now do the actual work |
| 380 | | png_error error = png_write_bitmap(file, &pnginfo, avi_snap, 1 << 24, NULL); |
| 381 | | if (error != PNGERR_NONE) |
| 382 | | osd_printf_error("Error generating PNG for HLSL snapshot: png_error = %d\n", error); |
| 383 | | |
| 384 | | // free any data allocated |
| 385 | | png_free(&pnginfo); |
| 386 | | } |
| 387 | | } |
| 388 | | |
| 389 | | // unlock |
| 390 | | result = (*d3dintf->surface.unlock_rect)(snap_copy_target); |
| 391 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 392 | | |
| 393 | | if(snap_texture != NULL) |
| 394 | | { |
| 395 | | (*d3dintf->texture.release)(snap_texture); |
| 396 | | snap_texture = NULL; |
| 397 | | } |
| 398 | | |
| 399 | | if(snap_target != NULL) |
| 400 | | { |
| 401 | | (*d3dintf->surface.release)(snap_target); |
| 402 | | snap_target = NULL; |
| 403 | | } |
| 404 | | |
| 405 | | if(snap_copy_texture != NULL) |
| 406 | | { |
| 407 | | (*d3dintf->texture.release)(snap_copy_texture); |
| 408 | | snap_copy_texture = NULL; |
| 409 | | } |
| 410 | | |
| 411 | | if(snap_copy_target != NULL) |
| 412 | | { |
| 413 | | (*d3dintf->surface.release)(snap_copy_target); |
| 414 | | snap_copy_target = NULL; |
| 415 | | } |
| 416 | | } |
| 417 | | |
| 418 | | |
| 419 | | //============================================================ |
| 420 | | // shaders::record_texture |
| 421 | | //============================================================ |
| 422 | | |
| 423 | | void shaders::record_texture() |
| 424 | | { |
| 425 | | if (!master_enable || !d3dintf->post_fx_available) |
| 426 | | return; |
| 427 | | |
| 428 | | surface *surface = avi_final_target; |
| 429 | | |
| 430 | | // ignore if nothing to do |
| 431 | | if (avi_output_file == NULL || surface == NULL) |
| 432 | | return; |
| 433 | | |
| 434 | | // get the current time |
| 435 | | attotime curtime = machine->time(); |
| 436 | | |
| 437 | | avi_update_snap(surface); |
| 438 | | |
| 439 | | // loop until we hit the right time |
| 440 | | while (avi_next_frame_time <= curtime) |
| 441 | | { |
| 442 | | // handle an AVI recording |
| 443 | | // write the next frame |
| 444 | | avi_error avierr = avi_append_video_frame(avi_output_file, avi_snap); |
| 445 | | if (avierr != AVIERR_NONE) |
| 446 | | { |
| 447 | | end_avi_recording(); |
| 448 | | return; |
| 449 | | } |
| 450 | | |
| 451 | | // advance time |
| 452 | | avi_next_frame_time += avi_frame_period; |
| 453 | | avi_frame++; |
| 454 | | } |
| 455 | | } |
| 456 | | |
| 457 | | |
| 458 | | //============================================================ |
| 459 | | // shaders::end_hlsl_avi_recording |
| 460 | | //============================================================ |
| 461 | | |
| 462 | | void shaders::end_avi_recording() |
| 463 | | { |
| 464 | | if (!master_enable || !d3dintf->post_fx_available) |
| 465 | | return; |
| 466 | | |
| 467 | | if (avi_output_file != NULL) |
| 468 | | avi_close(avi_output_file); |
| 469 | | |
| 470 | | avi_output_file = NULL; |
| 471 | | avi_frame = 0; |
| 472 | | } |
| 473 | | |
| 474 | | |
| 475 | | //============================================================ |
| 476 | | // shaders::toggle |
| 477 | | //============================================================ |
| 478 | | |
| 479 | | void shaders::toggle() |
| 480 | | { |
| 481 | | if (master_enable) |
| 482 | | { |
| 483 | | if (initialized) |
| 484 | | { |
| 485 | | delete_resources(false); |
| 486 | | } |
| 487 | | master_enable = !master_enable; |
| 488 | | } |
| 489 | | else |
| 490 | | { |
| 491 | | if (!initialized) |
| 492 | | { |
| 493 | | master_enable = !master_enable; |
| 494 | | bool failed = create_resources(false); |
| 495 | | if (failed) |
| 496 | | { |
| 497 | | master_enable = false; |
| 498 | | } |
| 499 | | } |
| 500 | | else |
| 501 | | { |
| 502 | | master_enable = !master_enable; |
| 503 | | } |
| 504 | | } |
| 505 | | } |
| 506 | | |
| 507 | | //============================================================ |
| 508 | | // shaders::begin_avi_recording |
| 509 | | //============================================================ |
| 510 | | |
| 511 | | void shaders::begin_avi_recording(const char *name) |
| 512 | | { |
| 513 | | if (!master_enable || !d3dintf->post_fx_available) |
| 514 | | return; |
| 515 | | |
| 516 | | // stop any existing recording |
| 517 | | end_avi_recording(); |
| 518 | | |
| 519 | | // reset the state |
| 520 | | avi_frame = 0; |
| 521 | | avi_next_frame_time = machine->time(); |
| 522 | | |
| 523 | | // build up information about this new movie |
| 524 | | avi_movie_info info; |
| 525 | | info.video_format = 0; |
| 526 | | info.video_timescale = 1000 * ((machine->first_screen() != NULL) ? ATTOSECONDS_TO_HZ(machine->first_screen()->frame_period().attoseconds) : screen_device::DEFAULT_FRAME_RATE); |
| 527 | | info.video_sampletime = 1000; |
| 528 | | info.video_numsamples = 0; |
| 529 | | info.video_width = snap_width; |
| 530 | | info.video_height = snap_height; |
| 531 | | info.video_depth = 24; |
| 532 | | |
| 533 | | info.audio_format = 0; |
| 534 | | info.audio_timescale = machine->sample_rate(); |
| 535 | | info.audio_sampletime = 1; |
| 536 | | info.audio_numsamples = 0; |
| 537 | | info.audio_channels = 2; |
| 538 | | info.audio_samplebits = 16; |
| 539 | | info.audio_samplerate = machine->sample_rate(); |
| 540 | | |
| 541 | | // create a new temporary movie file |
| 542 | | file_error filerr; |
| 543 | | astring fullpath; |
| 544 | | { |
| 545 | | emu_file tempfile(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); |
| 546 | | if (name != NULL) |
| 547 | | { |
| 548 | | filerr = tempfile.open(name); |
| 549 | | } |
| 550 | | else |
| 551 | | { |
| 552 | | filerr = open_next(d3d, tempfile, NULL, "avi", 0); |
| 553 | | } |
| 554 | | |
| 555 | | // compute the frame time |
| 556 | | { |
| 557 | | avi_frame_period = attotime::from_seconds(1000) / info.video_timescale; |
| 558 | | } |
| 559 | | |
| 560 | | // if we succeeded, make a copy of the name and create the real file over top |
| 561 | | if (filerr == FILERR_NONE) |
| 562 | | { |
| 563 | | fullpath = tempfile.fullpath(); |
| 564 | | } |
| 565 | | } |
| 566 | | |
| 567 | | if (filerr == FILERR_NONE) |
| 568 | | { |
| 569 | | // create the file and free the string |
| 570 | | avi_error avierr = avi_create(fullpath, &info, &avi_output_file); |
| 571 | | if (avierr != AVIERR_NONE) |
| 572 | | { |
| 573 | | osd_printf_error("Error creating AVI: %s\n", avi_error_string(avierr)); |
| 574 | | } |
| 575 | | } |
| 576 | | } |
| 577 | | |
| 578 | | |
| 579 | | //============================================================ |
| 580 | | // remove_cache_target - remove an active cache target when |
| 581 | | // refcount hits zero |
| 582 | | //============================================================ |
| 583 | | |
| 584 | | void shaders::remove_cache_target(cache_target *cache) |
| 585 | | { |
| 586 | | if (cache != NULL) |
| 587 | | { |
| 588 | | if (cache == cachehead) |
| 589 | | { |
| 590 | | cachehead = cachehead->next; |
| 591 | | } |
| 592 | | |
| 593 | | if (cache->prev != NULL) |
| 594 | | { |
| 595 | | cache->prev->next = cache->next; |
| 596 | | } |
| 597 | | |
| 598 | | if (cache->next != NULL) |
| 599 | | { |
| 600 | | cache->next->prev = cache->prev; |
| 601 | | } |
| 602 | | |
| 603 | | global_free(cache); |
| 604 | | } |
| 605 | | } |
| 606 | | |
| 607 | | |
| 608 | | //============================================================ |
| 609 | | // remove_render_target - remove an active target |
| 610 | | //============================================================ |
| 611 | | |
| 612 | | void shaders::remove_render_target(texture_info *texture) |
| 613 | | { |
| 614 | | remove_render_target(find_render_target(texture)); |
| 615 | | } |
| 616 | | |
| 617 | | void shaders::remove_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) |
| 618 | | { |
| 619 | | render_target *target = find_render_target(width, height, screen_index, page_index); |
| 620 | | if (target != NULL) |
| 621 | | { |
| 622 | | remove_render_target(target); |
| 623 | | } |
| 624 | | } |
| 625 | | |
| 626 | | void shaders::remove_render_target(render_target *rt) |
| 627 | | { |
| 628 | | if (rt != NULL) |
| 629 | | { |
| 630 | | if (rt == targethead) |
| 631 | | { |
| 632 | | targethead = targethead->next; |
| 633 | | } |
| 634 | | |
| 635 | | if (rt->prev != NULL) |
| 636 | | { |
| 637 | | rt->prev->next = rt->next; |
| 638 | | } |
| 639 | | |
| 640 | | if (rt->next != NULL) |
| 641 | | { |
| 642 | | rt->next->prev = rt->prev; |
| 643 | | } |
| 644 | | |
| 645 | | cache_target *cache = find_cache_target(rt->screen_index, rt->width, rt->height); |
| 646 | | if (cache != NULL) |
| 647 | | { |
| 648 | | remove_cache_target(cache); |
| 649 | | } |
| 650 | | |
| 651 | | int screen_index = rt->screen_index; |
| 652 | | int other_page = 1 - rt->page_index; |
| 653 | | int width = rt->width; |
| 654 | | int height = rt->height; |
| 655 | | |
| 656 | | global_free(rt); |
| 657 | | |
| 658 | | // Remove other double-buffered page (if it exists) |
| 659 | | remove_render_target(width, height, screen_index, other_page); |
| 660 | | } |
| 661 | | } |
| 662 | | |
| 663 | | |
| 664 | | //============================================================ |
| 665 | | // shaders::set_texture |
| 666 | | //============================================================ |
| 667 | | |
| 668 | | void shaders::set_texture(texture_info *texture) |
| 669 | | { |
| 670 | | if (!master_enable || !d3dintf->post_fx_available) |
| 671 | | return; |
| 672 | | |
| 673 | | if(texture != NULL) |
| 674 | | { |
| 675 | | paused = texture->paused(); |
| 676 | | texture->advance_frame(); |
| 677 | | } |
| 678 | | |
| 679 | | texture_info *default_texture = d3d->get_default_texture(); |
| 680 | | default_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 681 | | if (options->yiq_enable) |
| 682 | | yiq_encode_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 683 | | else |
| 684 | | color_effect->set_texture("Diffuse", (texture == NULL) ? default_texture->get_finaltex() : texture->get_finaltex()); |
| 685 | | } |
| 686 | | |
| 687 | | |
| 688 | | //============================================================ |
| 689 | | // shaders::init |
| 690 | | //============================================================ |
| 691 | | |
| 692 | | void shaders::init(base *d3dintf, running_machine *machine, d3d::renderer *renderer) |
| 693 | | { |
| 694 | | if (!d3dintf->post_fx_available) |
| 695 | | return; |
| 696 | | |
| 697 | | g_load_effect = (direct3dx9_loadeffect_ptr)GetProcAddress(d3dintf->libhandle, "D3DXCreateEffectFromFileW"); |
| 698 | | if (g_load_effect == NULL) |
| 699 | | { |
| 700 | | printf("Direct3D: Unable to find D3DXCreateEffectFromFileW\n"); |
| 701 | | d3dintf->post_fx_available = false; |
| 702 | | return; |
| 703 | | } |
| 704 | | |
| 705 | | this->d3dintf = d3dintf; |
| 706 | | this->machine = machine; |
| 707 | | this->d3d = renderer; |
| 708 | | |
| 709 | | master_enable = downcast<windows_options &>(machine->options()).d3d_hlsl_enable(); |
| 710 | | prescale_size_x = 1; |
| 711 | | prescale_size_y = 1; |
| 712 | | preset = downcast<windows_options &>(machine->options()).d3d_hlsl_preset(); |
| 713 | | if (preset < -1 || preset > 3) |
| 714 | | { |
| 715 | | preset = -1; |
| 716 | | } |
| 717 | | |
| 718 | | snap_width = downcast<windows_options &>(machine->options()).d3d_snap_width(); |
| 719 | | snap_height = downcast<windows_options &>(machine->options()).d3d_snap_height(); |
| 720 | | prescale_force_x = 0; |
| 721 | | prescale_force_y = 0; |
| 722 | | |
| 723 | | windows_options &winoptions = downcast<windows_options &>(machine->options()); |
| 724 | | |
| 725 | | options = (hlsl_options*)global_alloc_clear(hlsl_options); |
| 726 | | |
| 727 | | options->params_dirty = true; |
| 728 | | strcpy(options->shadow_mask_texture, downcast<windows_options &>(machine->options()).screen_shadow_mask_texture()); // unsafe |
| 729 | | |
| 730 | | prescale_force_x = winoptions.d3d_hlsl_prescale_x(); |
| 731 | | prescale_force_y = winoptions.d3d_hlsl_prescale_y(); |
| 732 | | if(preset == -1) |
| 733 | | { |
| 734 | | options->shadow_mask_alpha = winoptions.screen_shadow_mask_alpha(); |
| 735 | | options->shadow_mask_count_x = winoptions.screen_shadow_mask_count_x(); |
| 736 | | options->shadow_mask_count_y = winoptions.screen_shadow_mask_count_y(); |
| 737 | | options->shadow_mask_u_size = winoptions.screen_shadow_mask_u_size(); |
| 738 | | options->shadow_mask_v_size = winoptions.screen_shadow_mask_v_size(); |
| 739 | | options->curvature = winoptions.screen_curvature(); |
| 740 | | options->pincushion = winoptions.screen_pincushion(); |
| 741 | | options->scanline_alpha = winoptions.screen_scanline_amount(); |
| 742 | | options->scanline_scale = winoptions.screen_scanline_scale(); |
| 743 | | options->scanline_height = winoptions.screen_scanline_height(); |
| 744 | | options->scanline_bright_scale = winoptions.screen_scanline_bright_scale(); |
| 745 | | options->scanline_bright_offset = winoptions.screen_scanline_bright_offset(); |
| 746 | | options->scanline_offset = winoptions.screen_scanline_offset(); |
| 747 | | get_vector(winoptions.screen_defocus(), 2, options->defocus, TRUE); |
| 748 | | get_vector(winoptions.screen_converge_x(), 3, options->converge_x, TRUE); |
| 749 | | get_vector(winoptions.screen_converge_y(), 3, options->converge_y, TRUE); |
| 750 | | get_vector(winoptions.screen_radial_converge_x(), 3, options->radial_converge_x, TRUE); |
| 751 | | get_vector(winoptions.screen_radial_converge_y(), 3, options->radial_converge_y, TRUE); |
| 752 | | get_vector(winoptions.screen_red_ratio(), 3, options->red_ratio, TRUE); |
| 753 | | get_vector(winoptions.screen_grn_ratio(), 3, options->grn_ratio, TRUE); |
| 754 | | get_vector(winoptions.screen_blu_ratio(), 3, options->blu_ratio, TRUE); |
| 755 | | get_vector(winoptions.screen_offset(), 3, options->offset, TRUE); |
| 756 | | get_vector(winoptions.screen_scale(), 3, options->scale, TRUE); |
| 757 | | get_vector(winoptions.screen_power(), 3, options->power, TRUE); |
| 758 | | get_vector(winoptions.screen_floor(), 3, options->floor, TRUE); |
| 759 | | get_vector(winoptions.screen_phosphor(), 3, options->phosphor, TRUE); |
| 760 | | options->saturation = winoptions.screen_saturation(); |
| 761 | | } |
| 762 | | else |
| 763 | | { |
| 764 | | options = &s_hlsl_presets[preset]; |
| 765 | | } |
| 766 | | |
| 767 | | options->yiq_enable = winoptions.screen_yiq_enable(); |
| 768 | | options->yiq_cc = winoptions.screen_yiq_cc(); |
| 769 | | options->yiq_a = winoptions.screen_yiq_a(); |
| 770 | | options->yiq_b = winoptions.screen_yiq_b(); |
| 771 | | options->yiq_o = winoptions.screen_yiq_o(); |
| 772 | | options->yiq_p = winoptions.screen_yiq_p(); |
| 773 | | options->yiq_n = winoptions.screen_yiq_n(); |
| 774 | | options->yiq_y = winoptions.screen_yiq_y(); |
| 775 | | options->yiq_i = winoptions.screen_yiq_i(); |
| 776 | | options->yiq_q = winoptions.screen_yiq_q(); |
| 777 | | options->yiq_scan_time = winoptions.screen_yiq_scan_time(); |
| 778 | | options->yiq_phase_count = winoptions.screen_yiq_phase_count(); |
| 779 | | options->vector_length_scale = winoptions.screen_vector_length_scale(); |
| 780 | | options->vector_length_ratio = winoptions.screen_vector_length_ratio(); |
| 781 | | options->vector_bloom_scale = winoptions.screen_vector_bloom_scale(); |
| 782 | | options->raster_bloom_scale = winoptions.screen_raster_bloom_scale(); |
| 783 | | options->bloom_level0_weight = winoptions.screen_bloom_lvl0_weight(); |
| 784 | | options->bloom_level1_weight = winoptions.screen_bloom_lvl1_weight(); |
| 785 | | options->bloom_level2_weight = winoptions.screen_bloom_lvl2_weight(); |
| 786 | | options->bloom_level3_weight = winoptions.screen_bloom_lvl3_weight(); |
| 787 | | options->bloom_level4_weight = winoptions.screen_bloom_lvl4_weight(); |
| 788 | | options->bloom_level5_weight = winoptions.screen_bloom_lvl5_weight(); |
| 789 | | options->bloom_level6_weight = winoptions.screen_bloom_lvl6_weight(); |
| 790 | | options->bloom_level7_weight = winoptions.screen_bloom_lvl7_weight(); |
| 791 | | options->bloom_level8_weight = winoptions.screen_bloom_lvl8_weight(); |
| 792 | | options->bloom_level9_weight = winoptions.screen_bloom_lvl9_weight(); |
| 793 | | options->bloom_level10_weight = winoptions.screen_bloom_lvl10_weight(); |
| 794 | | |
| 795 | | options->params_dirty = true; |
| 796 | | |
| 797 | | g_slider_list = init_slider_list(); |
| 798 | | } |
| 799 | | |
| 800 | | |
| 801 | | |
| 802 | | //============================================================ |
| 803 | | // shaders::init_fsfx_quad |
| 804 | | //============================================================ |
| 805 | | |
| 806 | | void shaders::init_fsfx_quad(void *vertbuf) |
| 807 | | { |
| 808 | | // Called at the start of each frame by the D3D code in order to reserve two triangles |
| 809 | | // that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2 |
| 810 | | // instead of having to do bookkeeping about a specific screen quad |
| 811 | | if (!master_enable || !d3dintf->post_fx_available) |
| 812 | | return; |
| 813 | | |
| 814 | | // get a pointer to the vertex buffer |
| 815 | | fsfx_vertices = (vertex *)vertbuf; |
| 816 | | if (fsfx_vertices == NULL) |
| 817 | | return; |
| 818 | | |
| 819 | | // fill in the vertexes clockwise |
| 820 | | fsfx_vertices[0].x = 0.0f; |
| 821 | | fsfx_vertices[0].y = 0.0f; |
| 822 | | fsfx_vertices[1].x = d3d->get_width(); |
| 823 | | fsfx_vertices[1].y = 0.0f; |
| 824 | | fsfx_vertices[2].x = 0.0f; |
| 825 | | fsfx_vertices[2].y = d3d->get_height(); |
| 826 | | fsfx_vertices[3].x = d3d->get_width(); |
| 827 | | fsfx_vertices[3].y = 0.0f; |
| 828 | | fsfx_vertices[4].x = 0.0f; |
| 829 | | fsfx_vertices[4].y = d3d->get_height(); |
| 830 | | fsfx_vertices[5].x = d3d->get_width(); |
| 831 | | fsfx_vertices[5].y = d3d->get_height(); |
| 832 | | |
| 833 | | fsfx_vertices[0].u0 = 0.0f; |
| 834 | | fsfx_vertices[0].v0 = 0.0f; |
| 835 | | |
| 836 | | fsfx_vertices[1].u0 = 1.0f; |
| 837 | | fsfx_vertices[1].v0 = 0.0f; |
| 838 | | |
| 839 | | fsfx_vertices[2].u0 = 0.0f; |
| 840 | | fsfx_vertices[2].v0 = 1.0f; |
| 841 | | |
| 842 | | fsfx_vertices[3].u0 = 1.0f; |
| 843 | | fsfx_vertices[3].v0 = 0.0f; |
| 844 | | |
| 845 | | fsfx_vertices[4].u0 = 0.0f; |
| 846 | | fsfx_vertices[4].v0 = 1.0f; |
| 847 | | |
| 848 | | fsfx_vertices[5].u0 = 1.0f; |
| 849 | | fsfx_vertices[5].v0 = 1.0f; |
| 850 | | |
| 851 | | fsfx_vertices[0].u1 = 0.0f; |
| 852 | | fsfx_vertices[0].v1 = 0.0f; |
| 853 | | fsfx_vertices[1].u1 = 0.0f; |
| 854 | | fsfx_vertices[1].v1 = 0.0f; |
| 855 | | fsfx_vertices[2].u1 = 0.0f; |
| 856 | | fsfx_vertices[2].v1 = 0.0f; |
| 857 | | fsfx_vertices[3].u1 = 0.0f; |
| 858 | | fsfx_vertices[3].v1 = 0.0f; |
| 859 | | fsfx_vertices[4].u1 = 0.0f; |
| 860 | | fsfx_vertices[4].v1 = 0.0f; |
| 861 | | fsfx_vertices[5].u1 = 0.0f; |
| 862 | | fsfx_vertices[5].v1 = 0.0f; |
| 863 | | |
| 864 | | // set the color, Z parameters to standard values |
| 865 | | for (int i = 0; i < 6; i++) |
| 866 | | { |
| 867 | | fsfx_vertices[i].z = 0.0f; |
| 868 | | fsfx_vertices[i].rhw = 1.0f; |
| 869 | | fsfx_vertices[i].color = D3DCOLOR_ARGB(255, 255, 255, 255); |
| 870 | | } |
| 871 | | } |
| 872 | | |
| 873 | | |
| 874 | | |
| 875 | | //============================================================ |
| 876 | | // shaders::create_resources |
| 877 | | //============================================================ |
| 878 | | |
| 879 | | int shaders::create_resources(bool reset) |
| 880 | | { |
| 881 | | if (!master_enable || !d3dintf->post_fx_available) |
| 882 | | return 0; |
| 883 | | |
| 884 | | HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); |
| 885 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 886 | | |
| 887 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), 4, 4, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &black_texture); |
| 888 | | if (result != D3D_OK) |
| 889 | | { |
| 890 | | osd_printf_verbose("Direct3D: Unable to init video-memory target for black texture (%08x)\n", (UINT32)result); |
| 891 | | return 1; |
| 892 | | } |
| 893 | | (*d3dintf->texture.get_surface_level)(black_texture, 0, &black_surface); |
| 894 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, black_surface); |
| 895 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 896 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 897 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 898 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 899 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 900 | | |
| 901 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &avi_copy_texture); |
| 902 | | if (result != D3D_OK) |
| 903 | | { |
| 904 | | osd_printf_verbose("Direct3D: Unable to init system-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); |
| 905 | | return 1; |
| 906 | | } |
| 907 | | (*d3dintf->texture.get_surface_level)(avi_copy_texture, 0, &avi_copy_surface); |
| 908 | | |
| 909 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)snap_width, (int)snap_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &avi_final_texture); |
| 910 | | if (result != D3D_OK) |
| 911 | | { |
| 912 | | osd_printf_verbose("Direct3D: Unable to init video-memory target for HLSL AVI dumping (%08x)\n", (UINT32)result); |
| 913 | | return 1; |
| 914 | | } |
| 915 | | (*d3dintf->texture.get_surface_level)(avi_final_texture, 0, &avi_final_target); |
| 916 | | |
| 917 | | emu_file file(machine->options().art_path(), OPEN_FLAG_READ); |
| 918 | | render_load_png(shadow_bitmap, file, NULL, options->shadow_mask_texture); |
| 919 | | |
| 920 | | // experimental: if we have a shadow bitmap, create a texture for it |
| 921 | | if (shadow_bitmap.valid()) |
| 922 | | { |
| 923 | | render_texinfo texture; |
| 924 | | |
| 925 | | // fake in the basic data so it looks like it came from render.c |
| 926 | | texture.base = shadow_bitmap.raw_pixptr(0); |
| 927 | | texture.rowpixels = shadow_bitmap.rowpixels(); |
| 928 | | texture.width = shadow_bitmap.width(); |
| 929 | | texture.height = shadow_bitmap.height(); |
| 930 | | texture.palette = NULL; |
| 931 | | texture.seqid = 0; |
| 932 | | |
| 933 | | // FIXME: should shadow bitmap really use prescale? |
| 934 | | // now create it |
| 935 | | shadow_texture = new texture_info(d3d->get_texture_manager(), &texture, video_config.prescale, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)); |
| 936 | | } |
| 937 | | |
| 938 | | const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir(); |
| 939 | | |
| 940 | | default_effect = new effect(this, d3d->get_device(), "primary.fx", fx_dir); |
| 941 | | post_effect = new effect(this, d3d->get_device(), "post.fx", fx_dir); |
| 942 | | prescale_effect = new effect(this, d3d->get_device(), "prescale.fx", fx_dir); |
| 943 | | phosphor_effect = new effect(this, d3d->get_device(), "phosphor.fx", fx_dir); |
| 944 | | focus_effect = new effect(this, d3d->get_device(), "focus.fx", fx_dir); |
| 945 | | deconverge_effect = new effect(this, d3d->get_device(), "deconverge.fx", fx_dir); |
| 946 | | color_effect = new effect(this, d3d->get_device(), "color.fx", fx_dir); |
| 947 | | yiq_encode_effect = new effect(this, d3d->get_device(), "yiq_encode.fx", fx_dir); |
| 948 | | yiq_decode_effect = new effect(this, d3d->get_device(), "yiq_decode.fx", fx_dir); |
| 949 | | bloom_effect = new effect(this, d3d->get_device(), "bloom.fx", fx_dir); |
| 950 | | downsample_effect = new effect(this, d3d->get_device(), "downsample.fx", fx_dir); |
| 951 | | vector_effect = new effect(this, d3d->get_device(), "vector.fx", fx_dir); |
| 952 | | |
| 953 | | if (!default_effect->is_valid()) return 1; |
| 954 | | if (!post_effect->is_valid()) return 1; |
| 955 | | if (!prescale_effect->is_valid()) return 1; |
| 956 | | if (!phosphor_effect->is_valid()) return 1; |
| 957 | | if (!focus_effect->is_valid()) return 1; |
| 958 | | if (!deconverge_effect->is_valid()) return 1; |
| 959 | | if (!color_effect->is_valid()) return 1; |
| 960 | | if (!yiq_encode_effect->is_valid()) return 1; |
| 961 | | if (!yiq_decode_effect->is_valid()) return 1; |
| 962 | | if (!bloom_effect->is_valid()) return 1; |
| 963 | | if (!downsample_effect->is_valid()) return 1; |
| 964 | | if (!vector_effect->is_valid()) return 1; |
| 965 | | |
| 966 | | yiq_encode_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 967 | | yiq_encode_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 968 | | yiq_encode_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 969 | | yiq_encode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); |
| 970 | | yiq_encode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); |
| 971 | | yiq_encode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); |
| 972 | | yiq_encode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); |
| 973 | | yiq_encode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); |
| 974 | | yiq_encode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); |
| 975 | | yiq_encode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); |
| 976 | | yiq_encode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); |
| 977 | | yiq_encode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); |
| 978 | | |
| 979 | | yiq_decode_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 980 | | yiq_decode_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 981 | | yiq_decode_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 982 | | yiq_decode_effect->add_uniform("CCValue", uniform::UT_FLOAT, uniform::CU_NTSC_CCFREQ); |
| 983 | | yiq_decode_effect->add_uniform("AValue", uniform::UT_FLOAT, uniform::CU_NTSC_A); |
| 984 | | yiq_decode_effect->add_uniform("BValue", uniform::UT_FLOAT, uniform::CU_NTSC_B); |
| 985 | | yiq_decode_effect->add_uniform("OValue", uniform::UT_FLOAT, uniform::CU_NTSC_O); |
| 986 | | yiq_decode_effect->add_uniform("PValue", uniform::UT_FLOAT, uniform::CU_NTSC_P); |
| 987 | | yiq_decode_effect->add_uniform("NotchHalfWidth", uniform::UT_FLOAT, uniform::CU_NTSC_NOTCH); |
| 988 | | yiq_decode_effect->add_uniform("YFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_YFREQ); |
| 989 | | yiq_decode_effect->add_uniform("IFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_IFREQ); |
| 990 | | yiq_decode_effect->add_uniform("QFreqResponse", uniform::UT_FLOAT, uniform::CU_NTSC_QFREQ); |
| 991 | | yiq_decode_effect->add_uniform("ScanTime", uniform::UT_FLOAT, uniform::CU_NTSC_HTIME); |
| 992 | | |
| 993 | | color_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 994 | | color_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 995 | | |
| 996 | | color_effect->add_uniform("YIQEnable", uniform::UT_FLOAT, uniform::CU_NTSC_ENABLE); |
| 997 | | color_effect->add_uniform("RedRatios", uniform::UT_VEC3, uniform::CU_COLOR_RED_RATIOS); |
| 998 | | color_effect->add_uniform("GrnRatios", uniform::UT_VEC3, uniform::CU_COLOR_GRN_RATIOS); |
| 999 | | color_effect->add_uniform("BluRatios", uniform::UT_VEC3, uniform::CU_COLOR_BLU_RATIOS); |
| 1000 | | color_effect->add_uniform("Offset", uniform::UT_VEC3, uniform::CU_COLOR_OFFSET); |
| 1001 | | color_effect->add_uniform("Scale", uniform::UT_VEC3, uniform::CU_COLOR_SCALE); |
| 1002 | | color_effect->add_uniform("Saturation", uniform::UT_FLOAT, uniform::CU_COLOR_SATURATION); |
| 1003 | | |
| 1004 | | prescale_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1005 | | prescale_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1006 | | |
| 1007 | | deconverge_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1008 | | deconverge_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1009 | | deconverge_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 1010 | | deconverge_effect->add_uniform("ConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_X); |
| 1011 | | deconverge_effect->add_uniform("ConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_LINEAR_Y); |
| 1012 | | deconverge_effect->add_uniform("RadialConvergeX", uniform::UT_VEC3, uniform::CU_CONVERGE_RADIAL_X); |
| 1013 | | deconverge_effect->add_uniform("RadialConvergeY", uniform::UT_VEC3, uniform::CU_CONVERGE_RADIAL_Y); |
| 1014 | | |
| 1015 | | focus_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1016 | | focus_effect->add_uniform("Defocus", uniform::UT_VEC2, uniform::CU_FOCUS_SIZE); |
| 1017 | | |
| 1018 | | phosphor_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1019 | | phosphor_effect->add_uniform("Phosphor", uniform::UT_VEC3, uniform::CU_PHOSPHOR_LIFE); |
| 1020 | | phosphor_effect->add_uniform("Passthrough", uniform::UT_FLOAT, uniform::CU_PHOSPHOR_IGNORE); |
| 1021 | | |
| 1022 | | post_effect->add_uniform("SourceDims", uniform::UT_VEC2, uniform::CU_SOURCE_DIMS); |
| 1023 | | post_effect->add_uniform("SourceRect", uniform::UT_VEC2, uniform::CU_SOURCE_RECT); |
| 1024 | | post_effect->add_uniform("ScreenDims", uniform::UT_VEC2, uniform::CU_SCREEN_DIMS); |
| 1025 | | |
| 1026 | | post_effect->add_uniform("PincushionAmount", uniform::UT_FLOAT, uniform::CU_POST_PINCUSHION); |
| 1027 | | post_effect->add_uniform("CurvatureAmount", uniform::UT_FLOAT, uniform::CU_POST_CURVATURE); |
| 1028 | | |
| 1029 | | post_effect->add_uniform("ShadowAlpha", uniform::UT_FLOAT, uniform::CU_POST_SHADOW_ALPHA); |
| 1030 | | post_effect->add_uniform("ShadowCount", uniform::UT_VEC2, uniform::CU_POST_SHADOW_COUNT); |
| 1031 | | post_effect->add_uniform("ShadowUV", uniform::UT_VEC2, uniform::CU_POST_SHADOW_UV); |
| 1032 | | post_effect->add_uniform("ShadowDims", uniform::UT_VEC2, uniform::CU_POST_SHADOW_DIMS); |
| 1033 | | |
| 1034 | | post_effect->add_uniform("ScanlineAlpha", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_ALPHA); |
| 1035 | | post_effect->add_uniform("ScanlineScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_SCALE); |
| 1036 | | post_effect->add_uniform("ScanlineHeight", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_HEIGHT); |
| 1037 | | post_effect->add_uniform("ScanlineBrightScale", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_SCALE); |
| 1038 | | post_effect->add_uniform("ScanlineBrightOffset", uniform::UT_FLOAT, uniform::CU_POST_SCANLINE_BRIGHT_OFFSET); |
| 1039 | | post_effect->add_uniform("Power", uniform::UT_VEC3, uniform::CU_POST_POWER); |
| 1040 | | post_effect->add_uniform("Floor", uniform::UT_VEC3, uniform::CU_POST_FLOOR); |
| 1041 | | |
| 1042 | | initialized = true; |
| 1043 | | |
| 1044 | | return 0; |
| 1045 | | } |
| 1046 | | |
| 1047 | | |
| 1048 | | //============================================================ |
| 1049 | | // shaders::begin_draw |
| 1050 | | //============================================================ |
| 1051 | | |
| 1052 | | void shaders::begin_draw() |
| 1053 | | { |
| 1054 | | if (!master_enable || !d3dintf->post_fx_available) |
| 1055 | | return; |
| 1056 | | |
| 1057 | | curr_effect = default_effect; |
| 1058 | | |
| 1059 | | default_effect->set_technique("TestTechnique"); |
| 1060 | | post_effect->set_technique("ScanMaskTechnique"); |
| 1061 | | phosphor_effect->set_technique("TestTechnique"); |
| 1062 | | focus_effect->set_technique("TestTechnique"); |
| 1063 | | deconverge_effect->set_technique("DeconvergeTechnique"); |
| 1064 | | color_effect->set_technique("ColorTechnique"); |
| 1065 | | yiq_encode_effect->set_technique("EncodeTechnique"); |
| 1066 | | yiq_decode_effect->set_technique("DecodeTechnique"); |
| 1067 | | |
| 1068 | | HRESULT result = (*d3dintf->device.get_render_target)(d3d->get_device(), 0, &backbuffer); |
| 1069 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 1070 | | } |
| 1071 | | |
| 1072 | | |
| 1073 | | //============================================================ |
| 1074 | | // shaders::begin_frame |
| 1075 | | //============================================================ |
| 1076 | | |
| 1077 | | void shaders::begin_frame() |
| 1078 | | { |
| 1079 | | record_texture(); |
| 1080 | | } |
| 1081 | | |
| 1082 | | |
| 1083 | | //============================================================ |
| 1084 | | // shaders::blit |
| 1085 | | //============================================================ |
| 1086 | | |
| 1087 | | void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, |
| 1088 | | UINT32 prim_index, UINT32 prim_count, int dstw, int dsth) |
| 1089 | | { |
| 1090 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); |
| 1091 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1092 | | |
| 1093 | | curr_effect = default_effect; |
| 1094 | | |
| 1095 | | curr_effect->set_texture("Diffuse", src); |
| 1096 | | |
| 1097 | | float dst_dims[2] = { (float)dstw, (float)dsth }; |
| 1098 | | curr_effect->set_vector("ScreenDims", 2, dst_dims); |
| 1099 | | curr_effect->set_float("PostPass", 1.0f); |
| 1100 | | curr_effect->set_float("PincushionAmount", options->pincushion); |
| 1101 | | curr_effect->set_float("Brighten", 0.0f); |
| 1102 | | |
| 1103 | | unsigned int num_passes = 0; |
| 1104 | | curr_effect->begin(&num_passes, 0); |
| 1105 | | |
| 1106 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1107 | | { |
| 1108 | | curr_effect->begin_pass(pass); |
| 1109 | | // add the primitives |
| 1110 | | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); |
| 1111 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1112 | | curr_effect->end_pass(); |
| 1113 | | } |
| 1114 | | |
| 1115 | | curr_effect->end(); |
| 1116 | | |
| 1117 | | if (new_dst) |
| 1118 | | { |
| 1119 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); |
| 1120 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1121 | | } |
| 1122 | | } |
| 1123 | | |
| 1124 | | |
| 1125 | | |
| 1126 | | //============================================================ |
| 1127 | | // shaders::blit |
| 1128 | | //============================================================ |
| 1129 | | |
| 1130 | | void shaders::blit(surface *dst, texture *src, surface *new_dst, D3DPRIMITIVETYPE prim_type, |
| 1131 | | UINT32 prim_index, UINT32 prim_count) |
| 1132 | | { |
| 1133 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, dst); |
| 1134 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1135 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); |
| 1136 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1137 | | |
| 1138 | | curr_effect = default_effect; |
| 1139 | | |
| 1140 | | curr_effect->set_texture("Diffuse", src); |
| 1141 | | |
| 1142 | | vec2f screendims = d3d->get_dims(); |
| 1143 | | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1144 | | curr_effect->set_float("PostPass", 1.0f); |
| 1145 | | curr_effect->set_float("PincushionAmount", options->pincushion); |
| 1146 | | curr_effect->set_float("Brighten", 1.0f); |
| 1147 | | |
| 1148 | | unsigned int num_passes = 0; |
| 1149 | | curr_effect->begin(&num_passes, 0); |
| 1150 | | |
| 1151 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1152 | | { |
| 1153 | | curr_effect->begin_pass(pass); |
| 1154 | | // add the primitives |
| 1155 | | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), prim_type, prim_index, prim_count); |
| 1156 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1157 | | curr_effect->end_pass(); |
| 1158 | | } |
| 1159 | | |
| 1160 | | curr_effect->end(); |
| 1161 | | |
| 1162 | | curr_effect->set_float("Brighten", 0.0f); |
| 1163 | | |
| 1164 | | if (new_dst) |
| 1165 | | { |
| 1166 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, new_dst); |
| 1167 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1168 | | } |
| 1169 | | } |
| 1170 | | |
| 1171 | | //============================================================ |
| 1172 | | // shaders::end_frame |
| 1173 | | //============================================================ |
| 1174 | | |
| 1175 | | void shaders::end_frame() |
| 1176 | | { |
| 1177 | | if (!master_enable || !d3dintf->post_fx_available) |
| 1178 | | return; |
| 1179 | | |
| 1180 | | if(render_snap && snap_rendered) |
| 1181 | | { |
| 1182 | | render_snapshot(snap_target); |
| 1183 | | } |
| 1184 | | |
| 1185 | | if (!lines_pending) |
| 1186 | | return; |
| 1187 | | |
| 1188 | | lines_pending = false; |
| 1189 | | |
| 1190 | | /*render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1191 | | if (rt == NULL) |
| 1192 | | { |
| 1193 | | return; |
| 1194 | | } |
| 1195 | | |
| 1196 | | blit(backbuffer, rt->render_texture[1], NULL, vecbuf_type, vecbuf_index, vecbuf_count); |
| 1197 | | |
| 1198 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1199 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1200 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1201 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1202 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1203 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result);*/ |
| 1204 | | } |
| 1205 | | |
| 1206 | | |
| 1207 | | //============================================================ |
| 1208 | | // shaders::init_effect_info |
| 1209 | | //============================================================ |
| 1210 | | |
| 1211 | | void shaders::init_effect_info(poly_info *poly) |
| 1212 | | { |
| 1213 | | if (!master_enable || !d3dintf->post_fx_available) |
| 1214 | | return; |
| 1215 | | |
| 1216 | | texture_info *texture = poly->get_texture(); |
| 1217 | | |
| 1218 | | if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && texture != NULL) |
| 1219 | | { |
| 1220 | | // Plug in all of the shader settings we're going to need |
| 1221 | | // This is extremely slow, but we're not rendering models here, |
| 1222 | | // just post-processing. |
| 1223 | | curr_effect = post_effect; |
| 1224 | | |
| 1225 | | curr_effect->set_float("ScanlineOffset", (texture->get_cur_frame() == 0) ? 0.0f : options->scanline_offset); |
| 1226 | | } |
| 1227 | | else |
| 1228 | | { |
| 1229 | | curr_effect = default_effect; |
| 1230 | | |
| 1231 | | curr_effect->set_float("FixedAlpha", 1.0f); |
| 1232 | | } |
| 1233 | | } |
| 1234 | | |
| 1235 | | |
| 1236 | | //============================================================ |
| 1237 | | // shaders::find_render_target |
| 1238 | | //============================================================ |
| 1239 | | |
| 1240 | | render_target* shaders::find_render_target(texture_info *info) |
| 1241 | | { |
| 1242 | | render_target *curr = targethead; |
| 1243 | | UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; |
| 1244 | | UINT32 screen_index = screen_index_data >> 1; |
| 1245 | | UINT32 page_index = screen_index_data & 1; |
| 1246 | | |
| 1247 | | while (curr != NULL && (curr->screen_index != screen_index || curr->page_index != page_index || |
| 1248 | | curr->width != info->get_texinfo().width || curr->height != info->get_texinfo().height)) |
| 1249 | | { |
| 1250 | | curr = curr->next; |
| 1251 | | } |
| 1252 | | |
| 1253 | | return curr; |
| 1254 | | } |
| 1255 | | |
| 1256 | | |
| 1257 | | //============================================================ |
| 1258 | | // shaders::find_render_target |
| 1259 | | //============================================================ |
| 1260 | | |
| 1261 | | render_target* shaders::find_render_target(int width, int height, UINT32 screen_index, UINT32 page_index) |
| 1262 | | { |
| 1263 | | render_target *curr = targethead; |
| 1264 | | |
| 1265 | | while (curr != NULL && (curr->width != width || curr->height != height || curr->screen_index != screen_index || curr->page_index != page_index)) |
| 1266 | | { |
| 1267 | | curr = curr->next; |
| 1268 | | } |
| 1269 | | |
| 1270 | | return curr; |
| 1271 | | } |
| 1272 | | |
| 1273 | | |
| 1274 | | //============================================================ |
| 1275 | | // shaders::find_cache_target |
| 1276 | | //============================================================ |
| 1277 | | |
| 1278 | | cache_target* shaders::find_cache_target(UINT32 screen_index, int width, int height) |
| 1279 | | { |
| 1280 | | cache_target *curr = cachehead; |
| 1281 | | |
| 1282 | | while (curr != NULL && (curr->screen_index != screen_index || curr->width != width || curr->height != height)) |
| 1283 | | { |
| 1284 | | curr = curr->next; |
| 1285 | | } |
| 1286 | | |
| 1287 | | return curr; |
| 1288 | | } |
| 1289 | | |
| 1290 | | void shaders::ntsc_pass(render_target *rt, vec2f &sourcedims, vec2f &delta) |
| 1291 | | { |
| 1292 | | UINT num_passes = 0; |
| 1293 | | |
| 1294 | | if(options->yiq_enable) |
| 1295 | | { |
| 1296 | | // Convert our signal into YIQ |
| 1297 | | curr_effect = yiq_encode_effect; |
| 1298 | | curr_effect->update_uniforms(); |
| 1299 | | |
| 1300 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[4]); |
| 1301 | | |
| 1302 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1303 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1304 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1305 | | |
| 1306 | | curr_effect->begin(&num_passes, 0); |
| 1307 | | |
| 1308 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1309 | | { |
| 1310 | | curr_effect->begin_pass(pass); |
| 1311 | | // add the primitives |
| 1312 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1313 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1314 | | curr_effect->end_pass(); |
| 1315 | | } |
| 1316 | | |
| 1317 | | curr_effect->end(); |
| 1318 | | |
| 1319 | | // Convert our signal from YIQ |
| 1320 | | curr_effect = yiq_decode_effect; |
| 1321 | | |
| 1322 | | curr_effect->set_texture("Composite", rt->render_texture[4]); |
| 1323 | | curr_effect->set_texture("Diffuse", curr_texture->get_finaltex()); |
| 1324 | | curr_effect->update_uniforms(); |
| 1325 | | |
| 1326 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); |
| 1327 | | |
| 1328 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1329 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1330 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1331 | | |
| 1332 | | curr_effect->begin(&num_passes, 0); |
| 1333 | | |
| 1334 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1335 | | { |
| 1336 | | curr_effect->begin_pass(pass); |
| 1337 | | // add the primitives |
| 1338 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1339 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1340 | | curr_effect->end_pass(); |
| 1341 | | } |
| 1342 | | |
| 1343 | | curr_effect->end(); |
| 1344 | | |
| 1345 | | curr_effect = color_effect; |
| 1346 | | |
| 1347 | | curr_effect->set_texture("Diffuse", rt->render_texture[3]); |
| 1348 | | } |
| 1349 | | } |
| 1350 | | |
| 1351 | | void shaders::color_convolution_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims) |
| 1352 | | { |
| 1353 | | UINT num_passes = 0; |
| 1354 | | |
| 1355 | | curr_effect = color_effect; |
| 1356 | | curr_effect->update_uniforms(); |
| 1357 | | |
| 1358 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->smalltarget); |
| 1359 | | |
| 1360 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1361 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1362 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1363 | | |
| 1364 | | curr_effect->begin(&num_passes, 0); |
| 1365 | | |
| 1366 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1367 | | { |
| 1368 | | curr_effect->begin_pass(pass); |
| 1369 | | // add the primitives |
| 1370 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1371 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1372 | | curr_effect->end_pass(); |
| 1373 | | } |
| 1374 | | |
| 1375 | | curr_effect->end(); |
| 1376 | | } |
| 1377 | | |
| 1378 | | void shaders::prescale_pass(render_target *rt, vec2f &texsize, vec2f &sourcedims) |
| 1379 | | { |
| 1380 | | UINT num_passes = 0; |
| 1381 | | |
| 1382 | | curr_effect = prescale_effect; |
| 1383 | | curr_effect->update_uniforms(); |
| 1384 | | curr_effect->set_texture("Diffuse", rt->smalltexture); |
| 1385 | | |
| 1386 | | curr_effect->begin(&num_passes, 0); |
| 1387 | | |
| 1388 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->prescaletarget); |
| 1389 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1390 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1391 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1392 | | |
| 1393 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1394 | | { |
| 1395 | | curr_effect->begin_pass(pass); |
| 1396 | | // add the primitives |
| 1397 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1398 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1399 | | curr_effect->end_pass(); |
| 1400 | | } |
| 1401 | | |
| 1402 | | curr_effect->end(); |
| 1403 | | } |
| 1404 | | |
| 1405 | | void shaders::deconverge_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims) |
| 1406 | | { |
| 1407 | | UINT num_passes = 0; |
| 1408 | | |
| 1409 | | curr_effect = deconverge_effect; |
| 1410 | | curr_effect->update_uniforms(); |
| 1411 | | curr_effect->set_texture("Diffuse", rt->prescaletexture); |
| 1412 | | |
| 1413 | | curr_effect->begin(&num_passes, 0); |
| 1414 | | |
| 1415 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); |
| 1416 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1417 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1418 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1419 | | |
| 1420 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1421 | | { |
| 1422 | | curr_effect->begin_pass(pass); |
| 1423 | | // add the primitives |
| 1424 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1425 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1426 | | curr_effect->end_pass(); |
| 1427 | | } |
| 1428 | | |
| 1429 | | curr_effect->end(); |
| 1430 | | } |
| 1431 | | |
| 1432 | | void shaders::defocus_pass(render_target *rt, vec2f &texsize) |
| 1433 | | { |
| 1434 | | UINT num_passes = 0; |
| 1435 | | |
| 1436 | | // Defocus pass 1 |
| 1437 | | curr_effect = focus_effect; |
| 1438 | | curr_effect->update_uniforms(); |
| 1439 | | curr_effect->set_texture("Diffuse", rt->render_texture[2]); |
| 1440 | | |
| 1441 | | curr_effect->begin(&num_passes, 0); |
| 1442 | | |
| 1443 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1444 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1445 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1446 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1447 | | |
| 1448 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1449 | | { |
| 1450 | | curr_effect->begin_pass(pass); |
| 1451 | | // add the primitives |
| 1452 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1453 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1454 | | curr_effect->end_pass(); |
| 1455 | | } |
| 1456 | | |
| 1457 | | curr_effect->end(); |
| 1458 | | |
| 1459 | | // Defocus pass 2 |
| 1460 | | |
| 1461 | | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1462 | | |
| 1463 | | curr_effect->begin(&num_passes, 0); |
| 1464 | | |
| 1465 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1466 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 7\n", (int)result); |
| 1467 | | |
| 1468 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1469 | | { |
| 1470 | | curr_effect->begin_pass(pass); |
| 1471 | | // add the primitives |
| 1472 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1473 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1474 | | curr_effect->end_pass(); |
| 1475 | | } |
| 1476 | | |
| 1477 | | curr_effect->end(); |
| 1478 | | } |
| 1479 | | |
| 1480 | | void shaders::phosphor_pass(render_target *rt, cache_target *ct, vec2f &texsize, bool focus_enable) |
| 1481 | | { |
| 1482 | | UINT num_passes = 0; |
| 1483 | | |
| 1484 | | curr_effect = phosphor_effect; |
| 1485 | | phosphor_passthrough = false; |
| 1486 | | curr_effect->update_uniforms(); |
| 1487 | | |
| 1488 | | float rtsize[2] = { rt->target_width, rt->target_height }; |
| 1489 | | curr_effect->set_vector("TargetDims", 2, rtsize); |
| 1490 | | |
| 1491 | | curr_effect->set_texture("Diffuse", focus_enable ? rt->render_texture[1] : rt->render_texture[2]); |
| 1492 | | curr_effect->set_texture("LastPass", ct->last_texture); |
| 1493 | | |
| 1494 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1495 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); |
| 1496 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1497 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1498 | | |
| 1499 | | curr_effect->begin(&num_passes, 0); |
| 1500 | | |
| 1501 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1502 | | { |
| 1503 | | curr_effect->begin_pass(pass); |
| 1504 | | // add the primitives |
| 1505 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1506 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1507 | | curr_effect->end_pass(); |
| 1508 | | } |
| 1509 | | |
| 1510 | | curr_effect->end(); |
| 1511 | | |
| 1512 | | // Pass along our phosphor'd screen |
| 1513 | | phosphor_passthrough = true; |
| 1514 | | curr_effect->update_uniforms(); |
| 1515 | | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1516 | | curr_effect->set_texture("LastPass", rt->render_texture[0]); |
| 1517 | | |
| 1518 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, ct->last_target); // Avoid changing targets due to page flipping |
| 1519 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 5\n", (int)result); |
| 1520 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1521 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1522 | | |
| 1523 | | curr_effect->begin(&num_passes, 0); |
| 1524 | | |
| 1525 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1526 | | { |
| 1527 | | curr_effect->begin_pass(pass); |
| 1528 | | // add the primitives |
| 1529 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1530 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1531 | | curr_effect->end_pass(); |
| 1532 | | } |
| 1533 | | |
| 1534 | | curr_effect->end(); |
| 1535 | | } |
| 1536 | | |
| 1537 | | void shaders::avi_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum) |
| 1538 | | { |
| 1539 | | UINT num_passes = 0; |
| 1540 | | |
| 1541 | | curr_effect = post_effect; |
| 1542 | | curr_effect->update_uniforms(); |
| 1543 | | curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); |
| 1544 | | |
| 1545 | | // Scanlines and shadow mask, at high res for AVI logging |
| 1546 | | if(avi_output_file != NULL) |
| 1547 | | { |
| 1548 | | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1549 | | |
| 1550 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, avi_final_target); |
| 1551 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1552 | | |
| 1553 | | curr_effect->begin(&num_passes, 0); |
| 1554 | | |
| 1555 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1556 | | { |
| 1557 | | curr_effect->begin_pass(pass); |
| 1558 | | // add the primitives |
| 1559 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1560 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1561 | | curr_effect->end_pass(); |
| 1562 | | } |
| 1563 | | |
| 1564 | | curr_effect->end(); |
| 1565 | | } |
| 1566 | | |
| 1567 | | if(render_snap) |
| 1568 | | { |
| 1569 | | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1570 | | |
| 1571 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, snap_target); |
| 1572 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1573 | | |
| 1574 | | curr_effect->begin(&num_passes, 0); |
| 1575 | | |
| 1576 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1577 | | { |
| 1578 | | curr_effect->begin_pass(pass); |
| 1579 | | // add the primitives |
| 1580 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1581 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1582 | | curr_effect->end_pass(); |
| 1583 | | } |
| 1584 | | |
| 1585 | | curr_effect->end(); |
| 1586 | | |
| 1587 | | snap_rendered = true; |
| 1588 | | } |
| 1589 | | } |
| 1590 | | |
| 1591 | | void shaders::screen_post_pass(render_target *rt, vec2f &texsize, vec2f &delta, vec2f &sourcedims, poly_info *poly, int vertnum) |
| 1592 | | { |
| 1593 | | UINT num_passes = 0; |
| 1594 | | |
| 1595 | | curr_effect = post_effect; |
| 1596 | | curr_effect->update_uniforms(); |
| 1597 | | curr_effect->set_texture("ShadowTexture", shadow_texture == NULL ? NULL : shadow_texture->get_finaltex()); |
| 1598 | | |
| 1599 | | curr_effect->set_texture("DiffuseTexture", rt->render_texture[0]); |
| 1600 | | |
| 1601 | | d3d->set_wrap(D3DTADDRESS_MIRROR); |
| 1602 | | |
| 1603 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[2]); |
| 1604 | | |
| 1605 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 0, 0); |
| 1606 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1607 | | |
| 1608 | | curr_effect->begin(&num_passes, 0); |
| 1609 | | |
| 1610 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1611 | | { |
| 1612 | | curr_effect->begin_pass(pass); |
| 1613 | | // add the primitives |
| 1614 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1615 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1616 | | curr_effect->end_pass(); |
| 1617 | | } |
| 1618 | | |
| 1619 | | curr_effect->end(); |
| 1620 | | |
| 1621 | | d3d->set_wrap(PRIMFLAG_GET_TEXWRAP(poly->get_texture()->get_flags()) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); |
| 1622 | | } |
| 1623 | | |
| 1624 | | void shaders::raster_bloom_pass(render_target *rt, vec2f &texsize, vec2f &delta, poly_info *poly, int vertnum) |
| 1625 | | { |
| 1626 | | UINT num_passes = 0; |
| 1627 | | |
| 1628 | | curr_effect = downsample_effect; |
| 1629 | | |
| 1630 | | curr_effect->set_texture("Diffuse", rt->render_texture[2]); |
| 1631 | | curr_effect->set_float("BloomRescale", options->raster_bloom_scale); |
| 1632 | | |
| 1633 | | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 1634 | | int bloom_index = 0; |
| 1635 | | float bloom_width = rt->target_width; |
| 1636 | | float bloom_height = rt->target_height; |
| 1637 | | vec2f screendims = d3d->get_dims(); |
| 1638 | | curr_effect->set_vector("ScreenSize", 2, &screendims.c.x); |
| 1639 | | float bloom_dims[11][2]; |
| 1640 | | for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 1641 | | { |
| 1642 | | bloom_dims[bloom_index][0] = bloom_width; |
| 1643 | | bloom_dims[bloom_index][1] = bloom_height; |
| 1644 | | curr_effect->set_vector("TargetSize", 2, bloom_dims[bloom_index]); |
| 1645 | | |
| 1646 | | curr_effect->begin(&num_passes, 0); |
| 1647 | | |
| 1648 | | curr_effect->set_texture("DiffuseTexture", (bloom_index == 0) ? rt->render_texture[2] : rt->bloom_texture[bloom_index - 1]); |
| 1649 | | |
| 1650 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); |
| 1651 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1652 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1653 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1654 | | |
| 1655 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1656 | | { |
| 1657 | | curr_effect->begin_pass(pass); |
| 1658 | | // add the primitives |
| 1659 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1660 | | //result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1661 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1662 | | curr_effect->end_pass(); |
| 1663 | | } |
| 1664 | | |
| 1665 | | curr_effect->end(); |
| 1666 | | |
| 1667 | | bloom_index++; |
| 1668 | | bloom_width *= 0.5f; |
| 1669 | | bloom_height *= 0.5f; |
| 1670 | | } |
| 1671 | | |
| 1672 | | curr_effect = bloom_effect; |
| 1673 | | |
| 1674 | | float target_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1675 | | curr_effect->set_vector("TargetSize", 2, target_size); |
| 1676 | | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, options->bloom_level2_weight, options->bloom_level3_weight }; |
| 1677 | | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, options->bloom_level6_weight, options->bloom_level7_weight }; |
| 1678 | | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, options->bloom_level10_weight }; |
| 1679 | | curr_effect->set_vector("Level0123Weight", 4, weight0123); |
| 1680 | | curr_effect->set_vector("Level4567Weight", 4, weight4567); |
| 1681 | | curr_effect->set_vector("Level89AWeight", 3, weight89A); |
| 1682 | | curr_effect->set_vector("Level01Size", 4, bloom_dims[0]); |
| 1683 | | curr_effect->set_vector("Level23Size", 4, bloom_dims[2]); |
| 1684 | | curr_effect->set_vector("Level45Size", 4, bloom_dims[4]); |
| 1685 | | curr_effect->set_vector("Level67Size", 4, bloom_dims[6]); |
| 1686 | | curr_effect->set_vector("Level89Size", 4, bloom_dims[8]); |
| 1687 | | curr_effect->set_vector("LevelASize", 2, bloom_dims[10]); |
| 1688 | | |
| 1689 | | curr_effect->set_texture("DiffuseA", rt->render_texture[2]); |
| 1690 | | |
| 1691 | | char name[9] = "Diffuse*"; |
| 1692 | | for(int index = 1; index < bloom_index; index++) |
| 1693 | | { |
| 1694 | | name[7] = 'A' + index; |
| 1695 | | curr_effect->set_texture(name, rt->bloom_texture[index - 1]); |
| 1696 | | } |
| 1697 | | for(int index = bloom_index; index < 11; index++) |
| 1698 | | { |
| 1699 | | name[7] = 'A' + index; |
| 1700 | | curr_effect->set_texture(name, black_texture); |
| 1701 | | } |
| 1702 | | |
| 1703 | | curr_effect->begin(&num_passes, 0); |
| 1704 | | |
| 1705 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1706 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1707 | | |
| 1708 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1709 | | { |
| 1710 | | curr_effect->begin_pass(pass); |
| 1711 | | // add the primitives |
| 1712 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1713 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1714 | | curr_effect->end_pass(); |
| 1715 | | } |
| 1716 | | |
| 1717 | | curr_effect->end(); |
| 1718 | | } |
| 1719 | | |
| 1720 | | //============================================================ |
| 1721 | | // shaders::render_quad |
| 1722 | | //============================================================ |
| 1723 | | |
| 1724 | | void shaders::render_quad(poly_info *poly, int vertnum) |
| 1725 | | { |
| 1726 | | if (!master_enable || !d3dintf->post_fx_available) |
| 1727 | | return; |
| 1728 | | |
| 1729 | | UINT num_passes = 0; |
| 1730 | | curr_texture = poly->get_texture(); |
| 1731 | | |
| 1732 | | if(PRIMFLAG_GET_SCREENTEX(d3d->get_last_texture_flags()) && curr_texture != NULL) |
| 1733 | | { |
| 1734 | | render_target *rt = find_render_target(curr_texture); |
| 1735 | | if (rt == NULL) |
| 1736 | | { |
| 1737 | | return; |
| 1738 | | } |
| 1739 | | cache_target *ct = find_cache_target(rt->screen_index, curr_texture->get_texinfo().width, curr_texture->get_texinfo().height); |
| 1740 | | |
| 1741 | | vec2f& sourcedims = curr_texture->get_rawdims(); |
| 1742 | | vec2f delta = curr_texture->get_uvstop() - curr_texture->get_uvstart(); |
| 1743 | | vec2f texsize(rt->width, rt->height); |
| 1744 | | float defocus_x = options->defocus[0]; |
| 1745 | | float defocus_y = options->defocus[1]; |
| 1746 | | bool focus_enable = defocus_x != 0.0f || defocus_y != 0.0f; |
| 1747 | | |
| 1748 | | ntsc_pass(rt, sourcedims, delta); |
| 1749 | | color_convolution_pass(rt, texsize, sourcedims); |
| 1750 | | prescale_pass(rt, texsize, sourcedims); |
| 1751 | | deconverge_pass(rt, texsize, delta, sourcedims); |
| 1752 | | if (focus_enable) |
| 1753 | | { |
| 1754 | | defocus_pass(rt, texsize); |
| 1755 | | } |
| 1756 | | phosphor_pass(rt, ct, texsize, focus_enable); |
| 1757 | | avi_post_pass(rt, texsize, delta, sourcedims, poly, vertnum); |
| 1758 | | screen_post_pass(rt, texsize, delta, sourcedims, poly, vertnum); |
| 1759 | | raster_bloom_pass(rt, texsize, delta, poly, vertnum); |
| 1760 | | |
| 1761 | | curr_texture->increment_frame_count(); |
| 1762 | | curr_texture->mask_frame_count(options->yiq_phase_count); |
| 1763 | | |
| 1764 | | options->params_dirty = false; |
| 1765 | | |
| 1766 | | } |
| 1767 | | else if(PRIMFLAG_GET_VECTOR(poly->get_flags()) && vector_enable) |
| 1768 | | { |
| 1769 | | render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1770 | | if (rt == NULL) |
| 1771 | | { |
| 1772 | | return; |
| 1773 | | } |
| 1774 | | |
| 1775 | | lines_pending = true; |
| 1776 | | |
| 1777 | | curr_effect = vector_effect; |
| 1778 | | |
| 1779 | | if(options->params_dirty) |
| 1780 | | { |
| 1781 | | vec2f screendims = d3d->get_dims(); |
| 1782 | | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1783 | | } |
| 1784 | | |
| 1785 | | float time_params[2] = { 0.0f, 0.0f }; |
| 1786 | | float length_params[3] = { poly->get_line_length(), options->vector_length_scale, options->vector_length_ratio }; |
| 1787 | | curr_effect->set_vector("TimeParams", 2, time_params); |
| 1788 | | curr_effect->set_vector("LengthParams", 3, length_params); |
| 1789 | | |
| 1790 | | curr_effect->begin(&num_passes, 0); |
| 1791 | | |
| 1792 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1793 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1794 | | |
| 1795 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1796 | | { |
| 1797 | | curr_effect->begin_pass(pass); |
| 1798 | | // add the primitives |
| 1799 | | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1800 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1801 | | curr_effect->end_pass(); |
| 1802 | | } |
| 1803 | | |
| 1804 | | curr_effect->end(); |
| 1805 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1806 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1807 | | |
| 1808 | | curr_effect = default_effect; |
| 1809 | | |
| 1810 | | curr_effect->set_float("FixedAlpha", 1.0f); |
| 1811 | | } |
| 1812 | | else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable) |
| 1813 | | { |
| 1814 | | render_target *rt = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 1815 | | |
| 1816 | | /* Bloom */ |
| 1817 | | curr_effect = downsample_effect; |
| 1818 | | |
| 1819 | | curr_effect->set_texture("Diffuse", rt->render_texture[0]); |
| 1820 | | curr_effect->set_float("BloomRescale", options->vector_bloom_scale); |
| 1821 | | |
| 1822 | | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 1823 | | int bloom_index = 0; |
| 1824 | | float bloom_width = rt->target_width; |
| 1825 | | float bloom_height = rt->target_height; |
| 1826 | | float screen_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1827 | | curr_effect->set_vector("ScreenSize", 2, screen_size); |
| 1828 | | float bloom_dims[11][2]; |
| 1829 | | for(; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 1830 | | { |
| 1831 | | bloom_dims[bloom_index][0] = bloom_width; |
| 1832 | | bloom_dims[bloom_index][1] = bloom_height; |
| 1833 | | curr_effect->set_vector("TargetSize", 2, bloom_dims[bloom_index]); |
| 1834 | | |
| 1835 | | curr_effect->begin(&num_passes, 0); |
| 1836 | | |
| 1837 | | curr_effect->set_texture("DiffuseTexture", (bloom_index == 0) ? rt->render_texture[0] : rt->bloom_texture[bloom_index - 1]); |
| 1838 | | |
| 1839 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->bloom_target[bloom_index]); |
| 1840 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1841 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1842 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1843 | | |
| 1844 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1845 | | { |
| 1846 | | curr_effect->begin_pass(pass); |
| 1847 | | // add the primitives |
| 1848 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1849 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1850 | | curr_effect->end_pass(); |
| 1851 | | } |
| 1852 | | |
| 1853 | | curr_effect->end(); |
| 1854 | | |
| 1855 | | bloom_index++; |
| 1856 | | bloom_width *= 0.5f; |
| 1857 | | bloom_height *= 0.5f; |
| 1858 | | } |
| 1859 | | |
| 1860 | | // Bloom composite pass |
| 1861 | | curr_effect = bloom_effect; |
| 1862 | | |
| 1863 | | float target_size[2] = { d3d->get_width(), d3d->get_height() }; |
| 1864 | | curr_effect->set_vector("TargetSize", 2, target_size); |
| 1865 | | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, |
| 1866 | | options->bloom_level2_weight, options->bloom_level3_weight }; |
| 1867 | | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, |
| 1868 | | options->bloom_level6_weight, options->bloom_level7_weight }; |
| 1869 | | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, |
| 1870 | | options->bloom_level10_weight }; |
| 1871 | | curr_effect->set_vector("Level0123Weight", 4, weight0123); |
| 1872 | | curr_effect->set_vector("Level4567Weight", 4, weight4567); |
| 1873 | | curr_effect->set_vector("Level89AWeight", 3, weight89A); |
| 1874 | | curr_effect->set_vector("Level01Size", 4, bloom_dims[0]); |
| 1875 | | curr_effect->set_vector("Level23Size", 4, bloom_dims[2]); |
| 1876 | | curr_effect->set_vector("Level45Size", 4, bloom_dims[4]); |
| 1877 | | curr_effect->set_vector("Level67Size", 4, bloom_dims[6]); |
| 1878 | | curr_effect->set_vector("Level89Size", 4, bloom_dims[8]); |
| 1879 | | curr_effect->set_vector("LevelASize", 2, bloom_dims[10]); |
| 1880 | | |
| 1881 | | curr_effect->set_texture("DiffuseA", rt->render_texture[0]); |
| 1882 | | |
| 1883 | | char name[9] = "Diffuse*"; |
| 1884 | | for(int index = 1; index < bloom_index; index++) |
| 1885 | | { |
| 1886 | | name[7] = 'A' + index; |
| 1887 | | curr_effect->set_texture(name, rt->bloom_texture[index - 1]); |
| 1888 | | } |
| 1889 | | for(int index = bloom_index; index < 11; index++) |
| 1890 | | { |
| 1891 | | name[7] = 'A' + index; |
| 1892 | | curr_effect->set_texture(name, black_texture); |
| 1893 | | } |
| 1894 | | |
| 1895 | | curr_effect->begin(&num_passes, 0); |
| 1896 | | |
| 1897 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[1]); |
| 1898 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 6\n", (int)result); |
| 1899 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1900 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1901 | | |
| 1902 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1903 | | { |
| 1904 | | curr_effect->begin_pass(pass); |
| 1905 | | // add the primitives |
| 1906 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1907 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1908 | | curr_effect->end_pass(); |
| 1909 | | } |
| 1910 | | |
| 1911 | | curr_effect->end(); |
| 1912 | | |
| 1913 | | /* Phosphor */ |
| 1914 | | curr_effect = phosphor_effect; |
| 1915 | | |
| 1916 | | if(options->params_dirty) |
| 1917 | | { |
| 1918 | | vec2f screendims = d3d->get_dims(); |
| 1919 | | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1920 | | curr_effect->set_vector("Phosphor", 3, options->phosphor); |
| 1921 | | } |
| 1922 | | float target_dims[2] = { d3d->get_width(), d3d->get_height() }; |
| 1923 | | curr_effect->set_vector("TargetDims", 2, target_dims); |
| 1924 | | curr_effect->set_float("Passthrough", 0.0f); |
| 1925 | | |
| 1926 | | curr_effect->set_texture("Diffuse", rt->render_texture[1]); |
| 1927 | | curr_effect->set_texture("LastPass", rt->render_texture[2]); |
| 1928 | | |
| 1929 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[3]); |
| 1930 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 4\n", (int)result); |
| 1931 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1932 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1933 | | |
| 1934 | | curr_effect->begin(&num_passes, 0); |
| 1935 | | |
| 1936 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1937 | | { |
| 1938 | | curr_effect->begin_pass(pass); |
| 1939 | | // add the primitives |
| 1940 | | result = (*d3dintf->device.draw_primitive)(d3d->get_device(), D3DPT_TRIANGLELIST, 0, 2); |
| 1941 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1942 | | curr_effect->end_pass(); |
| 1943 | | } |
| 1944 | | |
| 1945 | | curr_effect->end(); |
| 1946 | | |
| 1947 | | blit(rt->target[2], rt->render_texture[3], NULL, poly->get_type(), vertnum, poly->get_count()); |
| 1948 | | blit(backbuffer, rt->render_texture[3], backbuffer, poly->get_type(), vertnum, poly->get_count()); |
| 1949 | | |
| 1950 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, rt->target[0]); |
| 1951 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1952 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 1953 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 1954 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 1955 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 1956 | | |
| 1957 | | lines_pending = false; |
| 1958 | | } |
| 1959 | | else |
| 1960 | | { |
| 1961 | | curr_effect = default_effect; |
| 1962 | | |
| 1963 | | vec2f screendims = d3d->get_dims(); |
| 1964 | | curr_effect->set_vector("ScreenDims", 2, &screendims.c.x); |
| 1965 | | curr_effect->set_float("PostPass", 0.0f); |
| 1966 | | |
| 1967 | | curr_effect->begin(&num_passes, 0); |
| 1968 | | |
| 1969 | | for (UINT pass = 0; pass < num_passes; pass++) |
| 1970 | | { |
| 1971 | | curr_effect->begin_pass(pass); |
| 1972 | | // add the primitives |
| 1973 | | HRESULT result = (*d3dintf->device.draw_primitive)(d3d->get_device(), poly->get_type(), vertnum, poly->get_count()); |
| 1974 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1975 | | curr_effect->end_pass(); |
| 1976 | | } |
| 1977 | | |
| 1978 | | curr_effect->end(); |
| 1979 | | } |
| 1980 | | |
| 1981 | | curr_texture = NULL; |
| 1982 | | } |
| 1983 | | |
| 1984 | | |
| 1985 | | |
| 1986 | | //============================================================ |
| 1987 | | // shaders::end_draw |
| 1988 | | //============================================================ |
| 1989 | | |
| 1990 | | void shaders::end_draw() |
| 1991 | | { |
| 1992 | | if (!master_enable || !d3dintf->post_fx_available) |
| 1993 | | return; |
| 1994 | | |
| 1995 | | (*d3dintf->surface.release)(backbuffer); |
| 1996 | | } |
| 1997 | | |
| 1998 | | |
| 1999 | | //============================================================ |
| 2000 | | // shaders::register_prescaled_texture |
| 2001 | | //============================================================ |
| 2002 | | |
| 2003 | | bool shaders::register_prescaled_texture(texture_info *texture) |
| 2004 | | { |
| 2005 | | return register_texture(texture); |
| 2006 | | } |
| 2007 | | |
| 2008 | | |
| 2009 | | //============================================================ |
| 2010 | | // shaders::add_cache_target - register a cache target |
| 2011 | | //============================================================ |
| 2012 | | bool shaders::add_cache_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale, int screen_index) |
| 2013 | | { |
| 2014 | | cache_target* target = (cache_target*)global_alloc_clear(cache_target); |
| 2015 | | |
| 2016 | | if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) |
| 2017 | | { |
| 2018 | | global_free(target); |
| 2019 | | return false; |
| 2020 | | } |
| 2021 | | |
| 2022 | | if (info != NULL) |
| 2023 | | { |
| 2024 | | target->width = info->get_texinfo().width; |
| 2025 | | target->height = info->get_texinfo().height; |
| 2026 | | } |
| 2027 | | else |
| 2028 | | { |
| 2029 | | target->width = d3d->get_width(); |
| 2030 | | target->height = d3d->get_height(); |
| 2031 | | } |
| 2032 | | |
| 2033 | | target->next = cachehead; |
| 2034 | | target->prev = NULL; |
| 2035 | | |
| 2036 | | target->screen_index = screen_index; |
| 2037 | | |
| 2038 | | if (cachehead != NULL) |
| 2039 | | { |
| 2040 | | cachehead->prev = target; |
| 2041 | | } |
| 2042 | | cachehead = target; |
| 2043 | | |
| 2044 | | return true; |
| 2045 | | } |
| 2046 | | |
| 2047 | | render_target* shaders::get_vector_target() |
| 2048 | | { |
| 2049 | | if (!vector_enable) |
| 2050 | | { |
| 2051 | | return NULL; |
| 2052 | | } |
| 2053 | | |
| 2054 | | return find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 2055 | | } |
| 2056 | | |
| 2057 | | void shaders::create_vector_target(render_primitive *prim) |
| 2058 | | { |
| 2059 | | if (!add_render_target(d3d, NULL, d3d->get_width(), d3d->get_height(), 1, 1)) |
| 2060 | | { |
| 2061 | | vector_enable = false; |
| 2062 | | } |
| 2063 | | } |
| 2064 | | |
| 2065 | | //============================================================ |
| 2066 | | // shaders::add_render_target - register a render target |
| 2067 | | //============================================================ |
| 2068 | | |
| 2069 | | bool shaders::add_render_target(renderer* d3d, texture_info* info, int width, int height, int xprescale, int yprescale) |
| 2070 | | { |
| 2071 | | UINT32 screen_index = 0; |
| 2072 | | UINT32 page_index = 0; |
| 2073 | | if (info != NULL) |
| 2074 | | { |
| 2075 | | render_target *existing_target = find_render_target(info); |
| 2076 | | if (existing_target != NULL) |
| 2077 | | { |
| 2078 | | remove_render_target(existing_target); |
| 2079 | | } |
| 2080 | | |
| 2081 | | UINT32 screen_index_data = (UINT32)info->get_texinfo().osddata; |
| 2082 | | screen_index = screen_index_data >> 1; |
| 2083 | | page_index = screen_index_data & 1; |
| 2084 | | } |
| 2085 | | else |
| 2086 | | { |
| 2087 | | render_target *existing_target = find_render_target(d3d->get_width(), d3d->get_height(), 0, 0); |
| 2088 | | if (existing_target != NULL) |
| 2089 | | { |
| 2090 | | remove_render_target(existing_target); |
| 2091 | | } |
| 2092 | | } |
| 2093 | | |
| 2094 | | render_target* target = (render_target*)global_alloc_clear(render_target); |
| 2095 | | |
| 2096 | | if (!target->init(d3d, d3dintf, width, height, xprescale, yprescale)) |
| 2097 | | { |
| 2098 | | global_free(target); |
| 2099 | | return false; |
| 2100 | | } |
| 2101 | | |
| 2102 | | if (info != NULL) |
| 2103 | | { |
| 2104 | | target->width = info->get_texinfo().width; |
| 2105 | | target->height = info->get_texinfo().height; |
| 2106 | | } |
| 2107 | | else |
| 2108 | | { |
| 2109 | | target->width = d3d->get_width(); |
| 2110 | | target->height = d3d->get_height(); |
| 2111 | | } |
| 2112 | | |
| 2113 | | HRESULT result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, target->target[0]); |
| 2114 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 2115 | | result = (*d3dintf->device.clear)(d3d->get_device(), 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 2116 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 2117 | | result = (*d3dintf->device.set_render_target)(d3d->get_device(), 0, backbuffer); |
| 2118 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call\n", (int)result); |
| 2119 | | |
| 2120 | | target->screen_index = screen_index; |
| 2121 | | target->page_index = page_index; |
| 2122 | | |
| 2123 | | cache_target* cache = find_cache_target(target->screen_index, target->width, target->height); |
| 2124 | | if (cache == NULL) |
| 2125 | | { |
| 2126 | | if (!add_cache_target(d3d, info, width, height, xprescale, yprescale, target->screen_index)) |
| 2127 | | { |
| 2128 | | global_free(target); |
| 2129 | | return false; |
| 2130 | | } |
| 2131 | | } |
| 2132 | | |
| 2133 | | target->next = targethead; |
| 2134 | | target->prev = NULL; |
| 2135 | | |
| 2136 | | if (targethead != NULL) |
| 2137 | | { |
| 2138 | | targethead->prev = target; |
| 2139 | | } |
| 2140 | | targethead = target; |
| 2141 | | |
| 2142 | | return true; |
| 2143 | | } |
| 2144 | | |
| 2145 | | //============================================================ |
| 2146 | | // shaders::enumerate_screens |
| 2147 | | //============================================================ |
| 2148 | | void shaders::enumerate_screens() |
| 2149 | | { |
| 2150 | | screen_device_iterator iter(machine->root_device()); |
| 2151 | | num_screens = iter.count(); |
| 2152 | | } |
| 2153 | | |
| 2154 | | |
| 2155 | | //============================================================ |
| 2156 | | // shaders::register_texture(texture::info) |
| 2157 | | //============================================================ |
| 2158 | | |
| 2159 | | bool shaders::register_texture(texture_info *texture) |
| 2160 | | { |
| 2161 | | int width = texture->get_width(); |
| 2162 | | int height = texture->get_height(); |
| 2163 | | int xscale = texture->get_xscale(); |
| 2164 | | int yscale = texture->get_yscale(); |
| 2165 | | |
| 2166 | | if (!master_enable || !d3dintf->post_fx_available) |
| 2167 | | { |
| 2168 | | return false; |
| 2169 | | } |
| 2170 | | |
| 2171 | | enumerate_screens(); |
| 2172 | | |
| 2173 | | int hlsl_prescale_x = prescale_force_x; |
| 2174 | | int hlsl_prescale_y = prescale_force_y; |
| 2175 | | |
| 2176 | | // Find the nearest prescale factor that is over our screen size |
| 2177 | | if (hlsl_prescale_x == 0) |
| 2178 | | { |
| 2179 | | hlsl_prescale_x = 1; |
| 2180 | | while (width * xscale * hlsl_prescale_x <= d3d->get_width()) |
| 2181 | | { |
| 2182 | | hlsl_prescale_x++; |
| 2183 | | } |
| 2184 | | hlsl_prescale_x--; |
| 2185 | | } |
| 2186 | | |
| 2187 | | if (hlsl_prescale_y == 0) |
| 2188 | | { |
| 2189 | | hlsl_prescale_y = 1; |
| 2190 | | while (height * yscale * hlsl_prescale_y <= d3d->get_height()) |
| 2191 | | { |
| 2192 | | hlsl_prescale_y++; |
| 2193 | | } |
| 2194 | | hlsl_prescale_y--; |
| 2195 | | } |
| 2196 | | |
| 2197 | | hlsl_prescale_x = ((hlsl_prescale_x == 0) ? 1 : hlsl_prescale_x); |
| 2198 | | hlsl_prescale_y = ((hlsl_prescale_y == 0) ? 1 : hlsl_prescale_y); |
| 2199 | | |
| 2200 | | if (!add_render_target(d3d, texture, width, height, xscale * hlsl_prescale_x, yscale * hlsl_prescale_y)) |
| 2201 | | return false; |
| 2202 | | |
| 2203 | | options->params_dirty = true; |
| 2204 | | |
| 2205 | | return true; |
| 2206 | | } |
| 2207 | | |
| 2208 | | //============================================================ |
| 2209 | | // shaders::delete_resources |
| 2210 | | //============================================================ |
| 2211 | | |
| 2212 | | void shaders::delete_resources(bool reset) |
| 2213 | | { |
| 2214 | | if (!master_enable || !d3dintf->post_fx_available) |
| 2215 | | return; |
| 2216 | | |
| 2217 | | initialized = false; |
| 2218 | | |
| 2219 | | cache_target *currcache = cachehead; |
| 2220 | | while(cachehead != NULL) |
| 2221 | | { |
| 2222 | | cachehead = currcache->next; |
| 2223 | | global_free(currcache); |
| 2224 | | currcache = cachehead; |
| 2225 | | } |
| 2226 | | |
| 2227 | | render_target *currtarget = targethead; |
| 2228 | | while(targethead != NULL) |
| 2229 | | { |
| 2230 | | targethead = currtarget->next; |
| 2231 | | global_free(currtarget); |
| 2232 | | currtarget = targethead; |
| 2233 | | } |
| 2234 | | |
| 2235 | | if (downsample_effect != NULL) |
| 2236 | | { |
| 2237 | | delete downsample_effect; |
| 2238 | | downsample_effect = NULL; |
| 2239 | | } |
| 2240 | | if (bloom_effect != NULL) |
| 2241 | | { |
| 2242 | | delete bloom_effect; |
| 2243 | | bloom_effect = NULL; |
| 2244 | | } |
| 2245 | | if (vector_effect != NULL) |
| 2246 | | { |
| 2247 | | delete vector_effect; |
| 2248 | | vector_effect = NULL; |
| 2249 | | } |
| 2250 | | if (default_effect != NULL) |
| 2251 | | { |
| 2252 | | delete default_effect; |
| 2253 | | default_effect = NULL; |
| 2254 | | } |
| 2255 | | if (post_effect != NULL) |
| 2256 | | { |
| 2257 | | delete post_effect; |
| 2258 | | post_effect = NULL; |
| 2259 | | } |
| 2260 | | if (prescale_effect != NULL) |
| 2261 | | { |
| 2262 | | delete prescale_effect; |
| 2263 | | prescale_effect = NULL; |
| 2264 | | } |
| 2265 | | if (phosphor_effect != NULL) |
| 2266 | | { |
| 2267 | | delete phosphor_effect; |
| 2268 | | phosphor_effect = NULL; |
| 2269 | | } |
| 2270 | | if (focus_effect != NULL) |
| 2271 | | { |
| 2272 | | delete focus_effect; |
| 2273 | | focus_effect = NULL; |
| 2274 | | } |
| 2275 | | if (deconverge_effect != NULL) |
| 2276 | | { |
| 2277 | | delete deconverge_effect; |
| 2278 | | deconverge_effect = NULL; |
| 2279 | | } |
| 2280 | | if (color_effect != NULL) |
| 2281 | | { |
| 2282 | | delete color_effect; |
| 2283 | | color_effect = NULL; |
| 2284 | | } |
| 2285 | | if (yiq_encode_effect != NULL) |
| 2286 | | { |
| 2287 | | delete yiq_encode_effect; |
| 2288 | | yiq_encode_effect = NULL; |
| 2289 | | } |
| 2290 | | if (yiq_decode_effect != NULL) |
| 2291 | | { |
| 2292 | | delete yiq_decode_effect; |
| 2293 | | yiq_decode_effect = NULL; |
| 2294 | | } |
| 2295 | | |
| 2296 | | if (backbuffer != NULL) |
| 2297 | | { |
| 2298 | | (*d3dintf->surface.release)(backbuffer); |
| 2299 | | backbuffer = NULL; |
| 2300 | | } |
| 2301 | | |
| 2302 | | if (black_surface != NULL) |
| 2303 | | { |
| 2304 | | (*d3dintf->surface.release)(black_surface); |
| 2305 | | black_surface = NULL; |
| 2306 | | } |
| 2307 | | if (black_texture != NULL) |
| 2308 | | { |
| 2309 | | (*d3dintf->texture.release)(black_texture); |
| 2310 | | black_texture = NULL; |
| 2311 | | } |
| 2312 | | |
| 2313 | | if (avi_copy_texture != NULL) |
| 2314 | | { |
| 2315 | | (*d3dintf->texture.release)(avi_copy_texture); |
| 2316 | | avi_copy_texture = NULL; |
| 2317 | | } |
| 2318 | | |
| 2319 | | if (avi_copy_surface != NULL) |
| 2320 | | { |
| 2321 | | (*d3dintf->surface.release)(avi_copy_surface); |
| 2322 | | avi_copy_surface = NULL; |
| 2323 | | } |
| 2324 | | |
| 2325 | | if (avi_final_texture != NULL) |
| 2326 | | { |
| 2327 | | (*d3dintf->texture.release)(avi_final_texture); |
| 2328 | | avi_final_texture = NULL; |
| 2329 | | } |
| 2330 | | |
| 2331 | | if (avi_final_target != NULL) |
| 2332 | | { |
| 2333 | | (*d3dintf->surface.release)(avi_final_target); |
| 2334 | | avi_final_target = NULL; |
| 2335 | | } |
| 2336 | | |
| 2337 | | shadow_bitmap.reset(); |
| 2338 | | } |
| 2339 | | |
| 2340 | | |
| 2341 | | //============================================================ |
| 2342 | | // get_vector |
| 2343 | | //============================================================ |
| 2344 | | |
| 2345 | | static void get_vector(const char *data, int count, float *out, int report_error) |
| 2346 | | { |
| 2347 | | if (count > 3) |
| 2348 | | { |
| 2349 | | if (sscanf(data, "%f,%f,%f,%f", &out[0], &out[1], &out[2], &out[3]) < 4 && report_error) |
| 2350 | | osd_printf_error("Illegal quad vector value = %s\n", data); |
| 2351 | | } |
| 2352 | | else if(count > 2) |
| 2353 | | { |
| 2354 | | if (sscanf(data, "%f,%f,%f", &out[0], &out[1], &out[2]) < 3 && report_error) |
| 2355 | | osd_printf_error("Illegal triple vector value = %s\n", data); |
| 2356 | | } |
| 2357 | | else if(count > 1) |
| 2358 | | { |
| 2359 | | if (sscanf(data, "%f,%f", &out[0], &out[1]) < 2 && report_error) |
| 2360 | | osd_printf_error("Illegal double vector value = %s\n", data); |
| 2361 | | } |
| 2362 | | else if(count > 0) |
| 2363 | | { |
| 2364 | | if (sscanf(data, "%f", &out[0]) < 1 && report_error) |
| 2365 | | osd_printf_error("Illegal single vector value = %s\n", data); |
| 2366 | | } |
| 2367 | | } |
| 2368 | | |
| 2369 | | |
| 2370 | | /*------------------------------------------------- |
| 2371 | | slider_alloc - allocate a new slider entry |
| 2372 | | currently duplicated from ui.c, this could |
| 2373 | | be done in a more ideal way. |
| 2374 | | -------------------------------------------------*/ |
| 2375 | | |
| 2376 | | static slider_state *slider_alloc(running_machine &machine, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg) |
| 2377 | | { |
| 2378 | | int size = sizeof(slider_state) + strlen(title); |
| 2379 | | slider_state *state = (slider_state *)auto_alloc_array_clear(machine, UINT8, size); |
| 2380 | | |
| 2381 | | state->minval = minval; |
| 2382 | | state->defval = defval; |
| 2383 | | state->maxval = maxval; |
| 2384 | | state->incval = incval; |
| 2385 | | state->update = update; |
| 2386 | | state->arg = arg; |
| 2387 | | strcpy(state->description, title); |
| 2388 | | |
| 2389 | | return state; |
| 2390 | | } |
| 2391 | | |
| 2392 | | |
| 2393 | | //============================================================ |
| 2394 | | // assorted global slider accessors |
| 2395 | | //============================================================ |
| 2396 | | |
| 2397 | | static INT32 slider_set(float *option, float scale, const char *fmt, astring *string, INT32 newval) |
| 2398 | | { |
| 2399 | | if (option != NULL && newval != SLIDER_NOCHANGE) *option = (float)newval * scale; |
| 2400 | | if (string != NULL) string->printf(fmt, *option); |
| 2401 | | return floor(*option / scale + 0.5f); |
| 2402 | | } |
| 2403 | | |
| 2404 | | static INT32 slider_shadow_mask_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2405 | | { |
| 2406 | | return slider_set(&(((hlsl_options*)arg)->shadow_mask_alpha), 0.01f, "%2.2f", string, newval); |
| 2407 | | } |
| 2408 | | |
| 2409 | | static INT32 slider_shadow_mask_x_count(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2410 | | { |
| 2411 | | hlsl_options *options = (hlsl_options*)arg; |
| 2412 | | if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_x = newval; |
| 2413 | | if (string != NULL) string->printf("%d", options->shadow_mask_count_x); |
| 2414 | | options->params_dirty = true; |
| 2415 | | return options->shadow_mask_count_x; |
| 2416 | | } |
| 2417 | | |
| 2418 | | static INT32 slider_shadow_mask_y_count(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2419 | | { |
| 2420 | | hlsl_options *options = (hlsl_options*)arg; |
| 2421 | | if (newval != SLIDER_NOCHANGE) options->shadow_mask_count_y = newval; |
| 2422 | | if (string != NULL) string->printf("%d", options->shadow_mask_count_y); |
| 2423 | | options->params_dirty = true; |
| 2424 | | return options->shadow_mask_count_y; |
| 2425 | | } |
| 2426 | | |
| 2427 | | static INT32 slider_shadow_mask_usize(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2428 | | { |
| 2429 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2430 | | return slider_set(&(((hlsl_options*)arg)->shadow_mask_u_size), 1.0f / 32.0f, "%2.5f", string, newval); |
| 2431 | | } |
| 2432 | | |
| 2433 | | static INT32 slider_shadow_mask_vsize(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2434 | | { |
| 2435 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2436 | | return slider_set(&(((hlsl_options*)arg)->shadow_mask_v_size), 1.0f / 32.0f, "%2.5f", string, newval); |
| 2437 | | } |
| 2438 | | |
| 2439 | | static INT32 slider_curvature(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2440 | | { |
| 2441 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2442 | | return slider_set(&(((hlsl_options*)arg)->curvature), 0.01f, "%2.2f", string, newval); |
| 2443 | | } |
| 2444 | | |
| 2445 | | static INT32 slider_pincushion(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2446 | | { |
| 2447 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2448 | | return slider_set(&(((hlsl_options*)arg)->pincushion), 0.01f, "%2.2f", string, newval); |
| 2449 | | } |
| 2450 | | |
| 2451 | | static INT32 slider_scanline_alpha(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2452 | | { |
| 2453 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2454 | | return slider_set(&(((hlsl_options*)arg)->scanline_alpha), 0.01f, "%2.2f", string, newval); |
| 2455 | | } |
| 2456 | | |
| 2457 | | static INT32 slider_scanline_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2458 | | { |
| 2459 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2460 | | return slider_set(&(((hlsl_options*)arg)->scanline_scale), 0.05f, "%2.2f", string, newval); |
| 2461 | | } |
| 2462 | | |
| 2463 | | static INT32 slider_scanline_height(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2464 | | { |
| 2465 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2466 | | return slider_set(&(((hlsl_options*)arg)->scanline_height), 0.05f, "%2.2f", string, newval); |
| 2467 | | } |
| 2468 | | |
| 2469 | | static INT32 slider_scanline_bright_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2470 | | { |
| 2471 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2472 | | return slider_set(&(((hlsl_options*)arg)->scanline_bright_scale), 0.05f, "%2.2f", string, newval); |
| 2473 | | } |
| 2474 | | |
| 2475 | | static INT32 slider_scanline_bright_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2476 | | { |
| 2477 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2478 | | return slider_set(&(((hlsl_options*)arg)->scanline_bright_offset), 0.05f, "%2.2f", string, newval); |
| 2479 | | } |
| 2480 | | |
| 2481 | | static INT32 slider_scanline_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2482 | | { |
| 2483 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2484 | | return slider_set(&(((hlsl_options*)arg)->scanline_offset), 0.05f, "%2.2f", string, newval); |
| 2485 | | } |
| 2486 | | |
| 2487 | | static INT32 slider_defocus_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2488 | | { |
| 2489 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2490 | | return slider_set(&(((hlsl_options*)arg)->defocus[0]), 0.5f, "%2.1f", string, newval); |
| 2491 | | } |
| 2492 | | |
| 2493 | | static INT32 slider_defocus_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2494 | | { |
| 2495 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2496 | | return slider_set(&(((hlsl_options*)arg)->defocus[1]), 0.5f, "%2.1f", string, newval); |
| 2497 | | } |
| 2498 | | |
| 2499 | | static INT32 slider_red_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2500 | | { |
| 2501 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2502 | | return slider_set(&(((hlsl_options*)arg)->converge_x[0]), 0.1f, "%3.1f", string, newval); |
| 2503 | | } |
| 2504 | | |
| 2505 | | static INT32 slider_red_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2506 | | { |
| 2507 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2508 | | return slider_set(&(((hlsl_options*)arg)->converge_y[0]), 0.1f, "%3.1f", string, newval); |
| 2509 | | } |
| 2510 | | |
| 2511 | | static INT32 slider_green_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2512 | | { |
| 2513 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2514 | | return slider_set(&(((hlsl_options*)arg)->converge_x[1]), 0.1f, "%3.1f", string, newval); |
| 2515 | | } |
| 2516 | | |
| 2517 | | static INT32 slider_green_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2518 | | { |
| 2519 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2520 | | return slider_set(&(((hlsl_options*)arg)->converge_y[1]), 0.1f, "%3.1f", string, newval); |
| 2521 | | } |
| 2522 | | |
| 2523 | | static INT32 slider_blue_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2524 | | { |
| 2525 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2526 | | return slider_set(&(((hlsl_options*)arg)->converge_x[2]), 0.1f, "%3.1f", string, newval); |
| 2527 | | } |
| 2528 | | |
| 2529 | | static INT32 slider_blue_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2530 | | { |
| 2531 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2532 | | return slider_set(&(((hlsl_options*)arg)->converge_y[2]), 0.1f, "%3.1f", string, newval); |
| 2533 | | } |
| 2534 | | |
| 2535 | | static INT32 slider_red_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2536 | | { |
| 2537 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2538 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[0]), 0.1f, "%3.1f", string, newval); |
| 2539 | | } |
| 2540 | | |
| 2541 | | static INT32 slider_red_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2542 | | { |
| 2543 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2544 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[0]), 0.1f, "%3.1f", string, newval); |
| 2545 | | } |
| 2546 | | |
| 2547 | | static INT32 slider_green_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2548 | | { |
| 2549 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2550 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[1]), 0.1f, "%3.1f", string, newval); |
| 2551 | | } |
| 2552 | | |
| 2553 | | static INT32 slider_green_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2554 | | { |
| 2555 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2556 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[1]), 0.1f, "%3.1f", string, newval); |
| 2557 | | } |
| 2558 | | |
| 2559 | | static INT32 slider_blue_radial_converge_x(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2560 | | { |
| 2561 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2562 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_x[2]), 0.1f, "%3.1f", string, newval); |
| 2563 | | } |
| 2564 | | |
| 2565 | | static INT32 slider_blue_radial_converge_y(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2566 | | { |
| 2567 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2568 | | return slider_set(&(((hlsl_options*)arg)->radial_converge_y[2]), 0.1f, "%3.1f", string, newval); |
| 2569 | | } |
| 2570 | | |
| 2571 | | static INT32 slider_red_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2572 | | { |
| 2573 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2574 | | return slider_set(&(((hlsl_options*)arg)->red_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2575 | | } |
| 2576 | | |
| 2577 | | static INT32 slider_red_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2578 | | { |
| 2579 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2580 | | return slider_set(&(((hlsl_options*)arg)->red_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2581 | | } |
| 2582 | | |
| 2583 | | static INT32 slider_red_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2584 | | { |
| 2585 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2586 | | return slider_set(&(((hlsl_options*)arg)->red_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2587 | | } |
| 2588 | | |
| 2589 | | static INT32 slider_green_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2590 | | { |
| 2591 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2592 | | return slider_set(&(((hlsl_options*)arg)->grn_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2593 | | } |
| 2594 | | |
| 2595 | | static INT32 slider_green_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2596 | | { |
| 2597 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2598 | | return slider_set(&(((hlsl_options*)arg)->grn_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2599 | | } |
| 2600 | | |
| 2601 | | static INT32 slider_green_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2602 | | { |
| 2603 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2604 | | return slider_set(&(((hlsl_options*)arg)->grn_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2605 | | } |
| 2606 | | |
| 2607 | | static INT32 slider_blue_from_r(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2608 | | { |
| 2609 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2610 | | return slider_set(&(((hlsl_options*)arg)->blu_ratio[0]), 0.005f, "%2.3f", string, newval); |
| 2611 | | } |
| 2612 | | |
| 2613 | | static INT32 slider_blue_from_g(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2614 | | { |
| 2615 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2616 | | return slider_set(&(((hlsl_options*)arg)->blu_ratio[1]), 0.005f, "%2.3f", string, newval); |
| 2617 | | } |
| 2618 | | |
| 2619 | | static INT32 slider_blue_from_b(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2620 | | { |
| 2621 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2622 | | return slider_set(&(((hlsl_options*)arg)->blu_ratio[2]), 0.005f, "%2.3f", string, newval); |
| 2623 | | } |
| 2624 | | |
| 2625 | | static INT32 slider_red_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2626 | | { |
| 2627 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2628 | | return slider_set(&(((hlsl_options*)arg)->offset[0]), 0.01f, "%2.2f", string, newval); |
| 2629 | | } |
| 2630 | | |
| 2631 | | static INT32 slider_green_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2632 | | { |
| 2633 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2634 | | return slider_set(&(((hlsl_options*)arg)->offset[1]), 0.01f, "%2.2f", string, newval); |
| 2635 | | } |
| 2636 | | |
| 2637 | | static INT32 slider_blue_offset(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2638 | | { |
| 2639 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2640 | | return slider_set(&(((hlsl_options*)arg)->offset[2]), 0.01f, "%2.2f", string, newval); |
| 2641 | | } |
| 2642 | | |
| 2643 | | static INT32 slider_red_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2644 | | { |
| 2645 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2646 | | return slider_set(&(((hlsl_options*)arg)->scale[0]), 0.01f, "%2.2f", string, newval); |
| 2647 | | } |
| 2648 | | |
| 2649 | | static INT32 slider_green_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2650 | | { |
| 2651 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2652 | | return slider_set(&(((hlsl_options*)arg)->scale[1]), 0.01f, "%2.2f", string, newval); |
| 2653 | | } |
| 2654 | | |
| 2655 | | static INT32 slider_blue_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2656 | | { |
| 2657 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2658 | | return slider_set(&(((hlsl_options*)arg)->scale[2]), 0.01f, "%2.2f", string, newval); |
| 2659 | | } |
| 2660 | | |
| 2661 | | static INT32 slider_red_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2662 | | { |
| 2663 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2664 | | return slider_set(&(((hlsl_options*)arg)->power[0]), 0.05f, "%2.2f", string, newval); |
| 2665 | | } |
| 2666 | | |
| 2667 | | static INT32 slider_green_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2668 | | { |
| 2669 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2670 | | return slider_set(&(((hlsl_options*)arg)->power[1]), 0.05f, "%2.2f", string, newval); |
| 2671 | | } |
| 2672 | | |
| 2673 | | static INT32 slider_blue_power(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2674 | | { |
| 2675 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2676 | | return slider_set(&(((hlsl_options*)arg)->power[2]), 0.05f, "%2.2f", string, newval); |
| 2677 | | } |
| 2678 | | |
| 2679 | | static INT32 slider_red_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2680 | | { |
| 2681 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2682 | | return slider_set(&(((hlsl_options*)arg)->floor[0]), 0.01f, "%2.2f", string, newval); |
| 2683 | | } |
| 2684 | | |
| 2685 | | static INT32 slider_green_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2686 | | { |
| 2687 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2688 | | return slider_set(&(((hlsl_options*)arg)->floor[1]), 0.01f, "%2.2f", string, newval); |
| 2689 | | } |
| 2690 | | |
| 2691 | | static INT32 slider_blue_floor(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2692 | | { |
| 2693 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2694 | | return slider_set(&(((hlsl_options*)arg)->floor[2]), 0.01f, "%2.2f", string, newval); |
| 2695 | | } |
| 2696 | | |
| 2697 | | static INT32 slider_red_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2698 | | { |
| 2699 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2700 | | return slider_set(&(((hlsl_options*)arg)->phosphor[0]), 0.01f, "%2.2f", string, newval); |
| 2701 | | } |
| 2702 | | |
| 2703 | | static INT32 slider_green_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2704 | | { |
| 2705 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2706 | | return slider_set(&(((hlsl_options*)arg)->phosphor[1]), 0.01f, "%2.2f", string, newval); |
| 2707 | | } |
| 2708 | | |
| 2709 | | static INT32 slider_blue_phosphor_life(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2710 | | { |
| 2711 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2712 | | return slider_set(&(((hlsl_options*)arg)->phosphor[2]), 0.01f, "%2.2f", string, newval); |
| 2713 | | } |
| 2714 | | |
| 2715 | | static INT32 slider_saturation(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2716 | | { |
| 2717 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2718 | | return slider_set(&(((hlsl_options*)arg)->saturation), 0.01f, "%2.2f", string, newval); |
| 2719 | | } |
| 2720 | | |
| 2721 | | static INT32 slider_vector_attenuation(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2722 | | { |
| 2723 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2724 | | return slider_set(&(((hlsl_options*)arg)->vector_length_scale), 0.01f, "%1.2f", string, newval); |
| 2725 | | } |
| 2726 | | |
| 2727 | | static INT32 slider_vector_length_max(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2728 | | { |
| 2729 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2730 | | return slider_set(&(((hlsl_options*)arg)->vector_length_ratio), 1.0f, "%4f", string, newval); |
| 2731 | | } |
| 2732 | | |
| 2733 | | static INT32 slider_vector_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2734 | | { |
| 2735 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2736 | | return slider_set(&(((hlsl_options*)arg)->vector_bloom_scale), 0.001f, "%1.3f", string, newval); |
| 2737 | | } |
| 2738 | | |
| 2739 | | static INT32 slider_raster_bloom_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2740 | | { |
| 2741 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2742 | | return slider_set(&(((hlsl_options*)arg)->raster_bloom_scale), 0.001f, "%1.3f", string, newval); |
| 2743 | | } |
| 2744 | | |
| 2745 | | static INT32 slider_bloom_lvl0_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2746 | | { |
| 2747 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2748 | | return slider_set(&(((hlsl_options*)arg)->bloom_level0_weight), 0.01f, "%1.2f", string, newval); |
| 2749 | | } |
| 2750 | | |
| 2751 | | static INT32 slider_bloom_lvl1_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2752 | | { |
| 2753 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2754 | | return slider_set(&(((hlsl_options*)arg)->bloom_level1_weight), 0.01f, "%1.2f", string, newval); |
| 2755 | | } |
| 2756 | | |
| 2757 | | static INT32 slider_bloom_lvl2_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2758 | | { |
| 2759 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2760 | | return slider_set(&(((hlsl_options*)arg)->bloom_level2_weight), 0.01f, "%1.2f", string, newval); |
| 2761 | | } |
| 2762 | | |
| 2763 | | static INT32 slider_bloom_lvl3_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2764 | | { |
| 2765 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2766 | | return slider_set(&(((hlsl_options*)arg)->bloom_level3_weight), 0.01f, "%1.2f", string, newval); |
| 2767 | | } |
| 2768 | | |
| 2769 | | static INT32 slider_bloom_lvl4_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2770 | | { |
| 2771 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2772 | | return slider_set(&(((hlsl_options*)arg)->bloom_level4_weight), 0.01f, "%1.2f", string, newval); |
| 2773 | | } |
| 2774 | | |
| 2775 | | static INT32 slider_bloom_lvl5_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2776 | | { |
| 2777 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2778 | | return slider_set(&(((hlsl_options*)arg)->bloom_level5_weight), 0.01f, "%1.2f", string, newval); |
| 2779 | | } |
| 2780 | | |
| 2781 | | static INT32 slider_bloom_lvl6_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2782 | | { |
| 2783 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2784 | | return slider_set(&(((hlsl_options*)arg)->bloom_level6_weight), 0.01f, "%1.2f", string, newval); |
| 2785 | | } |
| 2786 | | |
| 2787 | | static INT32 slider_bloom_lvl7_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2788 | | { |
| 2789 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2790 | | return slider_set(&(((hlsl_options*)arg)->bloom_level7_weight), 0.01f, "%1.2f", string, newval); |
| 2791 | | } |
| 2792 | | |
| 2793 | | static INT32 slider_bloom_lvl8_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2794 | | { |
| 2795 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2796 | | return slider_set(&(((hlsl_options*)arg)->bloom_level8_weight), 0.01f, "%1.2f", string, newval); |
| 2797 | | } |
| 2798 | | |
| 2799 | | static INT32 slider_bloom_lvl9_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2800 | | { |
| 2801 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2802 | | return slider_set(&(((hlsl_options*)arg)->bloom_level9_weight), 0.01f, "%1.2f", string, newval); |
| 2803 | | } |
| 2804 | | |
| 2805 | | static INT32 slider_bloom_lvl10_scale(running_machine &machine, void *arg, astring *string, INT32 newval) |
| 2806 | | { |
| 2807 | | ((hlsl_options*)arg)->params_dirty = true; |
| 2808 | | return slider_set(&(((hlsl_options*)arg)->bloom_level10_weight), 0.01f, "%1.2f", string, newval); |
| 2809 | | } |
| 2810 | | |
| 2811 | | //============================================================ |
| 2812 | | // init_slider_list |
| 2813 | | //============================================================ |
| 2814 | | |
| 2815 | | shaders::slider_desc shaders::s_sliders[] = |
| 2816 | | { |
| 2817 | | { "Shadow Mask Darkness", 0, 0, 100, 1, slider_shadow_mask_alpha }, |
| 2818 | | { "Shadow Mask X Count", 1, 320, 1024, 1, slider_shadow_mask_x_count }, |
| 2819 | | { "Shadow Mask Y Count", 1, 240, 1024, 1, slider_shadow_mask_y_count }, |
| 2820 | | { "Shadow Mask Pixel Count X", 1, 6, 64, 1, slider_shadow_mask_usize }, |
| 2821 | | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2822 | | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2823 | | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2824 | | { "Shadow Mask Pixel Count Y", 1, 7, 64, 1, slider_shadow_mask_vsize }, |
| 2825 | | { "Screen Curvature", 0, 3, 100, 1, slider_curvature }, |
| 2826 | | { "Image Pincushion", 0, 3, 100, 1, slider_pincushion }, |
| 2827 | | { "Scanline Darkness", 0, 100, 100, 1, slider_scanline_alpha }, |
| 2828 | | { "Scanline Screen Height", 1, 20, 80, 1, slider_scanline_scale }, |
| 2829 | | { "Scanline Indiv. Height", 1, 20, 80, 1, slider_scanline_height }, |
| 2830 | | { "Scanline Brightness", 0, 20, 40, 1, slider_scanline_bright_scale }, |
| 2831 | | { "Scanline Brightness Overdrive", 0, 0, 20, 1, slider_scanline_bright_offset }, |
| 2832 | | { "Scanline Jitter", 0, 0, 40, 1, slider_scanline_offset }, |
| 2833 | | { "Defocus X", 0, 0, 64, 1, slider_defocus_x }, |
| 2834 | | { "Defocus Y", 0, 0, 64, 1, slider_defocus_y }, |
| 2835 | | { "Red Position Offset X", -1500, 3, 1500, 1, slider_red_converge_x }, |
| 2836 | | { "Red Position Offset Y", -1500, 0, 1500, 1, slider_red_converge_y }, |
| 2837 | | { "Green Position Offset X", -1500, 0, 1500, 1, slider_green_converge_x }, |
| 2838 | | { "Green Position Offset Y", -1500, 3, 1500, 1, slider_green_converge_y }, |
| 2839 | | { "Blue Position Offset X", -1500, 3, 1500, 1, slider_blue_converge_x }, |
| 2840 | | { "Blue Position Offset Y", -1500, 3, 1500, 1, slider_blue_converge_y }, |
| 2841 | | { "Red Convergence X", -1500, 0, 1500, 1, slider_red_radial_converge_x }, |
| 2842 | | { "Red Convergence Y", -1500, 0, 1500, 1, slider_red_radial_converge_y }, |
| 2843 | | { "Green Convergence X", -1500, 0, 1500, 1, slider_green_radial_converge_x }, |
| 2844 | | { "Green Convergence Y", -1500, 0, 1500, 1, slider_green_radial_converge_y }, |
| 2845 | | { "Blue Convergence X", -1500, 0, 1500, 1, slider_blue_radial_converge_x }, |
| 2846 | | { "Blue Convergence Y", -1500, 0, 1500, 1, slider_blue_radial_converge_y }, |
| 2847 | | { "Red Output from Red Input", -400, 0, 400, 5, slider_red_from_r }, |
| 2848 | | { "Red Output from Green Input", -400, 0, 400, 5, slider_red_from_g }, |
| 2849 | | { "Red Output from Blue Input", -400, 0, 400, 5, slider_red_from_b }, |
| 2850 | | { "Green Output from Red Input", -400, 0, 400, 5, slider_green_from_r }, |
| 2851 | | { "Green Output from Green Input", -400, 0, 400, 5, slider_green_from_g }, |
| 2852 | | { "Green Output from Blue Input", -400, 0, 400, 5, slider_green_from_b }, |
| 2853 | | { "Blue Output from Red Input", -400, 0, 400, 5, slider_blue_from_r }, |
| 2854 | | { "Blue Output from Green Input", -400, 0, 400, 5, slider_blue_from_g }, |
| 2855 | | { "Blue Output from Blue Input", -400, 0, 400, 5, slider_blue_from_b }, |
| 2856 | | { "Saturation", 0, 140, 400, 1, slider_saturation }, |
| 2857 | | { "Red DC Offset", -100, 0, 100, 1, slider_red_offset }, |
| 2858 | | { "Green DC Offset", -100, 0, 100, 1, slider_green_offset }, |
| 2859 | | { "Blue DC Offset", -100, 0, 100, 1, slider_blue_offset }, |
| 2860 | | { "Red Scale", -200, 95, 200, 1, slider_red_scale }, |
| 2861 | | { "Green Scale", -200, 95, 200, 1, slider_green_scale }, |
| 2862 | | { "Blue Scale", -200, 95, 200, 1, slider_blue_scale }, |
| 2863 | | { "Red Gamma", -80, 16, 80, 1, slider_red_power }, |
| 2864 | | { "Green Gamma", -80, 16, 80, 1, slider_green_power }, |
| 2865 | | { "Blue Gamma", -80, 16, 80, 1, slider_blue_power }, |
| 2866 | | { "Red Floor", 0, 5, 100, 1, slider_red_floor }, |
| 2867 | | { "Green Floor", 0, 5, 100, 1, slider_green_floor }, |
| 2868 | | { "Blue Floor", 0, 5, 100, 1, slider_blue_floor }, |
| 2869 | | { "Red Phosphor Life", 0, 40, 100, 1, slider_red_phosphor_life }, |
| 2870 | | { "Green Phosphor Life", 0, 40, 100, 1, slider_green_phosphor_life }, |
| 2871 | | { "Blue Phosphor Life", 0, 40, 100, 1, slider_blue_phosphor_life }, |
| 2872 | | { "Vector Length Attenuation", 0, 80, 100, 1, slider_vector_attenuation }, |
| 2873 | | { "Vector Attenuation Length Limit", 1, 500, 1000, 1, slider_vector_length_max }, |
| 2874 | | { "Vector Bloom Scale", 0, 300, 1000, 5, slider_vector_bloom_scale }, |
| 2875 | | { "Raster Bloom Scale", 0, 225, 1000, 5, slider_raster_bloom_scale }, |
| 2876 | | { "Bloom Level 0 Scale", 0, 100, 100, 1, slider_bloom_lvl0_scale }, |
| 2877 | | { "Bloom Level 1 Scale", 0, 21, 100, 1, slider_bloom_lvl1_scale }, |
| 2878 | | { "Bloom Level 2 Scale", 0, 19, 100, 1, slider_bloom_lvl2_scale }, |
| 2879 | | { "Bloom Level 3 Scale", 0, 17, 100, 1, slider_bloom_lvl3_scale }, |
| 2880 | | { "Bloom Level 4 Scale", 0, 15, 100, 1, slider_bloom_lvl4_scale }, |
| 2881 | | { "Bloom Level 5 Scale", 0, 14, 100, 1, slider_bloom_lvl5_scale }, |
| 2882 | | { "Bloom Level 6 Scale", 0, 13, 100, 1, slider_bloom_lvl6_scale }, |
| 2883 | | { "Bloom Level 7 Scale", 0, 12, 100, 1, slider_bloom_lvl7_scale }, |
| 2884 | | { "Bloom Level 8 Scale", 0, 11, 100, 1, slider_bloom_lvl8_scale }, |
| 2885 | | { "Bloom Level 9 Scale", 0, 10, 100, 1, slider_bloom_lvl9_scale }, |
| 2886 | | { "Bloom Level 10 Scale", 0, 9, 100, 1, slider_bloom_lvl10_scale }, |
| 2887 | | { NULL, 0, 0, 0, 0, NULL }, |
| 2888 | | }; |
| 2889 | | |
| 2890 | | slider_state *shaders::init_slider_list() |
| 2891 | | { |
| 2892 | | if (!master_enable || !d3dintf->post_fx_available) |
| 2893 | | { |
| 2894 | | g_slider_list = NULL; |
| 2895 | | return NULL; |
| 2896 | | } |
| 2897 | | |
| 2898 | | slider_state *listhead = NULL; |
| 2899 | | slider_state **tailptr = &listhead; |
| 2900 | | |
| 2901 | | for (int index = 0; s_sliders[index].name != NULL; index++) |
| 2902 | | { |
| 2903 | | slider_desc *slider = &s_sliders[index]; |
| 2904 | | *tailptr = slider_alloc(*machine, slider->name, slider->minval, slider->defval, slider->maxval, slider->step, slider->adjustor, (void*)options); |
| 2905 | | tailptr = &(*tailptr)->next; |
| 2906 | | } |
| 2907 | | |
| 2908 | | return listhead; |
| 2909 | | } |
| 2910 | | |
| 2911 | | //============================================================ |
| 2912 | | // uniform functions |
| 2913 | | //============================================================ |
| 2914 | | |
| 2915 | | uniform::uniform(effect *shader, const char *name, uniform_type type, int id) |
| 2916 | | { |
| 2917 | | m_shader = shader; |
| 2918 | | m_type = type; |
| 2919 | | m_next = NULL; |
| 2920 | | m_handle = m_shader->get_parameter(NULL, name); |
| 2921 | | m_ival = 0; |
| 2922 | | memset(m_vec, 0, sizeof(float) * 4); |
| 2923 | | m_mval = NULL; |
| 2924 | | m_texture = NULL; |
| 2925 | | m_id = id; |
| 2926 | | |
| 2927 | | switch (type) |
| 2928 | | { |
| 2929 | | case UT_INT: |
| 2930 | | case UT_FLOAT: |
| 2931 | | case UT_MATRIX: |
| 2932 | | case UT_SAMPLER: |
| 2933 | | m_count = 1; |
| 2934 | | break; |
| 2935 | | case UT_VEC2: |
| 2936 | | m_count = 2; |
| 2937 | | break; |
| 2938 | | case UT_VEC3: |
| 2939 | | m_count = 3; |
| 2940 | | break; |
| 2941 | | case UT_VEC4: |
| 2942 | | m_count = 4; |
| 2943 | | break; |
| 2944 | | default: |
| 2945 | | m_count = 1; |
| 2946 | | break; |
| 2947 | | } |
| 2948 | | } |
| 2949 | | |
| 2950 | | void uniform::set_next(uniform *next) |
| 2951 | | { |
| 2952 | | m_next = next; |
| 2953 | | } |
| 2954 | | |
| 2955 | | void uniform::update() |
| 2956 | | { |
| 2957 | | if (m_id >= CU_COUNT) |
| 2958 | | { |
| 2959 | | return; |
| 2960 | | } |
| 2961 | | |
| 2962 | | shaders *shadersys = m_shader->m_shaders; |
| 2963 | | hlsl_options *options = shadersys->options; |
| 2964 | | renderer *d3d = shadersys->d3d; |
| 2965 | | |
| 2966 | | |
| 2967 | | switch(m_id) |
| 2968 | | { |
| 2969 | | case CU_SCREEN_DIMS: |
| 2970 | | { |
| 2971 | | vec2f screendims = d3d->get_dims(); |
| 2972 | | m_shader->set_vector("ScreenDims", 2, &screendims.c.x); |
| 2973 | | break; |
| 2974 | | } |
| 2975 | | case CU_SOURCE_DIMS: |
| 2976 | | { |
| 2977 | | vec2f& sourcedims = shadersys->curr_texture->get_rawdims(); |
| 2978 | | m_shader->set_vector("SourceDims", 2, &sourcedims.c.x); |
| 2979 | | break; |
| 2980 | | } |
| 2981 | | case CU_SOURCE_RECT: |
| 2982 | | { |
| 2983 | | vec2f delta = shadersys->curr_texture->get_uvstop() - shadersys->curr_texture->get_uvstart(); |
| 2984 | | m_shader->set_vector("SourceRect", 2, &delta.c.x); |
| 2985 | | break; |
| 2986 | | } |
| 2987 | | |
| 2988 | | case CU_NTSC_CCFREQ: |
| 2989 | | m_shader->set_float("CCValue", options->yiq_cc); |
| 2990 | | break; |
| 2991 | | case CU_NTSC_A: |
| 2992 | | m_shader->set_float("AValue", options->yiq_a); |
| 2993 | | break; |
| 2994 | | case CU_NTSC_B: |
| 2995 | | m_shader->set_float("BValue", options->yiq_b); |
| 2996 | | break; |
| 2997 | | case CU_NTSC_O: |
| 2998 | | m_shader->set_float("OValue", options->yiq_o); |
| 2999 | | break; |
| 3000 | | case CU_NTSC_P: |
| 3001 | | m_shader->set_float("PValue", options->yiq_p); |
| 3002 | | break; |
| 3003 | | case CU_NTSC_NOTCH: |
| 3004 | | m_shader->set_float("NotchHalfWidth", options->yiq_n); |
| 3005 | | break; |
| 3006 | | case CU_NTSC_YFREQ: |
| 3007 | | m_shader->set_float("YFreqResponse", options->yiq_y); |
| 3008 | | break; |
| 3009 | | case CU_NTSC_IFREQ: |
| 3010 | | m_shader->set_float("IFreqResponse", options->yiq_i); |
| 3011 | | break; |
| 3012 | | case CU_NTSC_QFREQ: |
| 3013 | | m_shader->set_float("QFreqResponse", options->yiq_q); |
| 3014 | | break; |
| 3015 | | case CU_NTSC_HTIME: |
| 3016 | | m_shader->set_float("ScanTime", options->yiq_scan_time); |
| 3017 | | break; |
| 3018 | | case CU_NTSC_ENABLE: |
| 3019 | | m_shader->set_float("YIQEnable", options->yiq_enable ? 1.0f : 0.0f); |
| 3020 | | break; |
| 3021 | | |
| 3022 | | case CU_COLOR_RED_RATIOS: |
| 3023 | | m_shader->set_vector("RedRatios", 3, options->red_ratio); |
| 3024 | | break; |
| 3025 | | case CU_COLOR_GRN_RATIOS: |
| 3026 | | m_shader->set_vector("GrnRatios", 3, options->grn_ratio); |
| 3027 | | break; |
| 3028 | | case CU_COLOR_BLU_RATIOS: |
| 3029 | | m_shader->set_vector("BluRatios", 3, options->blu_ratio); |
| 3030 | | break; |
| 3031 | | case CU_COLOR_OFFSET: |
| 3032 | | m_shader->set_vector("Offset", 3, options->offset); |
| 3033 | | break; |
| 3034 | | case CU_COLOR_SCALE: |
| 3035 | | m_shader->set_vector("Scale", 3, options->scale); |
| 3036 | | break; |
| 3037 | | case CU_COLOR_SATURATION: |
| 3038 | | m_shader->set_float("Saturation", options->saturation); |
| 3039 | | break; |
| 3040 | | |
| 3041 | | case CU_CONVERGE_LINEAR_X: |
| 3042 | | m_shader->set_vector("ConvergeX", 3, options->converge_x); |
| 3043 | | break; |
| 3044 | | case CU_CONVERGE_LINEAR_Y: |
| 3045 | | m_shader->set_vector("ConvergeY", 3, options->converge_y); |
| 3046 | | break; |
| 3047 | | case CU_CONVERGE_RADIAL_X: |
| 3048 | | m_shader->set_vector("RadialConvergeX", 3, options->radial_converge_x); |
| 3049 | | break; |
| 3050 | | case CU_CONVERGE_RADIAL_Y: |
| 3051 | | m_shader->set_vector("RadialConvergeY", 3, options->radial_converge_y); |
| 3052 | | break; |
| 3053 | | |
| 3054 | | case CU_FOCUS_SIZE: |
| 3055 | | m_shader->set_vector("Defocus", 2, &options->defocus[0]); |
| 3056 | | break; |
| 3057 | | |
| 3058 | | case CU_PHOSPHOR_LIFE: |
| 3059 | | m_shader->set_vector("Phosphor", 3, options->phosphor); |
| 3060 | | break; |
| 3061 | | case CU_PHOSPHOR_IGNORE: |
| 3062 | | m_shader->set_float("Passthrough", shadersys->phosphor_passthrough ? 1.0f : 0.0f); |
| 3063 | | break; |
| 3064 | | |
| 3065 | | case CU_POST_PINCUSHION: |
| 3066 | | m_shader->set_float("PincushionAmount", options->pincushion); |
| 3067 | | break; |
| 3068 | | case CU_POST_CURVATURE: |
| 3069 | | m_shader->set_float("CurvatureAmount", options->curvature); |
| 3070 | | break; |
| 3071 | | case CU_POST_SHADOW_ALPHA: |
| 3072 | | m_shader->set_float("ShadowAlpha", shadersys->shadow_texture == NULL ? 0.0f : options->shadow_mask_alpha); |
| 3073 | | break; |
| 3074 | | case CU_POST_SHADOW_COUNT: |
| 3075 | | { |
| 3076 | | float shadowcount[2] = { options->shadow_mask_count_x, options->shadow_mask_count_y }; |
| 3077 | | m_shader->set_vector("ShadowCount", 2, shadowcount); |
| 3078 | | break; |
| 3079 | | } |
| 3080 | | case CU_POST_SHADOW_UV: |
| 3081 | | { |
| 3082 | | float shadowuv[2] = { options->shadow_mask_u_size, options->shadow_mask_v_size }; |
| 3083 | | m_shader->set_vector("ShadowUV", 2, shadowuv); |
| 3084 | | break; |
| 3085 | | } |
| 3086 | | case CU_POST_SHADOW_DIMS: |
| 3087 | | { |
| 3088 | | vec2f shadow_dims; |
| 3089 | | |
| 3090 | | if (shadersys->shadow_texture) |
| 3091 | | { |
| 3092 | | shadow_dims = shadersys->shadow_texture->get_rawdims(); |
| 3093 | | } |
| 3094 | | else |
| 3095 | | { |
| 3096 | | shadow_dims.c.x = 1.0f; |
| 3097 | | shadow_dims.c.y = 1.0f; |
| 3098 | | } |
| 3099 | | |
| 3100 | | m_shader->set_vector("ShadowDims", 2, &shadow_dims.c.x); |
| 3101 | | break; |
| 3102 | | } |
| 3103 | | case CU_POST_SCANLINE_ALPHA: |
| 3104 | | m_shader->set_float("ScanlineAlpha", options->scanline_alpha); |
| 3105 | | break; |
| 3106 | | case CU_POST_SCANLINE_SCALE: |
| 3107 | | m_shader->set_float("ScanlineScale", options->scanline_scale); |
| 3108 | | break; |
| 3109 | | case CU_POST_SCANLINE_HEIGHT: |
| 3110 | | m_shader->set_float("ScanlineHeight", options->scanline_height); |
| 3111 | | break; |
| 3112 | | case CU_POST_SCANLINE_BRIGHT_SCALE: |
| 3113 | | m_shader->set_float("ScanlineBrightScale", options->scanline_bright_scale); |
| 3114 | | break; |
| 3115 | | case CU_POST_SCANLINE_BRIGHT_OFFSET: |
| 3116 | | m_shader->set_float("ScanlineBrightOffset", options->scanline_bright_offset); |
| 3117 | | break; |
| 3118 | | case CU_POST_POWER: |
| 3119 | | m_shader->set_vector("Power", 3, options->power); |
| 3120 | | break; |
| 3121 | | case CU_POST_FLOOR: |
| 3122 | | m_shader->set_vector("Floor", 3, options->floor); |
| 3123 | | break; |
| 3124 | | |
| 3125 | | case CU_BLOOM_RESCALE: |
| 3126 | | m_shader->set_float("BloomRescale", options->raster_bloom_scale); |
| 3127 | | break; |
| 3128 | | case CU_BLOOM_LVL0123_WEIGHTS: |
| 3129 | | { |
| 3130 | | float weight0123[4] = { options->bloom_level0_weight, options->bloom_level1_weight, options->bloom_level2_weight, options->bloom_level3_weight }; |
| 3131 | | m_shader->set_vector("Level0123Weight", 4, weight0123); |
| 3132 | | break; |
| 3133 | | } |
| 3134 | | case CU_BLOOM_LVL4567_WEIGHTS: |
| 3135 | | { |
| 3136 | | float weight4567[4] = { options->bloom_level4_weight, options->bloom_level5_weight, options->bloom_level6_weight, options->bloom_level7_weight }; |
| 3137 | | m_shader->set_vector("Level4567Weight", 4, weight4567); |
| 3138 | | break; |
| 3139 | | } |
| 3140 | | case CU_BLOOM_LVL89A_WEIGHTS: |
| 3141 | | { |
| 3142 | | float weight89A[3] = { options->bloom_level8_weight, options->bloom_level9_weight, options->bloom_level10_weight }; |
| 3143 | | m_shader->set_vector("Level89AWeight", 3, weight89A); |
| 3144 | | break; |
| 3145 | | } |
| 3146 | | } |
| 3147 | | } |
| 3148 | | |
| 3149 | | void uniform::set(float x, float y, float z, float w) |
| 3150 | | { |
| 3151 | | m_vec[0] = x; |
| 3152 | | m_vec[1] = y; |
| 3153 | | m_vec[2] = z; |
| 3154 | | m_vec[3] = w; |
| 3155 | | } |
| 3156 | | |
| 3157 | | void uniform::set(float x, float y, float z) |
| 3158 | | { |
| 3159 | | m_vec[0] = x; |
| 3160 | | m_vec[1] = y; |
| 3161 | | m_vec[2] = z; |
| 3162 | | } |
| 3163 | | |
| 3164 | | void uniform::set(float x, float y) |
| 3165 | | { |
| 3166 | | m_vec[0] = x; |
| 3167 | | m_vec[1] = y; |
| 3168 | | } |
| 3169 | | |
| 3170 | | void uniform::set(float x) |
| 3171 | | { |
| 3172 | | m_vec[0] = x; |
| 3173 | | } |
| 3174 | | |
| 3175 | | void uniform::set(int x) |
| 3176 | | { |
| 3177 | | m_ival = x; |
| 3178 | | } |
| 3179 | | |
| 3180 | | void uniform::set(matrix *mat) |
| 3181 | | { |
| 3182 | | m_mval = mat; |
| 3183 | | } |
| 3184 | | |
| 3185 | | void uniform::set(texture *tex) |
| 3186 | | { |
| 3187 | | m_texture = tex; |
| 3188 | | } |
| 3189 | | |
| 3190 | | void uniform::upload() |
| 3191 | | { |
| 3192 | | switch(m_type) |
| 3193 | | { |
| 3194 | | case UT_INT: |
| 3195 | | m_shader->set_int(m_handle, m_ival); |
| 3196 | | break; |
| 3197 | | case UT_FLOAT: |
| 3198 | | m_shader->set_float(m_handle, m_vec[0]); |
| 3199 | | break; |
| 3200 | | case UT_VEC2: |
| 3201 | | case UT_VEC3: |
| 3202 | | case UT_VEC4: |
| 3203 | | m_shader->set_vector(m_handle, m_count, m_vec); |
| 3204 | | break; |
| 3205 | | case UT_MATRIX: |
| 3206 | | m_shader->set_matrix(m_handle, m_mval); |
| 3207 | | break; |
| 3208 | | case UT_SAMPLER: |
| 3209 | | m_shader->set_texture(m_handle, m_texture); |
| 3210 | | break; |
| 3211 | | } |
| 3212 | | } |
| 3213 | | |
| 3214 | | //============================================================ |
| 3215 | | // effect functions |
| 3216 | | //============================================================ |
| 3217 | | |
| 3218 | | effect::effect(shaders *shadersys, device *dev, const char *name, const char *path) |
| 3219 | | { |
| 3220 | | IDirect3DDevice9 *device = (IDirect3DDevice9 *)dev; |
| 3221 | | LPD3DXBUFFER buffer_errors = NULL; |
| 3222 | | |
| 3223 | | m_shaders = shadersys; |
| 3224 | | m_uniform_head = NULL; |
| 3225 | | m_uniform_tail = NULL; |
| 3226 | | m_effect = NULL; |
| 3227 | | m_valid = false; |
| 3228 | | |
| 3229 | | char name_cstr[1024]; |
| 3230 | | sprintf(name_cstr, "%s\\%s", path, name); |
| 3231 | | TCHAR *effect_name = tstring_from_utf8(name_cstr); |
| 3232 | | |
| 3233 | | HRESULT hr = (*g_load_effect)(device, effect_name, NULL, NULL, 0, NULL, &m_effect, &buffer_errors); |
| 3234 | | if(FAILED(hr)) |
| 3235 | | { |
| 3236 | | if(buffer_errors != NULL) |
| 3237 | | { |
| 3238 | | LPVOID compile_errors = buffer_errors->GetBufferPointer(); |
| 3239 | | printf("Unable to compile shader: %s\n", (const char*)compile_errors); fflush(stdout); |
| 3240 | | } |
| 3241 | | else |
| 3242 | | { |
| 3243 | | printf("Shader %s is missing, corrupt or cannot be compiled.\n", (const char*)name); fflush(stdout); |
| 3244 | | } |
| 3245 | | } |
| 3246 | | else |
| 3247 | | { |
| 3248 | | m_valid = true; |
| 3249 | | } |
| 3250 | | |
| 3251 | | osd_free(effect_name); |
| 3252 | | } |
| 3253 | | |
| 3254 | | effect::~effect() |
| 3255 | | { |
| 3256 | | m_effect->Release(); |
| 3257 | | m_effect = NULL; |
| 3258 | | uniform *curr = m_uniform_head; |
| 3259 | | while (curr != NULL) |
| 3260 | | { |
| 3261 | | uniform *next = curr->get_next(); |
| 3262 | | delete curr; |
| 3263 | | curr = next; |
| 3264 | | } |
| 3265 | | m_uniform_head = NULL; |
| 3266 | | m_uniform_tail = NULL; |
| 3267 | | } |
| 3268 | | |
| 3269 | | void effect::add_uniform(const char *name, uniform::uniform_type type, int id) |
| 3270 | | { |
| 3271 | | uniform *newuniform = new uniform(this, name, type, id); |
| 3272 | | if (newuniform == NULL) |
| 3273 | | { |
| 3274 | | return; |
| 3275 | | } |
| 3276 | | |
| 3277 | | if (m_uniform_head == NULL) |
| 3278 | | { |
| 3279 | | m_uniform_head = newuniform; |
| 3280 | | } |
| 3281 | | if (m_uniform_tail != NULL) |
| 3282 | | { |
| 3283 | | m_uniform_tail->set_next(newuniform); |
| 3284 | | } |
| 3285 | | m_uniform_tail = newuniform; |
| 3286 | | } |
| 3287 | | |
| 3288 | | void effect::update_uniforms() |
| 3289 | | { |
| 3290 | | uniform *curr = m_uniform_head; |
| 3291 | | while(curr != NULL) |
| 3292 | | { |
| 3293 | | curr->update(); |
| 3294 | | curr = curr->get_next(); |
| 3295 | | } |
| 3296 | | } |
| 3297 | | |
| 3298 | | void effect::begin(UINT *passes, DWORD flags) |
| 3299 | | { |
| 3300 | | m_effect->Begin(passes, flags); |
| 3301 | | } |
| 3302 | | |
| 3303 | | void effect::end() |
| 3304 | | { |
| 3305 | | m_effect->End(); |
| 3306 | | } |
| 3307 | | |
| 3308 | | void effect::begin_pass(UINT pass) |
| 3309 | | { |
| 3310 | | m_effect->BeginPass(pass); |
| 3311 | | } |
| 3312 | | |
| 3313 | | void effect::end_pass() |
| 3314 | | { |
| 3315 | | m_effect->EndPass(); |
| 3316 | | } |
| 3317 | | |
| 3318 | | void effect::set_technique(const char *name) |
| 3319 | | { |
| 3320 | | m_effect->SetTechnique(name); |
| 3321 | | } |
| 3322 | | |
| 3323 | | void effect::set_vector(D3DXHANDLE param, int count, float *vector) |
| 3324 | | { |
| 3325 | | static D3DXVECTOR4 out_vector; |
| 3326 | | if (count > 0) |
| 3327 | | out_vector.x = vector[0]; |
| 3328 | | if (count > 1) |
| 3329 | | out_vector.y = vector[1]; |
| 3330 | | if (count > 2) |
| 3331 | | out_vector.z = vector[2]; |
| 3332 | | if (count > 3) |
| 3333 | | out_vector.w = vector[3]; |
| 3334 | | m_effect->SetVector(param, &out_vector); |
| 3335 | | } |
| 3336 | | |
| 3337 | | void effect::set_float(D3DXHANDLE param, float value) |
| 3338 | | { |
| 3339 | | m_effect->SetFloat(param, value); |
| 3340 | | } |
| 3341 | | |
| 3342 | | void effect::set_int(D3DXHANDLE param, int value) |
| 3343 | | { |
| 3344 | | m_effect->SetInt(param, value); |
| 3345 | | } |
| 3346 | | |
| 3347 | | void effect::set_matrix(D3DXHANDLE param, matrix *matrix) |
| 3348 | | { |
| 3349 | | m_effect->SetMatrix(param, (D3DXMATRIX*)matrix); |
| 3350 | | } |
| 3351 | | |
| 3352 | | void effect::set_texture(D3DXHANDLE param, texture *tex) |
| 3353 | | { |
| 3354 | | m_effect->SetTexture(param, (IDirect3DTexture9*)tex); |
| 3355 | | } |
| 3356 | | |
| 3357 | | D3DXHANDLE effect::get_parameter(D3DXHANDLE param, const char *name) |
| 3358 | | { |
| 3359 | | return m_effect->GetParameterByName(param, name); |
| 3360 | | } |
| 3361 | | |
| 3362 | | ULONG effect::release() |
| 3363 | | { |
| 3364 | | return m_effect->Release(); |
| 3365 | | } |
| 3366 | | |
| 3367 | | }; |
| 3368 | | |
| 3369 | | //============================================================ |
| 3370 | | // get_slider_list |
| 3371 | | //============================================================ |
| 3372 | | |
| 3373 | | void *windows_osd_interface::get_slider_list() |
| 3374 | | { |
| 3375 | | return (void*)g_slider_list; |
| 3376 | | } |
| 3377 | | |
| 3378 | | |
| 3379 | | |
| 3380 | | // NOTE: The function below is taken directly from src/emu/video.c and should likely be moved into a global helper function. |
| 3381 | | //------------------------------------------------- |
| 3382 | | // open_next - open the next non-existing file of |
| 3383 | | // type filetype according to our numbering |
| 3384 | | // scheme |
| 3385 | | //------------------------------------------------- |
| 3386 | | |
| 3387 | | static file_error open_next(d3d::renderer *d3d, emu_file &file, const char *templ, const char *extension, int idx) |
| 3388 | | { |
| 3389 | | UINT32 origflags = file.openflags(); |
| 3390 | | |
| 3391 | | // handle defaults |
| 3392 | | const char *snapname = templ ? templ : d3d->window().machine().options().snap_name(); |
| 3393 | | |
| 3394 | | if (snapname == NULL || snapname[0] == 0) |
| 3395 | | snapname = "%g/%i"; |
| 3396 | | astring snapstr(snapname); |
| 3397 | | |
| 3398 | | // strip any extension in the provided name |
| 3399 | | int index = snapstr.rchr(0, '.'); |
| 3400 | | if (index != -1) |
| 3401 | | snapstr.substr(0, index); |
| 3402 | | |
| 3403 | | // handle %d in the template (for image devices) |
| 3404 | | astring snapdev("%d_"); |
| 3405 | | int pos = snapstr.find(0, snapdev); |
| 3406 | | |
| 3407 | | if (pos != -1) |
| 3408 | | { |
| 3409 | | // if more %d are found, revert to default and ignore them all |
| 3410 | | if (snapstr.find(pos + 3, snapdev) != -1) |
| 3411 | | snapstr.cpy("%g/%i"); |
| 3412 | | // else if there is a single %d, try to create the correct snapname |
| 3413 | | else |
| 3414 | | { |
| 3415 | | int name_found = 0; |
| 3416 | | |
| 3417 | | // find length of the device name |
| 3418 | | int end1 = snapstr.find(pos + 3, "/"); |
| 3419 | | int end2 = snapstr.find(pos + 3, "%"); |
| 3420 | | int end = -1; |
| 3421 | | |
| 3422 | | if ((end1 != -1) && (end2 != -1)) |
| 3423 | | end = MIN(end1, end2); |
| 3424 | | else if (end1 != -1) |
| 3425 | | end = end1; |
| 3426 | | else if (end2 != -1) |
| 3427 | | end = end2; |
| 3428 | | else |
| 3429 | | end = snapstr.len(); |
| 3430 | | |
| 3431 | | if (end - pos < 3) |
| 3432 | | fatalerror("Something very wrong is going on!!!\n"); |
| 3433 | | |
| 3434 | | // copy the device name to an astring |
| 3435 | | astring snapdevname; |
| 3436 | | snapdevname.cpysubstr(snapstr, pos + 3, end - pos - 3); |
| 3437 | | |
| 3438 | | // verify that there is such a device for this system |
| 3439 | | image_interface_iterator iter(d3d->window().machine().root_device()); |
| 3440 | | for (device_image_interface *image = iter.first(); image != NULL; iter.next()) |
| 3441 | | { |
| 3442 | | // get the device name |
| 3443 | | astring tempdevname(image->brief_instance_name()); |
| 3444 | | |
| 3445 | | if (snapdevname.cmp(tempdevname) == 0) |
| 3446 | | { |
| 3447 | | // verify that such a device has an image mounted |
| 3448 | | if (image->basename() != NULL) |
| 3449 | | { |
| 3450 | | astring filename(image->basename()); |
| 3451 | | |
| 3452 | | // strip extension |
| 3453 | | filename.substr(0, filename.rchr(0, '.')); |
| 3454 | | |
| 3455 | | // setup snapname and remove the %d_ |
| 3456 | | snapstr.replace(0, snapdevname, filename); |
| 3457 | | snapstr.del(pos, 3); |
| 3458 | | |
| 3459 | | name_found = 1; |
| 3460 | | } |
| 3461 | | } |
| 3462 | | } |
| 3463 | | |
| 3464 | | // or fallback to default |
| 3465 | | if (name_found == 0) |
| 3466 | | snapstr.cpy("%g/%i"); |
| 3467 | | } |
| 3468 | | } |
| 3469 | | |
| 3470 | | // add our own index |
| 3471 | | // add our own extension |
| 3472 | | snapstr.cat(".").cat(extension); |
| 3473 | | |
| 3474 | | // substitute path and gamename up front |
| 3475 | | snapstr.replace(0, "/", PATH_SEPARATOR); |
| 3476 | | snapstr.replace(0, "%g", d3d->window().machine().basename()); |
| 3477 | | |
| 3478 | | // determine if the template has an index; if not, we always use the same name |
| 3479 | | astring fname; |
| 3480 | | if (snapstr.find(0, "%i") == -1) |
| 3481 | | fname.cpy(snapstr); |
| 3482 | | |
| 3483 | | // otherwise, we scan for the next available filename |
| 3484 | | else |
| 3485 | | { |
| 3486 | | // try until we succeed |
| 3487 | | astring seqtext; |
| 3488 | | file.set_openflags(OPEN_FLAG_READ); |
| 3489 | | for (int seq = 0; ; seq++) |
| 3490 | | { |
| 3491 | | // build up the filename |
| 3492 | | fname.cpy(snapstr).replace(0, "%i", seqtext.format("%04d_%d", seq, idx).cstr()); |
| 3493 | | |
| 3494 | | // try to open the file; stop when we fail |
| 3495 | | file_error filerr = file.open(fname); |
| 3496 | | if (filerr != FILERR_NONE) |
| 3497 | | break; |
| 3498 | | } |
| 3499 | | } |
| 3500 | | |
| 3501 | | // create the final file |
| 3502 | | file.set_openflags(origflags); |
| 3503 | | return file.open(fname); |
| 3504 | | } |
trunk/src/osd/windows/drawd3d.c
| r244651 | r244652 | |
| 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 | | |
| 183 | | //============================================================ |
| 184 | | // drawd3d_window_init |
| 185 | | //============================================================ |
| 186 | | |
| 187 | | int d3d::renderer::create() |
| 188 | | { |
| 189 | | if (!initialize()) |
| 190 | | { |
| 191 | | destroy(); |
| 192 | | osd_printf_error("Unable to initialize Direct3D.\n"); |
| 193 | | return 1; |
| 194 | | } |
| 195 | | |
| 196 | | return 0; |
| 197 | | } |
| 198 | | |
| 199 | | //============================================================ |
| 200 | | // drawd3d_exit |
| 201 | | //============================================================ |
| 202 | | |
| 203 | | static void drawd3d_exit(void) |
| 204 | | { |
| 205 | | if (d3dintf != NULL) |
| 206 | | (*d3dintf->d3d.release)(d3dintf); |
| 207 | | } |
| 208 | | |
| 209 | | void d3d::renderer::toggle_fsfx() |
| 210 | | { |
| 211 | | set_restarting(true); |
| 212 | | } |
| 213 | | |
| 214 | | void d3d::renderer::record() |
| 215 | | { |
| 216 | | get_shaders()->window_record(); |
| 217 | | } |
| 218 | | |
| 219 | | void d3d::renderer::save() |
| 220 | | { |
| 221 | | get_shaders()->window_save(); |
| 222 | | } |
| 223 | | |
| 224 | | |
| 225 | | |
| 226 | | //============================================================ |
| 227 | | // drawd3d_window_destroy |
| 228 | | //============================================================ |
| 229 | | |
| 230 | | void d3d::renderer::destroy() |
| 231 | | { |
| 232 | | if (get_shaders() != NULL && get_shaders()->recording()) |
| 233 | | get_shaders()->window_record(); |
| 234 | | |
| 235 | | } |
| 236 | | |
| 237 | | |
| 238 | | |
| 239 | | //============================================================ |
| 240 | | // drawd3d_window_get_primitives |
| 241 | | //============================================================ |
| 242 | | |
| 243 | | render_primitive_list *d3d::renderer::get_primitives() |
| 244 | | { |
| 245 | | RECT client; |
| 246 | | |
| 247 | | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 248 | | if (rect_width(&client) > 0 && rect_height(&client) > 0) |
| 249 | | { |
| 250 | | window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); |
| 251 | | window().target()->set_max_update_rate((get_refresh() == 0) ? get_origmode().RefreshRate : get_refresh()); |
| 252 | | } |
| 253 | | return &window().target()->get_primitives(); |
| 254 | | } |
| 255 | | |
| 256 | | //============================================================ |
| 257 | | // drawnone_create |
| 258 | | //============================================================ |
| 259 | | |
| 260 | | static osd_renderer *drawd3d_create(osd_window *window) |
| 261 | | { |
| 262 | | return global_alloc(d3d::renderer(window)); |
| 263 | | } |
| 264 | | |
| 265 | | int drawd3d_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 266 | | { |
| 267 | | d3dintf = NULL; |
| 268 | | |
| 269 | | // Use Direct3D9 |
| 270 | | d3dintf = d3d::drawd3d9_init(); |
| 271 | | |
| 272 | | // if we failed, note the error |
| 273 | | if (d3dintf == NULL) |
| 274 | | { |
| 275 | | osd_printf_error("Unable to initialize Direct3D.\n"); |
| 276 | | return 1; |
| 277 | | } |
| 278 | | |
| 279 | | // fill in the callbacks |
| 280 | | memset(callbacks, 0, sizeof(*callbacks)); |
| 281 | | callbacks->exit = drawd3d_exit; |
| 282 | | callbacks->create = drawd3d_create; |
| 283 | | return 0; |
| 284 | | } |
| 285 | | |
| 286 | | //============================================================ |
| 287 | | // drawd3d_window_draw |
| 288 | | //============================================================ |
| 289 | | |
| 290 | | int d3d::renderer::draw(const int update) |
| 291 | | { |
| 292 | | int check = pre_window_draw_check(); |
| 293 | | if (check >= 0) |
| 294 | | return check; |
| 295 | | |
| 296 | | begin_frame(); |
| 297 | | process_primitives(); |
| 298 | | end_frame(); |
| 299 | | |
| 300 | | return 0; |
| 301 | | } |
| 302 | | |
| 303 | | namespace d3d |
| 304 | | { |
| 305 | | void renderer::set_texture(texture_info *texture) |
| 306 | | { |
| 307 | | if (texture != m_last_texture) |
| 308 | | { |
| 309 | | m_last_texture = texture; |
| 310 | | m_last_texture_flags = (texture == NULL ? 0 : texture->get_flags()); |
| 311 | | HRESULT result = (*d3dintf->device.set_texture)(m_device, 0, (texture == NULL) ? get_default_texture()->get_finaltex() : texture->get_finaltex()); |
| 312 | | m_shaders->set_texture(texture); |
| 313 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result); |
| 314 | | } |
| 315 | | } |
| 316 | | |
| 317 | | |
| 318 | | void renderer::set_filter(int filter) |
| 319 | | { |
| 320 | | if (filter != m_last_filter) |
| 321 | | { |
| 322 | | m_last_filter = filter; |
| 323 | | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 324 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 325 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 326 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 327 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 328 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 329 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT); |
| 330 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 331 | | } |
| 332 | | } |
| 333 | | |
| 334 | | |
| 335 | | void renderer::set_wrap(D3DTEXTUREADDRESS wrap) |
| 336 | | { |
| 337 | | if (wrap != m_last_wrap) |
| 338 | | { |
| 339 | | m_last_wrap = wrap; |
| 340 | | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap); |
| 341 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 342 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap); |
| 343 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 344 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSU, wrap); |
| 345 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 346 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, (D3DTEXTURESTAGESTATETYPE)D3DTSS_ADDRESSV, wrap); |
| 347 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 348 | | } |
| 349 | | } |
| 350 | | |
| 351 | | |
| 352 | | void renderer::set_modmode(DWORD modmode) |
| 353 | | { |
| 354 | | if (modmode != m_last_modmode) |
| 355 | | { |
| 356 | | m_last_modmode = modmode; |
| 357 | | HRESULT result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, modmode); |
| 358 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 359 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, modmode); |
| 360 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture_stage_state call\n", (int)result); |
| 361 | | } |
| 362 | | } |
| 363 | | |
| 364 | | |
| 365 | | void renderer::set_blendmode(int blendmode) |
| 366 | | { |
| 367 | | int blendenable; |
| 368 | | int blendop; |
| 369 | | int blendsrc; |
| 370 | | int blenddst; |
| 371 | | |
| 372 | | // choose the parameters |
| 373 | | switch (blendmode) |
| 374 | | { |
| 375 | | default: |
| 376 | | case BLENDMODE_NONE: blendenable = FALSE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break; |
| 377 | | case BLENDMODE_ALPHA: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_INVSRCALPHA; break; |
| 378 | | case BLENDMODE_RGB_MULTIPLY: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_DESTCOLOR; blenddst = D3DBLEND_ZERO; break; |
| 379 | | case BLENDMODE_ADD: blendenable = TRUE; blendop = D3DBLENDOP_ADD; blendsrc = D3DBLEND_SRCALPHA; blenddst = D3DBLEND_ONE; break; |
| 380 | | } |
| 381 | | |
| 382 | | // adjust the bits that changed |
| 383 | | if (blendenable != m_last_blendenable) |
| 384 | | { |
| 385 | | m_last_blendenable = blendenable; |
| 386 | | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHABLENDENABLE, blendenable); |
| 387 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 388 | | } |
| 389 | | |
| 390 | | if (blendop != m_last_blendop) |
| 391 | | { |
| 392 | | m_last_blendop = blendop; |
| 393 | | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_BLENDOP, blendop); |
| 394 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 395 | | } |
| 396 | | |
| 397 | | if (blendsrc != m_last_blendsrc) |
| 398 | | { |
| 399 | | m_last_blendsrc = blendsrc; |
| 400 | | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SRCBLEND, blendsrc); |
| 401 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 402 | | } |
| 403 | | |
| 404 | | if (blenddst != m_last_blenddst) |
| 405 | | { |
| 406 | | m_last_blenddst = blenddst; |
| 407 | | HRESULT result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DESTBLEND, blenddst); |
| 408 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_state call\n", (int)result); |
| 409 | | } |
| 410 | | } |
| 411 | | |
| 412 | | |
| 413 | | void renderer::reset_render_states() |
| 414 | | { |
| 415 | | // this ensures subsequent calls to the above setters will force-update the data |
| 416 | | m_last_texture = (texture_info *)~0; |
| 417 | | m_last_filter = -1; |
| 418 | | m_last_blendenable = -1; |
| 419 | | m_last_blendop = -1; |
| 420 | | m_last_blendsrc = -1; |
| 421 | | m_last_blenddst = -1; |
| 422 | | m_last_wrap = (D3DTEXTUREADDRESS)-1; |
| 423 | | } |
| 424 | | |
| 425 | | |
| 426 | | |
| 427 | | texture_manager::texture_manager(renderer *d3d) |
| 428 | | { |
| 429 | | m_renderer = d3d; |
| 430 | | |
| 431 | | m_texlist = NULL; |
| 432 | | m_vector_texture = NULL; |
| 433 | | m_default_texture = NULL; |
| 434 | | |
| 435 | | // check for dynamic texture support |
| 436 | | DWORD tempcaps; |
| 437 | | HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps); |
| 438 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 439 | | m_dynamic_supported = ((tempcaps & D3DCAPS2_DYNAMICTEXTURES) != 0); |
| 440 | | if (m_dynamic_supported) osd_printf_verbose("Direct3D: Using dynamic textures\n"); |
| 441 | | |
| 442 | | // check for stretchrect support |
| 443 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_STRETCH_RECT_FILTER, &tempcaps); |
| 444 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 445 | | m_stretch_supported = ((tempcaps & D3DPTFILTERCAPS_MAGFPOINT) != 0); |
| 446 | | if (m_stretch_supported && video_config.prescale > 1) osd_printf_verbose("Direct3D: Using StretchRect for prescaling\n"); |
| 447 | | |
| 448 | | // get texture caps |
| 449 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_TEXTURE_CAPS, &m_texture_caps); |
| 450 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 451 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_ASPECT, &m_texture_max_aspect); |
| 452 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 453 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_WIDTH, &m_texture_max_width); |
| 454 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 455 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, CAPS_MAX_TEXTURE_HEIGHT, &m_texture_max_height); |
| 456 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 457 | | |
| 458 | | // pick a YUV texture format |
| 459 | | m_yuv_format = D3DFMT_UYVY; |
| 460 | | result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_UYVY); |
| 461 | | if (result != D3D_OK) |
| 462 | | { |
| 463 | | m_yuv_format = D3DFMT_YUY2; |
| 464 | | result = (*d3dintf->d3d.check_device_format)(d3dintf, d3d->get_adapter(), D3DDEVTYPE_HAL, d3d->get_pixel_format(), 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); |
| 465 | | if (result != D3D_OK) |
| 466 | | m_yuv_format = D3DFMT_A8R8G8B8; |
| 467 | | } |
| 468 | | osd_printf_verbose("Direct3D: YUV format = %s\n", (m_yuv_format == D3DFMT_YUY2) ? "YUY2" : (m_yuv_format == D3DFMT_UYVY) ? "UYVY" : "RGB"); |
| 469 | | |
| 470 | | // set the max texture size |
| 471 | | d3d->window().target()->set_max_texture_size(m_texture_max_width, m_texture_max_height); |
| 472 | | osd_printf_verbose("Direct3D: Max texture size = %dx%d\n", (int)m_texture_max_width, (int)m_texture_max_height); |
| 473 | | } |
| 474 | | |
| 475 | | texture_manager::~texture_manager() |
| 476 | | { |
| 477 | | } |
| 478 | | |
| 479 | | void texture_manager::create_resources() |
| 480 | | { |
| 481 | | // experimental: load a PNG to use for vector rendering; it is treated |
| 482 | | // as a brightness map |
| 483 | | emu_file file(m_renderer->window().machine().options().art_path(), OPEN_FLAG_READ); |
| 484 | | render_load_png(m_vector_bitmap, file, NULL, "vector.png"); |
| 485 | | if (m_vector_bitmap.valid()) |
| 486 | | { |
| 487 | | m_vector_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); |
| 488 | | render_load_png(m_vector_bitmap, file, NULL, "vector.png", true); |
| 489 | | } |
| 490 | | |
| 491 | | m_default_bitmap.allocate(8, 8); |
| 492 | | m_default_bitmap.fill(rgb_t(0xff,0xff,0xff,0xff)); |
| 493 | | |
| 494 | | if (m_default_bitmap.valid()) |
| 495 | | { |
| 496 | | render_texinfo texture; |
| 497 | | |
| 498 | | // fake in the basic data so it looks like it came from render.c |
| 499 | | texture.base = m_default_bitmap.raw_pixptr(0); |
| 500 | | texture.rowpixels = m_default_bitmap.rowpixels(); |
| 501 | | texture.width = m_default_bitmap.width(); |
| 502 | | texture.height = m_default_bitmap.height(); |
| 503 | | texture.palette = NULL; |
| 504 | | texture.seqid = 0; |
| 505 | | |
| 506 | | // now create it |
| 507 | | m_default_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32))); |
| 508 | | } |
| 509 | | |
| 510 | | // experimental: if we have a vector bitmap, create a texture for it |
| 511 | | if (m_vector_bitmap.valid()) |
| 512 | | { |
| 513 | | render_texinfo texture; |
| 514 | | |
| 515 | | // fake in the basic data so it looks like it came from render.c |
| 516 | | texture.base = &m_vector_bitmap.pix32(0); |
| 517 | | texture.rowpixels = m_vector_bitmap.rowpixels(); |
| 518 | | texture.width = m_vector_bitmap.width(); |
| 519 | | texture.height = m_vector_bitmap.height(); |
| 520 | | texture.palette = NULL; |
| 521 | | texture.seqid = 0; |
| 522 | | |
| 523 | | // now create it |
| 524 | | m_vector_texture = global_alloc(texture_info(this, &texture, m_renderer->window().prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32))); |
| 525 | | } |
| 526 | | } |
| 527 | | |
| 528 | | void texture_manager::delete_resources() |
| 529 | | { |
| 530 | | // is part of m_texlist and will be free'd there |
| 531 | | //global_free(m_default_texture); |
| 532 | | m_default_texture = NULL; |
| 533 | | |
| 534 | | //global_free(m_vector_texture); |
| 535 | | m_vector_texture = NULL; |
| 536 | | |
| 537 | | // free all textures |
| 538 | | while (m_texlist != NULL) |
| 539 | | { |
| 540 | | texture_info *tex = m_texlist; |
| 541 | | m_texlist = tex->get_next(); |
| 542 | | global_free(tex); |
| 543 | | } |
| 544 | | } |
| 545 | | |
| 546 | | UINT32 texture_manager::texture_compute_hash(const render_texinfo *texture, UINT32 flags) |
| 547 | | { |
| 548 | | return (FPTR)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)); |
| 549 | | } |
| 550 | | |
| 551 | | texture_info *texture_manager::find_texinfo(const render_texinfo *texinfo, UINT32 flags) |
| 552 | | { |
| 553 | | UINT32 hash = texture_compute_hash(texinfo, flags); |
| 554 | | texture_info *texture; |
| 555 | | |
| 556 | | // find a match |
| 557 | | for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) |
| 558 | | { |
| 559 | | UINT32 test_screen = (UINT32)texture->get_texinfo().osddata >> 1; |
| 560 | | UINT32 test_page = (UINT32)texture->get_texinfo().osddata & 1; |
| 561 | | UINT32 prim_screen = (UINT32)texinfo->osddata >> 1; |
| 562 | | UINT32 prim_page = (UINT32)texinfo->osddata & 1; |
| 563 | | if (test_screen != prim_screen || test_page != prim_page) |
| 564 | | { |
| 565 | | continue; |
| 566 | | } |
| 567 | | |
| 568 | | if (texture->get_hash() == hash && |
| 569 | | texture->get_texinfo().base == texinfo->base && |
| 570 | | texture->get_texinfo().width == texinfo->width && |
| 571 | | texture->get_texinfo().height == texinfo->height && |
| 572 | | ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0) |
| 573 | | { |
| 574 | | // Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache |
| 575 | | if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0) |
| 576 | | { |
| 577 | | if (m_renderer->get_shaders()->find_render_target(texture) != NULL) |
| 578 | | { |
| 579 | | return texture; |
| 580 | | } |
| 581 | | } |
| 582 | | else |
| 583 | | { |
| 584 | | return texture; |
| 585 | | } |
| 586 | | } |
| 587 | | } |
| 588 | | |
| 589 | | // Nothing found, check if we need to unregister something with HLSL |
| 590 | | if (m_renderer->get_shaders()->enabled()) |
| 591 | | { |
| 592 | | if (texinfo->width == 0 || texinfo->height == 0) |
| 593 | | { |
| 594 | | return NULL; |
| 595 | | } |
| 596 | | |
| 597 | | UINT32 prim_screen = texinfo->osddata >> 1; |
| 598 | | UINT32 prim_page = texinfo->osddata & 1; |
| 599 | | |
| 600 | | for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != NULL; texture = texture->get_next()) |
| 601 | | { |
| 602 | | UINT32 test_screen = texture->get_texinfo().osddata >> 1; |
| 603 | | UINT32 test_page = texture->get_texinfo().osddata & 1; |
| 604 | | if (test_screen != prim_screen || test_page != prim_page) |
| 605 | | { |
| 606 | | continue; |
| 607 | | } |
| 608 | | |
| 609 | | // Clear out our old texture reference |
| 610 | | if (texture->get_hash() == hash && |
| 611 | | texture->get_texinfo().base == texinfo->base && |
| 612 | | ((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 && |
| 613 | | (texture->get_texinfo().width != texinfo->width || |
| 614 | | texture->get_texinfo().height != texinfo->height)) |
| 615 | | { |
| 616 | | m_renderer->get_shaders()->remove_render_target(texture); |
| 617 | | } |
| 618 | | } |
| 619 | | } |
| 620 | | |
| 621 | | return NULL; |
| 622 | | } |
| 623 | | |
| 624 | | renderer::renderer(osd_window *window) |
| 625 | | : osd_renderer(window, FLAG_NONE) |
| 626 | | { |
| 627 | | m_device = NULL; |
| 628 | | m_restarting = false; |
| 629 | | m_shaders = NULL; |
| 630 | | m_numverts = 0; |
| 631 | | m_numpolys = 0; |
| 632 | | m_vertexbuf = NULL; |
| 633 | | m_lockedbuf = NULL; |
| 634 | | m_vectorbatch = NULL; |
| 635 | | m_last_texture = NULL; |
| 636 | | m_hlsl_buf = NULL; |
| 637 | | m_texture_manager = NULL; |
| 638 | | } |
| 639 | | |
| 640 | | int renderer::initialize() |
| 641 | | { |
| 642 | | // configure the adapter for the mode we want |
| 643 | | if (config_adapter_mode()) |
| 644 | | return false; |
| 645 | | |
| 646 | | // create the device immediately for the full screen case (defer for window mode) |
| 647 | | if (window().fullscreen() && device_create(window().m_focus_hwnd)) |
| 648 | | return false; |
| 649 | | |
| 650 | | return true; |
| 651 | | } |
| 652 | | |
| 653 | | int renderer::pre_window_draw_check() |
| 654 | | { |
| 655 | | // if we're in the middle of resizing, leave things alone |
| 656 | | if (window().m_resize_state == RESIZE_STATE_RESIZING) |
| 657 | | return 0; |
| 658 | | |
| 659 | | // if we're restarting the renderer, leave things alone |
| 660 | | if (m_restarting) |
| 661 | | { |
| 662 | | m_shaders->toggle(); |
| 663 | | |
| 664 | | // free all existing resources and re-create |
| 665 | | device_delete_resources(); |
| 666 | | device_create_resources(); |
| 667 | | |
| 668 | | m_restarting = false; |
| 669 | | } |
| 670 | | |
| 671 | | // if we have a device, check the cooperative level |
| 672 | | if (m_device != NULL) |
| 673 | | { |
| 674 | | if (device_test_cooperative()) |
| 675 | | { |
| 676 | | return 1; |
| 677 | | } |
| 678 | | } |
| 679 | | |
| 680 | | // in window mode, we need to track the window size |
| 681 | | if (!window().fullscreen() || m_device == NULL) |
| 682 | | { |
| 683 | | // if the size changes, skip this update since the render target will be out of date |
| 684 | | if (update_window_size()) |
| 685 | | return 0; |
| 686 | | |
| 687 | | // if we have no device, after updating the size, return an error so GDI can try |
| 688 | | if (m_device == NULL) |
| 689 | | return 1; |
| 690 | | } |
| 691 | | |
| 692 | | return -1; |
| 693 | | } |
| 694 | | |
| 695 | | void texture_manager::update_textures() |
| 696 | | { |
| 697 | | for (render_primitive *prim = m_renderer->window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 698 | | { |
| 699 | | if (prim->texture.base != NULL) |
| 700 | | { |
| 701 | | texture_info *texture = find_texinfo(&prim->texture, prim->flags); |
| 702 | | if (texture == NULL) |
| 703 | | { |
| 704 | | // if there isn't one, create a new texture |
| 705 | | global_alloc(texture_info(this, &prim->texture, m_renderer->window().prescale(), prim->flags)); |
| 706 | | } |
| 707 | | else |
| 708 | | { |
| 709 | | // if there is one, but with a different seqid, copy the data |
| 710 | | if (texture->get_texinfo().seqid != prim->texture.seqid) |
| 711 | | { |
| 712 | | texture->set_data(&prim->texture, prim->flags); |
| 713 | | texture->get_texinfo().seqid = prim->texture.seqid; |
| 714 | | } |
| 715 | | } |
| 716 | | } |
| 717 | | else if(m_renderer->get_shaders()->vector_enabled() && PRIMFLAG_GET_VECTORBUF(prim->flags)) |
| 718 | | { |
| 719 | | if (!m_renderer->get_shaders()->get_vector_target()) |
| 720 | | { |
| 721 | | m_renderer->get_shaders()->create_vector_target(prim); |
| 722 | | } |
| 723 | | } |
| 724 | | } |
| 725 | | } |
| 726 | | |
| 727 | | void renderer::begin_frame() |
| 728 | | { |
| 729 | | HRESULT result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 730 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device clear call\n", (int)result); |
| 731 | | |
| 732 | | m_shaders->begin_frame(); |
| 733 | | |
| 734 | | window().m_primlist->acquire_lock(); |
| 735 | | |
| 736 | | // first update any textures |
| 737 | | m_texture_manager->update_textures(); |
| 738 | | |
| 739 | | // begin the scene |
| 740 | | mtlog_add("drawd3d_window_draw: begin_scene"); |
| 741 | | result = (*d3dintf->device.begin_scene)(m_device); |
| 742 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result); |
| 743 | | |
| 744 | | m_lockedbuf = NULL; |
| 745 | | |
| 746 | | if(m_shaders->enabled()) |
| 747 | | { |
| 748 | | m_hlsl_buf = (void*)mesh_alloc(6); |
| 749 | | m_shaders->init_fsfx_quad(m_hlsl_buf); |
| 750 | | } |
| 751 | | |
| 752 | | m_line_count = 0; |
| 753 | | |
| 754 | | // loop over primitives |
| 755 | | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 756 | | if (prim->type == render_primitive::LINE && PRIMFLAG_GET_VECTOR(prim->flags)) |
| 757 | | m_line_count++; |
| 758 | | } |
| 759 | | |
| 760 | | void renderer::process_primitives() |
| 761 | | { |
| 762 | | // Rotating index for vector time offsets |
| 763 | | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 764 | | { |
| 765 | | switch (prim->type) |
| 766 | | { |
| 767 | | case render_primitive::LINE: |
| 768 | | if (PRIMFLAG_GET_VECTOR(prim->flags)) |
| 769 | | { |
| 770 | | if (m_line_count > 0) |
| 771 | | batch_vectors(); |
| 772 | | else |
| 773 | | continue; |
| 774 | | } |
| 775 | | else |
| 776 | | { |
| 777 | | draw_line(prim); |
| 778 | | } |
| 779 | | break; |
| 780 | | |
| 781 | | case render_primitive::QUAD: |
| 782 | | draw_quad(prim); |
| 783 | | break; |
| 784 | | |
| 785 | | default: |
| 786 | | throw emu_fatalerror("Unexpected render_primitive type"); |
| 787 | | } |
| 788 | | } |
| 789 | | } |
| 790 | | |
| 791 | | void renderer::end_frame() |
| 792 | | { |
| 793 | | window().m_primlist->release_lock(); |
| 794 | | |
| 795 | | // flush any pending polygons |
| 796 | | primitive_flush_pending(); |
| 797 | | |
| 798 | | m_shaders->end_frame(); |
| 799 | | |
| 800 | | // finish the scene |
| 801 | | HRESULT result = (*d3dintf->device.end_scene)(m_device); |
| 802 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result); |
| 803 | | |
| 804 | | // present the current buffers |
| 805 | | result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0); |
| 806 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device present call\n", (int)result); |
| 807 | | } |
| 808 | | |
| 809 | | //============================================================ |
| 810 | | // device_create |
| 811 | | //============================================================ |
| 812 | | |
| 813 | | int renderer::device_create(HWND device_hwnd) |
| 814 | | { |
| 815 | | // if a device exists, free it |
| 816 | | if (m_device != NULL) |
| 817 | | device_delete(); |
| 818 | | |
| 819 | | // verify the caps |
| 820 | | int verify = device_verify_caps(); |
| 821 | | if (verify == 2) |
| 822 | | { |
| 823 | | osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n"); |
| 824 | | return 1; |
| 825 | | } |
| 826 | | if (verify == 1) |
| 827 | | osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n"); |
| 828 | | |
| 829 | | // verify texture formats |
| 830 | | HRESULT result = (*d3dintf->d3d.check_device_format)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); |
| 831 | | if (result != D3D_OK) |
| 832 | | { |
| 833 | | osd_printf_error("Error: A8R8G8B8 format textures not supported\n"); |
| 834 | | return 1; |
| 835 | | } |
| 836 | | |
| 837 | | m_texture_manager = global_alloc(texture_manager(this)); |
| 838 | | |
| 839 | | try_again: |
| 840 | | // try for XRGB first |
| 841 | | m_screen_format = D3DFMT_X8R8G8B8; |
| 842 | | 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); |
| 843 | | if (result != D3D_OK) |
| 844 | | { |
| 845 | | // if not, try for ARGB |
| 846 | | m_screen_format = D3DFMT_A8R8G8B8; |
| 847 | | 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); |
| 848 | | if (result != D3D_OK && m_texture_manager->is_dynamic_supported()) |
| 849 | | { |
| 850 | | m_texture_manager->set_dynamic_supported(FALSE); |
| 851 | | goto try_again; |
| 852 | | } |
| 853 | | if (result != D3D_OK) |
| 854 | | { |
| 855 | | osd_printf_error("Error: unable to configure a screen texture format\n"); |
| 856 | | return 1; |
| 857 | | } |
| 858 | | } |
| 859 | | |
| 860 | | // initialize the D3D presentation parameters |
| 861 | | memset(&m_presentation, 0, sizeof(m_presentation)); |
| 862 | | m_presentation.BackBufferWidth = m_width; |
| 863 | | m_presentation.BackBufferHeight = m_height; |
| 864 | | m_presentation.BackBufferFormat = m_pixformat; |
| 865 | | m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1; |
| 866 | | m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE; |
| 867 | | m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD; |
| 868 | | m_presentation.hDeviceWindow = window().m_hwnd; |
| 869 | | m_presentation.Windowed = !window().fullscreen() || window().win_has_menu(); |
| 870 | | m_presentation.EnableAutoDepthStencil = FALSE; |
| 871 | | m_presentation.AutoDepthStencilFormat = D3DFMT_D16; |
| 872 | | m_presentation.Flags = 0; |
| 873 | | m_presentation.FullScreen_RefreshRateInHz = m_refresh; |
| 874 | | m_presentation.PresentationInterval = ((video_config.triplebuf && window().fullscreen()) || |
| 875 | | video_config.waitvsync || video_config.syncrefresh) ? |
| 876 | | D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; |
| 877 | | |
| 878 | | // create the D3D device |
| 879 | | result = (*d3dintf->d3d.create_device)(d3dintf, m_adapter, D3DDEVTYPE_HAL, device_hwnd, |
| 880 | | D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device); |
| 881 | | if (result != D3D_OK) |
| 882 | | { |
| 883 | | // if we got a "DEVICELOST" error, it may be transitory; count it and only fail if |
| 884 | | // we exceed a threshold |
| 885 | | if (result == D3DERR_DEVICELOST) |
| 886 | | { |
| 887 | | m_create_error_count++; |
| 888 | | if (m_create_error_count < 10) |
| 889 | | { |
| 890 | | return 0; |
| 891 | | } |
| 892 | | } |
| 893 | | |
| 894 | | // fatal error if we just can't do it |
| 895 | | osd_printf_error("Unable to create the Direct3D device (%08X)\n", (UINT32)result); |
| 896 | | return 1; |
| 897 | | } |
| 898 | | m_create_error_count = 0; |
| 899 | | osd_printf_verbose("Direct3D: Device created at %dx%d\n", m_width, m_height); |
| 900 | | |
| 901 | | // set the gamma if we need to |
| 902 | | if (window().fullscreen()) |
| 903 | | { |
| 904 | | // only set the gamma if it's not 1.0f |
| 905 | | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 906 | | float brightness = options.full_screen_brightness(); |
| 907 | | float contrast = options.full_screen_contrast(); |
| 908 | | float gamma = options.full_screen_gamma(); |
| 909 | | if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) |
| 910 | | { |
| 911 | | // warn if we can't do it |
| 912 | | if (!m_gamma_supported) |
| 913 | | { |
| 914 | | osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n"); |
| 915 | | } |
| 916 | | else |
| 917 | | { |
| 918 | | // create a standard ramp and set it |
| 919 | | D3DGAMMARAMP ramp; |
| 920 | | for (int i = 0; i < 256; i++) |
| 921 | | { |
| 922 | | ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; |
| 923 | | } |
| 924 | | (*d3dintf->device.set_gamma_ramp)(m_device, 0, &ramp); |
| 925 | | } |
| 926 | | } |
| 927 | | } |
| 928 | | |
| 929 | | int ret = m_shaders->create_resources(false); |
| 930 | | if (ret != 0) |
| 931 | | return ret; |
| 932 | | |
| 933 | | return device_create_resources(); |
| 934 | | } |
| 935 | | |
| 936 | | |
| 937 | | |
| 938 | | //============================================================ |
| 939 | | // device_create_resources |
| 940 | | //============================================================ |
| 941 | | |
| 942 | | int renderer::device_create_resources() |
| 943 | | { |
| 944 | | // allocate a vertex buffer to use |
| 945 | | HRESULT result = (*d3dintf->device.create_vertex_buffer)(m_device, |
| 946 | | sizeof(vertex) * VERTEX_BUFFER_SIZE, |
| 947 | | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY, |
| 948 | | VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW), |
| 949 | | D3DPOOL_DEFAULT, &m_vertexbuf); |
| 950 | | if (result != D3D_OK) |
| 951 | | { |
| 952 | | osd_printf_error("Error creating vertex buffer (%08X)\n", (UINT32)result); |
| 953 | | return 1; |
| 954 | | } |
| 955 | | |
| 956 | | // set the vertex format |
| 957 | | result = (*d3dintf->device.set_vertex_format)(m_device, (D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && |
| 958 | | d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW))); |
| 959 | | if (result != D3D_OK) |
| 960 | | { |
| 961 | | osd_printf_error("Error setting vertex format (%08X)\n", (UINT32)result); |
| 962 | | return 1; |
| 963 | | } |
| 964 | | |
| 965 | | // set the fixed render state |
| 966 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZENABLE, D3DZB_FALSE); |
| 967 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FILLMODE, D3DFILL_SOLID); |
| 968 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SHADEMODE, D3DSHADE_FLAT); |
| 969 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZWRITEENABLE, FALSE); |
| 970 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHATESTENABLE, TRUE); |
| 971 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LASTPIXEL, TRUE); |
| 972 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CULLMODE, D3DCULL_NONE); |
| 973 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ZFUNC, D3DCMP_LESS); |
| 974 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAREF, 0); |
| 975 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); |
| 976 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_DITHERENABLE, FALSE); |
| 977 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_FOGENABLE, FALSE); |
| 978 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_SPECULARENABLE, FALSE); |
| 979 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_STENCILENABLE, FALSE); |
| 980 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_WRAP0, FALSE); |
| 981 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_CLIPPING, TRUE); |
| 982 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_LIGHTING, FALSE); |
| 983 | | result = (*d3dintf->device.set_render_state)(m_device, D3DRS_COLORVERTEX, TRUE); |
| 984 | | |
| 985 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); |
| 986 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); |
| 987 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_COLOROP, D3DTOP_MODULATE); |
| 988 | | result = (*d3dintf->device.set_texture_stage_state)(m_device, 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); |
| 989 | | |
| 990 | | // reset the local states to force updates |
| 991 | | reset_render_states(); |
| 992 | | |
| 993 | | // clear the buffer |
| 994 | | result = (*d3dintf->device.clear)(m_device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 0, 0); |
| 995 | | result = (*d3dintf->device.present)(m_device, NULL, NULL, NULL, NULL, 0); |
| 996 | | |
| 997 | | m_texture_manager->create_resources(); |
| 998 | | |
| 999 | | return 0; |
| 1000 | | } |
| 1001 | | |
| 1002 | | |
| 1003 | | |
| 1004 | | //============================================================ |
| 1005 | | // device_delete |
| 1006 | | //============================================================ |
| 1007 | | |
| 1008 | | renderer::~renderer() |
| 1009 | | { |
| 1010 | | device_delete(); |
| 1011 | | } |
| 1012 | | |
| 1013 | | void renderer::device_delete() |
| 1014 | | { |
| 1015 | | if (m_shaders != NULL) |
| 1016 | | { |
| 1017 | | // free our effects |
| 1018 | | m_shaders->delete_resources(false); |
| 1019 | | |
| 1020 | | // delete the HLSL interface |
| 1021 | | global_free(m_shaders); |
| 1022 | | } |
| 1023 | | |
| 1024 | | // free our base resources |
| 1025 | | device_delete_resources(); |
| 1026 | | |
| 1027 | | if (m_texture_manager != NULL) |
| 1028 | | { |
| 1029 | | global_free(m_texture_manager); |
| 1030 | | } |
| 1031 | | m_texture_manager = NULL; |
| 1032 | | |
| 1033 | | // free the device itself |
| 1034 | | if (m_device != NULL) |
| 1035 | | { |
| 1036 | | (*d3dintf->device.reset)(m_device, &m_presentation); |
| 1037 | | (*d3dintf->device.release)(m_device); |
| 1038 | | } |
| 1039 | | m_device = NULL; |
| 1040 | | } |
| 1041 | | |
| 1042 | | //============================================================ |
| 1043 | | // device_delete_resources |
| 1044 | | //============================================================ |
| 1045 | | |
| 1046 | | void renderer::device_delete_resources() |
| 1047 | | { |
| 1048 | | if (m_texture_manager != NULL) |
| 1049 | | m_texture_manager->delete_resources(); |
| 1050 | | // free the vertex buffer |
| 1051 | | if (m_vertexbuf != NULL) |
| 1052 | | (*d3dintf->vertexbuf.release)(m_vertexbuf); |
| 1053 | | m_vertexbuf = NULL; |
| 1054 | | } |
| 1055 | | |
| 1056 | | |
| 1057 | | |
| 1058 | | //============================================================ |
| 1059 | | // device_verify_caps |
| 1060 | | //============================================================ |
| 1061 | | |
| 1062 | | int renderer::device_verify_caps() |
| 1063 | | { |
| 1064 | | int retval = 0; |
| 1065 | | |
| 1066 | | m_shaders = global_alloc_clear(shaders); |
| 1067 | | // FIXME: Dynamic cast |
| 1068 | | m_shaders->init(d3dintf, &window().machine(), this); |
| 1069 | | |
| 1070 | | DWORD tempcaps; |
| 1071 | | HRESULT result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_MAX_PS30_INSN_SLOTS, &tempcaps); |
| 1072 | | if (result != D3D_OK) osd_printf_verbose("Direct3D Error %08X during get_caps_dword call\n", (int)result); |
| 1073 | | if (tempcaps < 512) |
| 1074 | | { |
| 1075 | | osd_printf_verbose("Direct3D: Warning - Device does not support Pixel Shader 3.0, falling back to non-PS rendering\n"); |
| 1076 | | d3dintf->post_fx_available = false; |
| 1077 | | } |
| 1078 | | |
| 1079 | | // verify presentation capabilities |
| 1080 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_PRESENTATION_INTERVALS, &tempcaps); |
| 1081 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1082 | | if (!(tempcaps & D3DPRESENT_INTERVAL_IMMEDIATE)) |
| 1083 | | { |
| 1084 | | osd_printf_verbose("Direct3D: Error - Device does not support immediate presentations\n"); |
| 1085 | | retval = 2; |
| 1086 | | } |
| 1087 | | if (!(tempcaps & D3DPRESENT_INTERVAL_ONE)) |
| 1088 | | { |
| 1089 | | osd_printf_verbose("Direct3D: Error - Device does not support per-refresh presentations\n"); |
| 1090 | | retval = 2; |
| 1091 | | } |
| 1092 | | |
| 1093 | | // verify device capabilities |
| 1094 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_DEV_CAPS, &tempcaps); |
| 1095 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1096 | | if (!(tempcaps & D3DDEVCAPS_CANRENDERAFTERFLIP)) |
| 1097 | | { |
| 1098 | | osd_printf_verbose("Direct3D: Warning - Device does not support queued rendering after a page flip\n"); |
| 1099 | | retval = 1; |
| 1100 | | } |
| 1101 | | if (!(tempcaps & D3DDEVCAPS_HWRASTERIZATION)) |
| 1102 | | { |
| 1103 | | osd_printf_verbose("Direct3D: Warning - Device does not support hardware rasterization\n"); |
| 1104 | | retval = 1; |
| 1105 | | } |
| 1106 | | |
| 1107 | | // verify texture operation capabilities |
| 1108 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_TEXTURE_OP_CAPS, &tempcaps); |
| 1109 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1110 | | if (!(tempcaps & D3DTEXOPCAPS_MODULATE)) |
| 1111 | | { |
| 1112 | | osd_printf_verbose("Direct3D: Warning - Device does not support texture modulation\n"); |
| 1113 | | retval = 1; |
| 1114 | | } |
| 1115 | | |
| 1116 | | // set a simpler flag to indicate mod2x and mod4x texture modes |
| 1117 | | m_mod2x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE2X) != 0); |
| 1118 | | m_mod4x_supported = ((tempcaps & D3DTEXOPCAPS_MODULATE4X) != 0); |
| 1119 | | |
| 1120 | | result = (*d3dintf->d3d.get_caps_dword)(d3dintf, m_adapter, D3DDEVTYPE_HAL, CAPS_CAPS2, &tempcaps); |
| 1121 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during get_caps_dword call\n", (int)result); |
| 1122 | | m_gamma_supported = ((tempcaps & D3DCAPS2_FULLSCREENGAMMA) != 0); |
| 1123 | | |
| 1124 | | return retval; |
| 1125 | | } |
| 1126 | | |
| 1127 | | |
| 1128 | | |
| 1129 | | //============================================================ |
| 1130 | | // device_test_cooperative |
| 1131 | | //============================================================ |
| 1132 | | |
| 1133 | | int renderer::device_test_cooperative() |
| 1134 | | { |
| 1135 | | // check our current status; if we lost the device, punt to GDI |
| 1136 | | HRESULT result = (*d3dintf->device.test_cooperative_level)(m_device); |
| 1137 | | if (result == D3DERR_DEVICELOST) |
| 1138 | | return 1; |
| 1139 | | |
| 1140 | | // if we're able to reset ourselves, try it |
| 1141 | | if (result == D3DERR_DEVICENOTRESET) |
| 1142 | | { |
| 1143 | | osd_printf_verbose("Direct3D: resetting device\n"); |
| 1144 | | |
| 1145 | | // free all existing resources and call reset on the device |
| 1146 | | //device_delete(); |
| 1147 | | device_delete_resources(); |
| 1148 | | m_shaders->delete_resources(true); |
| 1149 | | result = (*d3dintf->device.reset)(m_device, &m_presentation); |
| 1150 | | |
| 1151 | | // if it didn't work, punt to GDI |
| 1152 | | if (result != D3D_OK) |
| 1153 | | { |
| 1154 | | osd_printf_error("Unable to reset, result %08x\n", (UINT32)result); |
| 1155 | | return 1; |
| 1156 | | } |
| 1157 | | |
| 1158 | | // try to create the resources again; if that didn't work, delete the whole thing |
| 1159 | | if (device_create_resources()) |
| 1160 | | { |
| 1161 | | osd_printf_verbose("Direct3D: failed to recreate resources for device; failing permanently\n"); |
| 1162 | | device_delete(); |
| 1163 | | return 1; |
| 1164 | | } |
| 1165 | | |
| 1166 | | if (m_shaders->create_resources(true)) |
| 1167 | | { |
| 1168 | | osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n"); |
| 1169 | | device_delete(); |
| 1170 | | return 1; |
| 1171 | | } |
| 1172 | | } |
| 1173 | | return 0; |
| 1174 | | } |
| 1175 | | |
| 1176 | | |
| 1177 | | |
| 1178 | | //============================================================ |
| 1179 | | // config_adapter_mode |
| 1180 | | //============================================================ |
| 1181 | | |
| 1182 | | int renderer::config_adapter_mode() |
| 1183 | | { |
| 1184 | | adapter_identifier identifier; |
| 1185 | | |
| 1186 | | // choose the monitor number |
| 1187 | | m_adapter = get_adapter_for_monitor(); |
| 1188 | | |
| 1189 | | // get the identifier |
| 1190 | | HRESULT result = (*d3dintf->d3d.get_adapter_identifier)(d3dintf, m_adapter, 0, &identifier); |
| 1191 | | if (result != D3D_OK) |
| 1192 | | { |
| 1193 | | osd_printf_error("Error getting identifier for adapter #%d\n", m_adapter); |
| 1194 | | return 1; |
| 1195 | | } |
| 1196 | | osd_printf_verbose("Direct3D: Configuring adapter #%d = %s\n", m_adapter, identifier.Description); |
| 1197 | | |
| 1198 | | // get the current display mode |
| 1199 | | result = (*d3dintf->d3d.get_adapter_display_mode)(d3dintf, m_adapter, &m_origmode); |
| 1200 | | if (result != D3D_OK) |
| 1201 | | { |
| 1202 | | osd_printf_error("Error getting mode for adapter #%d\n", m_adapter); |
| 1203 | | return 1; |
| 1204 | | } |
| 1205 | | |
| 1206 | | // choose a resolution: window mode case |
| 1207 | | if (!window().fullscreen() || !video_config.switchres || window().win_has_menu()) |
| 1208 | | { |
| 1209 | | RECT client; |
| 1210 | | |
| 1211 | | // bounds are from the window client rect |
| 1212 | | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 1213 | | m_width = client.right - client.left; |
| 1214 | | m_height = client.bottom - client.top; |
| 1215 | | |
| 1216 | | // pix format is from the current mode |
| 1217 | | m_pixformat = m_origmode.Format; |
| 1218 | | m_refresh = 0; |
| 1219 | | |
| 1220 | | // make sure it's a pixel format we can get behind |
| 1221 | | if (m_pixformat != D3DFMT_X1R5G5B5 && m_pixformat != D3DFMT_R5G6B5 && m_pixformat != D3DFMT_X8R8G8B8) |
| 1222 | | { |
| 1223 | | osd_printf_error("Device %s currently in an unsupported mode\n", window().monitor()->devicename()); |
| 1224 | | return 1; |
| 1225 | | } |
| 1226 | | } |
| 1227 | | |
| 1228 | | // choose a resolution: full screen mode case |
| 1229 | | else |
| 1230 | | { |
| 1231 | | // default to the current mode exactly |
| 1232 | | m_width = m_origmode.Width; |
| 1233 | | m_height = m_origmode.Height; |
| 1234 | | m_pixformat = m_origmode.Format; |
| 1235 | | m_refresh = m_origmode.RefreshRate; |
| 1236 | | |
| 1237 | | // if we're allowed to switch resolutions, override with something better |
| 1238 | | if (video_config.switchres) |
| 1239 | | pick_best_mode(); |
| 1240 | | } |
| 1241 | | |
| 1242 | | // see if we can handle the device type |
| 1243 | | result = (*d3dintf->d3d.check_device_type)(d3dintf, m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_pixformat, !window().fullscreen()); |
| 1244 | | if (result != D3D_OK) |
| 1245 | | { |
| 1246 | | osd_printf_error("Proposed video mode not supported on device %s\n", window().monitor()->devicename()); |
| 1247 | | return 1; |
| 1248 | | } |
| 1249 | | return 0; |
| 1250 | | } |
| 1251 | | |
| 1252 | | |
| 1253 | | |
| 1254 | | //============================================================ |
| 1255 | | // get_adapter_for_monitor |
| 1256 | | //============================================================ |
| 1257 | | |
| 1258 | | int renderer::get_adapter_for_monitor() |
| 1259 | | { |
| 1260 | | int maxadapter = (*d3dintf->d3d.get_adapter_count)(d3dintf); |
| 1261 | | |
| 1262 | | // iterate over adapters until we error or find a match |
| 1263 | | for (int adapternum = 0; adapternum < maxadapter; adapternum++) |
| 1264 | | { |
| 1265 | | // get the monitor for this adapter |
| 1266 | | HMONITOR curmonitor = (*d3dintf->d3d.get_adapter_monitor)(d3dintf, adapternum); |
| 1267 | | |
| 1268 | | // if we match the proposed monitor, this is it |
| 1269 | | if (curmonitor == window().monitor()->handle()) |
| 1270 | | { |
| 1271 | | return adapternum; |
| 1272 | | } |
| 1273 | | } |
| 1274 | | |
| 1275 | | // default to the default |
| 1276 | | return D3DADAPTER_DEFAULT; |
| 1277 | | } |
| 1278 | | |
| 1279 | | |
| 1280 | | |
| 1281 | | //============================================================ |
| 1282 | | // pick_best_mode |
| 1283 | | //============================================================ |
| 1284 | | |
| 1285 | | void renderer::pick_best_mode() |
| 1286 | | { |
| 1287 | | double target_refresh = 60.0; |
| 1288 | | INT32 minwidth, minheight; |
| 1289 | | float best_score = 0.0f; |
| 1290 | | |
| 1291 | | // determine the refresh rate of the primary screen |
| 1292 | | const screen_device *primary_screen = window().machine().config().first_screen(); |
| 1293 | | if (primary_screen != NULL) |
| 1294 | | { |
| 1295 | | target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); |
| 1296 | | } |
| 1297 | | |
| 1298 | | // determine the minimum width/height for the selected target |
| 1299 | | // note: technically we should not be calling this from an alternate window |
| 1300 | | // thread; however, it is only done during init time, and the init code on |
| 1301 | | // the main thread is waiting for us to finish, so it is safe to do so here |
| 1302 | | window().target()->compute_minimum_size(minwidth, minheight); |
| 1303 | | |
| 1304 | | // use those as the target for now |
| 1305 | | INT32 target_width = minwidth; |
| 1306 | | INT32 target_height = minheight; |
| 1307 | | |
| 1308 | | // determine the maximum number of modes |
| 1309 | | int maxmodes = (*d3dintf->d3d.get_adapter_mode_count)(d3dintf, m_adapter, D3DFMT_X8R8G8B8); |
| 1310 | | |
| 1311 | | // enumerate all the video modes and find the best match |
| 1312 | | osd_printf_verbose("Direct3D: Selecting video mode...\n"); |
| 1313 | | for (int modenum = 0; modenum < maxmodes; modenum++) |
| 1314 | | { |
| 1315 | | // check this mode |
| 1316 | | D3DDISPLAYMODE mode; |
| 1317 | | HRESULT result = (*d3dintf->d3d.enum_adapter_modes)(d3dintf, m_adapter, D3DFMT_X8R8G8B8, modenum, &mode); |
| 1318 | | if (result != D3D_OK) |
| 1319 | | break; |
| 1320 | | |
| 1321 | | // skip non-32 bit modes |
| 1322 | | if (mode.Format != D3DFMT_X8R8G8B8) |
| 1323 | | continue; |
| 1324 | | |
| 1325 | | // compute initial score based on difference between target and current |
| 1326 | | float size_score = 1.0f / (1.0f + fabs((float)(mode.Width - target_width)) + fabs((float)(mode.Height - target_height))); |
| 1327 | | |
| 1328 | | // if the mode is too small, give a big penalty |
| 1329 | | if (mode.Width < minwidth || mode.Height < minheight) |
| 1330 | | size_score *= 0.01f; |
| 1331 | | |
| 1332 | | // if mode is smaller than we'd like, it only scores up to 0.1 |
| 1333 | | if (mode.Width < target_width || mode.Height < target_height) |
| 1334 | | size_score *= 0.1f; |
| 1335 | | |
| 1336 | | // if we're looking for a particular mode, that's a winner |
| 1337 | | if (mode.Width == window().m_win_config.width && mode.Height == window().m_win_config.height) |
| 1338 | | size_score = 2.0f; |
| 1339 | | |
| 1340 | | // compute refresh score |
| 1341 | | float refresh_score = 1.0f / (1.0f + fabs((double)mode.RefreshRate - target_refresh)); |
| 1342 | | |
| 1343 | | // if refresh is smaller than we'd like, it only scores up to 0.1 |
| 1344 | | if ((double)mode.RefreshRate < target_refresh) |
| 1345 | | refresh_score *= 0.1f; |
| 1346 | | |
| 1347 | | // if we're looking for a particular refresh, make sure it matches |
| 1348 | | if (mode.RefreshRate == window().m_win_config.refresh) |
| 1349 | | refresh_score = 2.0f; |
| 1350 | | |
| 1351 | | // weight size and refresh equally |
| 1352 | | float final_score = size_score + refresh_score; |
| 1353 | | |
| 1354 | | // best so far? |
| 1355 | | osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", mode.Width, mode.Height, mode.RefreshRate, final_score * 1000.0f); |
| 1356 | | if (final_score > best_score) |
| 1357 | | { |
| 1358 | | best_score = final_score; |
| 1359 | | m_width = mode.Width; |
| 1360 | | m_height = mode.Height; |
| 1361 | | m_pixformat = mode.Format; |
| 1362 | | m_refresh = mode.RefreshRate; |
| 1363 | | } |
| 1364 | | } |
| 1365 | | osd_printf_verbose("Direct3D: Mode selected = %4dx%4d@%3dHz\n", m_width, m_height, m_refresh); |
| 1366 | | } |
| 1367 | | |
| 1368 | | |
| 1369 | | |
| 1370 | | //============================================================ |
| 1371 | | // update_window_size |
| 1372 | | //============================================================ |
| 1373 | | |
| 1374 | | int renderer::update_window_size() |
| 1375 | | { |
| 1376 | | // get the current window bounds |
| 1377 | | RECT client; |
| 1378 | | GetClientRectExceptMenu(window().m_hwnd, &client, window().fullscreen()); |
| 1379 | | |
| 1380 | | // if we have a device and matching width/height, nothing to do |
| 1381 | | if (m_device != NULL && rect_width(&client) == m_width && rect_height(&client) == m_height) |
| 1382 | | { |
| 1383 | | // clear out any pending resizing if the area didn't change |
| 1384 | | if (window().m_resize_state == RESIZE_STATE_PENDING) |
| 1385 | | window().m_resize_state = RESIZE_STATE_NORMAL; |
| 1386 | | return FALSE; |
| 1387 | | } |
| 1388 | | |
| 1389 | | // if we're in the middle of resizing, leave it alone as well |
| 1390 | | if (window().m_resize_state == RESIZE_STATE_RESIZING) |
| 1391 | | return FALSE; |
| 1392 | | |
| 1393 | | // set the new bounds and create the device again |
| 1394 | | m_width = rect_width(&client); |
| 1395 | | m_height = rect_height(&client); |
| 1396 | | if (device_create(window().m_focus_hwnd)) |
| 1397 | | return FALSE; |
| 1398 | | |
| 1399 | | // reset the resize state to normal, and indicate we made a change |
| 1400 | | window().m_resize_state = RESIZE_STATE_NORMAL; |
| 1401 | | return TRUE; |
| 1402 | | } |
| 1403 | | |
| 1404 | | //============================================================ |
| 1405 | | // batch_vectors |
| 1406 | | //============================================================ |
| 1407 | | |
| 1408 | | void renderer::batch_vectors() |
| 1409 | | { |
| 1410 | | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 1411 | | |
| 1412 | | int vector_size = (options.antialias() ? 24 : 6); |
| 1413 | | m_vectorbatch = mesh_alloc(m_line_count * vector_size); |
| 1414 | | m_batchindex = 0; |
| 1415 | | |
| 1416 | | static int start_index = 0; |
| 1417 | | int line_index = 0; |
| 1418 | | float period = options.screen_vector_time_period(); |
| 1419 | | UINT32 cached_flags = 0; |
| 1420 | | for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 1421 | | { |
| 1422 | | switch (prim->type) |
| 1423 | | { |
| 1424 | | case render_primitive::LINE: |
| 1425 | | if (PRIMFLAG_GET_VECTOR(prim->flags)) |
| 1426 | | { |
| 1427 | | if (period == 0.0f || m_line_count == 0) |
| 1428 | | { |
| 1429 | | batch_vector(prim, 1.0f); |
| 1430 | | } |
| 1431 | | else |
| 1432 | | { |
| 1433 | | batch_vector(prim, (float)(start_index + line_index) / ((float)m_line_count * period)); |
| 1434 | | line_index++; |
| 1435 | | } |
| 1436 | | cached_flags = prim->flags; |
| 1437 | | } |
| 1438 | | break; |
| 1439 | | |
| 1440 | | default: |
| 1441 | | // Skip |
| 1442 | | break; |
| 1443 | | } |
| 1444 | | } |
| 1445 | | |
| 1446 | | // now add a polygon entry |
| 1447 | | m_poly[m_numpolys].init(D3DPT_TRIANGLELIST, m_line_count * (options.antialias() ? 8 : 2), vector_size * m_line_count, cached_flags, |
| 1448 | | m_texture_manager->get_vector_texture(), D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f); |
| 1449 | | m_numpolys++; |
| 1450 | | |
| 1451 | | start_index += (int)((float)line_index * period); |
| 1452 | | if (m_line_count > 0) |
| 1453 | | { |
| 1454 | | start_index %= m_line_count; |
| 1455 | | } |
| 1456 | | |
| 1457 | | m_line_count = 0; |
| 1458 | | } |
| 1459 | | |
| 1460 | | void renderer::batch_vector(const render_primitive *prim, float line_time) |
| 1461 | | { |
| 1462 | | // compute the effective width based on the direction of the line |
| 1463 | | float effwidth = prim->width; |
| 1464 | | if (effwidth < 0.5f) |
| 1465 | | { |
| 1466 | | effwidth = 0.5f; |
| 1467 | | } |
| 1468 | | |
| 1469 | | // determine the bounds of a quad to draw this line |
| 1470 | | render_bounds b0, b1; |
| 1471 | | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1472 | | |
| 1473 | | // iterate over AA steps |
| 1474 | | for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; |
| 1475 | | step->weight != 0; step++) |
| 1476 | | { |
| 1477 | | // get a pointer to the vertex buffer |
| 1478 | | if (m_vectorbatch == NULL) |
| 1479 | | return; |
| 1480 | | |
| 1481 | | m_vectorbatch[m_batchindex + 0].x = b0.x0 + step->xoffs; |
| 1482 | | m_vectorbatch[m_batchindex + 0].y = b0.y0 + step->yoffs; |
| 1483 | | m_vectorbatch[m_batchindex + 1].x = b0.x1 + step->xoffs; |
| 1484 | | m_vectorbatch[m_batchindex + 1].y = b0.y1 + step->yoffs; |
| 1485 | | m_vectorbatch[m_batchindex + 2].x = b1.x0 + step->xoffs; |
| 1486 | | m_vectorbatch[m_batchindex + 2].y = b1.y0 + step->yoffs; |
| 1487 | | |
| 1488 | | m_vectorbatch[m_batchindex + 3].x = b0.x1 + step->xoffs; |
| 1489 | | m_vectorbatch[m_batchindex + 3].y = b0.y1 + step->yoffs; |
| 1490 | | m_vectorbatch[m_batchindex + 4].x = b1.x0 + step->xoffs; |
| 1491 | | m_vectorbatch[m_batchindex + 4].y = b1.y0 + step->yoffs; |
| 1492 | | m_vectorbatch[m_batchindex + 5].x = b1.x1 + step->xoffs; |
| 1493 | | m_vectorbatch[m_batchindex + 5].y = b1.y1 + step->yoffs; |
| 1494 | | |
| 1495 | | float dx = b1.x1 - b0.x1; |
| 1496 | | float dy = b1.y1 - b0.y1; |
| 1497 | | float line_length = sqrtf(dx * dx + dy * dy); |
| 1498 | | |
| 1499 | | // determine the color of the line |
| 1500 | | INT32 r = (INT32)(prim->color.r * step->weight * 255.0f); |
| 1501 | | INT32 g = (INT32)(prim->color.g * step->weight * 255.0f); |
| 1502 | | INT32 b = (INT32)(prim->color.b * step->weight * 255.0f); |
| 1503 | | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1504 | | if (r > 255 || g > 255 || b > 255) |
| 1505 | | { |
| 1506 | | if (r > 2*255 || g > 2*255 || b > 2*255) |
| 1507 | | { |
| 1508 | | r >>= 2; g >>= 2; b >>= 2; |
| 1509 | | } |
| 1510 | | else |
| 1511 | | { |
| 1512 | | r >>= 1; g >>= 1; b >>= 1; |
| 1513 | | } |
| 1514 | | } |
| 1515 | | if (r > 255) r = 255; |
| 1516 | | if (g > 255) g = 255; |
| 1517 | | if (b > 255) b = 255; |
| 1518 | | if (a > 255) a = 255; |
| 1519 | | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1520 | | |
| 1521 | | vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart()); |
| 1522 | | vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop()); |
| 1523 | | |
| 1524 | | m_vectorbatch[m_batchindex + 0].u0 = start.c.x; |
| 1525 | | m_vectorbatch[m_batchindex + 0].v0 = start.c.y; |
| 1526 | | m_vectorbatch[m_batchindex + 1].u0 = start.c.x; |
| 1527 | | m_vectorbatch[m_batchindex + 1].v0 = stop.c.y; |
| 1528 | | m_vectorbatch[m_batchindex + 2].u0 = stop.c.x; |
| 1529 | | m_vectorbatch[m_batchindex + 2].v0 = start.c.y; |
| 1530 | | |
| 1531 | | m_vectorbatch[m_batchindex + 3].u0 = start.c.x; |
| 1532 | | m_vectorbatch[m_batchindex + 3].v0 = stop.c.y; |
| 1533 | | m_vectorbatch[m_batchindex + 4].u0 = stop.c.x; |
| 1534 | | m_vectorbatch[m_batchindex + 4].v0 = start.c.y; |
| 1535 | | m_vectorbatch[m_batchindex + 5].u0 = stop.c.x; |
| 1536 | | m_vectorbatch[m_batchindex + 5].v0 = stop.c.y; |
| 1537 | | |
| 1538 | | m_vectorbatch[m_batchindex + 0].u1 = line_length; |
| 1539 | | m_vectorbatch[m_batchindex + 1].u1 = line_length; |
| 1540 | | m_vectorbatch[m_batchindex + 2].u1 = line_length; |
| 1541 | | m_vectorbatch[m_batchindex + 3].u1 = line_length; |
| 1542 | | m_vectorbatch[m_batchindex + 4].u1 = line_length; |
| 1543 | | m_vectorbatch[m_batchindex + 5].u1 = line_length; |
| 1544 | | |
| 1545 | | // set the color, Z parameters to standard values |
| 1546 | | for (int i = 0; i < 6; i++) |
| 1547 | | { |
| 1548 | | m_vectorbatch[m_batchindex + i].z = 0.0f; |
| 1549 | | m_vectorbatch[m_batchindex + i].rhw = 1.0f; |
| 1550 | | m_vectorbatch[m_batchindex + i].color = color; |
| 1551 | | } |
| 1552 | | |
| 1553 | | m_batchindex += 6; |
| 1554 | | } |
| 1555 | | } |
| 1556 | | |
| 1557 | | //============================================================ |
| 1558 | | // draw_line |
| 1559 | | //============================================================ |
| 1560 | | |
| 1561 | | void renderer::draw_line(const render_primitive *prim) |
| 1562 | | { |
| 1563 | | // compute the effective width based on the direction of the line |
| 1564 | | float effwidth = prim->width; |
| 1565 | | if (effwidth < 0.5f) |
| 1566 | | { |
| 1567 | | effwidth = 0.5f; |
| 1568 | | } |
| 1569 | | |
| 1570 | | // determine the bounds of a quad to draw this line |
| 1571 | | render_bounds b0, b1; |
| 1572 | | render_line_to_quad(&prim->bounds, effwidth, &b0, &b1); |
| 1573 | | |
| 1574 | | // iterate over AA steps |
| 1575 | | for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim->flags) ? line_aa_4step : line_aa_1step; |
| 1576 | | step->weight != 0; step++) |
| 1577 | | { |
| 1578 | | // get a pointer to the vertex buffer |
| 1579 | | vertex *vertex = mesh_alloc(4); |
| 1580 | | if (vertex == NULL) |
| 1581 | | return; |
| 1582 | | |
| 1583 | | // rotate the unit vector by 135 degrees and add to point 0 |
| 1584 | | vertex[0].x = b0.x0 + step->xoffs; |
| 1585 | | vertex[0].y = b0.y0 + step->yoffs; |
| 1586 | | |
| 1587 | | // rotate the unit vector by -135 degrees and add to point 0 |
| 1588 | | vertex[1].x = b0.x1 + step->xoffs; |
| 1589 | | vertex[1].y = b0.y1 + step->yoffs; |
| 1590 | | |
| 1591 | | // rotate the unit vector by 45 degrees and add to point 1 |
| 1592 | | vertex[2].x = b1.x0 + step->xoffs; |
| 1593 | | vertex[2].y = b1.y0 + step->yoffs; |
| 1594 | | |
| 1595 | | // rotate the unit vector by -45 degrees and add to point 1 |
| 1596 | | vertex[3].x = b1.x1 + step->xoffs; |
| 1597 | | vertex[3].y = b1.y1 + step->yoffs; |
| 1598 | | |
| 1599 | | // determine the color of the line |
| 1600 | | INT32 r = (INT32)(prim->color.r * step->weight * 255.0f); |
| 1601 | | INT32 g = (INT32)(prim->color.g * step->weight * 255.0f); |
| 1602 | | INT32 b = (INT32)(prim->color.b * step->weight * 255.0f); |
| 1603 | | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1604 | | if (r > 255) r = 255; |
| 1605 | | if (g > 255) g = 255; |
| 1606 | | if (b > 255) b = 255; |
| 1607 | | if (a > 255) a = 255; |
| 1608 | | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1609 | | |
| 1610 | | vec2f& start = (get_vector_texture() ? get_vector_texture()->get_uvstart() : get_default_texture()->get_uvstart()); |
| 1611 | | vec2f& stop = (get_vector_texture() ? get_vector_texture()->get_uvstop() : get_default_texture()->get_uvstop()); |
| 1612 | | |
| 1613 | | vertex[0].u0 = start.c.x; |
| 1614 | | vertex[0].v0 = start.c.y; |
| 1615 | | |
| 1616 | | vertex[2].u0 = stop.c.x; |
| 1617 | | vertex[2].v0 = start.c.y; |
| 1618 | | |
| 1619 | | vertex[1].u0 = start.c.x; |
| 1620 | | vertex[1].v0 = stop.c.y; |
| 1621 | | |
| 1622 | | vertex[3].u0 = stop.c.x; |
| 1623 | | vertex[3].v0 = stop.c.y; |
| 1624 | | |
| 1625 | | // set the color, Z parameters to standard values |
| 1626 | | for (int i = 0; i < 4; i++) |
| 1627 | | { |
| 1628 | | vertex[i].z = 0.0f; |
| 1629 | | vertex[i].rhw = 1.0f; |
| 1630 | | vertex[i].color = color; |
| 1631 | | } |
| 1632 | | |
| 1633 | | // now add a polygon entry |
| 1634 | | m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, get_vector_texture(), |
| 1635 | | D3DTOP_MODULATE, 0.0f, 1.0f, 0.0f, 0.0f); |
| 1636 | | m_numpolys++; |
| 1637 | | } |
| 1638 | | } |
| 1639 | | |
| 1640 | | |
| 1641 | | |
| 1642 | | //============================================================ |
| 1643 | | // draw_quad |
| 1644 | | //============================================================ |
| 1645 | | |
| 1646 | | void renderer::draw_quad(const render_primitive *prim) |
| 1647 | | { |
| 1648 | | texture_info *texture = m_texture_manager->find_texinfo(&prim->texture, prim->flags); |
| 1649 | | |
| 1650 | | if (texture == NULL) |
| 1651 | | { |
| 1652 | | texture = get_default_texture(); |
| 1653 | | } |
| 1654 | | |
| 1655 | | // get a pointer to the vertex buffer |
| 1656 | | vertex *vertex = mesh_alloc(4); |
| 1657 | | if (vertex == NULL) |
| 1658 | | return; |
| 1659 | | |
| 1660 | | // fill in the vertexes clockwise |
| 1661 | | vertex[0].x = prim->bounds.x0 - 0.5f; |
| 1662 | | vertex[0].y = prim->bounds.y0 - 0.5f; |
| 1663 | | vertex[1].x = prim->bounds.x1 - 0.5f; |
| 1664 | | vertex[1].y = prim->bounds.y0 - 0.5f; |
| 1665 | | vertex[2].x = prim->bounds.x0 - 0.5f; |
| 1666 | | vertex[2].y = prim->bounds.y1 - 0.5f; |
| 1667 | | vertex[3].x = prim->bounds.x1 - 0.5f; |
| 1668 | | vertex[3].y = prim->bounds.y1 - 0.5f; |
| 1669 | | float width = prim->bounds.x1 - prim->bounds.x0; |
| 1670 | | float height = prim->bounds.y1 - prim->bounds.y0; |
| 1671 | | |
| 1672 | | // set the texture coordinates |
| 1673 | | if(texture != NULL) |
| 1674 | | { |
| 1675 | | vec2f& start = texture->get_uvstart(); |
| 1676 | | vec2f& stop = texture->get_uvstop(); |
| 1677 | | vec2f delta = stop - start; |
| 1678 | | vertex[0].u0 = start.c.x + delta.c.x * prim->texcoords.tl.u; |
| 1679 | | vertex[0].v0 = start.c.y + delta.c.y * prim->texcoords.tl.v; |
| 1680 | | vertex[1].u0 = start.c.x + delta.c.x * prim->texcoords.tr.u; |
| 1681 | | vertex[1].v0 = start.c.y + delta.c.y * prim->texcoords.tr.v; |
| 1682 | | vertex[2].u0 = start.c.x + delta.c.x * prim->texcoords.bl.u; |
| 1683 | | vertex[2].v0 = start.c.y + delta.c.y * prim->texcoords.bl.v; |
| 1684 | | vertex[3].u0 = start.c.x + delta.c.x * prim->texcoords.br.u; |
| 1685 | | vertex[3].v0 = start.c.y + delta.c.y * prim->texcoords.br.v; |
| 1686 | | } |
| 1687 | | |
| 1688 | | // determine the color, allowing for over modulation |
| 1689 | | INT32 r = (INT32)(prim->color.r * 255.0f); |
| 1690 | | INT32 g = (INT32)(prim->color.g * 255.0f); |
| 1691 | | INT32 b = (INT32)(prim->color.b * 255.0f); |
| 1692 | | INT32 a = (INT32)(prim->color.a * 255.0f); |
| 1693 | | DWORD modmode = D3DTOP_MODULATE; |
| 1694 | | if (texture != NULL) |
| 1695 | | { |
| 1696 | | if (m_mod2x_supported && (r > 255 || g > 255 || b > 255)) |
| 1697 | | { |
| 1698 | | if (m_mod4x_supported && (r > 2*255 || g > 2*255 || b > 2*255)) |
| 1699 | | { |
| 1700 | | r >>= 2; g >>= 2; b >>= 2; |
| 1701 | | modmode = D3DTOP_MODULATE4X; |
| 1702 | | } |
| 1703 | | else |
| 1704 | | { |
| 1705 | | r >>= 1; g >>= 1; b >>= 1; |
| 1706 | | modmode = D3DTOP_MODULATE2X; |
| 1707 | | } |
| 1708 | | } |
| 1709 | | } |
| 1710 | | if (r > 255) r = 255; |
| 1711 | | if (g > 255) g = 255; |
| 1712 | | if (b > 255) b = 255; |
| 1713 | | if (a > 255) a = 255; |
| 1714 | | DWORD color = D3DCOLOR_ARGB(a, r, g, b); |
| 1715 | | |
| 1716 | | // set the color, Z parameters to standard values |
| 1717 | | for (int i = 0; i < 4; i++) |
| 1718 | | { |
| 1719 | | vertex[i].z = 0.0f; |
| 1720 | | vertex[i].rhw = 1.0f; |
| 1721 | | vertex[i].color = color; |
| 1722 | | } |
| 1723 | | |
| 1724 | | // now add a polygon entry |
| 1725 | | m_poly[m_numpolys].init(D3DPT_TRIANGLESTRIP, 2, 4, prim->flags, texture, modmode, width, height); |
| 1726 | | m_numpolys++; |
| 1727 | | } |
| 1728 | | |
| 1729 | | void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts, |
| 1730 | | UINT32 flags, texture_info *texture, UINT32 modmode, |
| 1731 | | float line_time, float line_length, |
| 1732 | | float prim_width, float prim_height) |
| 1733 | | { |
| 1734 | | init(type, count, numverts, flags, texture, modmode, prim_width, prim_height); |
| 1735 | | m_line_time = line_time; |
| 1736 | | m_line_length = line_length; |
| 1737 | | } |
| 1738 | | |
| 1739 | | void poly_info::init(D3DPRIMITIVETYPE type, UINT32 count, UINT32 numverts, |
| 1740 | | UINT32 flags, texture_info *texture, UINT32 modmode, |
| 1741 | | float prim_width, float prim_height) |
| 1742 | | { |
| 1743 | | m_type = type; |
| 1744 | | m_count = count; |
| 1745 | | m_numverts = numverts; |
| 1746 | | m_flags = flags; |
| 1747 | | m_texture = texture; |
| 1748 | | m_modmode = modmode; |
| 1749 | | m_prim_width = prim_width; |
| 1750 | | m_prim_height = prim_height; |
| 1751 | | } |
| 1752 | | |
| 1753 | | //============================================================ |
| 1754 | | // primitive_alloc |
| 1755 | | //============================================================ |
| 1756 | | |
| 1757 | | vertex *renderer::mesh_alloc(int numverts) |
| 1758 | | { |
| 1759 | | HRESULT result; |
| 1760 | | |
| 1761 | | // if we're going to overflow, flush |
| 1762 | | if (m_lockedbuf != NULL && m_numverts + numverts >= VERTEX_BUFFER_SIZE) |
| 1763 | | { |
| 1764 | | primitive_flush_pending(); |
| 1765 | | |
| 1766 | | if(m_shaders->enabled()) |
| 1767 | | { |
| 1768 | | m_hlsl_buf = (void*)mesh_alloc(6); |
| 1769 | | m_shaders->init_fsfx_quad(m_hlsl_buf); |
| 1770 | | } |
| 1771 | | } |
| 1772 | | |
| 1773 | | // if we don't have a lock, grab it now |
| 1774 | | if (m_lockedbuf == NULL) |
| 1775 | | { |
| 1776 | | result = (*d3dintf->vertexbuf.lock)(m_vertexbuf, 0, 0, (VOID **)&m_lockedbuf, D3DLOCK_DISCARD); |
| 1777 | | if (result != D3D_OK) |
| 1778 | | return NULL; |
| 1779 | | } |
| 1780 | | |
| 1781 | | // if we already have the lock and enough room, just return a pointer |
| 1782 | | if (m_lockedbuf != NULL && m_numverts + numverts < VERTEX_BUFFER_SIZE) |
| 1783 | | { |
| 1784 | | int oldverts = m_numverts; |
| 1785 | | m_numverts += numverts; |
| 1786 | | return &m_lockedbuf[oldverts]; |
| 1787 | | } |
| 1788 | | return NULL; |
| 1789 | | } |
| 1790 | | |
| 1791 | | |
| 1792 | | |
| 1793 | | //============================================================ |
| 1794 | | // primitive_flush_pending |
| 1795 | | //============================================================ |
| 1796 | | |
| 1797 | | void renderer::primitive_flush_pending() |
| 1798 | | { |
| 1799 | | // ignore if we're not locked |
| 1800 | | if (m_lockedbuf == NULL) |
| 1801 | | { |
| 1802 | | return; |
| 1803 | | } |
| 1804 | | |
| 1805 | | // unlock the buffer |
| 1806 | | HRESULT result = (*d3dintf->vertexbuf.unlock)(m_vertexbuf); |
| 1807 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result); |
| 1808 | | m_lockedbuf = NULL; |
| 1809 | | |
| 1810 | | // set the stream |
| 1811 | | result = (*d3dintf->device.set_stream_source)(m_device, 0, m_vertexbuf, sizeof(vertex)); |
| 1812 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result); |
| 1813 | | |
| 1814 | | m_shaders->begin_draw(); |
| 1815 | | |
| 1816 | | int vertnum = 0; |
| 1817 | | if (m_shaders->enabled()) |
| 1818 | | { |
| 1819 | | vertnum = 6; |
| 1820 | | } |
| 1821 | | |
| 1822 | | // now do the polys |
| 1823 | | for (int polynum = 0; polynum < m_numpolys; polynum++) |
| 1824 | | { |
| 1825 | | UINT32 flags = m_poly[polynum].get_flags(); |
| 1826 | | texture_info *texture = m_poly[polynum].get_texture(); |
| 1827 | | int newfilter; |
| 1828 | | |
| 1829 | | // set the texture if different |
| 1830 | | set_texture(texture); |
| 1831 | | |
| 1832 | | // set filtering if different |
| 1833 | | if (texture != NULL) |
| 1834 | | { |
| 1835 | | newfilter = FALSE; |
| 1836 | | if (PRIMFLAG_GET_SCREENTEX(flags)) |
| 1837 | | newfilter = video_config.filter; |
| 1838 | | set_filter(newfilter); |
| 1839 | | set_wrap(PRIMFLAG_GET_TEXWRAP(flags) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP); |
| 1840 | | set_modmode(m_poly[polynum].get_modmode()); |
| 1841 | | |
| 1842 | | m_shaders->init_effect_info(&m_poly[polynum]); |
| 1843 | | } |
| 1844 | | |
| 1845 | | // set the blendmode if different |
| 1846 | | set_blendmode(PRIMFLAG_GET_BLENDMODE(flags)); |
| 1847 | | |
| 1848 | | if (vertnum + m_poly[polynum].get_vertcount() > m_numverts) |
| 1849 | | { |
| 1850 | | osd_printf_error("Error: vertnum (%d) plus poly vertex count (%d) > %d\n", vertnum, m_poly[polynum].get_vertcount(), m_numverts); |
| 1851 | | fflush(stdout); |
| 1852 | | } |
| 1853 | | |
| 1854 | | assert(vertnum + m_poly[polynum].get_vertcount() <= m_numverts); |
| 1855 | | |
| 1856 | | if(m_shaders->enabled() && d3dintf->post_fx_available) |
| 1857 | | { |
| 1858 | | m_shaders->render_quad(&m_poly[polynum], vertnum); |
| 1859 | | } |
| 1860 | | else |
| 1861 | | { |
| 1862 | | // add the primitives |
| 1863 | | result = (*d3dintf->device.draw_primitive)(m_device, m_poly[polynum].get_type(), vertnum, |
| 1864 | | m_poly[polynum].get_count()); |
| 1865 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 1866 | | } |
| 1867 | | |
| 1868 | | vertnum += m_poly[polynum].get_vertcount(); |
| 1869 | | } |
| 1870 | | |
| 1871 | | m_shaders->end_draw(); |
| 1872 | | |
| 1873 | | // reset the vertex count |
| 1874 | | m_numverts = 0; |
| 1875 | | m_numpolys = 0; |
| 1876 | | } |
| 1877 | | |
| 1878 | | //============================================================ |
| 1879 | | // texture_info destructor |
| 1880 | | //============================================================ |
| 1881 | | |
| 1882 | | texture_info::~texture_info() |
| 1883 | | { |
| 1884 | | if (m_d3dfinaltex != NULL) |
| 1885 | | { |
| 1886 | | if (m_d3dtex == m_d3dfinaltex) |
| 1887 | | { |
| 1888 | | m_d3dtex = NULL; |
| 1889 | | } |
| 1890 | | (*d3dintf->texture.release)(m_d3dfinaltex); |
| 1891 | | m_d3dfinaltex = NULL; |
| 1892 | | } |
| 1893 | | if (m_d3dtex != NULL) |
| 1894 | | { |
| 1895 | | (*d3dintf->texture.release)(m_d3dtex); |
| 1896 | | m_d3dtex = NULL; |
| 1897 | | } |
| 1898 | | if (m_d3dsurface != NULL) |
| 1899 | | { |
| 1900 | | (*d3dintf->surface.release)(m_d3dsurface); |
| 1901 | | m_d3dsurface = NULL; |
| 1902 | | } |
| 1903 | | } |
| 1904 | | |
| 1905 | | //============================================================ |
| 1906 | | // texture_info constructor |
| 1907 | | //============================================================ |
| 1908 | | |
| 1909 | | texture_info::texture_info(texture_manager *manager, const render_texinfo* texsource, int prescale, UINT32 flags) |
| 1910 | | { |
| 1911 | | HRESULT result; |
| 1912 | | |
| 1913 | | // fill in the core data |
| 1914 | | m_texture_manager = manager; |
| 1915 | | m_renderer = m_texture_manager->get_d3d(); |
| 1916 | | m_hash = m_texture_manager->texture_compute_hash(texsource, flags); |
| 1917 | | m_flags = flags; |
| 1918 | | m_texinfo = *texsource; |
| 1919 | | m_xprescale = prescale; |
| 1920 | | m_yprescale = prescale; |
| 1921 | | |
| 1922 | | m_d3dtex = NULL; |
| 1923 | | m_d3dsurface = NULL; |
| 1924 | | m_d3dfinaltex = NULL; |
| 1925 | | |
| 1926 | | // compute the size |
| 1927 | | compute_size(texsource->width, texsource->height); |
| 1928 | | |
| 1929 | | // non-screen textures are easy |
| 1930 | | if (!PRIMFLAG_GET_SCREENTEX(flags)) |
| 1931 | | { |
| 1932 | | assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); |
| 1933 | | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex); |
| 1934 | | if (result != D3D_OK) |
| 1935 | | goto error; |
| 1936 | | m_d3dfinaltex = m_d3dtex; |
| 1937 | | m_type = TEXTURE_TYPE_PLAIN; |
| 1938 | | } |
| 1939 | | |
| 1940 | | // screen textures are allocated differently |
| 1941 | | else |
| 1942 | | { |
| 1943 | | D3DFORMAT format; |
| 1944 | | DWORD usage = m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0; |
| 1945 | | D3DPOOL pool = m_texture_manager->is_dynamic_supported() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; |
| 1946 | | int maxdim = MAX(m_renderer->get_presentation()->BackBufferWidth, m_renderer->get_presentation()->BackBufferHeight); |
| 1947 | | |
| 1948 | | // pick the format |
| 1949 | | if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_YUY16) |
| 1950 | | { |
| 1951 | | format = m_texture_manager->get_yuv_format(); |
| 1952 | | } |
| 1953 | | else if (PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_ARGB32 || PRIMFLAG_GET_TEXFORMAT(flags) == TEXFORMAT_PALETTEA16) |
| 1954 | | { |
| 1955 | | format = D3DFMT_A8R8G8B8; |
| 1956 | | } |
| 1957 | | else |
| 1958 | | { |
| 1959 | | format = m_renderer->get_screen_format(); |
| 1960 | | } |
| 1961 | | |
| 1962 | | // don't prescale above screen size |
| 1963 | | while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale >= 2 * maxdim) |
| 1964 | | { |
| 1965 | | m_xprescale--; |
| 1966 | | } |
| 1967 | | while (m_xprescale > 1 && m_rawdims.c.x * m_xprescale > manager->get_max_texture_width()) |
| 1968 | | { |
| 1969 | | m_xprescale--; |
| 1970 | | } |
| 1971 | | while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale >= 2 * maxdim) |
| 1972 | | { |
| 1973 | | m_yprescale--; |
| 1974 | | } |
| 1975 | | while (m_yprescale > 1 && m_rawdims.c.y * m_yprescale > manager->get_max_texture_height()) |
| 1976 | | { |
| 1977 | | m_yprescale--; |
| 1978 | | } |
| 1979 | | |
| 1980 | | int prescale = m_renderer->window().prescale(); |
| 1981 | | if (m_xprescale != prescale || m_yprescale != prescale) |
| 1982 | | { |
| 1983 | | osd_printf_verbose("Direct3D: adjusting prescale from %dx%d to %dx%d\n", prescale, prescale, m_xprescale, m_yprescale); |
| 1984 | | } |
| 1985 | | |
| 1986 | | // loop until we allocate something or error |
| 1987 | | for (int attempt = 0; attempt < 2; attempt++) |
| 1988 | | { |
| 1989 | | // second attempt is always 1:1 |
| 1990 | | if (attempt == 1) |
| 1991 | | { |
| 1992 | | m_xprescale = m_yprescale = 1; |
| 1993 | | } |
| 1994 | | |
| 1995 | | // screen textures with no prescaling are pretty easy |
| 1996 | | if (m_xprescale == 1 && m_yprescale == 1) |
| 1997 | | { |
| 1998 | | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); |
| 1999 | | if (result == D3D_OK) |
| 2000 | | { |
| 2001 | | m_d3dfinaltex = m_d3dtex; |
| 2002 | | m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; |
| 2003 | | if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this)) |
| 2004 | | { |
| 2005 | | goto error; |
| 2006 | | } |
| 2007 | | |
| 2008 | | break; |
| 2009 | | } |
| 2010 | | } |
| 2011 | | |
| 2012 | | // screen textures with prescaling require two allocations |
| 2013 | | else |
| 2014 | | { |
| 2015 | | // use an offscreen plain surface for stretching if supported |
| 2016 | | // (won't work for YUY textures) |
| 2017 | | if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) |
| 2018 | | { |
| 2019 | | result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface); |
| 2020 | | if (result != D3D_OK) |
| 2021 | | { |
| 2022 | | continue; |
| 2023 | | } |
| 2024 | | m_type = TEXTURE_TYPE_SURFACE; |
| 2025 | | } |
| 2026 | | |
| 2027 | | // otherwise, we allocate a dynamic texture for the source |
| 2028 | | else |
| 2029 | | { |
| 2030 | | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); |
| 2031 | | if (result != D3D_OK) |
| 2032 | | { |
| 2033 | | continue; |
| 2034 | | } |
| 2035 | | m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; |
| 2036 | | } |
| 2037 | | |
| 2038 | | // for the target surface, we allocate a render target texture |
| 2039 | | int scwidth = m_rawdims.c.x * m_xprescale; |
| 2040 | | int scheight = m_rawdims.c.y * m_yprescale; |
| 2041 | | |
| 2042 | | // target surfaces typically cannot be YCbCr, so we always pick RGB in that case |
| 2043 | | D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; |
| 2044 | | result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex); |
| 2045 | | if (result == D3D_OK) |
| 2046 | | { |
| 2047 | | if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this)) |
| 2048 | | { |
| 2049 | | goto error; |
| 2050 | | } |
| 2051 | | break; |
| 2052 | | } |
| 2053 | | (*d3dintf->texture.release)(m_d3dtex); |
| 2054 | | m_d3dtex = NULL; |
| 2055 | | } |
| 2056 | | } |
| 2057 | | } |
| 2058 | | |
| 2059 | | // copy the data to the texture |
| 2060 | | set_data(texsource, flags); |
| 2061 | | |
| 2062 | | //texsource->osdhandle = (void*)this; |
| 2063 | | // add us to the texture list |
| 2064 | | if(m_texture_manager->get_texlist() != NULL) |
| 2065 | | m_texture_manager->get_texlist()->m_prev = this; |
| 2066 | | m_prev = NULL; |
| 2067 | | m_next = m_texture_manager->get_texlist(); |
| 2068 | | m_texture_manager->set_texlist(this); |
| 2069 | | return; |
| 2070 | | |
| 2071 | | error: |
| 2072 | | d3dintf->post_fx_available = false; |
| 2073 | | osd_printf_error("Direct3D: Critical warning: A texture failed to allocate. Expect things to get bad quickly.\n"); |
| 2074 | | if (m_d3dsurface != NULL) |
| 2075 | | (*d3dintf->surface.release)(m_d3dsurface); |
| 2076 | | if (m_d3dtex != NULL) |
| 2077 | | (*d3dintf->texture.release)(m_d3dtex); |
| 2078 | | } |
| 2079 | | |
| 2080 | | |
| 2081 | | |
| 2082 | | //============================================================ |
| 2083 | | // texture_info::compute_size |
| 2084 | | //============================================================ |
| 2085 | | |
| 2086 | | void texture_info::compute_size(int texwidth, int texheight) |
| 2087 | | { |
| 2088 | | int finalheight = texheight; |
| 2089 | | int finalwidth = texwidth; |
| 2090 | | |
| 2091 | | // if we're not wrapping, add a 1-2 pixel border on all sides |
| 2092 | | m_xborderpix = 0; |
| 2093 | | m_yborderpix = 0; |
| 2094 | | if (ENABLE_BORDER_PIX && !(m_flags & PRIMFLAG_TEXWRAP_MASK)) |
| 2095 | | { |
| 2096 | | // note we need 2 pixels in X for YUY textures |
| 2097 | | m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; |
| 2098 | | m_yborderpix = 1; |
| 2099 | | } |
| 2100 | | |
| 2101 | | // compute final texture size |
| 2102 | | finalwidth += 2 * m_xborderpix; |
| 2103 | | finalheight += 2 * m_yborderpix; |
| 2104 | | |
| 2105 | | // round width/height up to nearest power of 2 if we need to |
| 2106 | | if (!(m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) |
| 2107 | | { |
| 2108 | | // first the width |
| 2109 | | if (finalwidth & (finalwidth - 1)) |
| 2110 | | { |
| 2111 | | finalwidth |= finalwidth >> 1; |
| 2112 | | finalwidth |= finalwidth >> 2; |
| 2113 | | finalwidth |= finalwidth >> 4; |
| 2114 | | finalwidth |= finalwidth >> 8; |
| 2115 | | finalwidth++; |
| 2116 | | } |
| 2117 | | |
| 2118 | | // then the height |
| 2119 | | if (finalheight & (finalheight - 1)) |
| 2120 | | { |
| 2121 | | finalheight |= finalheight >> 1; |
| 2122 | | finalheight |= finalheight >> 2; |
| 2123 | | finalheight |= finalheight >> 4; |
| 2124 | | finalheight |= finalheight >> 8; |
| 2125 | | finalheight++; |
| 2126 | | } |
| 2127 | | } |
| 2128 | | |
| 2129 | | // round up to square if we need to |
| 2130 | | if (m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY) |
| 2131 | | { |
| 2132 | | if (finalwidth < finalheight) |
| 2133 | | finalwidth = finalheight; |
| 2134 | | else |
| 2135 | | finalheight = finalwidth; |
| 2136 | | } |
| 2137 | | |
| 2138 | | // adjust the aspect ratio if we need to |
| 2139 | | while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) |
| 2140 | | { |
| 2141 | | finalwidth *= 2; |
| 2142 | | } |
| 2143 | | while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) |
| 2144 | | { |
| 2145 | | finalheight *= 2; |
| 2146 | | } |
| 2147 | | |
| 2148 | | // if we added pixels for the border, and that just barely pushed us over, take it back |
| 2149 | | if ((finalwidth > m_texture_manager->get_max_texture_width() && finalwidth - 2 * m_xborderpix <= m_texture_manager->get_max_texture_width()) || |
| 2150 | | (finalheight > m_texture_manager->get_max_texture_height() && finalheight - 2 * m_yborderpix <= m_texture_manager->get_max_texture_height())) |
| 2151 | | { |
| 2152 | | finalwidth -= 2 * m_xborderpix; |
| 2153 | | finalheight -= 2 * m_yborderpix; |
| 2154 | | m_xborderpix = 0; |
| 2155 | | m_yborderpix = 0; |
| 2156 | | } |
| 2157 | | |
| 2158 | | // if we're above the max width/height, do what? |
| 2159 | | if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) |
| 2160 | | { |
| 2161 | | static int printed = FALSE; |
| 2162 | | 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()); |
| 2163 | | printed = TRUE; |
| 2164 | | } |
| 2165 | | |
| 2166 | | // compute the U/V scale factors |
| 2167 | | m_start.c.x = (float)m_xborderpix / (float)finalwidth; |
| 2168 | | m_start.c.y = (float)m_yborderpix / (float)finalheight; |
| 2169 | | m_stop.c.x = (float)(texwidth + m_xborderpix) / (float)finalwidth; |
| 2170 | | m_stop.c.y = (float)(texheight + m_yborderpix) / (float)finalheight; |
| 2171 | | |
| 2172 | | // set the final values |
| 2173 | | m_rawdims.c.x = finalwidth; |
| 2174 | | m_rawdims.c.y = finalheight; |
| 2175 | | } |
| 2176 | | |
| 2177 | | |
| 2178 | | |
| 2179 | | //============================================================ |
| 2180 | | // copyline_palette16 |
| 2181 | | //============================================================ |
| 2182 | | |
| 2183 | | INLINE void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2184 | | { |
| 2185 | | int x; |
| 2186 | | |
| 2187 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2188 | | if (xborderpix) |
| 2189 | | *dst++ = 0xff000000 | palette[*src]; |
| 2190 | | for (x = 0; x < width; x++) |
| 2191 | | *dst++ = 0xff000000 | palette[*src++]; |
| 2192 | | if (xborderpix) |
| 2193 | | *dst++ = 0xff000000 | palette[*--src]; |
| 2194 | | } |
| 2195 | | |
| 2196 | | |
| 2197 | | |
| 2198 | | //============================================================ |
| 2199 | | // copyline_palettea16 |
| 2200 | | //============================================================ |
| 2201 | | |
| 2202 | | INLINE void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2203 | | { |
| 2204 | | int x; |
| 2205 | | |
| 2206 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2207 | | if (xborderpix) |
| 2208 | | *dst++ = palette[*src]; |
| 2209 | | for (x = 0; x < width; x++) |
| 2210 | | *dst++ = palette[*src++]; |
| 2211 | | if (xborderpix) |
| 2212 | | *dst++ = palette[*--src]; |
| 2213 | | } |
| 2214 | | |
| 2215 | | |
| 2216 | | |
| 2217 | | //============================================================ |
| 2218 | | // copyline_rgb32 |
| 2219 | | //============================================================ |
| 2220 | | |
| 2221 | | INLINE void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix) |
| 2222 | | { |
| 2223 | | int x; |
| 2224 | | |
| 2225 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2226 | | |
| 2227 | | // palette (really RGB map) case |
| 2228 | | if (palette != NULL) |
| 2229 | | { |
| 2230 | | if (xborderpix) |
| 2231 | | { |
| 2232 | | rgb_t srcpix = *src; |
| 2233 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2234 | | } |
| 2235 | | for (x = 0; x < width; x++) |
| 2236 | | { |
| 2237 | | rgb_t srcpix = *src++; |
| 2238 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2239 | | } |
| 2240 | | if (xborderpix) |
| 2241 | | { |
| 2242 | | rgb_t srcpix = *--src; |
| 2243 | | *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2244 | | } |
| 2245 | | } |
| 2246 | | |
| 2247 | | // direct case |
| 2248 | | else |
| 2249 | | { |
| 2250 | | if (xborderpix) |
| 2251 | | *dst++ = 0xff000000 | *src; |
| 2252 | | for (x = 0; x < width; x++) |
| 2253 | | *dst++ = 0xff000000 | *src++; |
| 2254 | | if (xborderpix) |
| 2255 | | *dst++ = 0xff000000 | *--src; |
| 2256 | | } |
| 2257 | | } |
| 2258 | | |
| 2259 | | |
| 2260 | | |
| 2261 | | //============================================================ |
| 2262 | | // copyline_argb32 |
| 2263 | | //============================================================ |
| 2264 | | |
| 2265 | | INLINE void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette, int xborderpix) |
| 2266 | | { |
| 2267 | | int x; |
| 2268 | | |
| 2269 | | assert(xborderpix == 0 || xborderpix == 1); |
| 2270 | | |
| 2271 | | // palette (really RGB map) case |
| 2272 | | if (palette != NULL) |
| 2273 | | { |
| 2274 | | if (xborderpix) |
| 2275 | | { |
| 2276 | | rgb_t srcpix = *src; |
| 2277 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2278 | | } |
| 2279 | | for (x = 0; x < width; x++) |
| 2280 | | { |
| 2281 | | rgb_t srcpix = *src++; |
| 2282 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2283 | | } |
| 2284 | | if (xborderpix) |
| 2285 | | { |
| 2286 | | rgb_t srcpix = *--src; |
| 2287 | | *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()]; |
| 2288 | | } |
| 2289 | | } |
| 2290 | | |
| 2291 | | // direct case |
| 2292 | | else |
| 2293 | | { |
| 2294 | | if (xborderpix) |
| 2295 | | *dst++ = *src; |
| 2296 | | for (x = 0; x < width; x++) |
| 2297 | | *dst++ = *src++; |
| 2298 | | if (xborderpix) |
| 2299 | | *dst++ = *--src; |
| 2300 | | } |
| 2301 | | } |
| 2302 | | |
| 2303 | | |
| 2304 | | |
| 2305 | | //============================================================ |
| 2306 | | // copyline_yuy16_to_yuy2 |
| 2307 | | //============================================================ |
| 2308 | | |
| 2309 | | INLINE void copyline_yuy16_to_yuy2(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2310 | | { |
| 2311 | | int x; |
| 2312 | | |
| 2313 | | assert(xborderpix == 0 || xborderpix == 2); |
| 2314 | | assert(width % 2 == 0); |
| 2315 | | |
| 2316 | | // palette (really RGB map) case |
| 2317 | | if (palette != NULL) |
| 2318 | | { |
| 2319 | | if (xborderpix) |
| 2320 | | { |
| 2321 | | UINT16 srcpix0 = *src++; |
| 2322 | | UINT16 srcpix1 = *src--; |
| 2323 | | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8); |
| 2324 | | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix1 << 8); |
| 2325 | | } |
| 2326 | | for (x = 0; x < width; x += 2) |
| 2327 | | { |
| 2328 | | UINT16 srcpix0 = *src++; |
| 2329 | | UINT16 srcpix1 = *src++; |
| 2330 | | *dst++ = palette[0x000 + (srcpix0 >> 8)] | (srcpix0 << 8); |
| 2331 | | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8); |
| 2332 | | } |
| 2333 | | if (xborderpix) |
| 2334 | | { |
| 2335 | | UINT16 srcpix1 = *--src; |
| 2336 | | UINT16 srcpix0 = *--src; |
| 2337 | | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix0 << 8); |
| 2338 | | *dst++ = palette[0x000 + (srcpix1 >> 8)] | (srcpix1 << 8); |
| 2339 | | } |
| 2340 | | } |
| 2341 | | |
| 2342 | | // direct case |
| 2343 | | else |
| 2344 | | { |
| 2345 | | if (xborderpix) |
| 2346 | | { |
| 2347 | | UINT16 srcpix0 = *src++; |
| 2348 | | UINT16 srcpix1 = *src--; |
| 2349 | | *dst++ = (srcpix0 >> 8) | (srcpix0 << 8); |
| 2350 | | *dst++ = (srcpix0 >> 8) | (srcpix1 << 8); |
| 2351 | | } |
| 2352 | | for (x = 0; x < width; x += 2) |
| 2353 | | { |
| 2354 | | UINT16 srcpix0 = *src++; |
| 2355 | | UINT16 srcpix1 = *src++; |
| 2356 | | *dst++ = (srcpix0 >> 8) | (srcpix0 << 8); |
| 2357 | | *dst++ = (srcpix1 >> 8) | (srcpix1 << 8); |
| 2358 | | } |
| 2359 | | if (xborderpix) |
| 2360 | | { |
| 2361 | | UINT16 srcpix1 = *--src; |
| 2362 | | UINT16 srcpix0 = *--src; |
| 2363 | | *dst++ = (srcpix1 >> 8) | (srcpix0 << 8); |
| 2364 | | *dst++ = (srcpix1 >> 8) | (srcpix1 << 8); |
| 2365 | | } |
| 2366 | | } |
| 2367 | | } |
| 2368 | | |
| 2369 | | |
| 2370 | | |
| 2371 | | //============================================================ |
| 2372 | | // copyline_yuy16_to_uyvy |
| 2373 | | //============================================================ |
| 2374 | | |
| 2375 | | INLINE void copyline_yuy16_to_uyvy(UINT16 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2376 | | { |
| 2377 | | int x; |
| 2378 | | |
| 2379 | | assert(xborderpix == 0 || xborderpix == 2); |
| 2380 | | assert(width % 2 == 0); |
| 2381 | | |
| 2382 | | // palette (really RGB map) case |
| 2383 | | if (palette != NULL) |
| 2384 | | { |
| 2385 | | if (xborderpix) |
| 2386 | | { |
| 2387 | | UINT16 srcpix0 = *src++; |
| 2388 | | UINT16 srcpix1 = *src--; |
| 2389 | | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff); |
| 2390 | | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix1 & 0xff); |
| 2391 | | } |
| 2392 | | for (x = 0; x < width; x += 2) |
| 2393 | | { |
| 2394 | | UINT16 srcpix0 = *src++; |
| 2395 | | UINT16 srcpix1 = *src++; |
| 2396 | | *dst++ = palette[0x100 + (srcpix0 >> 8)] | (srcpix0 & 0xff); |
| 2397 | | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff); |
| 2398 | | } |
| 2399 | | if (xborderpix) |
| 2400 | | { |
| 2401 | | UINT16 srcpix1 = *--src; |
| 2402 | | UINT16 srcpix0 = *--src; |
| 2403 | | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix0 & 0xff); |
| 2404 | | *dst++ = palette[0x100 + (srcpix1 >> 8)] | (srcpix1 & 0xff); |
| 2405 | | } |
| 2406 | | } |
| 2407 | | |
| 2408 | | // direct case |
| 2409 | | else |
| 2410 | | { |
| 2411 | | if (xborderpix) |
| 2412 | | { |
| 2413 | | UINT16 srcpix0 = src[0]; |
| 2414 | | UINT16 srcpix1 = src[1]; |
| 2415 | | *dst++ = srcpix0; |
| 2416 | | *dst++ = (srcpix0 & 0xff00) | (srcpix1 & 0x00ff); |
| 2417 | | } |
| 2418 | | for (x = 0; x < width; x += 2) |
| 2419 | | { |
| 2420 | | *dst++ = *src++; |
| 2421 | | *dst++ = *src++; |
| 2422 | | } |
| 2423 | | if (xborderpix) |
| 2424 | | { |
| 2425 | | UINT16 srcpix1 = *--src; |
| 2426 | | UINT16 srcpix0 = *--src; |
| 2427 | | *dst++ = (srcpix1 & 0xff00) | (srcpix0 & 0x00ff); |
| 2428 | | *dst++ = srcpix1; |
| 2429 | | } |
| 2430 | | } |
| 2431 | | } |
| 2432 | | |
| 2433 | | |
| 2434 | | |
| 2435 | | //============================================================ |
| 2436 | | // copyline_yuy16_to_argb |
| 2437 | | //============================================================ |
| 2438 | | |
| 2439 | | INLINE void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xborderpix) |
| 2440 | | { |
| 2441 | | int x; |
| 2442 | | |
| 2443 | | assert(xborderpix == 0 || xborderpix == 2); |
| 2444 | | assert(width % 2 == 0); |
| 2445 | | |
| 2446 | | // palette (really RGB map) case |
| 2447 | | if (palette != NULL) |
| 2448 | | { |
| 2449 | | if (xborderpix) |
| 2450 | | { |
| 2451 | | UINT16 srcpix0 = src[0]; |
| 2452 | | UINT16 srcpix1 = src[1]; |
| 2453 | | UINT8 cb = srcpix0 & 0xff; |
| 2454 | | UINT8 cr = srcpix1 & 0xff; |
| 2455 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2456 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2457 | | } |
| 2458 | | for (x = 0; x < width / 2; x++) |
| 2459 | | { |
| 2460 | | UINT16 srcpix0 = *src++; |
| 2461 | | UINT16 srcpix1 = *src++; |
| 2462 | | UINT8 cb = srcpix0 & 0xff; |
| 2463 | | UINT8 cr = srcpix1 & 0xff; |
| 2464 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); |
| 2465 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2466 | | } |
| 2467 | | if (xborderpix) |
| 2468 | | { |
| 2469 | | UINT16 srcpix1 = *--src; |
| 2470 | | UINT16 srcpix0 = *--src; |
| 2471 | | UINT8 cb = srcpix0 & 0xff; |
| 2472 | | UINT8 cr = srcpix1 & 0xff; |
| 2473 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2474 | | *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); |
| 2475 | | } |
| 2476 | | } |
| 2477 | | |
| 2478 | | // direct case |
| 2479 | | else |
| 2480 | | { |
| 2481 | | if (xborderpix) |
| 2482 | | { |
| 2483 | | UINT16 srcpix0 = src[0]; |
| 2484 | | UINT16 srcpix1 = src[1]; |
| 2485 | | UINT8 cb = srcpix0 & 0xff; |
| 2486 | | UINT8 cr = srcpix1 & 0xff; |
| 2487 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2488 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2489 | | } |
| 2490 | | for (x = 0; x < width; x += 2) |
| 2491 | | { |
| 2492 | | UINT16 srcpix0 = *src++; |
| 2493 | | UINT16 srcpix1 = *src++; |
| 2494 | | UINT8 cb = srcpix0 & 0xff; |
| 2495 | | UINT8 cr = srcpix1 & 0xff; |
| 2496 | | *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); |
| 2497 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2498 | | } |
| 2499 | | if (xborderpix) |
| 2500 | | { |
| 2501 | | UINT16 srcpix1 = *--src; |
| 2502 | | UINT16 srcpix0 = *--src; |
| 2503 | | UINT8 cb = srcpix0 & 0xff; |
| 2504 | | UINT8 cr = srcpix1 & 0xff; |
| 2505 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2506 | | *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); |
| 2507 | | } |
| 2508 | | } |
| 2509 | | } |
| 2510 | | |
| 2511 | | |
| 2512 | | |
| 2513 | | //============================================================ |
| 2514 | | // texture_set_data |
| 2515 | | //============================================================ |
| 2516 | | |
| 2517 | | void texture_info::set_data(const render_texinfo *texsource, UINT32 flags) |
| 2518 | | { |
| 2519 | | D3DLOCKED_RECT rect; |
| 2520 | | HRESULT result; |
| 2521 | | |
| 2522 | | // lock the texture |
| 2523 | | switch (m_type) |
| 2524 | | { |
| 2525 | | default: |
| 2526 | | case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, 0); break; |
| 2527 | | case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.lock_rect)(m_d3dtex, 0, &rect, NULL, D3DLOCK_DISCARD); break; |
| 2528 | | case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.lock_rect)(m_d3dsurface, &rect, NULL, D3DLOCK_DISCARD); break; |
| 2529 | | } |
| 2530 | | if (result != D3D_OK) |
| 2531 | | { |
| 2532 | | return; |
| 2533 | | } |
| 2534 | | |
| 2535 | | // loop over Y |
| 2536 | | int miny = 0 - m_yborderpix; |
| 2537 | | int maxy = texsource->height + m_yborderpix; |
| 2538 | | for (int dsty = miny; dsty < maxy; dsty++) |
| 2539 | | { |
| 2540 | | int srcy = (dsty < 0) ? 0 : (dsty >= texsource->height) ? texsource->height - 1 : dsty; |
| 2541 | | void *dst = (BYTE *)rect.pBits + (dsty + m_yborderpix) * rect.Pitch; |
| 2542 | | |
| 2543 | | // switch off of the format and |
| 2544 | | switch (PRIMFLAG_GET_TEXFORMAT(flags)) |
| 2545 | | { |
| 2546 | | case TEXFORMAT_PALETTE16: |
| 2547 | | copyline_palette16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2548 | | break; |
| 2549 | | |
| 2550 | | case TEXFORMAT_PALETTEA16: |
| 2551 | | copyline_palettea16((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2552 | | break; |
| 2553 | | |
| 2554 | | case TEXFORMAT_RGB32: |
| 2555 | | copyline_rgb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2556 | | break; |
| 2557 | | |
| 2558 | | case TEXFORMAT_ARGB32: |
| 2559 | | copyline_argb32((UINT32 *)dst, (UINT32 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2560 | | break; |
| 2561 | | |
| 2562 | | case TEXFORMAT_YUY16: |
| 2563 | | if (m_texture_manager->get_yuv_format() == D3DFMT_YUY2) |
| 2564 | | copyline_yuy16_to_yuy2((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2565 | | else if (m_texture_manager->get_yuv_format() == D3DFMT_UYVY) |
| 2566 | | copyline_yuy16_to_uyvy((UINT16 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2567 | | else |
| 2568 | | copyline_yuy16_to_argb((UINT32 *)dst, (UINT16 *)texsource->base + srcy * texsource->rowpixels, texsource->width, texsource->palette, m_xborderpix); |
| 2569 | | break; |
| 2570 | | |
| 2571 | | default: |
| 2572 | | osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags)); |
| 2573 | | break; |
| 2574 | | } |
| 2575 | | } |
| 2576 | | |
| 2577 | | // unlock |
| 2578 | | switch (m_type) |
| 2579 | | { |
| 2580 | | default: |
| 2581 | | case TEXTURE_TYPE_PLAIN: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break; |
| 2582 | | case TEXTURE_TYPE_DYNAMIC: result = (*d3dintf->texture.unlock_rect)(m_d3dtex, 0); break; |
| 2583 | | case TEXTURE_TYPE_SURFACE: result = (*d3dintf->surface.unlock_rect)(m_d3dsurface); break; |
| 2584 | | } |
| 2585 | | if (result != D3D_OK) |
| 2586 | | { |
| 2587 | | osd_printf_verbose("Direct3D: Error %08X during texture unlock_rect call\n", (int)result); |
| 2588 | | } |
| 2589 | | |
| 2590 | | // prescale |
| 2591 | | prescale(); |
| 2592 | | } |
| 2593 | | |
| 2594 | | |
| 2595 | | |
| 2596 | | //============================================================ |
| 2597 | | // texture_info::prescale |
| 2598 | | //============================================================ |
| 2599 | | |
| 2600 | | void texture_info::prescale() |
| 2601 | | { |
| 2602 | | surface *scale_surface; |
| 2603 | | HRESULT result; |
| 2604 | | int i; |
| 2605 | | |
| 2606 | | // if we don't need to, just skip it |
| 2607 | | if (m_d3dtex == m_d3dfinaltex) |
| 2608 | | return; |
| 2609 | | |
| 2610 | | // for all cases, we need to get the surface of the render target |
| 2611 | | result = (*d3dintf->texture.get_surface_level)(m_d3dfinaltex, 0, &scale_surface); |
| 2612 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during texture get_surface_level call\n", (int)result); |
| 2613 | | |
| 2614 | | // if we have an offscreen plain surface, we can just StretchRect to it |
| 2615 | | if (m_type == TEXTURE_TYPE_SURFACE) |
| 2616 | | { |
| 2617 | | assert(m_d3dsurface != NULL); |
| 2618 | | |
| 2619 | | // set the source bounds |
| 2620 | | RECT source; |
| 2621 | | source.left = source.top = 0; |
| 2622 | | source.right = m_texinfo.width + 2 * m_xborderpix; |
| 2623 | | source.bottom = m_texinfo.height + 2 * m_yborderpix; |
| 2624 | | |
| 2625 | | // set the target bounds |
| 2626 | | RECT dest; |
| 2627 | | dest = source; |
| 2628 | | dest.right *= m_xprescale; |
| 2629 | | dest.bottom *= m_yprescale; |
| 2630 | | |
| 2631 | | // do the stretchrect |
| 2632 | | result = (*d3dintf->device.stretch_rect)(m_renderer->get_device(), m_d3dsurface, &source, scale_surface, &dest, D3DTEXF_POINT); |
| 2633 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device stretct_rect call\n", (int)result); |
| 2634 | | } |
| 2635 | | |
| 2636 | | // if we are using a texture render target, we need to do more preparations |
| 2637 | | else |
| 2638 | | { |
| 2639 | | surface *backbuffer; |
| 2640 | | |
| 2641 | | assert(m_d3dtex != NULL); |
| 2642 | | |
| 2643 | | // first remember the original render target and set the new one |
| 2644 | | result = (*d3dintf->device.get_render_target)(m_renderer->get_device(), 0, &backbuffer); |
| 2645 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device get_render_target call\n", (int)result); |
| 2646 | | result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, scale_surface); |
| 2647 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 1\n", (int)result); |
| 2648 | | m_renderer->reset_render_states(); |
| 2649 | | |
| 2650 | | // start the scene |
| 2651 | | result = (*d3dintf->device.begin_scene)(m_renderer->get_device()); |
| 2652 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device begin_scene call\n", (int)result); |
| 2653 | | |
| 2654 | | // configure the rendering pipeline |
| 2655 | | m_renderer->set_filter(FALSE); |
| 2656 | | m_renderer->set_blendmode(BLENDMODE_NONE); |
| 2657 | | result = (*d3dintf->device.set_texture)(m_renderer->get_device(), 0, m_d3dtex); |
| 2658 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_texture call\n", (int)result); |
| 2659 | | |
| 2660 | | // lock the vertex buffer |
| 2661 | | result = (*d3dintf->vertexbuf.lock)(m_renderer->get_vertex_buffer(), 0, 0, m_renderer->get_locked_buffer_ptr(), D3DLOCK_DISCARD); |
| 2662 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer lock call\n", (int)result); |
| 2663 | | |
| 2664 | | // configure the X/Y coordinates on the target surface |
| 2665 | | vertex *lockedbuf = m_renderer->get_locked_buffer(); |
| 2666 | | lockedbuf[0].x = -0.5f; |
| 2667 | | lockedbuf[0].y = -0.5f; |
| 2668 | | lockedbuf[1].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; |
| 2669 | | lockedbuf[1].y = -0.5f; |
| 2670 | | lockedbuf[2].x = -0.5f; |
| 2671 | | lockedbuf[2].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; |
| 2672 | | lockedbuf[3].x = (float)((m_texinfo.width + 2 * m_xborderpix) * m_xprescale) - 0.5f; |
| 2673 | | lockedbuf[3].y = (float)((m_texinfo.height + 2 * m_yborderpix) * m_yprescale) - 0.5f; |
| 2674 | | |
| 2675 | | // configure the U/V coordintes on the source texture |
| 2676 | | lockedbuf[0].u0 = 0.0f; |
| 2677 | | lockedbuf[0].v0 = 0.0f; |
| 2678 | | lockedbuf[1].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; |
| 2679 | | lockedbuf[1].v0 = 0.0f; |
| 2680 | | lockedbuf[2].u0 = 0.0f; |
| 2681 | | lockedbuf[2].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; |
| 2682 | | lockedbuf[3].u0 = (float)(m_texinfo.width + 2 * m_xborderpix) / (float)m_rawdims.c.x; |
| 2683 | | lockedbuf[3].v0 = (float)(m_texinfo.height + 2 * m_yborderpix) / (float)m_rawdims.c.y; |
| 2684 | | |
| 2685 | | // reset the remaining vertex parameters |
| 2686 | | for (i = 0; i < 4; i++) |
| 2687 | | { |
| 2688 | | lockedbuf[i].z = 0.0f; |
| 2689 | | lockedbuf[i].rhw = 1.0f; |
| 2690 | | lockedbuf[i].color = D3DCOLOR_ARGB(0xff,0xff,0xff,0xff); |
| 2691 | | } |
| 2692 | | |
| 2693 | | // unlock the vertex buffer |
| 2694 | | result = (*d3dintf->vertexbuf.unlock)(m_renderer->get_vertex_buffer()); |
| 2695 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during vertex buffer unlock call\n", (int)result); |
| 2696 | | m_renderer->set_locked_buffer(NULL); |
| 2697 | | |
| 2698 | | // set the stream and draw the triangle strip |
| 2699 | | result = (*d3dintf->device.set_stream_source)(m_renderer->get_device(), 0, m_renderer->get_vertex_buffer(), sizeof(vertex)); |
| 2700 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_stream_source call\n", (int)result); |
| 2701 | | result = (*d3dintf->device.draw_primitive)(m_renderer->get_device(), D3DPT_TRIANGLESTRIP, 0, 2); |
| 2702 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device draw_primitive call\n", (int)result); |
| 2703 | | |
| 2704 | | // end the scene |
| 2705 | | result = (*d3dintf->device.end_scene)(m_renderer->get_device()); |
| 2706 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device end_scene call\n", (int)result); |
| 2707 | | |
| 2708 | | // reset the render target and release our reference to the backbuffer |
| 2709 | | result = (*d3dintf->device.set_render_target)(m_renderer->get_device(), 0, backbuffer); |
| 2710 | | if (result != D3D_OK) osd_printf_verbose("Direct3D: Error %08X during device set_render_target call 2\n", (int)result); |
| 2711 | | (*d3dintf->surface.release)(backbuffer); |
| 2712 | | m_renderer->reset_render_states(); |
| 2713 | | } |
| 2714 | | |
| 2715 | | // release our reference to the target surface |
| 2716 | | (*d3dintf->surface.release)(scale_surface); |
| 2717 | | } |
| 2718 | | |
| 2719 | | |
| 2720 | | //============================================================ |
| 2721 | | // cache_target::~cache_target |
| 2722 | | //============================================================ |
| 2723 | | |
| 2724 | | cache_target::~cache_target() |
| 2725 | | { |
| 2726 | | for (int index = 0; index < 11; index++) |
| 2727 | | { |
| 2728 | | if (bloom_texture[index] != NULL) |
| 2729 | | { |
| 2730 | | (*d3dintf->texture.release)(bloom_texture[index]); |
| 2731 | | bloom_texture[index] = NULL; |
| 2732 | | } |
| 2733 | | if (bloom_target[index] != NULL) |
| 2734 | | { |
| 2735 | | (*d3dintf->surface.release)(bloom_target[index]); |
| 2736 | | bloom_target[index] = NULL; |
| 2737 | | } |
| 2738 | | } |
| 2739 | | |
| 2740 | | if (last_texture != NULL) |
| 2741 | | { |
| 2742 | | (*d3dintf->texture.release)(last_texture); |
| 2743 | | last_texture = NULL; |
| 2744 | | } |
| 2745 | | if (last_target != NULL) |
| 2746 | | { |
| 2747 | | (*d3dintf->surface.release)(last_target); |
| 2748 | | last_target = NULL; |
| 2749 | | } |
| 2750 | | } |
| 2751 | | |
| 2752 | | |
| 2753 | | //============================================================ |
| 2754 | | // cache_target::init - initializes a target cache |
| 2755 | | //============================================================ |
| 2756 | | |
| 2757 | | bool cache_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) |
| 2758 | | { |
| 2759 | | int bloom_size = (width < height) ? width : height; |
| 2760 | | int bloom_index = 0; |
| 2761 | | int bloom_width = width; |
| 2762 | | int bloom_height = height; |
| 2763 | | for (; bloom_size >= 2 && bloom_index < 11; bloom_size >>= 1) |
| 2764 | | { |
| 2765 | | bloom_width >>= 1; |
| 2766 | | bloom_height >>= 1; |
| 2767 | | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), bloom_width, bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]); |
| 2768 | | if (result != D3D_OK) |
| 2769 | | { |
| 2770 | | return false; |
| 2771 | | } |
| 2772 | | (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); |
| 2773 | | bloom_index++; |
| 2774 | | } |
| 2775 | | |
| 2776 | | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture); |
| 2777 | | if (result != D3D_OK) |
| 2778 | | return false; |
| 2779 | | (*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target); |
| 2780 | | |
| 2781 | | target_width = width * prescale_x; |
| 2782 | | target_height = height * prescale_y; |
| 2783 | | |
| 2784 | | return true; |
| 2785 | | } |
| 2786 | | |
| 2787 | | //============================================================ |
| 2788 | | // render_target::~render_target |
| 2789 | | //============================================================ |
| 2790 | | |
| 2791 | | render_target::~render_target() |
| 2792 | | { |
| 2793 | | for (int index = 0; index < 11; index++) |
| 2794 | | { |
| 2795 | | if (bloom_texture[index] != NULL) |
| 2796 | | { |
| 2797 | | (*d3dintf->texture.release)(bloom_texture[index]); |
| 2798 | | bloom_texture[index] = NULL; |
| 2799 | | } |
| 2800 | | if (bloom_target[index] != NULL) |
| 2801 | | { |
| 2802 | | (*d3dintf->surface.release)(bloom_target[index]); |
| 2803 | | bloom_target[index] = NULL; |
| 2804 | | } |
| 2805 | | } |
| 2806 | | |
| 2807 | | for (int index = 0; index < 5; index++) |
| 2808 | | { |
| 2809 | | if (render_texture[index] != NULL) |
| 2810 | | { |
| 2811 | | (*d3dintf->texture.release)(render_texture[index]); |
| 2812 | | render_texture[index] = NULL; |
| 2813 | | } |
| 2814 | | if (target[index] != NULL) |
| 2815 | | { |
| 2816 | | (*d3dintf->surface.release)(target[index]); |
| 2817 | | target[index] = NULL; |
| 2818 | | } |
| 2819 | | } |
| 2820 | | |
| 2821 | | if (prescaletexture != NULL) |
| 2822 | | { |
| 2823 | | (*d3dintf->texture.release)(prescaletexture); |
| 2824 | | prescaletexture = NULL; |
| 2825 | | } |
| 2826 | | if (prescaletarget != NULL) |
| 2827 | | { |
| 2828 | | (*d3dintf->surface.release)(prescaletarget); |
| 2829 | | prescaletarget = NULL; |
| 2830 | | } |
| 2831 | | |
| 2832 | | if (smalltexture != NULL) |
| 2833 | | { |
| 2834 | | (*d3dintf->texture.release)(smalltexture); |
| 2835 | | smalltexture = NULL; |
| 2836 | | } |
| 2837 | | if (smalltarget != NULL) |
| 2838 | | { |
| 2839 | | (*d3dintf->surface.release)(smalltarget); |
| 2840 | | smalltarget = NULL; |
| 2841 | | } |
| 2842 | | } |
| 2843 | | |
| 2844 | | |
| 2845 | | //============================================================ |
| 2846 | | // render_target::init - initializes a render target |
| 2847 | | //============================================================ |
| 2848 | | |
| 2849 | | bool render_target::init(renderer *d3d, base *d3dintf, int width, int height, int prescale_x, int prescale_y) |
| 2850 | | { |
| 2851 | | D3DFORMAT format = D3DFMT_A8R8G8B8; |
| 2852 | | |
| 2853 | | HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[0]); |
| 2854 | | if (result != D3D_OK) |
| 2855 | | return false; |
| 2856 | | (*d3dintf->texture.get_surface_level)(render_texture[0], 0, &target[0]); |
| 2857 | | |
| 2858 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[1]); |
| 2859 | | if (result != D3D_OK) |
| 2860 | | return false; |
| 2861 | | (*d3dintf->texture.get_surface_level)(render_texture[1], 0, &target[1]); |
| 2862 | | |
| 2863 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &render_texture[2]); |
| 2864 | | if (result != D3D_OK) |
| 2865 | | return false; |
| 2866 | | (*d3dintf->texture.get_surface_level)(render_texture[2], 0, &target[2]); |
| 2867 | | |
| 2868 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[3]); |
| 2869 | | if (result != D3D_OK) |
| 2870 | | return false; |
| 2871 | | (*d3dintf->texture.get_surface_level)(render_texture[3], 0, &target[3]); |
| 2872 | | |
| 2873 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &render_texture[4]); |
| 2874 | | if (result != D3D_OK) |
| 2875 | | return false; |
| 2876 | | (*d3dintf->texture.get_surface_level)(render_texture[4], 0, &target[4]); |
| 2877 | | |
| 2878 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &smalltexture); |
| 2879 | | if (result != D3D_OK) |
| 2880 | | return false; |
| 2881 | | (*d3dintf->texture.get_surface_level)(smalltexture, 0, &smalltarget); |
| 2882 | | |
| 2883 | | result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &prescaletexture); |
| 2884 | | if (result != D3D_OK) |
| 2885 | | return false; |
| 2886 | | (*d3dintf->texture.get_surface_level)(prescaletexture, 0, &prescaletarget); |
| 2887 | | |
| 2888 | | float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); |
| 2889 | | int bloom_index = 0; |
| 2890 | | float bloom_width = d3d->get_width(); |
| 2891 | | float bloom_height = d3d->get_height(); |
| 2892 | | for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) |
| 2893 | | { |
| 2894 | | bloom_width *= 0.5f; |
| 2895 | | bloom_height *= 0.5f; |
| 2896 | | 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]); |
| 2897 | | if (result != D3D_OK) |
| 2898 | | return false; |
| 2899 | | (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); |
| 2900 | | bloom_index++; |
| 2901 | | } |
| 2902 | | |
| 2903 | | this->width = width; |
| 2904 | | this->height = height; |
| 2905 | | |
| 2906 | | target_width = width * prescale_x; |
| 2907 | | target_height = height * prescale_y; |
| 2908 | | |
| 2909 | | return true; |
| 2910 | | } |
| 2911 | | |
| 2912 | | }; |
trunk/src/osd/windows/drawdd.c
| r244651 | r244652 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Aaron Giles |
| 3 | | //============================================================ |
| 4 | | // |
| 5 | | // drawdd.c - Win32 DirectDraw implementation |
| 6 | | // |
| 7 | | //============================================================ |
| 8 | | |
| 9 | | // standard windows headers |
| 10 | | #define WIN32_LEAN_AND_MEAN |
| 11 | | #include <windows.h> |
| 12 | | #include <mmsystem.h> |
| 13 | | #include <ddraw.h> |
| 14 | | #undef interface |
| 15 | | |
| 16 | | // MAME headers |
| 17 | | #include "emu.h" |
| 18 | | #include "render.h" |
| 19 | | #include "rendutil.h" |
| 20 | | #include "options.h" |
| 21 | | #include "rendersw.inc" |
| 22 | | |
| 23 | | // MAMEOS headers |
| 24 | | #include "winmain.h" |
| 25 | | #include "window.h" |
| 26 | | #include "config.h" |
| 27 | | |
| 28 | | |
| 29 | | |
| 30 | | //============================================================ |
| 31 | | // TYPE DEFINITIONS |
| 32 | | //============================================================ |
| 33 | | |
| 34 | | typedef HRESULT (WINAPI *directdrawcreateex_ptr)(GUID FAR *lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); |
| 35 | | typedef HRESULT (WINAPI *directdrawenumerateex_ptr)(LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); |
| 36 | | |
| 37 | | |
| 38 | | /* dd_info is the information about DirectDraw for the current screen */ |
| 39 | | class renderer_dd : public osd_renderer |
| 40 | | { |
| 41 | | public: |
| 42 | | renderer_dd(osd_window *window) |
| 43 | | : osd_renderer(window, FLAG_NONE), |
| 44 | | //adapter(0), |
| 45 | | adapter_ptr(NULL), |
| 46 | | clearouter(0), |
| 47 | | blitwidth(0), blitheight(0), |
| 48 | | //lastdest |
| 49 | | ddraw(NULL), |
| 50 | | primary(NULL), |
| 51 | | back(NULL), |
| 52 | | blit(NULL), |
| 53 | | clipper(NULL), |
| 54 | | gamma(NULL), |
| 55 | | //DDSURFACEDESC2 primarydesc; |
| 56 | | //DDSURFACEDESC2 blitdesc; |
| 57 | | //DDSURFACEDESC2 origmode; |
| 58 | | //ddcaps(0), |
| 59 | | //helcaps(0), |
| 60 | | membuffer(NULL), |
| 61 | | membuffersize(0) |
| 62 | | { } |
| 63 | | |
| 64 | | virtual ~renderer_dd() { } |
| 65 | | |
| 66 | | virtual int create(); |
| 67 | | virtual render_primitive_list *get_primitives(); |
| 68 | | virtual int draw(const int update); |
| 69 | | virtual void save() {}; |
| 70 | | virtual void record() {}; |
| 71 | | virtual void toggle_fsfx() {}; |
| 72 | | virtual void destroy(); |
| 73 | | |
| 74 | | int width, height; // current width, height |
| 75 | | int refresh; // current refresh rate |
| 76 | | |
| 77 | | private: |
| 78 | | |
| 79 | | inline void update_outer_rects(); |
| 80 | | |
| 81 | | // surface management |
| 82 | | int ddraw_create(); |
| 83 | | int ddraw_create_surfaces(); |
| 84 | | void ddraw_delete(); |
| 85 | | void ddraw_delete_surfaces(); |
| 86 | | int ddraw_verify_caps(); |
| 87 | | int ddraw_test_cooperative(); |
| 88 | | HRESULT create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type); |
| 89 | | int create_clipper(); |
| 90 | | |
| 91 | | // drawing helpers |
| 92 | | void compute_blit_surface_size(); |
| 93 | | void blit_to_primary(int srcwidth, int srcheight); |
| 94 | | |
| 95 | | // video modes |
| 96 | | int config_adapter_mode(); |
| 97 | | void get_adapter_for_monitor(win_monitor_info *monitor); |
| 98 | | void pick_best_mode(); |
| 99 | | |
| 100 | | // various |
| 101 | | void calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins); |
| 102 | | |
| 103 | | |
| 104 | | GUID adapter; // current display adapter |
| 105 | | GUID * adapter_ptr; // pointer to current display adapter |
| 106 | | int clearouter; // clear the outer areas? |
| 107 | | |
| 108 | | INT32 blitwidth, blitheight; // current blit width/height values |
| 109 | | RECT lastdest; // last destination rectangle |
| 110 | | |
| 111 | | IDirectDraw7 * ddraw; // pointer to the DirectDraw object |
| 112 | | IDirectDrawSurface7 * primary; // pointer to the primary surface object |
| 113 | | IDirectDrawSurface7 * back; // pointer to the back buffer surface object |
| 114 | | IDirectDrawSurface7 * blit; // pointer to the blit surface object |
| 115 | | IDirectDrawClipper * clipper; // pointer to the clipper object |
| 116 | | IDirectDrawGammaControl *gamma; // pointer to the gamma control object |
| 117 | | |
| 118 | | DDSURFACEDESC2 primarydesc; // description of the primary surface |
| 119 | | DDSURFACEDESC2 blitdesc; // description of the blitting surface |
| 120 | | DDSURFACEDESC2 origmode; // original video mode |
| 121 | | |
| 122 | | DDCAPS ddcaps; // capabilities of the device |
| 123 | | DDCAPS helcaps; // capabilities of the hardware |
| 124 | | |
| 125 | | UINT8 * membuffer; // memory buffer for complex rendering |
| 126 | | UINT32 membuffersize; // current size of the memory buffer |
| 127 | | }; |
| 128 | | |
| 129 | | |
| 130 | | /* monitor_enum_info holds information during a monitor enumeration */ |
| 131 | | struct monitor_enum_info |
| 132 | | { |
| 133 | | win_monitor_info * monitor; // pointer to monitor we want |
| 134 | | GUID guid; // GUID of the one we found |
| 135 | | GUID * guid_ptr; // pointer to our GUID |
| 136 | | int foundit; // TRUE if we found what we wanted |
| 137 | | }; |
| 138 | | |
| 139 | | |
| 140 | | /* mode_enum_info holds information during a display mode enumeration */ |
| 141 | | struct mode_enum_info |
| 142 | | { |
| 143 | | renderer_dd * renderer; |
| 144 | | osd_window * window; |
| 145 | | INT32 minimum_width, minimum_height; |
| 146 | | INT32 target_width, target_height; |
| 147 | | double target_refresh; |
| 148 | | float best_score; |
| 149 | | }; |
| 150 | | |
| 151 | | |
| 152 | | |
| 153 | | //============================================================ |
| 154 | | // GLOBALS |
| 155 | | //============================================================ |
| 156 | | |
| 157 | | static HINSTANCE dllhandle; |
| 158 | | static directdrawcreateex_ptr directdrawcreateex; |
| 159 | | static directdrawenumerateex_ptr directdrawenumerateex; |
| 160 | | |
| 161 | | |
| 162 | | |
| 163 | | //============================================================ |
| 164 | | // INLINES |
| 165 | | //============================================================ |
| 166 | | |
| 167 | | inline void renderer_dd::update_outer_rects() |
| 168 | | { |
| 169 | | clearouter = (back != NULL) ? 3 : 1; |
| 170 | | } |
| 171 | | |
| 172 | | |
| 173 | | INLINE int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) |
| 174 | | { |
| 175 | | float aspect0 = (float)width0 / (float)height0; |
| 176 | | float aspect1 = (float)width1 / (float)height1; |
| 177 | | return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; |
| 178 | | } |
| 179 | | |
| 180 | | |
| 181 | | |
| 182 | | //============================================================ |
| 183 | | // PROTOTYPES |
| 184 | | //============================================================ |
| 185 | | |
| 186 | | // core functions |
| 187 | | static void drawdd_exit(void); |
| 188 | | |
| 189 | | |
| 190 | | |
| 191 | | //============================================================ |
| 192 | | // drawnone_create |
| 193 | | //============================================================ |
| 194 | | |
| 195 | | static osd_renderer *drawdd_create(osd_window *window) |
| 196 | | { |
| 197 | | return global_alloc(renderer_dd(window)); |
| 198 | | } |
| 199 | | |
| 200 | | |
| 201 | | //============================================================ |
| 202 | | // drawdd_init |
| 203 | | //============================================================ |
| 204 | | |
| 205 | | int drawdd_init(running_machine &machine, osd_draw_callbacks *callbacks) |
| 206 | | { |
| 207 | | // dynamically grab the create function from ddraw.dll |
| 208 | | dllhandle = LoadLibrary(TEXT("ddraw.dll")); |
| 209 | | if (dllhandle == NULL) |
| 210 | | { |
| 211 | | osd_printf_verbose("DirectDraw: Unable to access ddraw.dll\n"); |
| 212 | | return 1; |
| 213 | | } |
| 214 | | |
| 215 | | // import the create function |
| 216 | | directdrawcreateex = (directdrawcreateex_ptr)GetProcAddress(dllhandle, "DirectDrawCreateEx"); |
| 217 | | if (directdrawcreateex == NULL) |
| 218 | | { |
| 219 | | osd_printf_verbose("DirectDraw: Unable to find DirectDrawCreateEx\n"); |
| 220 | | FreeLibrary(dllhandle); |
| 221 | | dllhandle = NULL; |
| 222 | | return 1; |
| 223 | | } |
| 224 | | |
| 225 | | // import the enumerate function |
| 226 | | directdrawenumerateex = (directdrawenumerateex_ptr)GetProcAddress(dllhandle, "DirectDrawEnumerateExA"); |
| 227 | | if (directdrawenumerateex == NULL) |
| 228 | | { |
| 229 | | osd_printf_verbose("DirectDraw: Unable to find DirectDrawEnumerateExA\n"); |
| 230 | | FreeLibrary(dllhandle); |
| 231 | | dllhandle = NULL; |
| 232 | | return 1; |
| 233 | | } |
| 234 | | |
| 235 | | // fill in the callbacks |
| 236 | | memset(callbacks, 0, sizeof(*callbacks)); |
| 237 | | callbacks->exit = drawdd_exit; |
| 238 | | callbacks->create = drawdd_create; |
| 239 | | |
| 240 | | osd_printf_verbose("DirectDraw: Using DirectDraw 7\n"); |
| 241 | | return 0; |
| 242 | | } |
| 243 | | |
| 244 | | |
| 245 | | |
| 246 | | //============================================================ |
| 247 | | // drawdd_exit |
| 248 | | //============================================================ |
| 249 | | |
| 250 | | static void drawdd_exit(void) |
| 251 | | { |
| 252 | | if (dllhandle != NULL) |
| 253 | | FreeLibrary(dllhandle); |
| 254 | | } |
| 255 | | |
| 256 | | |
| 257 | | |
| 258 | | //============================================================ |
| 259 | | // drawdd_window_init |
| 260 | | //============================================================ |
| 261 | | |
| 262 | | int renderer_dd::create() |
| 263 | | { |
| 264 | | // configure the adapter for the mode we want |
| 265 | | if (config_adapter_mode()) |
| 266 | | goto error; |
| 267 | | |
| 268 | | // create the ddraw object |
| 269 | | if (ddraw_create()) |
| 270 | | goto error; |
| 271 | | |
| 272 | | return 0; |
| 273 | | |
| 274 | | error: |
| 275 | | destroy(); |
| 276 | | osd_printf_error("Unable to initialize DirectDraw.\n"); |
| 277 | | return 1; |
| 278 | | } |
| 279 | | |
| 280 | | |
| 281 | | |
| 282 | | //============================================================ |
| 283 | | // drawdd_window_destroy |
| 284 | | //============================================================ |
| 285 | | |
| 286 | | void renderer_dd::destroy() |
| 287 | | { |
| 288 | | // delete the ddraw object |
| 289 | | ddraw_delete(); |
| 290 | | } |
| 291 | | |
| 292 | | |
| 293 | | |
| 294 | | //============================================================ |
| 295 | | // drawdd_window_get_primitives |
| 296 | | //============================================================ |
| 297 | | |
| 298 | | render_primitive_list *renderer_dd::get_primitives() |
| 299 | | { |
| 300 | | compute_blit_surface_size(); |
| 301 | | window().target()->set_bounds(blitwidth, blitheight, 0); |
| 302 | | window().target()->set_max_update_rate((refresh == 0) ? origmode.dwRefreshRate : refresh); |
| 303 | | |
| 304 | | return &window().target()->get_primitives(); |
| 305 | | } |
| 306 | | |
| 307 | | |
| 308 | | |
| 309 | | //============================================================ |
| 310 | | // drawdd_window_draw |
| 311 | | //============================================================ |
| 312 | | |
| 313 | | int renderer_dd::draw(const int update) |
| 314 | | { |
| 315 | | render_primitive *prim; |
| 316 | | int usemembuffer = FALSE; |
| 317 | | HRESULT result; |
| 318 | | |
| 319 | | // if we're updating, remember to erase the outer stuff |
| 320 | | if (update) |
| 321 | | update_outer_rects(); |
| 322 | | |
| 323 | | // if we have a ddraw object, check the cooperative level |
| 324 | | if (ddraw_test_cooperative()) |
| 325 | | return 1; |
| 326 | | |
| 327 | | // get the size; if we're too small, delete the existing surfaces |
| 328 | | if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight) |
| 329 | | ddraw_delete_surfaces(); |
| 330 | | |
| 331 | | // if we need to create surfaces, do it now |
| 332 | | if (blit == NULL && ddraw_create_surfaces() != 0) |
| 333 | | return 1; |
| 334 | | |
| 335 | | // select our surface and lock it |
| 336 | | result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL); |
| 337 | | if (result == DDERR_SURFACELOST) |
| 338 | | { |
| 339 | | osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); |
| 340 | | ddraw_delete_surfaces(); |
| 341 | | return 1; |
| 342 | | } |
| 343 | | if (result != DD_OK) |
| 344 | | { |
| 345 | | osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); |
| 346 | | return 1; |
| 347 | | } |
| 348 | | |
| 349 | | // render to it |
| 350 | | window().m_primlist->acquire_lock(); |
| 351 | | |
| 352 | | // scan the list of primitives for tricky stuff |
| 353 | | for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) |
| 354 | | if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || |
| 355 | | (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) |
| 356 | | { |
| 357 | | usemembuffer = TRUE; |
| 358 | | break; |
| 359 | | } |
| 360 | | |
| 361 | | // if we're using the memory buffer, draw offscreen first and then copy |
| 362 | | if (usemembuffer) |
| 363 | | { |
| 364 | | int x, y; |
| 365 | | |
| 366 | | // based on the target format, use one of our standard renderers |
| 367 | | switch (blitdesc.ddpfPixelFormat.dwRBitMask) |
| 368 | | { |
| 369 | | case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 370 | | case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 371 | | case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 372 | | case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; |
| 373 | | default: |
| 374 | | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); |
| 375 | | break; |
| 376 | | } |
| 377 | | |
| 378 | | // handle copying to both 16bpp and 32bpp destinations |
| 379 | | for (y = 0; y < blitheight; y++) |
| 380 | | { |
| 381 | | if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) |
| 382 | | { |
| 383 | | UINT32 *src = (UINT32 *)membuffer + y * blitwidth; |
| 384 | | UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); |
| 385 | | for (x = 0; x < blitwidth; x++) |
| 386 | | *dst++ = *src++; |
| 387 | | } |
| 388 | | else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) |
| 389 | | { |
| 390 | | UINT16 *src = (UINT16 *)membuffer + y * blitwidth; |
| 391 | | UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); |
| 392 | | for (x = 0; x < blitwidth; x++) |
| 393 | | *dst++ = *src++; |
| 394 | | } |
| 395 | | } |
| 396 | | |
| 397 | | } |
| 398 | | |
| 399 | | // otherwise, draw directly |
| 400 | | else |
| 401 | | { |
| 402 | | // based on the target format, use one of our standard renderers |
| 403 | | switch (blitdesc.ddpfPixelFormat.dwRBitMask) |
| 404 | | { |
| 405 | | case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; |
| 406 | | case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; |
| 407 | | case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; |
| 408 | | case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; |
| 409 | | default: |
| 410 | | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); |
| 411 | | break; |
| 412 | | } |
| 413 | | } |
| 414 | | window().m_primlist->release_lock(); |
| 415 | | |
| 416 | | // unlock and blit |
| 417 | | result = IDirectDrawSurface7_Unlock(blit, NULL); |
| 418 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); |
| 419 | | |
| 420 | | // sync to VBLANK |
| 421 | | if ((video_config.waitvsync || video_config.syncrefresh) && window().machine().video().throttled() && (!window().fullscreen() || back == NULL)) |
| 422 | | { |
| 423 | | result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL); |
| 424 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); |
| 425 | | } |
| 426 | | |
| 427 | | // complete the blitting |
| 428 | | blit_to_primary(blitwidth, blitheight); |
| 429 | | return 0; |
| 430 | | } |
| 431 | | |
| 432 | | |
| 433 | | |
| 434 | | //============================================================ |
| 435 | | // ddraw_create |
| 436 | | //============================================================ |
| 437 | | |
| 438 | | int renderer_dd::ddraw_create() |
| 439 | | { |
| 440 | | HRESULT result; |
| 441 | | int verify; |
| 442 | | |
| 443 | | // if a device exists, free it |
| 444 | | if (ddraw != NULL) |
| 445 | | ddraw_delete(); |
| 446 | | |
| 447 | | // create the DirectDraw object |
| 448 | | result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); |
| 449 | | if (result != DD_OK) |
| 450 | | { |
| 451 | | osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); |
| 452 | | goto error; |
| 453 | | } |
| 454 | | |
| 455 | | // verify the caps |
| 456 | | verify = ddraw_verify_caps(); |
| 457 | | if (verify == 2) |
| 458 | | { |
| 459 | | osd_printf_error("DirectDraw: Error - Device does not meet minimum requirements for DirectDraw rendering\n"); |
| 460 | | goto error; |
| 461 | | } |
| 462 | | if (verify == 1) |
| 463 | | osd_printf_verbose("DirectDraw: Warning - Device may not perform well for DirectDraw rendering\n"); |
| 464 | | |
| 465 | | // set the cooperative level |
| 466 | | // for non-window modes, we will use full screen here |
| 467 | | result = IDirectDraw7_SetCooperativeLevel(ddraw, win_window_list->m_hwnd, DDSCL_SETFOCUSWINDOW); |
| 468 | | if (result != DD_OK) |
| 469 | | { |
| 470 | | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(FOCUSWINDOW) call\n", (int)result); |
| 471 | | goto error; |
| 472 | | } |
| 473 | | result = IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_SETDEVICEWINDOW | (window().fullscreen() ? DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE : DDSCL_NORMAL)); |
| 474 | | if (result != DD_OK) |
| 475 | | { |
| 476 | | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(DEVICEWINDOW) call\n", (int)result); |
| 477 | | goto error; |
| 478 | | } |
| 479 | | |
| 480 | | // full screen mode: set the resolution |
| 481 | | if (window().fullscreen() && video_config.switchres) |
| 482 | | { |
| 483 | | result = IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, refresh, 0); |
| 484 | | if (result != DD_OK) |
| 485 | | { |
| 486 | | osd_printf_verbose("DirectDraw: Error %08X attempting to set video mode %dx%d@%d call\n", (int)result, width, height, refresh); |
| 487 | | goto error; |
| 488 | | } |
| 489 | | } |
| 490 | | |
| 491 | | return ddraw_create_surfaces(); |
| 492 | | |
| 493 | | error: |
| 494 | | ddraw_delete(); |
| 495 | | return 1; |
| 496 | | } |
| 497 | | |
| 498 | | |
| 499 | | |
| 500 | | //============================================================ |
| 501 | | // ddraw_create_surfaces |
| 502 | | //============================================================ |
| 503 | | |
| 504 | | int renderer_dd::ddraw_create_surfaces() |
| 505 | | { |
| 506 | | HRESULT result; |
| 507 | | |
| 508 | | // make a description of the primary surface |
| 509 | | memset(&primarydesc, 0, sizeof(primarydesc)); |
| 510 | | primarydesc.dwSize = sizeof(primarydesc); |
| 511 | | primarydesc.dwFlags = DDSD_CAPS; |
| 512 | | primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; |
| 513 | | |
| 514 | | // for triple-buffered full screen mode, allocate flipping surfaces |
| 515 | | if (window().fullscreen() && video_config.triplebuf) |
| 516 | | { |
| 517 | | primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; |
| 518 | | primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; |
| 519 | | primarydesc.dwBackBufferCount = 2; |
| 520 | | } |
| 521 | | |
| 522 | | // create the primary surface and report errors |
| 523 | | result = create_surface(&primarydesc, &primary, "primary"); |
| 524 | | if (result != DD_OK) goto error; |
| 525 | | |
| 526 | | // full screen mode: get the back surface |
| 527 | | back = NULL; |
| 528 | | if (window().fullscreen() && video_config.triplebuf) |
| 529 | | { |
| 530 | | DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; |
| 531 | | result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back); |
| 532 | | if (result != DD_OK) |
| 533 | | { |
| 534 | | osd_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result); |
| 535 | | goto error; |
| 536 | | } |
| 537 | | } |
| 538 | | |
| 539 | | // now make a description of our blit surface, based on the primary surface |
| 540 | | if (blitwidth == 0 || blitheight == 0) |
| 541 | | compute_blit_surface_size(); |
| 542 | | blitdesc = primarydesc; |
| 543 | | blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; |
| 544 | | blitdesc.dwWidth = blitwidth; |
| 545 | | blitdesc.dwHeight = blitheight; |
| 546 | | blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; |
| 547 | | |
| 548 | | // then create the blit surface, fall back to system memory if video mem doesn't work |
| 549 | | result = create_surface(&blitdesc, &blit, "blit"); |
| 550 | | if (result != DD_OK) |
| 551 | | { |
| 552 | | blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; |
| 553 | | result = create_surface(&blitdesc, &blit, "blit"); |
| 554 | | } |
| 555 | | if (result != DD_OK) goto error; |
| 556 | | |
| 557 | | // create a memory buffer for offscreen drawing |
| 558 | | if (membuffersize < blitwidth * blitheight * 4) |
| 559 | | { |
| 560 | | membuffersize = blitwidth * blitheight * 4; |
| 561 | | global_free_array(membuffer); |
| 562 | | membuffer = global_alloc_array(UINT8, membuffersize); |
| 563 | | } |
| 564 | | if (membuffer == NULL) |
| 565 | | goto error; |
| 566 | | |
| 567 | | // create a clipper for windowed mode |
| 568 | | if (!window().fullscreen() && create_clipper()) |
| 569 | | goto error; |
| 570 | | |
| 571 | | // full screen mode: set the gamma |
| 572 | | if (window().fullscreen()) |
| 573 | | { |
| 574 | | // only set the gamma if it's not 1.0f |
| 575 | | windows_options &options = downcast<windows_options &>(window().machine().options()); |
| 576 | | float brightness = options.full_screen_brightness(); |
| 577 | | float contrast = options.full_screen_contrast(); |
| 578 | | float fgamma = options.full_screen_gamma(); |
| 579 | | if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f) |
| 580 | | { |
| 581 | | // see if we can get a GammaControl object |
| 582 | | result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma); |
| 583 | | if (result != DD_OK) |
| 584 | | { |
| 585 | | osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); |
| 586 | | this->gamma = NULL; |
| 587 | | } |
| 588 | | |
| 589 | | // proceed if we can |
| 590 | | if (this->gamma != NULL) |
| 591 | | { |
| 592 | | DDGAMMARAMP ramp; |
| 593 | | int i; |
| 594 | | |
| 595 | | // create a standard ramp and set it |
| 596 | | for (i = 0; i < 256; i++) |
| 597 | | ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, fgamma) << 8; |
| 598 | | |
| 599 | | // attempt to set it |
| 600 | | result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp); |
| 601 | | if (result != DD_OK) |
| 602 | | osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); |
| 603 | | } |
| 604 | | } |
| 605 | | } |
| 606 | | |
| 607 | | // force some updates |
| 608 | | update_outer_rects(); |
| 609 | | return 0; |
| 610 | | |
| 611 | | error: |
| 612 | | ddraw_delete_surfaces(); |
| 613 | | return 1; |
| 614 | | } |
| 615 | | |
| 616 | | |
| 617 | | |
| 618 | | //============================================================ |
| 619 | | // ddraw_delete |
| 620 | | //============================================================ |
| 621 | | |
| 622 | | void renderer_dd::ddraw_delete() |
| 623 | | { |
| 624 | | // free surfaces |
| 625 | | ddraw_delete_surfaces(); |
| 626 | | |
| 627 | | // restore resolutions |
| 628 | | if (ddraw != NULL) |
| 629 | | IDirectDraw7_RestoreDisplayMode(ddraw); |
| 630 | | |
| 631 | | // reset cooperative level |
| 632 | | if (ddraw != NULL && window().m_hwnd != NULL) |
| 633 | | IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_NORMAL); |
| 634 | | |
| 635 | | // release the DirectDraw object itself |
| 636 | | if (ddraw != NULL) |
| 637 | | IDirectDraw7_Release(ddraw); |
| 638 | | ddraw = NULL; |
| 639 | | } |
| 640 | | |
| 641 | | |
| 642 | | |
| 643 | | //============================================================ |
| 644 | | // ddraw_delete_surfaces |
| 645 | | //============================================================ |
| 646 | | |
| 647 | | void renderer_dd::ddraw_delete_surfaces() |
| 648 | | { |
| 649 | | // release the gamma control |
| 650 | | if (gamma != NULL) |
| 651 | | IDirectDrawGammaControl_Release(gamma); |
| 652 | | gamma = NULL; |
| 653 | | |
| 654 | | // release the clipper |
| 655 | | if (clipper != NULL) |
| 656 | | IDirectDrawClipper_Release(clipper); |
| 657 | | clipper = NULL; |
| 658 | | |
| 659 | | // free the memory buffer |
| 660 | | global_free_array(membuffer); |
| 661 | | membuffer = NULL; |
| 662 | | membuffersize = 0; |
| 663 | | |
| 664 | | // release the blit surface |
| 665 | | if (blit != NULL) |
| 666 | | IDirectDrawSurface7_Release(blit); |
| 667 | | blit = NULL; |
| 668 | | |
| 669 | | // release the back surface |
| 670 | | if (back != NULL) |
| 671 | | IDirectDrawSurface7_Release(back); |
| 672 | | back = NULL; |
| 673 | | |
| 674 | | // release the primary surface |
| 675 | | if (primary != NULL) |
| 676 | | IDirectDrawSurface7_Release(primary); |
| 677 | | primary = NULL; |
| 678 | | } |
| 679 | | |
| 680 | | |
| 681 | | |
| 682 | | //============================================================ |
| 683 | | // ddraw_verify_caps |
| 684 | | //============================================================ |
| 685 | | |
| 686 | | int renderer_dd::ddraw_verify_caps() |
| 687 | | { |
| 688 | | int retval = 0; |
| 689 | | HRESULT result; |
| 690 | | |
| 691 | | // get the capabilities |
| 692 | | ddcaps.dwSize = sizeof(ddcaps); |
| 693 | | helcaps.dwSize = sizeof(helcaps); |
| 694 | | result = IDirectDraw7_GetCaps(ddraw, &ddcaps, &helcaps); |
| 695 | | if (result != DD_OK) |
| 696 | | { |
| 697 | | osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_GetCaps call\n", (int)result); |
| 698 | | return 1; |
| 699 | | } |
| 700 | | |
| 701 | | // determine if hardware stretching is available |
| 702 | | if ((ddcaps.dwCaps & DDCAPS_BLTSTRETCH) == 0) |
| 703 | | { |
| 704 | | osd_printf_verbose("DirectDraw: Warning - Device does not support hardware stretching\n"); |
| 705 | | retval = 1; |
| 706 | | } |
| 707 | | |
| 708 | | return retval; |
| 709 | | } |
| 710 | | |
| 711 | | |
| 712 | | |
| 713 | | //============================================================ |
| 714 | | // ddraw_test_cooperative |
| 715 | | //============================================================ |
| 716 | | |
| 717 | | int renderer_dd::ddraw_test_cooperative() |
| 718 | | { |
| 719 | | HRESULT result; |
| 720 | | |
| 721 | | // check our current status; if we lost the device, punt to GDI |
| 722 | | result = IDirectDraw7_TestCooperativeLevel(ddraw); |
| 723 | | switch (result) |
| 724 | | { |
| 725 | | // punt to GDI if someone else has exclusive mode |
| 726 | | case DDERR_NOEXCLUSIVEMODE: |
| 727 | | case DDERR_EXCLUSIVEMODEALREADYSET: |
| 728 | | ddraw_delete_surfaces(); |
| 729 | | return 1; |
| 730 | | |
| 731 | | // if we're ok, but we don't have a primary surface, create one |
| 732 | | default: |
| 733 | | case DD_OK: |
| 734 | | if (primary == NULL) |
| 735 | | return ddraw_create_surfaces(); |
| 736 | | return 0; |
| 737 | | } |
| 738 | | } |
| 739 | | |
| 740 | | |
| 741 | | |
| 742 | | //============================================================ |
| 743 | | // create_surface |
| 744 | | //============================================================ |
| 745 | | |
| 746 | | HRESULT renderer_dd::create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type) |
| 747 | | { |
| 748 | | HRESULT result; |
| 749 | | |
| 750 | | // create the surface as requested |
| 751 | | result = IDirectDraw7_CreateSurface(ddraw, desc, surface, NULL); |
| 752 | | if (result != DD_OK) |
| 753 | | { |
| 754 | | osd_printf_verbose("DirectDraw: Error %08X creating %s surface\n", (int)result, type); |
| 755 | | return result; |
| 756 | | } |
| 757 | | |
| 758 | | // get a description of the primary surface |
| 759 | | result = IDirectDrawSurface7_GetSurfaceDesc(*surface, desc); |
| 760 | | if (result != DD_OK) |
| 761 | | { |
| 762 | | osd_printf_verbose("DirectDraw: Error %08X getting %s surface desciption\n", (int)result, type); |
| 763 | | IDirectDrawSurface7_Release(*surface); |
| 764 | | *surface = NULL; |
| 765 | | return result; |
| 766 | | } |
| 767 | | |
| 768 | | // print out the good stuff |
| 769 | | osd_printf_verbose("DirectDraw: %s surface created: %dx%dx%d (R=%08X G=%08X B=%08X)\n", |
| 770 | | type, |
| 771 | | (int)desc->dwWidth, |
| 772 | | (int)desc->dwHeight, |
| 773 | | (int)desc->ddpfPixelFormat.dwRGBBitCount, |
| 774 | | (UINT32)desc->ddpfPixelFormat.dwRBitMask, |
| 775 | | (UINT32)desc->ddpfPixelFormat.dwGBitMask, |
| 776 | | (UINT32)desc->ddpfPixelFormat.dwBBitMask); |
| 777 | | return result; |
| 778 | | } |
| 779 | | |
| 780 | | |
| 781 | | |
| 782 | | //============================================================ |
| 783 | | // create_clipper |
| 784 | | //============================================================ |
| 785 | | |
| 786 | | int renderer_dd::create_clipper() |
| 787 | | { |
| 788 | | HRESULT result; |
| 789 | | |
| 790 | | // create a clipper for the primary surface |
| 791 | | result = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL); |
| 792 | | if (result != DD_OK) |
| 793 | | { |
| 794 | | osd_printf_verbose("DirectDraw: Error %08X creating clipper\n", (int)result); |
| 795 | | return 1; |
| 796 | | } |
| 797 | | |
| 798 | | // set the clipper's hwnd |
| 799 | | result = IDirectDrawClipper_SetHWnd(clipper, 0, window().m_hwnd); |
| 800 | | if (result != DD_OK) |
| 801 | | { |
| 802 | | osd_printf_verbose("DirectDraw: Error %08X setting clipper hwnd\n", (int)result); |
| 803 | | return 1; |
| 804 | | } |
| 805 | | |
| 806 | | // set the clipper on the primary surface |
| 807 | | result = IDirectDrawSurface7_SetClipper(primary, clipper); |
| 808 | | if (result != DD_OK) |
| 809 | | { |
| 810 | | osd_printf_verbose("DirectDraw: Error %08X setting clipper on primary surface\n", (int)result); |
| 811 | | return 1; |
| 812 | | } |
| 813 | | return 0; |
| 814 | | } |
| 815 | | |
| 816 | | |
| 817 | | |
| 818 | | //============================================================ |
| 819 | | // compute_blit_surface_size |
| 820 | | //============================================================ |
| 821 | | |
| 822 | | void renderer_dd::compute_blit_surface_size() |
| 823 | | { |
| 824 | | INT32 newwidth, newheight; |
| 825 | | int xscale, yscale; |
| 826 | | RECT client; |
| 827 | | |
| 828 | | // start with the minimum size |
| 829 | | window().target()->compute_minimum_size(newwidth, newheight); |
| 830 | | |
| 831 | | // get the window's client rectangle |
| 832 | | GetClientRect(window().m_hwnd, &client); |
| 833 | | |
| 834 | | // hardware stretch case: apply prescale |
| 835 | | if (video_config.hwstretch) |
| 836 | | { |
| 837 | | int prescale = (window().prescale() < 1) ? 1 : window().prescale(); |
| 838 | | |
| 839 | | // clamp the prescale to something smaller than the target bounds |
| 840 | | xscale = prescale; |
| 841 | | while (xscale > 1 && newwidth * xscale > rect_width(&client)) |
| 842 | | xscale--; |
| 843 | | yscale = prescale; |
| 844 | | while (yscale > 1 && newheight * yscale > rect_height(&client)) |
| 845 | | yscale--; |
| 846 | | } |
| 847 | | |
| 848 | | // non stretch case |
| 849 | | else |
| 850 | | { |
| 851 | | INT32 target_width = rect_width(&client); |
| 852 | | INT32 target_height = rect_height(&client); |
| 853 | | float desired_aspect = 1.0f; |
| 854 | | |
| 855 | | // compute the appropriate visible area if we're trying to keepaspect |
| 856 | | if (video_config.keepaspect) |
| 857 | | { |
| 858 | | win_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); |
| 859 | | window().target()->compute_visible_area(target_width, target_height, monitor->aspect(), window().target()->orientation(), target_width, target_height); |
| 860 | | desired_aspect = (float)target_width / (float)target_height; |
| 861 | | } |
| 862 | | |
| 863 | | // compute maximum integral scaling to fit the window |
| 864 | | xscale = (target_width + 2) / newwidth; |
| 865 | | yscale = (target_height + 2) / newheight; |
| 866 | | |
| 867 | | // try a little harder to keep the aspect ratio if desired |
| 868 | | if (video_config.keepaspect) |
| 869 | | { |
| 870 | | // if we could stretch more in the X direction, and that makes a better fit, bump the xscale |
| 871 | | while (newwidth * (xscale + 1) <= rect_width(&client) && |
| 872 | | better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) |
| 873 | | xscale++; |
| 874 | | |
| 875 | | // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale |
| 876 | | while (newheight * (yscale + 1) <= rect_height(&client) && |
| 877 | | better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) |
| 878 | | yscale++; |
| 879 | | |
| 880 | | // now that we've maxed out, see if backing off the maximally stretched one makes a better fit |
| 881 | | if (rect_width(&client) - newwidth * xscale < rect_height(&client) - newheight * yscale) |
| 882 | | { |
| 883 | | while (xscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect)) |
| 884 | | xscale--; |
| 885 | | } |
| 886 | | else |
| 887 | | { |
| 888 | | while (yscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect)) |
| 889 | | yscale--; |
| 890 | | } |
| 891 | | } |
| 892 | | } |
| 893 | | |
| 894 | | // ensure at least a scale factor of 1 |
| 895 | | if (xscale == 0) xscale = 1; |
| 896 | | if (yscale == 0) yscale = 1; |
| 897 | | |
| 898 | | // apply the final scale |
| 899 | | newwidth *= xscale; |
| 900 | | newheight *= yscale; |
| 901 | | if (newwidth != blitwidth || newheight != blitheight) |
| 902 | | { |
| 903 | | // force some updates |
| 904 | | update_outer_rects(); |
| 905 | | osd_printf_verbose("DirectDraw: New blit size = %dx%d\n", newwidth, newheight); |
| 906 | | } |
| 907 | | blitwidth = newwidth; |
| 908 | | blitheight = newheight; |
| 909 | | } |
| 910 | | |
| 911 | | |
| 912 | | |
| 913 | | //============================================================ |
| 914 | | // calc_fullscreen_margins |
| 915 | | //============================================================ |
| 916 | | |
| 917 | | void renderer_dd::calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins) |
| 918 | | { |
| 919 | | margins->left = 0; |
| 920 | | margins->top = 0; |
| 921 | | margins->right = desc_width; |
| 922 | | margins->bottom = desc_height; |
| 923 | | |
| 924 | | if (window().win_has_menu()) |
| 925 | | { |
| 926 | | static int height_with_menubar = 0; |
| 927 | | if (height_with_menubar == 0) |
| 928 | | { |
| 929 | | RECT with_menu = { 100, 100, 200, 200 }; |
| 930 | | RECT without_menu = { 100, 100, 200, 200 }; |
| 931 | | AdjustWindowRect(&with_menu, WS_OVERLAPPED, TRUE); |
| 932 | | AdjustWindowRect(&without_menu, WS_OVERLAPPED, FALSE); |
| 933 | | height_with_menubar = (with_menu.bottom - with_menu.top) - (without_menu.bottom - without_menu.top); |
| 934 | | } |
| 935 | | margins->top = height_with_menubar; |
| 936 | | } |
| 937 | | } |
| 938 | | |
| 939 | | |
| 940 | | |
| 941 | | //============================================================ |
| 942 | | // blit_to_primary |
| 943 | | //============================================================ |
| 944 | | |
| 945 | | void renderer_dd::blit_to_primary(int srcwidth, int srcheight) |
| 946 | | { |
| 947 | | IDirectDrawSurface7 *target = (back != NULL) ? back : primary; |
| 948 | | win_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); |
| 949 | | DDBLTFX blitfx = { sizeof(DDBLTFX) }; |
| 950 | | RECT clear, outer, dest, source; |
| 951 | | INT32 dstwidth, dstheight; |
| 952 | | HRESULT result; |
| 953 | | |
| 954 | | // compute source rect |
| 955 | | source.left = source.top = 0; |
| 956 | | source.right = srcwidth; |
| 957 | | source.bottom = srcheight; |
| 958 | | |
| 959 | | // compute outer rect -- windowed version |
| 960 | | if (!window().fullscreen()) |
| 961 | | { |
| 962 | | GetClientRect(window().m_hwnd, &outer); |
| 963 | | ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[0]); |
| 964 | | ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[1]); |
| 965 | | |
| 966 | | // adjust to be relative to the monitor |
| 967 | | osd_rect pos = monitor->position_size(); |
| 968 | | outer.left -= pos.left(); |
| 969 | | outer.right -= pos.left(); |
| 970 | | outer.top -= pos.top(); |
| 971 | | outer.bottom -= pos.top(); |
| 972 | | } |
| 973 | | |
| 974 | | // compute outer rect -- full screen version |
| 975 | | else |
| 976 | | { |
| 977 | | calc_fullscreen_margins(primarydesc.dwWidth, primarydesc.dwHeight, &outer); |
| 978 | | } |
| 979 | | |
| 980 | | // if we're respecting the aspect ratio, we need to adjust to fit |
| 981 | | dstwidth = rect_width(&outer); |
| 982 | | dstheight = rect_height(&outer); |
| 983 | | if (!video_config.hwstretch) |
| 984 | | { |
| 985 | | // trim the source if necessary |
| 986 | | if (rect_width(&outer) < srcwidth) |
| 987 | | { |
| 988 | | source.left += (srcwidth - rect_width(&outer)) / 2; |
| 989 | | source.right = source.left + rect_width(&outer); |
| 990 | | } |
| 991 | | if (rect_height(&outer) < srcheight) |
| 992 | | { |
| 993 | | source.top += (srcheight - rect_height(&outer)) / 2; |
| 994 | | source.bottom = source.top + rect_height(&outer); |
| 995 | | } |
| 996 | | |
| 997 | | // match the destination and source sizes |
| 998 | | dstwidth = srcwidth = source.right - source.left; |
| 999 | | dstheight = srcheight = source.bottom - source.top; |
| 1000 | | } |
| 1001 | | else if (video_config.keepaspect) |
| 1002 | | { |
| 1003 | | // compute the appropriate visible area |
| 1004 | | window().target()->compute_visible_area(rect_width(&outer), rect_height(&outer), monitor->aspect(), window().target()->orientation(), dstwidth, dstheight); |
| 1005 | | } |
| 1006 | | |
| 1007 | | // center within |
| 1008 | | dest.left = outer.left + (rect_width(&outer) - dstwidth) / 2; |
| 1009 | | dest.right = dest.left + dstwidth; |
| 1010 | | dest.top = outer.top + (rect_height(&outer) - dstheight) / 2; |
| 1011 | | dest.bottom = dest.top + dstheight; |
| 1012 | | |
| 1013 | | // compare against last destination; if different, force a redraw |
| 1014 | | if (dest.left != lastdest.left || dest.right != lastdest.right || dest.top != lastdest.top || dest.bottom != lastdest.bottom) |
| 1015 | | { |
| 1016 | | lastdest = dest; |
| 1017 | | update_outer_rects(); |
| 1018 | | } |
| 1019 | | |
| 1020 | | // clear outer rects if we need to |
| 1021 | | if (clearouter != 0) |
| 1022 | | { |
| 1023 | | clearouter--; |
| 1024 | | |
| 1025 | | // clear the left edge |
| 1026 | | if (dest.left > outer.left) |
| 1027 | | { |
| 1028 | | clear = outer; |
| 1029 | | clear.right = dest.left; |
| 1030 | | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1031 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1032 | | } |
| 1033 | | |
| 1034 | | // clear the right edge |
| 1035 | | if (dest.right < outer.right) |
| 1036 | | { |
| 1037 | | clear = outer; |
| 1038 | | clear.left = dest.right; |
| 1039 | | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1040 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1041 | | } |
| 1042 | | |
| 1043 | | // clear the top edge |
| 1044 | | if (dest.top > outer.top) |
| 1045 | | { |
| 1046 | | clear = outer; |
| 1047 | | clear.bottom = dest.top; |
| 1048 | | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1049 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1050 | | } |
| 1051 | | |
| 1052 | | // clear the bottom edge |
| 1053 | | if (dest.bottom < outer.bottom) |
| 1054 | | { |
| 1055 | | clear = outer; |
| 1056 | | clear.top = dest.bottom; |
| 1057 | | result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); |
| 1058 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); |
| 1059 | | } |
| 1060 | | } |
| 1061 | | |
| 1062 | | // do the blit |
| 1063 | | result = IDirectDrawSurface7_Blt(target, &dest, blit, &source, DDBLT_WAIT, NULL); |
| 1064 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X blitting to the screen\n", (int)result); |
| 1065 | | |
| 1066 | | // page flip if triple buffered |
| 1067 | | if (window().fullscreen() && back != NULL) |
| 1068 | | { |
| 1069 | | result = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT); |
| 1070 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); |
| 1071 | | } |
| 1072 | | } |
| 1073 | | |
| 1074 | | |
| 1075 | | |
| 1076 | | //============================================================ |
| 1077 | | // config_adapter_mode |
| 1078 | | //============================================================ |
| 1079 | | |
| 1080 | | int renderer_dd::config_adapter_mode() |
| 1081 | | { |
| 1082 | | DDDEVICEIDENTIFIER2 identifier; |
| 1083 | | HRESULT result; |
| 1084 | | |
| 1085 | | // choose the monitor number |
| 1086 | | get_adapter_for_monitor(window().monitor()); |
| 1087 | | |
| 1088 | | // create a temporary DirectDraw object |
| 1089 | | result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); |
| 1090 | | if (result != DD_OK) |
| 1091 | | { |
| 1092 | | osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); |
| 1093 | | return 1; |
| 1094 | | } |
| 1095 | | |
| 1096 | | // get the identifier |
| 1097 | | result = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0); |
| 1098 | | if (result != DD_OK) |
| 1099 | | { |
| 1100 | | osd_printf_error("Error getting identifier for device\n"); |
| 1101 | | return 1; |
| 1102 | | } |
| 1103 | | osd_printf_verbose("DirectDraw: Configuring device %s\n", identifier.szDescription); |
| 1104 | | |
| 1105 | | // get the current display mode |
| 1106 | | memset(&origmode, 0, sizeof(origmode)); |
| 1107 | | origmode.dwSize = sizeof(origmode); |
| 1108 | | result = IDirectDraw7_GetDisplayMode(ddraw, &origmode); |
| 1109 | | if (result != DD_OK) |
| 1110 | | { |
| 1111 | | osd_printf_verbose("DirectDraw: Error %08X getting current display mode\n", (int)result); |
| 1112 | | IDirectDraw7_Release(ddraw); |
| 1113 | | return 1; |
| 1114 | | } |
| 1115 | | |
| 1116 | | // choose a resolution: full screen mode case |
| 1117 | | if (window().fullscreen()) |
| 1118 | | { |
| 1119 | | // default to the current mode exactly |
| 1120 | | width = origmode.dwWidth; |
| 1121 | | height = origmode.dwHeight; |
| 1122 | | refresh = origmode.dwRefreshRate; |
| 1123 | | |
| 1124 | | // if we're allowed to switch resolutions, override with something better |
| 1125 | | if (video_config.switchres) |
| 1126 | | pick_best_mode(); |
| 1127 | | } |
| 1128 | | |
| 1129 | | // release the DirectDraw object |
| 1130 | | IDirectDraw7_Release(ddraw); |
| 1131 | | ddraw = NULL; |
| 1132 | | |
| 1133 | | // if we're not changing resolutions, make sure we have a resolution we can handle |
| 1134 | | if (!window().fullscreen() || !video_config.switchres) |
| 1135 | | { |
| 1136 | | switch (origmode.ddpfPixelFormat.dwRBitMask) |
| 1137 | | { |
| 1138 | | case 0x00ff0000: |
| 1139 | | case 0x000000ff: |
| 1140 | | case 0xf800: |
| 1141 | | case 0x7c00: |
| 1142 | | break; |
| 1143 | | |
| 1144 | | default: |
| 1145 | | osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)origmode.ddpfPixelFormat.dwRBitMask, (int)origmode.ddpfPixelFormat.dwGBitMask, (int)origmode.ddpfPixelFormat.dwBBitMask); |
| 1146 | | return 1; |
| 1147 | | } |
| 1148 | | } |
| 1149 | | |
| 1150 | | return 0; |
| 1151 | | } |
| 1152 | | |
| 1153 | | |
| 1154 | | |
| 1155 | | //============================================================ |
| 1156 | | // monitor_enum_callback |
| 1157 | | //============================================================ |
| 1158 | | |
| 1159 | | static BOOL WINAPI monitor_enum_callback(GUID FAR *guid, LPSTR description, LPSTR name, LPVOID context, HMONITOR hmonitor) |
| 1160 | | { |
| 1161 | | monitor_enum_info *einfo = (monitor_enum_info *)context; |
| 1162 | | |
| 1163 | | // do we match the desired monitor? |
| 1164 | | if (hmonitor == einfo->monitor->handle() || (hmonitor == NULL && einfo->monitor->is_primary())) |
| 1165 | | { |
| 1166 | | einfo->guid_ptr = (guid != NULL) ? &einfo->guid : NULL; |
| 1167 | | if (guid != NULL) |
| 1168 | | einfo->guid = *guid; |
| 1169 | | einfo->foundit = TRUE; |
| 1170 | | } |
| 1171 | | return 1; |
| 1172 | | } |
| 1173 | | |
| 1174 | | |
| 1175 | | |
| 1176 | | //============================================================ |
| 1177 | | // get_adapter_for_monitor |
| 1178 | | //============================================================ |
| 1179 | | |
| 1180 | | void renderer_dd::get_adapter_for_monitor(win_monitor_info *monitor) |
| 1181 | | { |
| 1182 | | monitor_enum_info einfo; |
| 1183 | | HRESULT result; |
| 1184 | | |
| 1185 | | // try to find our monitor |
| 1186 | | memset(&einfo, 0, sizeof(einfo)); |
| 1187 | | einfo.monitor = monitor; |
| 1188 | | result = (*directdrawenumerateex)(monitor_enum_callback, &einfo, DDENUM_ATTACHEDSECONDARYDEVICES); |
| 1189 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during DirectDrawEnumerateEx call\n", (int)result); |
| 1190 | | |
| 1191 | | // set up the adapter |
| 1192 | | if (einfo.foundit && einfo.guid_ptr != NULL) |
| 1193 | | { |
| 1194 | | adapter = einfo.guid; |
| 1195 | | adapter_ptr = &adapter; |
| 1196 | | } |
| 1197 | | else |
| 1198 | | adapter_ptr = NULL; |
| 1199 | | } |
| 1200 | | |
| 1201 | | |
| 1202 | | |
| 1203 | | //============================================================ |
| 1204 | | // enum_modes_callback |
| 1205 | | //============================================================ |
| 1206 | | |
| 1207 | | static HRESULT WINAPI enum_modes_callback(LPDDSURFACEDESC2 desc, LPVOID context) |
| 1208 | | { |
| 1209 | | float size_score, refresh_score, final_score; |
| 1210 | | mode_enum_info *einfo = (mode_enum_info *)context; |
| 1211 | | renderer_dd *dd = einfo->renderer; |
| 1212 | | |
| 1213 | | // skip non-32 bit modes |
| 1214 | | if (desc->ddpfPixelFormat.dwRGBBitCount != 32) |
| 1215 | | return DDENUMRET_OK; |
| 1216 | | |
| 1217 | | // compute initial score based on difference between target and current |
| 1218 | | size_score = 1.0f / (1.0f + fabs((float)((INT32)desc->dwWidth - einfo->target_width)) + fabs((float)((INT32)desc->dwHeight - einfo->target_height))); |
| 1219 | | |
| 1220 | | // if the mode is too small, give a big penalty |
| 1221 | | if (desc->dwWidth < einfo->minimum_width || desc->dwHeight < einfo->minimum_height) |
| 1222 | | size_score *= 0.01f; |
| 1223 | | |
| 1224 | | // if mode is smaller than we'd like, it only scores up to 0.1 |
| 1225 | | if (desc->dwWidth < einfo->target_width || desc->dwHeight < einfo->target_height) |
| 1226 | | size_score *= 0.1f; |
| 1227 | | |
| 1228 | | // if we're looking for a particular mode, that's a winner |
| 1229 | | if (desc->dwWidth == einfo->window->m_win_config.width && desc->dwHeight == einfo->window->m_win_config.height) |
| 1230 | | size_score = 2.0f; |
| 1231 | | |
| 1232 | | // compute refresh score |
| 1233 | | refresh_score = 1.0f / (1.0f + fabs((double)desc->dwRefreshRate - einfo->target_refresh)); |
| 1234 | | |
| 1235 | | // if refresh is smaller than we'd like, it only scores up to 0.1 |
| 1236 | | if ((double)desc->dwRefreshRate < einfo->target_refresh) |
| 1237 | | refresh_score *= 0.1f; |
| 1238 | | |
| 1239 | | // if we're looking for a particular refresh, make sure it matches |
| 1240 | | if (desc->dwRefreshRate == einfo->window->m_win_config.refresh) |
| 1241 | | refresh_score = 2.0f; |
| 1242 | | |
| 1243 | | // weight size and refresh equally |
| 1244 | | final_score = size_score + refresh_score; |
| 1245 | | |
| 1246 | | // best so far? |
| 1247 | | osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", (int)desc->dwWidth, (int)desc->dwHeight, (int)desc->dwRefreshRate, final_score * 1000.0f); |
| 1248 | | if (final_score > einfo->best_score) |
| 1249 | | { |
| 1250 | | einfo->best_score = final_score; |
| 1251 | | dd->width = desc->dwWidth; |
| 1252 | | dd->height = desc->dwHeight; |
| 1253 | | dd->refresh = desc->dwRefreshRate; |
| 1254 | | } |
| 1255 | | return DDENUMRET_OK; |
| 1256 | | } |
| 1257 | | |
| 1258 | | |
| 1259 | | |
| 1260 | | //============================================================ |
| 1261 | | // pick_best_mode |
| 1262 | | //============================================================ |
| 1263 | | |
| 1264 | | void renderer_dd::pick_best_mode() |
| 1265 | | { |
| 1266 | | mode_enum_info einfo; |
| 1267 | | HRESULT result; |
| 1268 | | |
| 1269 | | // determine the minimum width/height for the selected target |
| 1270 | | // note: technically we should not be calling this from an alternate window |
| 1271 | | // thread; however, it is only done during init time, and the init code on |
| 1272 | | // the main thread is waiting for us to finish, so it is safe to do so here |
| 1273 | | window().target()->compute_minimum_size(einfo.minimum_width, einfo.minimum_height); |
| 1274 | | |
| 1275 | | // use those as the target for now |
| 1276 | | einfo.target_width = einfo.minimum_width * MAX(1, window().prescale()); |
| 1277 | | einfo.target_height = einfo.minimum_height * MAX(1, window().prescale()); |
| 1278 | | |
| 1279 | | // determine the refresh rate of the primary screen |
| 1280 | | einfo.target_refresh = 60.0; |
| 1281 | | const screen_device *primary_screen = window().machine().config().first_screen(); |
| 1282 | | if (primary_screen != NULL) |
| 1283 | | einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); |
| 1284 | | printf("Target refresh = %f\n", einfo.target_refresh); |
| 1285 | | |
| 1286 | | // if we're not stretching, allow some slop on the minimum since we can handle it |
| 1287 | | if (!video_config.hwstretch) |
| 1288 | | { |
| 1289 | | einfo.minimum_width -= 4; |
| 1290 | | einfo.minimum_height -= 4; |
| 1291 | | } |
| 1292 | | |
| 1293 | | // if we are stretching, aim for a mode approximately 2x the game's resolution |
| 1294 | | else if (window().prescale() <= 1) |
| 1295 | | { |
| 1296 | | einfo.target_width *= 2; |
| 1297 | | einfo.target_height *= 2; |
| 1298 | | } |
| 1299 | | |
| 1300 | | // fill in the rest of the data |
| 1301 | | einfo.window = &window(); |
| 1302 | | einfo.renderer = this; |
| 1303 | | einfo.best_score = 0.0f; |
| 1304 | | |
| 1305 | | // enumerate the modes |
| 1306 | | osd_printf_verbose("DirectDraw: Selecting video mode...\n"); |
| 1307 | | result = IDirectDraw7_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &einfo, enum_modes_callback); |
| 1308 | | if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during EnumDisplayModes call\n", (int)result); |
| 1309 | | osd_printf_verbose("DirectDraw: Mode selected = %4dx%4d@%3dHz\n", width, height, refresh); |
| 1310 | | } |