1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

Compare commits

...

29 Commits

Author SHA1 Message Date
Alfred Agrell
1953d1e774 mf/tests: Clobber the alignment and bytes per second, to test if the DMO fixes it. 2024-06-19 21:05:58 +02:00
Alfred Agrell
1b702aea3c winegstreamer: Recalculate alignment and bytes per second, instead of copying from input. 2024-06-19 21:05:58 +02:00
Alfred Agrell
73f2e64fd4 quartz/tests: Test that avi_decompressor_source_qc_Notify does not deadlock if called from a foreign thread during IMemInput_Receive. 2024-06-19 21:05:52 +02:00
Alfred Agrell
c4a162a8fe quartz: Allow concurrent calls to AVI decoder qc_Notify and Receive.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
1543fc8d1b msvfw32/tests: Test that Cinepak rejects unsupported output types. 2024-06-19 21:05:52 +02:00
Alfred Agrell
640698e432 iccvid: Reject unsupported output types.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
66ceeed861 quartz/tests: Add Cinepak test to avi splitter. 2024-06-19 21:05:52 +02:00
Alfred Agrell
fb523ed66f winegstreamer: Make AVI splitter use end of previous frame if the current frame doesn't have a timestamp.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Alfred Agrell
ed819cc973 winegstreamer: Implement AM_MEDIA_TYPE to wg_format converter for Cinepak video.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56698
2024-06-19 21:05:52 +02:00
Brendan McGrath
427e848d0d mf: Handle an error during Media Session Close.
Fixes the missing MESessionClosed event in this scenario.
2024-06-19 21:05:16 +02:00
Brendan McGrath
02ca366b5a mf: Handle MediaSession Close when state is SESSION_STATE_RESTARTING_SOURCES.
Fixes the missing MESessionClosed event in this scenario.
2024-06-19 21:05:15 +02:00
Brendan McGrath
af565ce846 mf/tests: Add additional tests for MESessionClosed event. 2024-06-19 21:05:15 +02:00
Hans Leidekker
bb46d4a621 odbc32: Rebind parameters when the result length array is resized. 2024-06-19 21:05:05 +02:00
Alexandre Julliard
2ac86fb8c3 kernelbase: Don't use WRITECOPY protection on anonymous mappings. 2024-06-19 21:01:47 +02:00
Alistair Leslie-Hughes
0a83c4f287 msado15: Use the correct version when loading the typelib. 2024-06-19 18:44:47 +02:00
Alexandros Frantzis
2e5b4ff32a winex11: Use default wglGetPixelFormatAttribivARB implementation.
Populate all the ARB related fields of advertised pixel formats, so that
the default implementation of wglGetPixelFormatAttribivARB (in opengl32)
will be used to get the pixel format attributes.
2024-06-19 18:43:07 +02:00
Alexandros Frantzis
8934fbcdbd winex11: Pass wgl_pixel_format to describe_pixel_format. 2024-06-19 18:43:07 +02:00
Alexandros Frantzis
35801043df winex11: Update describe_pixel_format coding style. 2024-06-19 18:43:07 +02:00
Alexandros Frantzis
3ecd3ff853 opengl32: Add default implementation for wglGetPixelFormatAttribfvARB.
The default implementation is always used, and never calls the driver
implementation of this function, so we can remove all the driver
implementations.
2024-06-19 18:42:45 +02:00
Alexandros Frantzis
5b126f7806 opengl32: Add default implementation for wglGetPixelFormatAttribivARB.
Extend the wgl_pixel_format struct with extra fields required to
implement wglGetPixelFormatAttribivARB in opengl32.dll. The default
implementation will be used automatically if the driver populates the
extra fields.
2024-06-19 18:40:29 +02:00
Eric Pouech
6d6fee9dda cmd: Fix delay expansion in FOR loop for filesets.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:10 +02:00
Eric Pouech
2e2a3f4539 cmd: Split parsing from executing FOR loops for filesets (/F).
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:09 +02:00
Eric Pouech
53f7a59992 cmd: Fix delay expansion in FOR /L loops.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:07 +02:00
Eric Pouech
9ba05f5e5b cmd: Split parsing from executing FOR loops for numbers (/L).
Introducing CMD_FOR_CONTROL structure to store parsing output
for consumption in execution.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-06-19 11:38:05 +02:00
Brendan Shanks
4a3365daff dbghelp: Add ARM/ARM64 machine types for Mach-O. 2024-06-19 11:15:32 +02:00
Elizabeth Figura
1200a80d76 ntdll/tests: Test IOSB handling with NtFlushBuffersFile. 2024-06-19 11:14:07 +02:00
Elizabeth Figura
898253af36 ntdll/tests: Test IOSB handling for a synchronous write which cannot be satisfied immediately. 2024-06-19 11:14:07 +02:00
Elizabeth Figura
d72567c626 ntdll/tests: Use NtReadFile to test WoW64 IOSB handling.
The current ioctls don't reliably return synchronously for overlapped handles
on Windows, which makes some of the conclusions drawn by the tests less clear.

Use NtReadFile instead, which will always return synchronously if there is data
in the pipe.
2024-06-19 11:14:06 +02:00
Alfred Agrell
e4e5d22145 quartz: Implement AMT/WMT differences for WMV media type.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56769
2024-06-19 11:13:29 +02:00
29 changed files with 1569 additions and 608 deletions

View File

@ -153,6 +153,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
#define MACHO_CPU_TYPE_X86 0x00000007
#define MACHO_CPU_TYPE_X86_64 0x01000007
#define MACHO_CPU_TYPE_ARM 0x0000000c
#define MACHO_CPU_TYPE_ARM64 0x0100000c
#define MACHO_MH_EXECUTE 0x2
#define MACHO_MH_DYLIB 0x6
@ -212,6 +214,8 @@ static USHORT macho_cpu_to_machine(unsigned cpu)
{
case MACHO_CPU_TYPE_X86: return IMAGE_FILE_MACHINE_I386;
case MACHO_CPU_TYPE_X86_64: return IMAGE_FILE_MACHINE_AMD64;
case MACHO_CPU_TYPE_ARM: return IMAGE_FILE_MACHINE_ARMNT;
case MACHO_CPU_TYPE_ARM64: return IMAGE_FILE_MACHINE_ARM64;
default:
FIXME("Untranslated Mach-O CPU %x\n", cpu);
return IMAGE_FILE_MACHINE_UNKNOWN;

View File

@ -797,26 +797,21 @@ static LRESULT ICCVID_DecompressQuery( ICCVID_Info *info, LPBITMAPINFO in, LPBIT
if( in->bmiHeader.biWidth != out->bmiHeader.biWidth )
return ICERR_BADFORMAT;
switch( out->bmiHeader.biBitCount )
switch( out->bmiHeader.biCompression )
{
case 16:
if ( out->bmiHeader.biCompression == BI_BITFIELDS )
{
if ( !ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) &&
!ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
{
TRACE("unsupported output bit field(s) for 16-bit colors\n");
return ICERR_BADFORMAT;
}
}
case BI_RGB:
if ( out->bmiHeader.biBitCount == 16 || out->bmiHeader.biBitCount == 24 || out->bmiHeader.biBitCount == 32 )
return ICERR_OK;
break;
case 24:
case 32:
case BI_BITFIELDS:
if ( out->bmiHeader.biBitCount == 16 && ICCVID_CheckMask(out->bmiColors, 0x7C00, 0x03E0, 0x001F) )
return ICERR_OK;
if ( out->bmiHeader.biBitCount == 16 && ICCVID_CheckMask(out->bmiColors, 0xF800, 0x07E0, 0x001F) )
return ICERR_OK;
break;
default:
TRACE("unsupported output bitcount = %d\n", out->bmiHeader.biBitCount );
return ICERR_BADFORMAT;
}
TRACE("unsupported output format\n");
return ICERR_BADFORMAT;
}
return ICERR_OK;

View File

@ -604,7 +604,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
SIZE_T size, SIZE_T *bytes_written )
{
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | PAGE_EXECUTE_WRITECOPY;
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE;
MEMORY_BASIC_INFORMATION info;
void *base_addr;
SIZE_T region_size;
@ -634,6 +634,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
base_addr = ROUND_ADDR( addr );
region_size = ROUND_SIZE( addr, size );
region_size = min( region_size, (char *)info.BaseAddress + info.RegionSize - (char *)base_addr );
prot |= (info.Type == MEM_PRIVATE) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_WRITECOPY;
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
base_addr, region_size, 1, prot );

View File

@ -1274,6 +1274,7 @@ static void session_close(struct media_session *session)
switch (session->state)
{
case SESSION_STATE_STOPPED:
case SESSION_STATE_RESTARTING_SOURCES:
hr = session_finalize_sinks(session);
break;
case SESSION_STATE_STARTED:
@ -3192,8 +3193,15 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
break;
}
if (session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION || FAILED(hr))
if (session->presentation.flags & SESSION_FLAG_END_OF_PRESENTATION)
session_set_stopped(session, hr);
else if (FAILED(hr))
{
if (session->presentation.flags & SESSION_FLAG_FINALIZE_SINKS)
session_set_closed(session, hr);
else
session_set_stopped(session, hr);
}
break;
default:

View File

@ -6249,6 +6249,8 @@ static void test_media_session_Start(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* Media session is shut down */
hr = IMFMediaSource_Shutdown(source);
@ -6331,6 +6333,8 @@ static void test_media_session_Start(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Shutdown(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSource_Shutdown(source);
@ -6534,6 +6538,88 @@ static void test_MFEnumDeviceSources(void)
CoUninitialize();
}
static void test_media_session_Close(void)
{
media_type_desc video_rgb32_desc =
{
ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
};
struct test_grabber_callback *grabber_callback;
IMFPresentationClock *presentation_clock;
IMFActivate *sink_activate;
IMFAsyncCallback *callback;
IMFMediaType *output_type;
IMFMediaSession *session;
IMFMediaSource *source;
IMFTopology *topology;
PROPVARIANT propvar;
IMFClock *clock;
UINT64 duration;
HRESULT hr;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
if (!(source = create_media_source(L"test.mp4", L"video/mp4")))
{
todo_wine /* Gitlab CI Debian runner */
win_skip("MP4 media source is not supported, skipping tests.\n");
MFShutdown();
return;
}
grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
hr = MFCreateMediaType(&output_type);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
init_media_type(output_type, video_rgb32_desc, -1);
hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate);
ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
IMFMediaType_Release(output_type);
hr = MFCreateMediaSession(NULL, &session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
topology = create_test_topology(source, sink_activate, &duration);
hr = IMFMediaSession_SetTopology(session, 0, topology);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFTopology_Release(topology);
hr = IMFMediaSession_GetClock(session, &clock);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFClock_Release(clock);
propvar.vt = VT_EMPTY;
hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
callback = create_test_callback(TRUE);
hr = wait_media_event(session, callback, MESessionStarted, 5000, &propvar);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Close(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSource_Shutdown(source);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = wait_media_event_until_blocking(session, callback, MESessionClosed, 5000, &propvar);
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_Shutdown(session);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFPresentationClock_Release(presentation_clock);
IMFAsyncCallback_Release(callback);
IMFMediaSession_Release(session);
IMFActivate_ShutdownObject(sink_activate);
IMFActivate_Release(sink_activate);
IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface);
IMFMediaSource_Release(source);
hr = MFShutdown();
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
}
START_TEST(mf)
{
init_functions();
@ -6568,4 +6654,5 @@ START_TEST(mf)
test_MFCreateSequencerSegmentOffset();
test_media_session_Start();
test_MFEnumDeviceSources();
test_media_session_Close();
}

View File

@ -3585,6 +3585,8 @@ static void test_wma_decoder_dmo_output_type(void)
good_output_type = (void *)buffer_good_output;
bad_output_type = (void *)buffer_bad_output;
init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate, 16);
((WAVEFORMATEX *)(input_type + 1))->nBlockAlign = 640;
((WAVEFORMATEX *)(input_type + 1))->nAvgBytesPerSec = 2000;
init_dmo_media_type_audio(good_output_type, &MEDIASUBTYPE_PCM, channel_count, rate, bits_per_sample);
memset(bad_output_type, 0, sizeof(buffer_bad_output));

View File

@ -159,7 +159,7 @@ static HRESULT load_typelib(void)
if(typelib)
return S_OK;
hres = LoadRegTypeLib(&LIBID_ADODB, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
hres = LoadRegTypeLib(&LIBID_ADODB, 2, 8, LOCALE_SYSTEM_DEFAULT, &tl);
if(FAILED(hres)) {
ERR("LoadRegTypeLib failed: %08lx\n", hres);
return hres;

View File

@ -190,6 +190,13 @@ static void test_Locate(void)
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biHeight = - bo.biHeight;
bo.biCompression = mmioFOURCC('U','Y','V','Y');
bo.biBitCount = bi.biBitCount = 16;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
ok(h == 0, "cvid->UYVY succeeded\n");
if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
bo.biCompression = BI_RGB;
bo.biBitCount = bi.biBitCount = 32;
h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
ok(h != 0, "cvid->RGB32 failed\n");

View File

@ -2125,14 +2125,31 @@ static void test_init_block(void)
}
static DWORD WINAPI iosb_delayed_write_thread(void *arg)
{
HANDLE client = arg;
DWORD size;
BOOL ret;
Sleep(100);
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
return 0;
}
static void test_iosb(void)
{
static const char pipe_name[] = "\\\\.\\pipe\\wow64iosbnamedpipe";
HANDLE client, server;
HANDLE client, server, thread;
NTSTATUS status;
ULONG64 func;
DWORD id;
ULONG64 read_func, flush_func;
IO_STATUS_BLOCK iosb32;
char buffer[6];
DWORD size;
BOOL ret;
struct
{
union
@ -2142,66 +2159,89 @@ static void test_iosb(void)
};
ULONG64 Information;
} iosb64;
ULONG64 args[] = { 0, 0, 0, 0, (ULONG_PTR)&iosb64, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 };
ULONG64 args[] = { 0, 0, 0, 0, (ULONG_PTR)&iosb64, (ULONG_PTR)buffer, sizeof(buffer), 0, 0 };
ULONG64 flush_args[] = { 0, (ULONG_PTR)&iosb64 };
if (!is_wow64) return;
if (!code_mem) return;
if (!ntdll_module) return;
func = get_proc_address64( ntdll_module, "NtFsControlFile" );
read_func = get_proc_address64( ntdll_module, "NtReadFile" );
flush_func = get_proc_address64( ntdll_module, "NtFlushBuffersFile" );
/* async calls set iosb32 but not iosb64 */
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4, 1024, 1024, 1000, NULL );
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING, "NtFsControlFile returned %lx\n", status );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING, "NtReadFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
ok( iosb32.Status == 0, "Wrong iostatus %lx\n", iosb32.Status );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb32.Information == sizeof("data"), "Wrong information %Ix\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb32.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == sizeof("data"), "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
if (iosb32.Information == sizeof("data"))
ok( !memcmp( buffer, "data", iosb32.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
}
/* syscalls which are always synchronous set iosb64 but not iosb32 */
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
id = 0xdeadbeef;
args[5] = FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE;
args[6] = (ULONG_PTR)"ClientProcessId";
args[7] = sizeof("ClientProcessId");
args[8] = (ULONG_PTR)&id;
args[9] = sizeof(id);
flush_args[0] = (LONG_PTR)server;
status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0, "info changed to %lx\n", (ULONG_PTR)iosb64.Information );
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_PENDING || status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == sizeof(id), "info changed to %Ix\n", iosb32.Information );
ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status );
ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
}
ok( id == GetCurrentProcessId(), "wrong id %lx / %lx\n", id, GetCurrentProcessId() );
CloseHandle( client );
CloseHandle( server );
/* synchronous calls set iosb64 but not iosb32 */
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND,
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4, 1024, 1024, 1000, NULL );
ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError() );
@ -2210,19 +2250,60 @@ static void test_iosb(void)
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError() );
ret = WriteFile( client, "data", sizeof("data"), &size, NULL );
ok( ret == TRUE, "got error %lu\n", GetLastError() );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
id = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status );
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "status changed to %lx\n", iosb64.Status );
ok( iosb64.Information == sizeof(id), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( id == GetCurrentProcessId(), "wrong id %lx / %lx\n", id, GetCurrentProcessId() );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb64.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
thread = CreateThread( NULL, 0, iosb_delayed_write_thread, client, 0, NULL );
memset( buffer, 0xcc, sizeof(buffer) );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
args[0] = (LONG_PTR)server;
status = call_func64( read_func, ARRAY_SIZE(args), args );
ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status );
todo_wine
{
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == sizeof("data"), "info changed to %Ix\n", (ULONG_PTR)iosb64.Information );
ok( !memcmp( buffer, "data", iosb64.Information ),
"got wrong data %s\n", debugstr_an(buffer, iosb64.Information) );
}
ret = WaitForSingleObject( thread, 1000 );
ok(!ret, "got %d\n", ret );
CloseHandle( thread );
memset( &iosb32, 0x55, sizeof(iosb32) );
iosb64.Pointer = PtrToUlong( &iosb32 );
iosb64.Information = 0xdeadbeef;
flush_args[0] = (LONG_PTR)server;
status = call_func64( flush_func, ARRAY_SIZE(flush_args), flush_args );
ok( status == STATUS_SUCCESS, "NtFlushBuffersFile returned %lx\n", status );
ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status );
ok( iosb32.Information == 0x55555555, "info changed to %lx\n", iosb32.Information );
ok( iosb64.Pointer == STATUS_SUCCESS, "pointer changed to %I64x\n", iosb64.Pointer );
ok( iosb64.Information == 0, "info changed to %lx\n", (ULONG_PTR)iosb64.Information );
CloseHandle( client );
CloseHandle( server );
}

View File

@ -234,6 +234,10 @@ SQLRETURN WINAPI SQLBindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber,
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_col, SQL_PARAM_INPUT_OUTPUT, ColumnNumber, handle->row_count )) return SQL_ERROR;
handle->bind_col.param[i].col.target_type = TargetType;
handle->bind_col.param[i].col.target_value = TargetValue;
handle->bind_col.param[i].col.buffer_length = BufferLength;
params.StatementHandle = handle->unix_handle;
if (StrLen_or_Ind) params.StrLen_or_Ind = handle->bind_col.param[i].len;
if (SUCCESS(( ret = ODBC_CALL( SQLBindCol, &params )))) handle->bind_col.param[i].ptr = StrLen_or_Ind;
@ -274,6 +278,11 @@ SQLRETURN WINAPI SQLBindParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNu
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_param, SQL_PARAM_INPUT, ParameterNumber, handle->row_count )) return SQL_ERROR;
handle->bind_param.param[i].param.value_type = ValueType;
handle->bind_param.param[i].param.parameter_type = ParameterType;
handle->bind_param.param[i].param.length_precision = LengthPrecision;
handle->bind_param.param[i].param.parameter_scale = ParameterScale;
handle->bind_param.param[i].param.parameter_value = ParameterValue;
params.StatementHandle = handle->unix_handle;
params.StrLen_or_Ind = handle->bind_param.param[i].len;
@ -1376,20 +1385,76 @@ static BOOL resize_result_lengths( struct handle *handle, UINT size )
UINT i;
for (i = 0; i < handle->bind_col.count; i++)
{
UINT8 *tmp = realloc( handle->bind_col.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!handle->bind_col.param[i].ptr) continue;
if (!(tmp = realloc( handle->bind_col.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_col.param[i].len)
{
struct SQLBindCol_params params;
params.StatementHandle = handle->unix_handle;
params.ColumnNumber = i + 1;
params.TargetType = handle->bind_col.param[i].col.target_type;
params.TargetValue = handle->bind_col.param[i].col.target_value;
params.BufferLength = handle->bind_col.param[i].col.buffer_length;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindCol, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_col.param[i].len = tmp;
}
for (i = 0; i < handle->bind_param.count; i++)
{
UINT8 *tmp = realloc( handle->bind_param.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!handle->bind_param.param[i].ptr) continue;
if (!(tmp = realloc( handle->bind_param.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_param.param[i].len)
{
struct SQLBindParam_params params;
params.StatementHandle = handle->unix_handle;
params.ParameterNumber = i + 1;
params.ValueType = handle->bind_param.param[i].param.value_type;
params.ParameterType = handle->bind_param.param[i].param.parameter_type;
params.LengthPrecision = handle->bind_param.param[i].param.length_precision;
params.ParameterScale = handle->bind_param.param[i].param.parameter_scale;
params.ParameterValue = handle->bind_param.param[i].param.parameter_value;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindParam, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_param.param[i].len = tmp;
}
for (i = 0; i < handle->bind_parameter.count; i++)
{
UINT8 *tmp = realloc( handle->bind_parameter.param[i].len, size * sizeof(UINT64) );
if (!tmp) return FALSE;
UINT8 *tmp;
if (!(tmp = realloc( handle->bind_parameter.param[i].len, size * sizeof(UINT64) ))) return FALSE;
if (tmp != handle->bind_parameter.param[i].len)
{
struct SQLBindParameter_params params;
params.StatementHandle = handle->unix_handle;
params.ParameterNumber = i + 1;
params.InputOutputType = handle->bind_parameter.param[i].parameter.input_output_type;
params.ValueType = handle->bind_parameter.param[i].parameter.value_type;
params.ParameterType = handle->bind_parameter.param[i].parameter.parameter_type;
params.ColumnSize = handle->bind_parameter.param[i].parameter.column_size;
params.DecimalDigits = handle->bind_parameter.param[i].parameter.decimal_digits;
params.ParameterValue = handle->bind_parameter.param[i].parameter.parameter_value;
params.BufferLength = handle->bind_parameter.param[i].parameter.buffer_length;
params.StrLen_or_Ind = tmp;
if (!SUCCESS(ODBC_CALL( SQLBindParameter, &params )))
{
free( tmp );
return FALSE;
}
}
handle->bind_parameter.param[i].len = tmp;
}
return TRUE;
@ -1984,6 +2049,13 @@ SQLRETURN WINAPI SQLBindParameter(SQLHSTMT StatementHandle, SQLUSMALLINT Paramet
return SQL_ERROR;
}
if (!alloc_binding( &handle->bind_parameter, InputOutputType, ParameterNumber, handle->row_count )) return SQL_ERROR;
handle->bind_parameter.param[i].parameter.input_output_type = InputOutputType;
handle->bind_parameter.param[i].parameter.value_type = ValueType;
handle->bind_parameter.param[i].parameter.parameter_type = ParameterType;
handle->bind_parameter.param[i].parameter.column_size = ColumnSize;
handle->bind_parameter.param[i].parameter.decimal_digits = DecimalDigits;
handle->bind_parameter.param[i].parameter.parameter_value = ParameterValue;
handle->bind_parameter.param[i].parameter.buffer_length = BufferLength;
params.StatementHandle = handle->unix_handle;
params.StrLen_or_Ind = handle->bind_parameter.param[i].len;

View File

@ -152,9 +152,42 @@ enum sql_funcs
unix_funcs_count
};
struct bind_col_args
{
INT16 target_type;
void *target_value;
INT64 buffer_length;
};
struct bind_param_args
{
INT16 value_type;
INT16 parameter_type;
UINT64 length_precision;
INT16 parameter_scale;
void *parameter_value;
};
struct bind_parameter_args
{
INT16 input_output_type;
INT16 value_type;
INT16 parameter_type;
UINT64 column_size;
INT16 decimal_digits;
void *parameter_value;
INT64 buffer_length;
};
struct param
{
INT16 type;
union
{
struct bind_col_args col;
struct bind_param_args param;
struct bind_parameter_args parameter;
};
UINT8 *len; /* result length array stored in Unix lib */
void *ptr; /* result length ptr passed by client */
};

View File

@ -181,6 +181,8 @@ my %manual_win_thunks =
"wglGetExtensionsStringARB" => 1,
"wglGetExtensionsStringEXT" => 1,
"wglGetPixelFormat" => 1,
"wglGetPixelFormatAttribfvARB" => 1,
"wglGetPixelFormatAttribivARB" => 1,
"wglGetProcAddress" => 1,
"wglQueryCurrentRendererStringWINE" => 1,
"wglQueryRendererStringWINE" => 1,
@ -884,6 +886,31 @@ print HEADER "struct wgl_pbuffer;\n\n";
print HEADER "struct wgl_pixel_format\n";
print HEADER "{\n";
print HEADER " PIXELFORMATDESCRIPTOR pfd;\n";
print HEADER " int swap_method;\n";
print HEADER " int transparent;\n";
print HEADER " int pixel_type;\n";
print HEADER " int draw_to_pbuffer;\n";
print HEADER " int max_pbuffer_pixels;\n";
print HEADER " int max_pbuffer_width;\n";
print HEADER " int max_pbuffer_height;\n";
print HEADER " int transparent_red_value;\n";
print HEADER " int transparent_red_value_valid;\n";
print HEADER " int transparent_green_value;\n";
print HEADER " int transparent_green_value_valid;\n";
print HEADER " int transparent_blue_value;\n";
print HEADER " int transparent_blue_value_valid;\n";
print HEADER " int transparent_alpha_value;\n";
print HEADER " int transparent_alpha_value_valid;\n";
print HEADER " int transparent_index_value;\n";
print HEADER " int transparent_index_value_valid;\n";
print HEADER " int sample_buffers;\n";
print HEADER " int samples;\n";
print HEADER " int bind_to_texture_rgb;\n";
print HEADER " int bind_to_texture_rgba;\n";
print HEADER " int bind_to_texture_rectangle_rgb;\n";
print HEADER " int bind_to_texture_rectangle_rgba;\n";
print HEADER " int framebuffer_srgb_capable;\n";
print HEADER " int float_components;\n";
print HEADER "};\n\n";
print HEADER "struct opengl_funcs\n{\n";

View File

@ -24217,24 +24217,6 @@ static HDC WINAPI wglGetPbufferDCARB( HPBUFFERARB hPbuffer )
return args.ret;
}
static BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues )
{
struct wglGetPixelFormatAttribfvARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .iPixelFormat = iPixelFormat, .iLayerPlane = iLayerPlane, .nAttributes = nAttributes, .piAttributes = piAttributes, .pfValues = pfValues };
NTSTATUS status;
TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, pfValues %p\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues );
if ((status = UNIX_CALL( wglGetPixelFormatAttribfvARB, &args ))) WARN( "wglGetPixelFormatAttribfvARB returned %#lx\n", status );
return args.ret;
}
static BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues )
{
struct wglGetPixelFormatAttribivARB_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .iPixelFormat = iPixelFormat, .iLayerPlane = iLayerPlane, .nAttributes = nAttributes, .piAttributes = piAttributes, .piValues = piValues };
NTSTATUS status;
TRACE( "hdc %p, iPixelFormat %d, iLayerPlane %d, nAttributes %u, piAttributes %p, piValues %p\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues );
if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args ))) WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status );
return args.ret;
}
static int WINAPI wglGetSwapIntervalEXT(void)
{
struct wglGetSwapIntervalEXT_params args = { .teb = NtCurrentTeb() };
@ -24340,6 +24322,8 @@ extern GLboolean WINAPI glUnmapNamedBufferEXT( GLuint buffer );
extern HDC WINAPI wglGetCurrentReadDCARB(void);
extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc );
extern const char * WINAPI wglGetExtensionsStringEXT(void);
extern BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues );
extern BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues );
extern const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute );
extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute );
const void *extension_procs[] =

View File

@ -322,7 +322,9 @@ static struct wgl_pixel_format *get_pixel_formats( HDC hdc, UINT *num_formats,
}
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
if (!(args.formats = malloc( sizeof(*args.formats) * args.num_formats ))) goto error;
/* Clear formats memory since not all drivers deal with all wgl_pixel_format
* fields at the moment. */
if (!(args.formats = calloc( args.num_formats, sizeof(*args.formats) ))) goto error;
args.max_formats = args.num_formats;
if ((status = UNIX_CALL( get_pixel_formats, &args ))) goto error;
@ -343,6 +345,153 @@ error:
return NULL;
}
static BOOL wgl_attrib_uses_layer( int attrib )
{
switch (attrib)
{
case WGL_ACCELERATION_ARB:
case WGL_TRANSPARENT_ARB:
case WGL_SHARE_DEPTH_ARB:
case WGL_SHARE_STENCIL_ARB:
case WGL_SHARE_ACCUM_ARB:
case WGL_TRANSPARENT_RED_VALUE_ARB:
case WGL_TRANSPARENT_GREEN_VALUE_ARB:
case WGL_TRANSPARENT_BLUE_VALUE_ARB:
case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
case WGL_TRANSPARENT_INDEX_VALUE_ARB:
case WGL_SUPPORT_GDI_ARB:
case WGL_SUPPORT_OPENGL_ARB:
case WGL_DOUBLE_BUFFER_ARB:
case WGL_STEREO_ARB:
case WGL_PIXEL_TYPE_ARB:
case WGL_COLOR_BITS_ARB:
case WGL_RED_BITS_ARB:
case WGL_RED_SHIFT_ARB:
case WGL_GREEN_BITS_ARB:
case WGL_GREEN_SHIFT_ARB:
case WGL_BLUE_BITS_ARB:
case WGL_BLUE_SHIFT_ARB:
case WGL_ALPHA_BITS_ARB:
case WGL_ALPHA_SHIFT_ARB:
case WGL_ACCUM_BITS_ARB:
case WGL_ACCUM_RED_BITS_ARB:
case WGL_ACCUM_GREEN_BITS_ARB:
case WGL_ACCUM_BLUE_BITS_ARB:
case WGL_ACCUM_ALPHA_BITS_ARB:
case WGL_DEPTH_BITS_ARB:
case WGL_STENCIL_BITS_ARB:
case WGL_AUX_BUFFERS_ARB:
case WGL_SAMPLE_BUFFERS_ARB:
case WGL_SAMPLES_ARB:
case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB:
case WGL_FLOAT_COMPONENTS_NV:
return TRUE;
default:
return FALSE;
}
}
static BOOL wgl_pixel_format_get_attrib( const struct wgl_pixel_format *fmt, int attrib, int *value )
{
int val = 0;
int valid = -1;
switch (attrib)
{
case WGL_DRAW_TO_WINDOW_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_WINDOW); break;
case WGL_DRAW_TO_BITMAP_ARB: val = !!(fmt->pfd.dwFlags & PFD_DRAW_TO_BITMAP); break;
case WGL_ACCELERATION_ARB:
if (fmt->pfd.dwFlags & PFD_GENERIC_ACCELERATED)
val = WGL_GENERIC_ACCELERATION_ARB;
else if (fmt->pfd.dwFlags & PFD_GENERIC_FORMAT)
val = WGL_NO_ACCELERATION_ARB;
else
val = WGL_FULL_ACCELERATION_ARB;
break;
case WGL_NEED_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_PALETTE); break;
case WGL_NEED_SYSTEM_PALETTE_ARB: val = !!(fmt->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE); break;
case WGL_SWAP_LAYER_BUFFERS_ARB: val = !!(fmt->pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS); break;
case WGL_SWAP_METHOD_ARB: val = fmt->swap_method; break;
case WGL_NUMBER_OVERLAYS_ARB:
case WGL_NUMBER_UNDERLAYS_ARB:
/* We don't support any overlays/underlays. */
val = 0;
break;
case WGL_TRANSPARENT_ARB: val = fmt->transparent; break;
case WGL_SHARE_DEPTH_ARB:
case WGL_SHARE_STENCIL_ARB:
case WGL_SHARE_ACCUM_ARB:
/* We support only a main plane at the moment which by definition
* shares the depth/stencil/accum buffers with itself. */
val = GL_TRUE;
break;
case WGL_SUPPORT_GDI_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_GDI); break;
case WGL_SUPPORT_OPENGL_ARB: val = !!(fmt->pfd.dwFlags & PFD_SUPPORT_OPENGL); break;
case WGL_DOUBLE_BUFFER_ARB: val = !!(fmt->pfd.dwFlags & PFD_DOUBLEBUFFER); break;
case WGL_STEREO_ARB: val = !!(fmt->pfd.dwFlags & PFD_STEREO); break;
case WGL_PIXEL_TYPE_ARB: val = fmt->pixel_type; break;
case WGL_COLOR_BITS_ARB: val = fmt->pfd.cColorBits; break;
case WGL_RED_BITS_ARB: val = fmt->pfd.cRedBits; break;
case WGL_RED_SHIFT_ARB: val = fmt->pfd.cRedShift; break;
case WGL_GREEN_BITS_ARB: val = fmt->pfd.cGreenBits; break;
case WGL_GREEN_SHIFT_ARB: val = fmt->pfd.cGreenShift; break;
case WGL_BLUE_BITS_ARB: val = fmt->pfd.cBlueBits; break;
case WGL_BLUE_SHIFT_ARB: val = fmt->pfd.cBlueShift; break;
case WGL_ALPHA_BITS_ARB: val = fmt->pfd.cAlphaBits; break;
case WGL_ALPHA_SHIFT_ARB: val = fmt->pfd.cAlphaShift; break;
case WGL_ACCUM_BITS_ARB: val = fmt->pfd.cAccumBits; break;
case WGL_ACCUM_RED_BITS_ARB: val = fmt->pfd.cAccumRedBits; break;
case WGL_ACCUM_GREEN_BITS_ARB: val = fmt->pfd.cAccumGreenBits; break;
case WGL_ACCUM_BLUE_BITS_ARB: val = fmt->pfd.cAccumBlueBits; break;
case WGL_ACCUM_ALPHA_BITS_ARB: val = fmt->pfd.cAccumAlphaBits; break;
case WGL_DEPTH_BITS_ARB: val = fmt->pfd.cDepthBits; break;
case WGL_STENCIL_BITS_ARB: val = fmt->pfd.cStencilBits; break;
case WGL_AUX_BUFFERS_ARB: val = fmt->pfd.cAuxBuffers; break;
case WGL_DRAW_TO_PBUFFER_ARB: val = fmt->draw_to_pbuffer; break;
case WGL_MAX_PBUFFER_PIXELS_ARB: val = fmt->max_pbuffer_pixels; break;
case WGL_MAX_PBUFFER_WIDTH_ARB: val = fmt->max_pbuffer_width; break;
case WGL_MAX_PBUFFER_HEIGHT_ARB: val = fmt->max_pbuffer_height; break;
case WGL_TRANSPARENT_RED_VALUE_ARB:
val = fmt->transparent_red_value;
valid = !!fmt->transparent_red_value_valid;
break;
case WGL_TRANSPARENT_GREEN_VALUE_ARB:
val = fmt->transparent_green_value;
valid = !!fmt->transparent_green_value_valid;
break;
case WGL_TRANSPARENT_BLUE_VALUE_ARB:
val = fmt->transparent_blue_value;
valid = !!fmt->transparent_blue_value_valid;
break;
case WGL_TRANSPARENT_ALPHA_VALUE_ARB:
val = fmt->transparent_alpha_value;
valid = !!fmt->transparent_alpha_value_valid;
break;
case WGL_TRANSPARENT_INDEX_VALUE_ARB:
val = fmt->transparent_index_value;
valid = !!fmt->transparent_index_value_valid;
break;
case WGL_SAMPLE_BUFFERS_ARB: val = fmt->sample_buffers; break;
case WGL_SAMPLES_ARB: val = fmt->samples; break;
case WGL_BIND_TO_TEXTURE_RGB_ARB: val = fmt->bind_to_texture_rgb; break;
case WGL_BIND_TO_TEXTURE_RGBA_ARB: val = fmt->bind_to_texture_rgba; break;
case WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV: val = fmt->bind_to_texture_rectangle_rgb; break;
case WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV: val = fmt->bind_to_texture_rectangle_rgba; break;
case WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB: val = fmt->framebuffer_srgb_capable; break;
case WGL_FLOAT_COMPONENTS_NV: val = fmt->float_components; break;
default:
FIXME( "unsupported 0x%x WGL attribute\n", attrib );
valid = 0;
break;
}
/* If we haven't already determined validity, use the default check */
if (valid == -1) valid = val != -1;
if (valid) *value = val;
return valid;
}
INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDESCRIPTOR *ppfd )
{
struct wgl_pixel_format *formats;
@ -360,6 +509,102 @@ INT WINAPI wglDescribePixelFormat( HDC hdc, int index, UINT size, PIXELFORMATDES
return num_onscreen_formats;
}
/***********************************************************************
* wglGetPixelFormatAttribivARB (OPENGL32.@)
*/
BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int index, int plane, UINT count,
const int *attributes, int *values )
{
static const DWORD invalid_data_error = 0xC007000D;
struct wgl_pixel_format *formats;
UINT i, num_formats, num_onscreen_formats;
TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
hdc, index, plane, count, attributes, values );
formats = get_pixel_formats( hdc, &num_formats, &num_onscreen_formats );
/* If the driver doesn't yet provide ARB attrib information in
* wgl_pixel_format, fall back to an explicit call. */
if (num_formats && !formats[0].pixel_type)
{
struct wglGetPixelFormatAttribivARB_params args =
{
.teb = NtCurrentTeb(),
.hdc = hdc,
.iPixelFormat = index,
.iLayerPlane = plane,
.nAttributes = count,
.piAttributes = attributes,
.piValues = values
};
NTSTATUS status;
if ((status = UNIX_CALL( wglGetPixelFormatAttribivARB, &args )))
WARN( "wglGetPixelFormatAttribivARB returned %#lx\n", status );
return args.ret;
}
if (!count) return TRUE;
if (count == 1 && attributes[0] == WGL_NUMBER_PIXEL_FORMATS_ARB)
{
values[0] = num_formats;
return TRUE;
}
if (index <= 0 || index > num_formats)
{
SetLastError( invalid_data_error );
return FALSE;
}
for (i = 0; i < count; ++i)
{
int attrib = attributes[i];
if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB)
{
values[i] = num_formats;
}
else if ((plane != 0 && wgl_attrib_uses_layer( attrib )) ||
!wgl_pixel_format_get_attrib( &formats[index - 1], attrib, &values[i] ))
{
SetLastError( invalid_data_error );
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* wglGetPixelFormatAttribfvARB (OPENGL32.@)
*/
BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int index, int plane, UINT count,
const int *attributes, FLOAT *values )
{
int *ivalues;
BOOL ret;
UINT i;
TRACE( "hdc %p, index %d, plane %d, count %u, attributes %p, values %p\n",
hdc, index, plane, count, attributes, values );
if (!(ivalues = malloc( count * sizeof(int) ))) return FALSE;
/* For now we can piggy-back on wglGetPixelFormatAttribivARB, since we don't support
* any non-integer attributes. */
ret = wglGetPixelFormatAttribivARB( hdc, index, plane, count, attributes, ivalues );
if (ret)
{
for (i = 0; i < count; i++)
values[i] = ivalues[i];
}
free( ivalues );
return ret;
}
/***********************************************************************
* wglGetPixelFormat (OPENGL32.@)
*/

View File

@ -48,6 +48,8 @@ struct avi_decompressor
HIC hvid;
BITMAPINFOHEADER* pBihIn;
CRITICAL_SECTION late_cs;
REFERENCE_TIME late;
};
@ -77,7 +79,9 @@ static HRESULT avi_decompressor_sink_query_accept(struct strmbase_pin *iface, co
static HRESULT avi_decompressor_sink_end_flush(struct strmbase_sink *iface)
{
struct avi_decompressor *filter = impl_from_strmbase_filter(iface->pin.filter);
EnterCriticalSection(&filter->late_cs);
filter->late = -1;
LeaveCriticalSection(&filter->late_cs);
if (filter->source.pin.peer)
return IPin_EndFlush(filter->source.pin.peer);
return S_OK;
@ -167,8 +171,10 @@ static HRESULT WINAPI avi_decompressor_sink_Receive(struct strmbase_sink *iface,
if (IMediaSample_IsSyncPoint(pSample) != S_OK)
flags |= ICDECOMPRESS_NOTKEYFRAME;
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
EnterCriticalSection(&This->late_cs);
if (hr == S_OK && AVIDec_DropSample(This, tStart))
flags |= ICDECOMPRESS_HURRYUP;
LeaveCriticalSection(&This->late_cs);
res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, &source_format->bmiHeader, pbDstStream);
if (res != ICERR_OK)
@ -482,12 +488,13 @@ static HRESULT WINAPI avi_decompressor_source_qc_Notify(IQualityControl *iface,
TRACE("filter %p, sender %p, type %#x, proportion %ld, late %s, timestamp %s.\n",
filter, sender, q.Type, q.Proportion, debugstr_time(q.Late), debugstr_time(q.TimeStamp));
EnterCriticalSection(&filter->filter.stream_cs);
/* can't take the stream CS here, Submarine Titans calls this function from a foreign thread while inside sink_Receive */
EnterCriticalSection(&filter->late_cs);
if (q.Late > 0)
filter->late = q.Late + q.TimeStamp;
else
filter->late = -1;
LeaveCriticalSection(&filter->filter.stream_cs);
LeaveCriticalSection(&filter->late_cs);
return S_OK;
}
@ -532,6 +539,9 @@ static void avi_decompressor_destroy(struct strmbase_filter *iface)
IPin_Disconnect(filter->source.pin.peer);
IPin_Disconnect(&filter->source.pin.IPin_iface);
filter->late_cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&filter->late_cs);
strmbase_sink_cleanup(&filter->sink);
strmbase_source_cleanup(&filter->source);
strmbase_passthrough_cleanup(&filter->passthrough);
@ -550,7 +560,9 @@ static HRESULT avi_decompressor_init_stream(struct strmbase_filter *iface)
if (!filter->source.pin.peer)
return S_OK;
EnterCriticalSection(&filter->late_cs);
filter->late = -1;
LeaveCriticalSection(&filter->late_cs);
source_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat;
if ((res = ICDecompressBegin(filter->hvid, filter->pBihIn, &source_format->bmiHeader)))
@ -618,6 +630,9 @@ HRESULT avi_dec_create(IUnknown *outer, IUnknown **out)
ISeekingPassThru_Init(&object->passthrough.ISeekingPassThru_iface, FALSE,
&object->sink.pin.IPin_iface);
InitializeCriticalSectionEx(&object->late_cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
object->late_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": object.late_cs");
TRACE("Created AVI decompressor %p.\n", object);
*out = &object->filter.IUnknown_inner;

View File

@ -873,6 +873,20 @@ static HRESULT testsink_connect(struct strmbase_sink *iface, IPin *peer, const A
return S_OK;
}
static DWORD WINAPI call_qc_notify(void *ptr)
{
struct testfilter *filter = ptr;
IQualityControl *qc;
Quality q = { Famine, 2000, -10000000, 10000000 };
IPin_QueryInterface(filter->sink.pin.peer, &IID_IQualityControl, (void**)&qc);
/* don't worry too much about what it returns, just check that it doesn't deadlock */
IQualityControl_Notify(qc, &filter->filter.IBaseFilter_iface, q);
IQualityControl_Release(qc);
return 0;
}
static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample *sample)
{
struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter);
@ -920,6 +934,13 @@ static HRESULT WINAPI testsink_Receive(struct strmbase_sink *iface, IMediaSample
hr = IMediaSample_IsSyncPoint(sample);
todo_wine_if (testmode == 5 || testmode == 6) ok(hr == S_OK, "Got hr %#lx.\n", hr);
if (testmode == 7)
{
HANDLE h = CreateThread(NULL, 0, call_qc_notify, filter, 0, NULL);
ok(WaitForSingleObject(h, 1000) == WAIT_OBJECT_0, "Didn't expect deadlock.\n");
CloseHandle(h);
}
return S_OK;
}
@ -1129,6 +1150,15 @@ static void test_sample_processing(IMediaControl *control, IMemInputPin *input,
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(!sink->got_sample, "Got %u calls to Receive().\n", sink->got_sample);
testmode = 7;
hr = IMediaSample_SetSyncPoint(sample, TRUE);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
sink->got_sample = 0;
hr = IMemInputPin_Receive(input, sample);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
ok(sink->got_sample == 1, "Got %u calls to Receive().\n", sink->got_sample);
sink->got_sample = 0;
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
@ -1174,7 +1204,7 @@ static void test_streaming_events(IMediaControl *control, IPin *sink,
ok(!testsink->got_eos, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
hr = IPin_EndOfStream(sink);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(!testsink->got_sample, "Got %u calls to Receive().\n", testsink->got_sample);
ok(!testsink->got_sample, "Got %u calls to Receive().\n", testsink->got_sample);
ok(testsink->got_eos == 1, "Got %u calls to IPin::EndOfStream().\n", testsink->got_eos);
testsink->got_eos = 0;
@ -1185,7 +1215,7 @@ static void test_streaming_events(IMediaControl *control, IPin *sink,
testmode = 0;
hr = IMemInputPin_Receive(input, sample);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(testsink->got_sample == 1, "Got %u calls to Receive().\n", testsink->got_sample);
ok(testsink->got_sample == 1, "Got %u calls to Receive().\n", testsink->got_sample);
testsink->got_sample = 0;
ok(!testsink->got_begin_flush, "Got %u calls to IPin::BeginFlush().\n", testsink->got_begin_flush);

View File

@ -1677,9 +1677,9 @@ static void test_seeking(void)
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
}
static void test_streaming(void)
static void test_streaming(const WCHAR *resname)
{
const WCHAR *filename = load_resource(L"test.avi");
const WCHAR *filename = load_resource(resname);
IBaseFilter *filter = create_avi_splitter();
IFilterGraph2 *graph = connect_input(filter, filename);
struct testfilter testsink;
@ -1691,6 +1691,8 @@ static void test_streaming(void)
ULONG ref;
DWORD ret;
winetest_push_context("File %ls", resname);
testfilter_init(&testsink);
IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
@ -1761,6 +1763,8 @@ static void test_streaming(void)
ok(!ref, "Got outstanding refcount %ld.\n", ref);
ret = DeleteFileW(filename);
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
winetest_pop_context();
}
START_TEST(avisplit)
@ -1787,7 +1791,8 @@ START_TEST(avisplit)
test_unconnected_filter_state();
test_connect_pin();
test_seeking();
test_streaming();
test_streaming(L"test.avi");
test_streaming(L"test_cinepak.avi");
CoUninitialize();
}

View File

@ -39,3 +39,7 @@ test.wav RCDATA "test.wav"
/* ffmpeg -f lavfi -i smptebars -f lavfi -i "sine=frequency=1000" -t 2.04 -r 25 -f mpeg -vcodec mpeg1video -vf scale=64x48 -acodec mp2 -ar 32k -ab 96k test2.mpg */
/* @makedep: test2.mpg */
test2.mpg RCDATA "test2.mpg"
/* ffmpeg -f lavfi -i smptebars -t 5 -r 1 -f avi -vcodec cinepak -pix_fmt rgb24 -vf scale=32x24 test_cinepak.avi */
/* @makedep: test_cinepak.avi */
test_cinepak.avi RCDATA "test_cinepak.avi"

Binary file not shown.

View File

@ -100,6 +100,9 @@ struct parser_source
bool need_segment;
bool eos;
bool interpolate_timestamps;
UINT64 prev_end_pts;
};
static inline struct parser *impl_from_strmbase_filter(struct strmbase_filter *iface)
@ -630,7 +633,7 @@ static bool amt_from_wg_format_video_cinepak(AM_MEDIA_TYPE *mt, const struct wg_
return true;
}
static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format)
static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm)
{
VIDEOINFOHEADER *video_format;
uint32_t frame_time;
@ -671,7 +674,8 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format));
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
if (wm)
SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height);
video_format->rcTarget = video_format->rcSource;
if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1)
video_format->AvgTimePerFrame = frame_time;
@ -681,6 +685,8 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form
video_format->bmiHeader.biPlanes = 1;
video_format->bmiHeader.biCompression = mt->subtype.Data1;
video_format->bmiHeader.biBitCount = 24;
if (!wm)
video_format->bmiHeader.biSizeImage = 3 * format->u.video.width * format->u.video.height;
video_format->dwBitRate = 0;
memcpy(video_format+1, format->u.video.codec_data, format->u.video.codec_data_len);
@ -747,7 +753,7 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
return amt_from_wg_format_video_cinepak(mt, format);
case WG_MAJOR_TYPE_VIDEO_WMV:
return amt_from_wg_format_video_wmv(mt, format);
return amt_from_wg_format_video_wmv(mt, format, wm);
case WG_MAJOR_TYPE_VIDEO_MPEG1:
return amt_from_wg_format_video_mpeg1(mt, format);
@ -977,6 +983,30 @@ static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *fo
return false;
}
static bool amt_to_wg_format_video_cinepak(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
const VIDEOINFOHEADER *video_format = (const VIDEOINFOHEADER *)mt->pbFormat;
if (!IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
{
FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype));
return false;
}
if (mt->cbFormat < sizeof(VIDEOINFOHEADER) || !mt->pbFormat)
{
ERR("Unexpected format size %lu.\n", mt->cbFormat);
return false;
}
format->major_type = WG_MAJOR_TYPE_VIDEO_CINEPAK;
format->u.video.width = video_format->bmiHeader.biWidth;
format->u.video.height = video_format->bmiHeader.biHeight;
format->u.video.fps_n = 10000000;
format->u.video.fps_d = video_format->AvgTimePerFrame;
return true;
}
static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format *format)
{
const VIDEOINFOHEADER *video_format = (const VIDEOINFOHEADER *)mt->pbFormat;
@ -1051,6 +1081,8 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Video))
{
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_CVID))
return amt_to_wg_format_video_cinepak(mt, format);
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)
@ -1153,30 +1185,34 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
return S_OK;
}
if (buffer->has_pts)
if (buffer->has_pts || (pin->interpolate_timestamps && pin->prev_end_pts != 0))
{
REFERENCE_TIME start_pts = buffer->pts;
UINT64 start_pts = (buffer->has_pts ? buffer->pts : pin->prev_end_pts);
REFERENCE_TIME start_reftime = start_pts;
if (offset)
start_pts += scale_uint64(offset, 10000000, bytes_per_second);
start_pts -= pin->seek.llCurrent;
start_pts *= pin->seek.dRate;
start_reftime += scale_uint64(offset, 10000000, bytes_per_second);
start_reftime -= pin->seek.llCurrent;
start_reftime *= pin->seek.dRate;
if (buffer->has_duration)
{
REFERENCE_TIME end_pts = buffer->pts + buffer->duration;
UINT64 end_pts = start_pts + buffer->duration;
REFERENCE_TIME end_reftime = end_pts;
pin->prev_end_pts = end_pts;
if (offset + size < buffer->size)
end_pts = buffer->pts + scale_uint64(offset + size, 10000000, bytes_per_second);
end_pts -= pin->seek.llCurrent;
end_pts *= pin->seek.dRate;
end_reftime = end_reftime + scale_uint64(offset + size, 10000000, bytes_per_second);
end_reftime -= pin->seek.llCurrent;
end_reftime *= pin->seek.dRate;
IMediaSample_SetTime(sample, &start_pts, &end_pts);
IMediaSample_SetMediaTime(sample, &start_pts, &end_pts);
IMediaSample_SetTime(sample, &start_reftime, &end_reftime);
IMediaSample_SetMediaTime(sample, &start_reftime, &end_reftime);
}
else
{
IMediaSample_SetTime(sample, &start_pts, NULL);
pin->prev_end_pts = 0;
IMediaSample_SetTime(sample, &start_reftime, NULL);
IMediaSample_SetMediaTime(sample, NULL, NULL);
}
}
@ -2291,6 +2327,7 @@ static const struct strmbase_sink_ops avi_splitter_sink_ops =
static BOOL avi_splitter_filter_init_gst(struct parser *filter)
{
wg_parser_t parser = filter->wg_parser;
struct parser_source *src;
uint32_t i, stream_count;
WCHAR source_name[20];
@ -2298,8 +2335,10 @@ static BOOL avi_splitter_filter_init_gst(struct parser *filter)
for (i = 0; i < stream_count; ++i)
{
swprintf(source_name, ARRAY_SIZE(source_name), L"Stream %02u", i);
if (!create_pin(filter, wg_parser_get_stream(parser, i), source_name))
src = create_pin(filter, wg_parser_get_stream(parser, i), source_name);
if (!src)
return FALSE;
src->interpolate_timestamps = TRUE;
}
return TRUE;

View File

@ -661,8 +661,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde
DMO_MEDIA_TYPE *type)
{
struct wma_decoder *decoder = impl_from_IMediaObject(iface);
UINT32 depth, channels, rate;
IMFMediaType *media_type;
UINT32 depth;
HRESULT hr;
TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type);
@ -686,6 +686,16 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde
else
hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
if (SUCCEEDED(hr))
hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
if (SUCCEEDED(hr))
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, depth * channels / 8);
if (SUCCEEDED(hr))
hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
if (SUCCEEDED(hr))
hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, depth * channels / 8 * rate);
if (SUCCEEDED(hr))
hr = IMFMediaType_DeleteItem(media_type, &MF_MT_USER_DATA);
if (SUCCEEDED(hr))

View File

@ -3391,45 +3391,6 @@ invalid_layer:
}
/**********************************************************************
* macdrv_wglGetPixelFormatAttribfvARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
*/
static BOOL macdrv_wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, FLOAT *pfValues)
{
int *attr;
int ret;
TRACE("hdc %p iPixelFormat %d iLayerPlane %d nAttributes %u piAttributes %p pfValues %p\n",
hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
/* Allocate a temporary array to store integer values */
attr = malloc(nAttributes * sizeof(int));
if (!attr)
{
ERR("couldn't allocate %d array\n", nAttributes);
return GL_FALSE;
}
/* Piggy-back on wglGetPixelFormatAttribivARB */
ret = macdrv_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
if (ret)
{
UINT i;
/* Convert integer values to float. Should also check for attributes
that can give decimal values here */
for (i = 0; i < nAttributes; i++)
pfValues[i] = attr[i];
}
free(attr);
return ret;
}
/**********************************************************************
* macdrv_wglGetSwapIntervalEXT
*
@ -4136,7 +4097,7 @@ static void load_extensions(void)
register_extension("WGL_ARB_pixel_format");
opengl_funcs.ext.p_wglChoosePixelFormatARB = macdrv_wglChoosePixelFormatARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = macdrv_wglGetPixelFormatAttribfvARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = macdrv_wglGetPixelFormatAttribivARB;
if (gluCheckExtension((GLubyte*)"GL_ARB_color_buffer_float", (GLubyte*)gl_info.glExtensions))

View File

@ -1553,132 +1553,208 @@ void destroy_gl_drawable( HWND hwnd )
/**
* glxdrv_DescribePixelFormat
* describe_pixel_format
*
* Get the pixel-format descriptor associated to the given id
* Get the wgl_pixel_format description for the given id
*/
static int describe_pixel_format( int iPixelFormat, PIXELFORMATDESCRIPTOR *ppfd )
static int describe_pixel_format( int iPixelFormat, struct wgl_pixel_format *pf )
{
/*XVisualInfo *vis;*/
int value;
int rb,gb,bb,ab;
const struct glx_pixel_format *fmt;
int value, drawable_type = 0, render_type = 0;
int rb, gb, bb, ab;
const struct glx_pixel_format *fmt;
if (!has_opengl()) return 0;
if (!has_opengl()) return 0;
/* Look for the iPixelFormat in our list of supported formats. If it is supported we get the index in the FBConfig table and the number of supported formats back */
fmt = get_pixel_format(gdi_display, iPixelFormat, TRUE /* Offscreen */);
if (!fmt) {
WARN("unexpected format %d\n", iPixelFormat);
return 0;
}
/* Look for the iPixelFormat in our list of supported formats. If it is
* supported we get the index in the FBConfig table and the number of
* supported formats back */
fmt = get_pixel_format( gdi_display, iPixelFormat, TRUE /* Offscreen */);
if (!fmt)
{
WARN( "unexpected format %d\n", iPixelFormat );
return 0;
}
memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
/* If we can't get basic information, there is no point continuing */
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &drawable_type )) return 0;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &render_type )) return 0;
/* These flags are always the same... */
ppfd->dwFlags = PFD_SUPPORT_OPENGL;
/* Now the flags extracted from the Visual */
memset( pf, 0, sizeof(*pf) );
pf->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pf->pfd.nVersion = 1;
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value);
if(value & GLX_WINDOW_BIT)
ppfd->dwFlags |= PFD_DRAW_TO_WINDOW;
/* These flags are always the same... */
pf->pfd.dwFlags = PFD_SUPPORT_OPENGL;
/* Now the flags extracted from the Visual */
/* On Windows bitmap rendering is only offered using the GDI Software renderer. We reserve some formats (see get_formats for more info)
* for bitmap rendering since we require indirect rendering for this. Further pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
* Radeon 9000 indicated that all bitmap formats have PFD_SUPPORT_GDI. Except for 2 formats on the Radeon 9000 none of the hw accelerated formats
* offered the GDI bit either. */
ppfd->dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
if (drawable_type & GLX_WINDOW_BIT) pf->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
/* PFD_GENERIC_FORMAT - gdi software rendering
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver (MCD e.g. 3dfx minigl)
* none set - full hardware accelerated by a ICD
*
* We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as that's what ATI and Nvidia Windows drivers do */
ppfd->dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
/* On Windows bitmap rendering is only offered using the GDI Software
* renderer. We reserve some formats (see get_formats for more info) for
* bitmap rendering since we require indirect rendering for this. Further
* pixel format logs of a GeforceFX, Geforce8800GT, Radeon HD3400 and a
* Radeon 9000 indicated that all bitmap formats have PFD_SUPPORT_GDI.
* Except for 2 formats on the Radeon 9000 none of the hw accelerated
* formats offered the GDI bit either. */
pf->pfd.dwFlags |= fmt->dwFlags & (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI);
if (!(ppfd->dwFlags & PFD_GENERIC_FORMAT))
ppfd->dwFlags |= PFD_SUPPORT_COMPOSITION;
/* PFD_GENERIC_FORMAT - gdi software rendering
* PFD_GENERIC_ACCELERATED - some parts are accelerated by a display driver
* (MCD e.g. 3dfx minigl) none set - full hardware accelerated by a ICD
*
* We only set PFD_GENERIC_FORMAT on bitmap formats (see get_formats) as
* that's what ATI and Nvidia Windows drivers do */
pf->pfd.dwFlags |= fmt->dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value);
if (value) {
ppfd->dwFlags |= PFD_DOUBLEBUFFER;
ppfd->dwFlags &= ~PFD_SUPPORT_GDI;
}
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
if (!(pf->pfd.dwFlags & PFD_GENERIC_FORMAT)) pf->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
/* Pixel type */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value);
if (value & GLX_RGBA_BIT)
ppfd->iPixelType = PFD_TYPE_RGBA;
else
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value );
if (value)
{
pf->pfd.dwFlags |= PFD_DOUBLEBUFFER;
pf->pfd.dwFlags &= ~PFD_SUPPORT_GDI;
}
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STEREO, &value );
if (value) pf->pfd.dwFlags |= PFD_STEREO;
/* Color bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value);
ppfd->cColorBits = value;
/* Pixel type */
if (render_type & GLX_RGBA_BIT) pf->pfd.iPixelType = PFD_TYPE_RGBA;
else pf->pfd.iPixelType = PFD_TYPE_COLORINDEX;
/* Red, green, blue and alpha bits / shifts */
if (ppfd->iPixelType == PFD_TYPE_RGBA) {
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab);
/* Color bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value );
pf->pfd.cColorBits = value;
ppfd->cBlueBits = bb;
ppfd->cBlueShift = 0;
ppfd->cGreenBits = gb;
ppfd->cGreenShift = bb;
ppfd->cRedBits = rb;
ppfd->cRedShift = gb + bb;
ppfd->cAlphaBits = ab;
if (ab)
ppfd->cAlphaShift = rb + gb + bb;
/* Red, green, blue and alpha bits / shifts */
if (pf->pfd.iPixelType == PFD_TYPE_RGBA)
{
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab );
pf->pfd.cBlueBits = bb;
pf->pfd.cBlueShift = 0;
pf->pfd.cGreenBits = gb;
pf->pfd.cGreenShift = bb;
pf->pfd.cRedBits = rb;
pf->pfd.cRedShift = gb + bb;
pf->pfd.cAlphaBits = ab;
if (ab) pf->pfd.cAlphaShift = rb + gb + bb;
else pf->pfd.cAlphaShift = 0;
}
else
ppfd->cAlphaShift = 0;
} else {
ppfd->cRedBits = 0;
ppfd->cRedShift = 0;
ppfd->cBlueBits = 0;
ppfd->cBlueShift = 0;
ppfd->cGreenBits = 0;
ppfd->cGreenShift = 0;
ppfd->cAlphaBits = 0;
ppfd->cAlphaShift = 0;
}
{
pf->pfd.cRedBits = 0;
pf->pfd.cRedShift = 0;
pf->pfd.cBlueBits = 0;
pf->pfd.cBlueShift = 0;
pf->pfd.cGreenBits = 0;
pf->pfd.cGreenShift = 0;
pf->pfd.cAlphaBits = 0;
pf->pfd.cAlphaShift = 0;
}
/* Accum RGBA bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb);
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab);
/* Accum RGBA bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &rb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &gb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &bb );
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &ab );
ppfd->cAccumBits = rb+gb+bb+ab;
ppfd->cAccumRedBits = rb;
ppfd->cAccumGreenBits = gb;
ppfd->cAccumBlueBits = bb;
ppfd->cAccumAlphaBits = ab;
pf->pfd.cAccumBits = rb + gb + bb + ab;
pf->pfd.cAccumRedBits = rb;
pf->pfd.cAccumGreenBits = gb;
pf->pfd.cAccumBlueBits = bb;
pf->pfd.cAccumAlphaBits = ab;
/* Aux bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value);
ppfd->cAuxBuffers = value;
/* Aux bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value );
pf->pfd.cAuxBuffers = value;
/* Depth bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value);
ppfd->cDepthBits = value;
/* Depth bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value );
pf->pfd.cDepthBits = value;
/* stencil bits */
pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value);
ppfd->cStencilBits = value;
/* stencil bits */
pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value );
pf->pfd.cStencilBits = value;
ppfd->iLayerType = PFD_MAIN_PLANE;
pf->pfd.iLayerType = PFD_MAIN_PLANE;
if (TRACE_ON(wgl)) {
dump_PIXELFORMATDESCRIPTOR(ppfd);
}
if (!has_swap_method) pf->swap_method = WGL_SWAP_EXCHANGE_ARB;
else if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SWAP_METHOD_OML, &value ))
{
switch (value) {
case GLX_SWAP_EXCHANGE_OML: pf->swap_method = WGL_SWAP_EXCHANGE_ARB; break;
case GLX_SWAP_COPY_OML: pf->swap_method = WGL_SWAP_COPY_ARB; break;
case GLX_SWAP_UNDEFINED_OML: pf->swap_method = WGL_SWAP_UNDEFINED_ARB; break;
default: { ERR( "Unexpected swap method %x.\n", value ); pf->swap_method = -1; break; }
}
}
else pf->swap_method = -1;
return nb_onscreen_formats;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_TYPE, &value) ) pf->transparent = -1;
else pf->transparent = value != GLX_NONE;
if (render_type & GLX_RGBA_BIT) pf->pixel_type = WGL_TYPE_RGBA_ARB;
else if (render_type & GLX_COLOR_INDEX_BIT) pf->pixel_type = WGL_TYPE_COLORINDEX_ARB;
else if (render_type & GLX_RGBA_FLOAT_BIT) pf->pixel_type = WGL_TYPE_RGBA_FLOAT_ATI;
else if (render_type & GLX_RGBA_FLOAT_ATI_BIT) pf->pixel_type = WGL_TYPE_RGBA_FLOAT_ATI;
else if (render_type & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) pf->pixel_type = WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT;
else { ERR( "unexpected RenderType(%x)\n", render_type ); pf->pixel_type = -1; }
pf->draw_to_pbuffer = (drawable_type & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_PIXELS, &value )) value = -1;
pf->max_pbuffer_pixels = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_WIDTH, &value )) value = -1;
pf->max_pbuffer_width = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_MAX_PBUFFER_HEIGHT, &value )) value = -1;
pf->max_pbuffer_height = value;
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_RED_VALUE, &value ))
{
pf->transparent_red_value_valid = GL_TRUE;
pf->transparent_red_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &value ))
{
pf->transparent_green_value_valid = GL_TRUE;
pf->transparent_green_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &value ))
{
pf->transparent_blue_value_valid = GL_TRUE;
pf->transparent_blue_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &value ))
{
pf->transparent_alpha_value_valid = GL_TRUE;
pf->transparent_alpha_value = value;
}
if (!pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &value ))
{
pf->transparent_index_value_valid = GL_TRUE;
pf->transparent_index_value = value;
}
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SAMPLE_BUFFERS_ARB, &value )) value = -1;
pf->sample_buffers = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_SAMPLES_ARB, &value )) value = -1;
pf->samples = value;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &value )) value = -1;
pf->framebuffer_srgb_capable = value;
pf->bind_to_texture_rgb = pf->bind_to_texture_rgba =
use_render_texture_emulation && render_type != GLX_COLOR_INDEX_BIT && (render_type & GLX_PBUFFER_BIT);
pf->bind_to_texture_rectangle_rgb = pf->bind_to_texture_rectangle_rgba = GL_FALSE;
if (pglXGetFBConfigAttrib( gdi_display, fmt->fbconfig, GLX_FLOAT_COMPONENTS_NV, &value )) value = -1;
pf->float_components = value;
if (TRACE_ON(wgl)) dump_PIXELFORMATDESCRIPTOR( &pf->pfd );
return nb_onscreen_formats;
}
@ -2520,7 +2596,7 @@ struct choose_pixel_format_arb_format
{
int format;
int original_index;
PIXELFORMATDESCRIPTOR pfd;
struct wgl_pixel_format pf;
int depth, stencil;
};
@ -2537,7 +2613,7 @@ static int compare_formats(const void *a, const void *b)
if (offscreen_a != offscreen_b)
return offscreen_a - offscreen_b;
if (memcmp(&fmt_a->pfd, &fmt_b->pfd, sizeof(fmt_a->pfd)))
if (memcmp(&fmt_a->pf.pfd, &fmt_b->pf.pfd, sizeof(fmt_a->pf.pfd)))
return fmt_a->original_index - fmt_b->original_index;
if (fmt_a->depth != fmt_b->depth)
return fmt_a->depth - fmt_b->depth;
@ -2652,16 +2728,16 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
format->format = i + 1;
format->original_index = it;
memset(&format->pfd, 0, sizeof(format->pfd));
if (!describe_pixel_format(format->format, &format->pfd))
memset(&format->pf, 0, sizeof(format->pf));
if (!describe_pixel_format(format->format, &format->pf))
ERR("describe_pixel_format failed, format %d.\n", format->format);
format->depth = format->pfd.cDepthBits;
format->stencil = format->pfd.cStencilBits;
if (!depth_bits && !(format->pfd.dwFlags & PFD_GENERIC_FORMAT))
format->depth = format->pf.pfd.cDepthBits;
format->stencil = format->pf.pfd.cStencilBits;
if (!depth_bits && !(format->pf.pfd.dwFlags & PFD_GENERIC_FORMAT))
{
format->pfd.cDepthBits = 0;
format->pfd.cStencilBits = 0;
format->pf.pfd.cDepthBits = 0;
format->pf.pfd.cStencilBits = 0;
}
++format_count;
@ -2678,329 +2754,6 @@ static BOOL X11DRV_wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, c
return GL_TRUE;
}
/**
* X11DRV_wglGetPixelFormatAttribivARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribivARB
*/
static BOOL X11DRV_wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, int *piValues )
{
UINT i;
const struct glx_pixel_format *fmt;
int hTest;
int tmp;
int curGLXAttr = 0;
PIXELFORMATDESCRIPTOR pfd;
TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues);
if (0 < iLayerPlane) {
FIXME("unsupported iLayerPlane(%d) > 0, returns FALSE\n", iLayerPlane);
return GL_FALSE;
}
/* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supported.
* We don't have to fail yet as a program can specify an invalid iPixelFormat (lets say 0) if it wants to query
* the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */
fmt = get_pixel_format(gdi_display, iPixelFormat, TRUE /* Offscreen */);
if(!fmt) {
WARN("Unable to convert iPixelFormat %d to a GLX one!\n", iPixelFormat);
}
if (!describe_pixel_format(iPixelFormat, &pfd))
{
WARN("describe_pixel_format failed.\n");
memset(&pfd, 0, sizeof(pfd));
}
for (i = 0; i < nAttributes; ++i) {
const int curWGLAttr = piAttributes[i];
TRACE("pAttr[%d] = %x\n", i, curWGLAttr);
switch (curWGLAttr) {
case WGL_NUMBER_PIXEL_FORMATS_ARB:
piValues[i] = nb_pixel_formats;
continue;
case WGL_SUPPORT_OPENGL_ARB:
piValues[i] = GL_TRUE;
continue;
case WGL_ACCELERATION_ARB:
curGLXAttr = GLX_CONFIG_CAVEAT;
if (!fmt) goto pix_error;
if(fmt->dwFlags & PFD_GENERIC_FORMAT)
piValues[i] = WGL_NO_ACCELERATION_ARB;
else if(fmt->dwFlags & PFD_GENERIC_ACCELERATED)
piValues[i] = WGL_GENERIC_ACCELERATION_ARB;
else
piValues[i] = WGL_FULL_ACCELERATION_ARB;
continue;
case WGL_TRANSPARENT_ARB:
curGLXAttr = GLX_TRANSPARENT_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
piValues[i] = GL_FALSE;
if (GLX_NONE != tmp) piValues[i] = GL_TRUE;
continue;
case WGL_PIXEL_TYPE_ARB:
curGLXAttr = GLX_RENDER_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp);
if (tmp & GLX_RGBA_BIT) { piValues[i] = WGL_TYPE_RGBA_ARB; }
else if (tmp & GLX_COLOR_INDEX_BIT) { piValues[i] = WGL_TYPE_COLORINDEX_ARB; }
else if (tmp & GLX_RGBA_FLOAT_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
else if (tmp & GLX_RGBA_FLOAT_ATI_BIT) { piValues[i] = WGL_TYPE_RGBA_FLOAT_ATI; }
else if (tmp & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { piValues[i] = WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT; }
else {
ERR("unexpected RenderType(%x)\n", tmp);
piValues[i] = WGL_TYPE_RGBA_ARB;
}
continue;
case WGL_COLOR_BITS_ARB:
curGLXAttr = GLX_BUFFER_SIZE;
break;
case WGL_BIND_TO_TEXTURE_RGB_ARB:
case WGL_BIND_TO_TEXTURE_RGBA_ARB:
if (!use_render_texture_emulation) {
piValues[i] = GL_FALSE;
continue;
}
curGLXAttr = GLX_RENDER_TYPE;
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp);
if (hTest) goto get_error;
if (GLX_COLOR_INDEX_BIT == tmp) {
piValues[i] = GL_FALSE;
continue;
}
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
if (hTest) goto get_error;
piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE;
continue;
case WGL_BLUE_BITS_ARB:
curGLXAttr = GLX_BLUE_SIZE;
break;
case WGL_RED_BITS_ARB:
curGLXAttr = GLX_RED_SIZE;
break;
case WGL_GREEN_BITS_ARB:
curGLXAttr = GLX_GREEN_SIZE;
break;
case WGL_ALPHA_BITS_ARB:
curGLXAttr = GLX_ALPHA_SIZE;
break;
case WGL_DEPTH_BITS_ARB:
curGLXAttr = GLX_DEPTH_SIZE;
break;
case WGL_STENCIL_BITS_ARB:
curGLXAttr = GLX_STENCIL_SIZE;
break;
case WGL_DOUBLE_BUFFER_ARB:
curGLXAttr = GLX_DOUBLEBUFFER;
break;
case WGL_STEREO_ARB:
curGLXAttr = GLX_STEREO;
break;
case WGL_AUX_BUFFERS_ARB:
curGLXAttr = GLX_AUX_BUFFERS;
break;
case WGL_RED_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cRedShift;
continue;
case WGL_GREEN_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cGreenShift;
continue;
case WGL_BLUE_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cBlueShift;
continue;
case WGL_ALPHA_SHIFT_ARB:
if (!pfd.nSize) goto pix_error;
piValues[i] = pfd.cAlphaShift;
continue;
case WGL_SUPPORT_GDI_ARB:
if (!fmt) goto pix_error;
piValues[i] = (fmt->dwFlags & PFD_SUPPORT_GDI) != 0;
continue;
case WGL_DRAW_TO_BITMAP_ARB:
if (!fmt) goto pix_error;
piValues[i] = (fmt->dwFlags & PFD_DRAW_TO_BITMAP) != 0;
continue;
case WGL_DRAW_TO_WINDOW_ARB:
case WGL_DRAW_TO_PBUFFER_ARB:
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp);
if (hTest) goto get_error;
if((curWGLAttr == WGL_DRAW_TO_WINDOW_ARB && (tmp&GLX_WINDOW_BIT)) ||
(curWGLAttr == WGL_DRAW_TO_PBUFFER_ARB && (tmp&GLX_PBUFFER_BIT)))
piValues[i] = GL_TRUE;
else
piValues[i] = GL_FALSE;
continue;
case WGL_SWAP_METHOD_ARB:
if (has_swap_method)
{
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_SWAP_METHOD_OML, &tmp);
if (hTest) goto get_error;
switch (tmp)
{
case GLX_SWAP_EXCHANGE_OML:
piValues[i] = WGL_SWAP_EXCHANGE_ARB;
break;
case GLX_SWAP_COPY_OML:
piValues[i] = WGL_SWAP_COPY_ARB;
break;
case GLX_SWAP_UNDEFINED_OML:
piValues[i] = WGL_SWAP_UNDEFINED_ARB;
break;
default:
ERR("Unexpected swap method %x.\n", tmp);
}
}
else
{
WARN("GLX_OML_swap_method not supported, returning WGL_SWAP_EXCHANGE_ARB.\n");
piValues[i] = WGL_SWAP_EXCHANGE_ARB;
}
continue;
case WGL_PBUFFER_LARGEST_ARB:
curGLXAttr = GLX_LARGEST_PBUFFER;
break;
case WGL_SAMPLE_BUFFERS_ARB:
curGLXAttr = GLX_SAMPLE_BUFFERS_ARB;
break;
case WGL_SAMPLES_ARB:
curGLXAttr = GLX_SAMPLES_ARB;
break;
case WGL_FLOAT_COMPONENTS_NV:
curGLXAttr = GLX_FLOAT_COMPONENTS_NV;
break;
case WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT:
curGLXAttr = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT;
break;
case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT:
curGLXAttr = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
break;
case WGL_ACCUM_RED_BITS_ARB:
curGLXAttr = GLX_ACCUM_RED_SIZE;
break;
case WGL_ACCUM_GREEN_BITS_ARB:
curGLXAttr = GLX_ACCUM_GREEN_SIZE;
break;
case WGL_ACCUM_BLUE_BITS_ARB:
curGLXAttr = GLX_ACCUM_BLUE_SIZE;
break;
case WGL_ACCUM_ALPHA_BITS_ARB:
curGLXAttr = GLX_ACCUM_ALPHA_SIZE;
break;
case WGL_ACCUM_BITS_ARB:
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_RED_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] = tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_GREEN_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_BLUE_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ACCUM_ALPHA_SIZE, &tmp);
if (hTest) goto get_error;
piValues[i] += tmp;
continue;
default:
FIXME("unsupported %x WGL Attribute\n", curWGLAttr);
}
/* Retrieve a GLX FBConfigAttrib when the attribute to query is valid and
* iPixelFormat != 0. When iPixelFormat is 0 the only value which makes
* sense to query is WGL_NUMBER_PIXEL_FORMATS_ARB.
*
* TODO: properly test the behavior of wglGetPixelFormatAttrib*v on Windows
* and check which options can work using iPixelFormat=0 and which not.
* A problem would be that this function is an extension. This would
* mean that the behavior could differ between different vendors (ATI, Nvidia, ..).
*/
if (0 != curGLXAttr && iPixelFormat != 0) {
if (!fmt) goto pix_error;
hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, piValues + i);
if (hTest) goto get_error;
curGLXAttr = 0;
} else {
piValues[i] = GL_FALSE;
}
}
return GL_TRUE;
get_error:
ERR("(%p): unexpected failure on GetFBConfigAttrib(%x) returns FALSE\n", hdc, curGLXAttr);
return GL_FALSE;
pix_error:
ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nb_pixel_formats);
return GL_FALSE;
}
/**
* X11DRV_wglGetPixelFormatAttribfvARB
*
* WGL_ARB_pixel_format: wglGetPixelFormatAttribfvARB
*/
static BOOL X11DRV_wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane,
UINT nAttributes, const int *piAttributes, FLOAT *pfValues )
{
int *attr;
int ret;
UINT i;
TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues);
/* Allocate a temporary array to store integer values */
attr = malloc( nAttributes * sizeof(int) );
if (!attr) {
ERR("couldn't allocate %d array\n", nAttributes);
return GL_FALSE;
}
/* Piggy-back on wglGetPixelFormatAttribivARB */
ret = X11DRV_wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, attr);
if (ret) {
/* Convert integer values to float. Should also check for attributes
that can give decimal values here */
for (i=0; i<nAttributes;i++) {
pfValues[i] = attr[i];
}
}
free( attr );
return ret;
}
/**
* X11DRV_wglBindTexImageARB
*
@ -3260,8 +3013,8 @@ static void X11DRV_WineGL_LoadExtensions(void)
register_extension( "WGL_ARB_pixel_format" );
opengl_funcs.ext.p_wglChoosePixelFormatARB = X11DRV_wglChoosePixelFormatARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = X11DRV_wglGetPixelFormatAttribfvARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = X11DRV_wglGetPixelFormatAttribivARB;
opengl_funcs.ext.p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */
opengl_funcs.ext.p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
if (has_extension( glxExtensions, "GLX_ARB_fbconfig_float"))
{
@ -3445,7 +3198,7 @@ static void glxdrv_get_pixel_formats( struct wgl_pixel_format *formats,
if (formats)
{
for (i = 0; i < min( max_formats, nb_pixel_formats ); ++i)
describe_pixel_format( i + 1, &formats[i].pfd );
describe_pixel_format( i + 1, &formats[i] );
}
*num_formats = nb_pixel_formats;
*num_onscreen_formats = nb_onscreen_formats;

View File

@ -7,7 +7,7 @@
#define WINE_GLAPI
#endif
#define WINE_WGL_DRIVER_VERSION 25
#define WINE_WGL_DRIVER_VERSION 26
struct wgl_context;
struct wgl_pbuffer;
@ -15,6 +15,31 @@ struct wgl_pbuffer;
struct wgl_pixel_format
{
PIXELFORMATDESCRIPTOR pfd;
int swap_method;
int transparent;
int pixel_type;
int draw_to_pbuffer;
int max_pbuffer_pixels;
int max_pbuffer_width;
int max_pbuffer_height;
int transparent_red_value;
int transparent_red_value_valid;
int transparent_green_value;
int transparent_green_value_valid;
int transparent_blue_value;
int transparent_blue_value_valid;
int transparent_alpha_value;
int transparent_alpha_value_valid;
int transparent_index_value;
int transparent_index_value_valid;
int sample_buffers;
int samples;
int bind_to_texture_rgb;
int bind_to_texture_rgba;
int bind_to_texture_rectangle_rgb;
int bind_to_texture_rectangle_rgba;
int framebuffer_srgb_capable;
int float_components;
};
struct opengl_funcs

View File

@ -1546,8 +1546,8 @@ void WCMD_echo (const WCHAR *args)
* first command to be executed may not be at the front of the
* commands->thiscommand string (eg. it may point after a DO or ELSE)
*/
static void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds)
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds)
{
CMD_NODE *curPosition = *cmdList;
int myDepth = CMD_node_get_depth(*cmdList);
@ -1850,11 +1850,11 @@ static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk)
* are recursively passed. If any have duplicates, then the * token should
* not be honoured.
*/
static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates)
int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates)
{
WCHAR *pos = tokenstr;
const WCHAR *pos = tokenstr;
int nexttoken = -1;
if (totalfound) *totalfound = 0;
@ -2136,7 +2136,7 @@ static FILE *WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
*
*/
void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
static void WCMD_for_OLD (WCHAR *p, CMD_NODE **cmdList) {
WIN32_FIND_DATAW fd;
HANDLE hff;
@ -2541,6 +2541,32 @@ void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
if (cmdEnd && CMD_node_get_command(cmdEnd)->command == NULL) *cmdList = CMD_node_next(cmdEnd);
}
void WCMD_for(WCHAR *p, CMD_NODE **cmdList)
{
CMD_FOR_CONTROL *for_ctrl;
for_ctrl = for_control_parse(p);
if (!for_ctrl)
{
/* temporary code: use OLD code for non migrated FOR constructs */
WCMD_for_OLD(p, cmdList);
return;
}
for (*cmdList = CMD_node_next(*cmdList); /* swallow options */
*cmdList && CMD_node_get_command(*cmdList)->command != NULL;
*cmdList = CMD_node_next(*cmdList))
{
for_control_append_set(for_ctrl, CMD_node_get_command(*cmdList)->command);
}
/* step over terminating NULL CMD_NODE of set */
*cmdList = CMD_node_next(*cmdList);
for_control_execute(for_ctrl, cmdList);
for_control_dispose(for_ctrl);
}
/**************************************************************************
* WCMD_give_help
*

View File

@ -757,11 +757,6 @@ setlocal EnableDelayedExpansion
set WINE_FOO=foo bar
for %%i in ("!WINE_FOO!") do echo %%i
for %%i in (!WINE_FOO!) do echo %%i
rem tests disabled for now... wine's cmd loops endlessly here
rem set WINE_FOO=4 4 4
rem for /l %%i in (!WINE_FOO!) do echo %%i
rem set WINE_FOO=4
rem for /l %%i in (1 2 !WINE_FOO!) do echo %%i
setlocal DisableDelayedExpansion
echo --- in digit variables

View File

@ -1014,21 +1014,21 @@ A D
B C
B D
--- nested FORs and args tempering
@todo_wine@inner argument {-foo, bar}
@todo_wine@inner argument {-x, y}
inner argument {-foo, bar}
inner argument {-x, y}
--- nesting and delayed expansion
a 1 2
@todo_wine@1-A2
@todo_wine@1-B1
@todo_wine@2-A1
@todo_wine@2-B2
@todo_wine@b 1 3
@todo_wine@1-A2
@todo_wine@1-B1
@todo_wine@2-A2
@todo_wine@2-B2
@todo_wine@3-A1
@todo_wine@3-B2
1-A2
1-B1
2-A1
2-B2
b 1 3
1-A2
1-B1
2-A2
2-B2
3-A1
3-B2
--- nesting if/for
@todo_wine@"f"
@todo_wine@"g"
@ -1385,7 +1385,7 @@ h=%h i=b j=c k= l= m=%m n=%n o=%o@or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
h=%h i=b j=c k= l= m=%m n=%n o=%o@or_broken@h=%h i=b j=c k= l= m= n=%n o=%o
1:3.14,%B
2:3.14,
@todo_wine@4:3,14
4:3,14
------ parameter splitting
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@
:forFParameterSplittingFunc myparam1=myvalue1 myparam2=myparam2 mytest@space@@space@@space@

View File

@ -83,6 +83,27 @@ typedef struct _CMD_IF_CONDITION
};
} CMD_IF_CONDITION;
typedef struct _CMD_FOR_CONTROL
{
enum for_control_operator {
CMD_FOR_FILE_SET /* /F */,
CMD_FOR_NUMBERS /* /L */} operator;
unsigned flags; /* |-ed CMD_FOR_FLAG_* */
int variable_index;
const WCHAR *set;
union
{
struct /* for CMD_FOR_FILE_SET */
{
WCHAR eol;
BOOL use_backq;
int num_lines_to_skip;
const WCHAR *delims;
const WCHAR *tokens;
};
};
} CMD_FOR_CONTROL;
typedef struct _CMD_COMMAND
{
WCHAR *command; /* Command string to execute */
@ -129,6 +150,21 @@ void if_condition_dispose(CMD_IF_CONDITION *);
BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test);
const char *debugstr_if_condition(const CMD_IF_CONDITION *cond);
void for_control_create(enum for_control_operator for_op, unsigned flags, const WCHAR *options, int var_idx, CMD_FOR_CONTROL *for_ctrl);
void for_control_create_fileset(unsigned flags, int var_idx, WCHAR eol, int num_lines_to_skip, BOOL use_backq,
const WCHAR *delims, const WCHAR *tokens,
CMD_FOR_CONTROL *for_ctrl);
CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var);
void for_control_append_set(CMD_FOR_CONTROL *for_ctrl, const WCHAR *string);
void for_control_dump(const CMD_FOR_CONTROL *for_ctrl);
void for_control_dispose(CMD_FOR_CONTROL *for_ctrl);
void for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE **cmdList);
int WCMD_for_nexttoken(int lasttoken, const WCHAR *tokenstr,
int *totalfound, BOOL *doall,
BOOL *duplicates);
void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds);
void WCMD_assoc (const WCHAR *, BOOL);
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
void WCMD_call (WCHAR *command);

View File

@ -991,6 +991,94 @@ static void command_dispose(CMD_COMMAND *cmd)
}
}
void for_control_dispose(CMD_FOR_CONTROL *for_ctrl)
{
free((void*)for_ctrl->set);
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
free((void*)for_ctrl->delims);
free((void*)for_ctrl->tokens);
break;
default:
break;
}
}
const char *debugstr_for_control(const CMD_FOR_CONTROL *for_ctrl)
{
static const char* for_ctrl_strings[] = {"file", "numbers"};
const char *flags, *options;
if (for_ctrl->operator >= ARRAY_SIZE(for_ctrl_strings))
{
FIXME("Unexpected operator\n");
return wine_dbg_sprintf("<<%u>>", for_ctrl->operator);
}
flags = "";
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
{
WCHAR eol_buf[4] = {L'\'', for_ctrl->eol, L'\'', L'\0'};
const WCHAR *eol = for_ctrl->eol ? eol_buf : L"<nul>";
options = wine_dbg_sprintf("eol=%ls skip=%d use_backq=%c delims=%s tokens=%s ",
eol, for_ctrl->num_lines_to_skip, for_ctrl->use_backq ? 'Y' : 'N',
wine_dbgstr_w(for_ctrl->delims), wine_dbgstr_w(for_ctrl->tokens));
}
break;
default:
options = "";
break;
}
return wine_dbg_sprintf("[FOR] %s %s%s%%%c (%ls)",
for_ctrl_strings[for_ctrl->operator], flags, options,
for_var_index_to_char(for_ctrl->variable_index), for_ctrl->set);
}
void for_control_create(enum for_control_operator for_op, unsigned flags, const WCHAR *options, int var_idx, CMD_FOR_CONTROL *for_ctrl)
{
for_ctrl->operator = for_op;
for_ctrl->flags = flags;
for_ctrl->variable_index = var_idx;
for_ctrl->set = NULL;
switch (for_ctrl->operator)
{
default:
break;
}
}
void for_control_create_fileset(unsigned flags, int var_idx, WCHAR eol, int num_lines_to_skip, BOOL use_backq,
const WCHAR *delims, const WCHAR *tokens,
CMD_FOR_CONTROL *for_ctrl)
{
for_ctrl->operator = CMD_FOR_FILE_SET;
for_ctrl->flags = flags;
for_ctrl->variable_index = var_idx;
for_ctrl->set = NULL;
for_ctrl->eol = eol;
for_ctrl->use_backq = use_backq;
for_ctrl->num_lines_to_skip = num_lines_to_skip;
for_ctrl->delims = delims;
for_ctrl->tokens = tokens;
}
void for_control_append_set(CMD_FOR_CONTROL *for_ctrl, const WCHAR *set)
{
if (for_ctrl->set)
{
for_ctrl->set = xrealloc((void*)for_ctrl->set,
(wcslen(for_ctrl->set) + 1 + wcslen(set) + 1) * sizeof(WCHAR));
wcscat((WCHAR*)for_ctrl->set, L" ");
wcscat((WCHAR*)for_ctrl->set, set);
}
else
for_ctrl->set = xstrdupW(set);
}
/***************************************************************************
* node_dispose_tree
*
@ -2093,6 +2181,170 @@ static BOOL WCMD_IsEndQuote(const WCHAR *quote, int quoteIndex)
return FALSE;
}
static WCHAR *for_fileset_option_split(WCHAR *from, const WCHAR* key)
{
size_t len = wcslen(key);
if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
from, len, key, len) != CSTR_EQUAL)
return NULL;
from += len;
if (len && key[len - 1] == L'=')
while (*from && *from != L' ' && *from != L'\t') from++;
return from;
}
CMD_FOR_CONTROL *for_control_parse(WCHAR *opts_var)
{
CMD_FOR_CONTROL *for_ctrl;
enum for_control_operator for_op;
WCHAR mode = L' ', option;
WCHAR options[MAXSTRING];
WCHAR *arg;
unsigned flags = 0;
int arg_index;
int var_idx;
options[0] = L'\0';
/* native allows two options only in the /D /R case, a repetition of the option
* and prints an error otherwise
*/
for (arg_index = 0; ; arg_index++)
{
arg = WCMD_parameter(opts_var, arg_index, NULL, FALSE, FALSE);
if (!arg || *arg != L'/') break;
option = towupper(arg[1]);
if (mode != L' ' && (mode != L'D' || option != 'R') && mode != option)
break;
switch (option)
{
case L'R':
if (mode == L'D')
{
mode = L'X';
break;
}
/* fall thru */
case L'D':
case L'L':
case L'F':
mode = option;
break;
default:
/* error unexpected 'arg' at this time */
WARN("for qualifier '%c' unhandled\n", *arg);
goto syntax_error;
}
}
switch (mode)
{
case L'L':
for_op = CMD_FOR_NUMBERS;
break;
case L'F':
for_op = CMD_FOR_FILE_SET;
break;
default:
return NULL;
}
if (mode == L'F')
{
/* Retrieve next parameter to see if is root/options (raw form required
* with for /f, or unquoted in for /r)
*/
arg = WCMD_parameter(opts_var, arg_index, NULL, for_op == CMD_FOR_FILE_SET, FALSE);
/* Next parm is either qualifier, path/options or variable -
* only care about it if it is the path/options
*/
if (arg && *arg != L'/' && *arg != L'%')
{
arg_index++;
wcscpy(options, arg);
}
}
/* Ensure line continues with variable */
arg = WCMD_parameter(opts_var, arg_index++, NULL, FALSE, FALSE);
if (!arg || *arg != L'%' || (var_idx = for_var_char_to_index(arg[1])) == -1)
goto syntax_error; /* FIXME native prints the offending token "%<whatever>" was unexpected at this time */
for_ctrl = xalloc(sizeof(*for_ctrl));
if (for_op == CMD_FOR_FILE_SET)
{
size_t len = wcslen(options);
WCHAR *p = options, *end;
WCHAR eol = L'\0';
int num_lines_to_skip = 0;
BOOL use_backq = FALSE;
WCHAR *delims = NULL, *tokens = NULL;
/* strip enclosing double-quotes when present */
if (len >= 2 && p[0] == L'"' && p[len - 1] == L'"')
{
p[len - 1] = L'\0';
p++;
}
for ( ; *p; p = end)
{
p = WCMD_skip_leading_spaces(p);
/* Save End of line character (Ignore line if first token (based on delims) starts with it) */
if ((end = for_fileset_option_split(p, L"eol=")))
{
/* assuming one char for eol marker */
if (end != p + 5) goto syntax_error;
eol = p[4];
}
/* Save number of lines to skip (Can be in base 10, hex (0x...) or octal (0xx) */
else if ((end = for_fileset_option_split(p, L"skip=")))
{
WCHAR *nextchar;
num_lines_to_skip = wcstoul(p + 5, &nextchar, 0);
if (end != nextchar) goto syntax_error;
}
/* Save if usebackq semantics are in effect */
else if ((end = for_fileset_option_split(p, L"usebackq")))
use_backq = TRUE;
/* Save the supplied delims */
else if ((end = for_fileset_option_split(p, L"delims=")))
{
size_t copy_len;
/* interpret space when last character of whole options string as part of delims= */
if (end[0] && !end[1]) end++;
copy_len = end - (p + 7) /* delims= */;
delims = xalloc((copy_len + 1) * sizeof(WCHAR));
memcpy(delims, p + 7, copy_len * sizeof(WCHAR));
delims[copy_len] = L'\0';
}
/* Save the tokens being requested */
else if ((end = for_fileset_option_split(p, L"tokens=")))
{
size_t copy_len;
copy_len = end - (p + 7) /* tokens= */;
tokens = xalloc((copy_len + 1) * sizeof(WCHAR));
memcpy(tokens, p + 7, copy_len * sizeof(WCHAR));
tokens[copy_len] = L'\0';
}
else
{
WARN("FOR option not found %ls\n", p);
goto syntax_error;
}
}
for_control_create_fileset(flags, var_idx, eol, num_lines_to_skip, use_backq,
delims ? delims : xstrdupW(L" \t"),
tokens ? tokens : xstrdupW(L"1"), for_ctrl);
}
else
for_control_create(for_op, flags, options, var_idx, for_ctrl);
return for_ctrl;
syntax_error:
WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR));
return NULL;
}
/***************************************************************************
* WCMD_ReadAndParseLine
*
@ -2710,6 +2962,97 @@ BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test)
return TRUE;
}
static CMD_NODE *for_loop_fileset_parse_line(CMD_NODE *cmdList, int varidx, WCHAR *buffer,
WCHAR forf_eol, const WCHAR *forf_delims, const WCHAR *forf_tokens)
{
WCHAR *parm;
int varoffset;
int nexttoken, lasttoken = -1;
BOOL starfound = FALSE;
BOOL thisduplicate = FALSE;
BOOL anyduplicates = FALSE;
int totalfound;
static WCHAR emptyW[] = L"";
/* Extract the parameters based on the tokens= value (There will always
be some value, as if it is not supplied, it defaults to tokens=1).
Rough logic:
Count how many tokens are named in the line, identify the lowest
Empty (set to null terminated string) that number of named variables
While lasttoken != nextlowest
%letter = parameter number 'nextlowest'
letter++ (if >26 or >52 abort)
Go through token= string finding next lowest number
If token ends in * set %letter = raw position of token(nextnumber+1)
*/
lasttoken = -1;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, &totalfound,
&starfound, &thisduplicate);
TRACE("Using var=%lc on %d max\n", for_var_index_to_char(varidx), totalfound);
/* Empty out variables */
for (varoffset = 0;
varoffset < totalfound && for_var_index_in_range(varidx, varoffset);
varoffset++)
WCMD_set_for_loop_variable(varidx + varoffset, emptyW);
/* Loop extracting the tokens
* Note: nexttoken of 0 means there were no tokens requested, to handle
* the special case of tokens=*
*/
varoffset = 0;
TRACE("Parsing buffer into tokens: '%s'\n", wine_dbgstr_w(buffer));
while (nexttoken > 0 && (nexttoken > lasttoken))
{
anyduplicates |= thisduplicate;
if (!for_var_index_in_range(varidx, varoffset))
{
WARN("Out of range offset\n");
break;
}
/* Extract the token number requested and set into the next variable context */
parm = WCMD_parameter_with_delims(buffer, (nexttoken-1), NULL, TRUE, FALSE, forf_delims);
TRACE("Parsed token %d(%d) as parameter %s\n", nexttoken,
varidx + varoffset, wine_dbgstr_w(parm));
if (parm)
{
WCMD_set_for_loop_variable(varidx + varoffset, parm);
varoffset++;
}
/* Find the next token */
lasttoken = nexttoken;
nexttoken = WCMD_for_nexttoken(lasttoken, forf_tokens, NULL,
&starfound, &thisduplicate);
}
/* If all the rest of the tokens were requested, and there is still space in
* the variable range, write them now
*/
if (!anyduplicates && starfound && for_var_index_in_range(varidx, varoffset))
{
nexttoken++;
WCMD_parameter_with_delims(buffer, (nexttoken-1), &parm, FALSE, FALSE, forf_delims);
TRACE("Parsed all remaining tokens (%d) as parameter %s\n",
varidx + varoffset, wine_dbgstr_w(parm));
if (parm)
WCMD_set_for_loop_variable(varidx + varoffset, parm);
}
/* Execute the body of the for loop with these values */
if (forloopcontext->variable[varidx] && forloopcontext->variable[varidx][0] != forf_eol)
{
/* +3 for "do " */
WCMD_part_execute(&cmdList, CMD_node_get_command(cmdList)->command + 3, FALSE, TRUE);
}
else
{
TRACE("Skipping line because of eol\n");
cmdList = NULL;
}
return cmdList;
}
void WCMD_save_for_loop_context(BOOL reset)
{
FOR_CONTEXT *new = xalloc(sizeof(*new));
@ -2748,6 +3091,179 @@ void WCMD_set_for_loop_variable(int var_idx, const WCHAR *value)
forloopcontext->variable[var_idx] = xstrdupW(value);
}
static BOOL match_ending_delim(WCHAR *string)
{
WCHAR *to = string + wcslen(string);
/* strip trailing delim */
if (to > string) to--;
if (to > string && *to == string[0])
{
*to = L'\0';
return TRUE;
}
WARN("Can't find ending delimiter (%ls)\n", string);
return FALSE;
}
static CMD_NODE *for_control_execute_from_FILE(CMD_FOR_CONTROL *for_ctrl, FILE *input, CMD_NODE *cmdList)
{
WCHAR buffer[MAXSTRING];
int skip_count = for_ctrl->num_lines_to_skip;
CMD_NODE *body = NULL;
/* Read line by line until end of file */
while (fgetws(buffer, ARRAY_SIZE(buffer), input))
{
size_t len;
if (skip_count)
{
TRACE("skipping %d\n", skip_count);
skip_count--;
continue;
}
len = wcslen(buffer);
/* Either our buffer isn't large enough to fit a full line, or there's a stray
* '\0' in the buffer.
*/
if (!feof(input) && (len == 0 || (buffer[len - 1] != '\n' && buffer[len - 1] != '\r')))
break;
while (len && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r'))
buffer[--len] = L'\0';
body = for_loop_fileset_parse_line(cmdList, for_ctrl->variable_index, buffer,
for_ctrl->eol, for_ctrl->delims, for_ctrl->tokens);
buffer[0] = 0;
}
return body;
}
static CMD_NODE *for_control_execute_fileset(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
{
WCHAR set[MAXSTRING];
WCHAR *args;
size_t len;
CMD_NODE *body = NULL;
FILE *input;
int i;
wcscpy(set, for_ctrl->set);
handleExpansion(set, context != NULL, delayedsubst);
args = WCMD_skip_leading_spaces(set);
for (len = wcslen(args); len && (args[len - 1] == L' ' || args[len - 1] == L'\t'); len--)
args[len - 1] = L'\0';
if (args[0] == (for_ctrl->use_backq ? L'\'' : L'"') && match_ending_delim(args))
{
args++;
if (!for_ctrl->num_lines_to_skip)
{
body = for_loop_fileset_parse_line(cmdList, for_ctrl->variable_index, args,
for_ctrl->eol, for_ctrl->delims, for_ctrl->tokens);
}
}
else if (args[0] == (for_ctrl->use_backq ? L'`' : L'\'') && match_ending_delim(args))
{
WCHAR temp_cmd[MAX_PATH];
args++;
wsprintfW(temp_cmd, L"CMD.EXE /C %s", args);
TRACE("Reading output of '%s'\n", wine_dbgstr_w(temp_cmd));
input = _wpopen(temp_cmd, L"rt,ccs=unicode");
if (!input)
{
WCMD_print_error();
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), args);
errorlevel = 1;
return NULL; /* FOR loop aborts at first failure here */
}
body = for_control_execute_from_FILE(for_ctrl, input, cmdList);
fclose(input);
}
else
{
for (i = 0; ; i++)
{
WCHAR *element = WCMD_parameter(args, i, NULL, TRUE, FALSE);
if (!element || !*element) break;
if (element[0] == L'"' && match_ending_delim(element)) element++;
/* Open the file, read line by line and process */
TRACE("Reading input to parse from '%s'\n", wine_dbgstr_w(element));
input = _wfopen(element, L"rt,ccs=unicode");
if (!input)
{
WCMD_print_error();
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), element);
errorlevel = 1;
return NULL; /* FOR loop aborts at first failure here */
}
body = for_control_execute_from_FILE(for_ctrl, input, cmdList);
fclose(input);
}
}
return body;
}
static CMD_NODE *for_control_execute_numbers(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *cmdList)
{
WCHAR set[MAXSTRING];
CMD_NODE *body = NULL;
int numbers[3] = {0, 0, 0}, var;
int i;
wcscpy(set, for_ctrl->set);
handleExpansion(set, context != NULL, delayedsubst);
/* Note: native doesn't check the actual number of parameters, and set
* them by default to 0.
* so (-10 1) is interpreted as (-10 1 0)
* and (10) loops for ever !!!
*/
for (i = 0; i < ARRAY_SIZE(numbers); i++)
{
WCHAR *element = WCMD_parameter(set, i, NULL, FALSE, FALSE);
if (!element || !*element) break;
/* native doesn't no error handling */
numbers[i] = wcstol(element, NULL, 0);
}
for (var = numbers[0];
(numbers[1] < 0) ? var >= numbers[2] : var <= numbers[2];
var += numbers[1])
{
WCHAR tmp[32];
body = cmdList;
swprintf(tmp, ARRAY_SIZE(tmp), L"%d", var);
WCMD_set_for_loop_variable(for_ctrl->variable_index, tmp);
TRACE("Processing FOR number %s\n", wine_dbgstr_w(tmp));
WCMD_part_execute(&body, CMD_node_get_command(cmdList)->command + 3, FALSE, TRUE);
}
return body;
}
void for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE **cmdList)
{
CMD_NODE *last;
WCMD_save_for_loop_context(FALSE);
switch (for_ctrl->operator)
{
case CMD_FOR_FILE_SET:
last = for_control_execute_fileset(for_ctrl, *cmdList);
break;
case CMD_FOR_NUMBERS:
last = for_control_execute_numbers(for_ctrl, *cmdList);
break;
default:
last = NULL;
break;
}
WCMD_restore_for_loop_context();
*cmdList = last;
}
/***************************************************************************
* WCMD_process_commands
*