Error Running jextract on d3d12.h

Jorn Vernee jorn.vernee at oracle.com
Mon Sep 14 13:39:33 UTC 2020


Ok, it looks like the formatting got messed up in the email, so I've 
uploaded the example here as well:

http://cr.openjdk.java.net/~jvernee/d3d12_example/Main.java

Jorn

On 14/09/2020 15:28, Jorn Vernee wrote:
> I've tried it out on my machine as well (I'm also on Windows). Here is 
> a little bit more complete example that prints out the adapter 
> description
>
> If you have extracted the shared/dxgi.h and the shared/guiddef.h 
> headers as well, you can do something like this:
>
>
> import jdk.incubator.foreign.FunctionDescriptor;
> import jdk.incubator.foreign.MemoryAccess;
> import jdk.incubator.foreign.MemoryAddress;
> import jdk.incubator.foreign.MemoryLayout;
> import jdk.incubator.foreign.MemorySegment;
> import jdk.incubator.foreign.NativeScope;
> import org.jextract.dxgi_h;
> import org.jextract.guiddef_h;
>
> import java.lang.invoke.MethodHandle;
> import java.lang.invoke.MethodType;
> import java.nio.charset.StandardCharsets;
>
> import static jdk.incubator.foreign.CSupport.*;
> import static org.jextract.dxgi_h.*;
>
> public class Main {
>
>     public static void main(String[] args)throws Throwable {
>         try (NativeScope scope =NativeScope.unboundedScope()) {
>             // IDXGIFactory1** dxgiFactory;
> var ppDxgiFactory =IDXGIFactory1.allocatePointer(scope);
>             // HRESULT = CreateDXGIFactory1(_uuid(dxgiFactory), 
> &dxgiFactory)) 
> checkResult(dxgi_h.CreateDXGIFactory1(IID_IDXGIFactory1,ppDxgiFactory));
>             // IDXGIFactory1* MemorySegment pDxgiFactory 
> =asSegment(MemoryAccess.getAddress(ppDxgiFactory),IDXGIFactory1.$LAYOUT());
>
>             // (This)->lpVtbl MemorySegment vtbl 
> =asSegment(IDXGIFactory1.lpVtbl$get(pDxgiFactory),IDXGIFactory1Vtbl.$LAYOUT());
>             // lpVtbl->EnumAdapters1 MemoryAddress addrEnumAdapters 
> =IDXGIFactory1Vtbl.EnumAdapters1$get(vtbl);
>
>             // link the pointer MethodHandle MH_EnumAdapters1 
> =getSystemLinker().downcallHandle(
>                 addrEnumAdapters,
> MethodType.methodType(int.class,MemoryAddress.class,int.class,MemoryAddress.class),
> FunctionDescriptor.of(C_INT,C_POINTER,C_INT,C_POINTER));
>
>             /* [annotation][out] _COM_Outptr_ IDXGIAdapter1** */ 
> MemorySegment ppOut =IDXGIAdapter1.allocatePointer(scope);
> checkResult((int)MH_EnumAdapters1.invokeExact(pDxgiFactory.address(),0,ppOut.address()));// 
> IDXGIAdapter1* MemorySegment pAdapter 
> =asSegment(MemoryAccess.getAddress(ppOut),IDXGIAdapter1.$LAYOUT());
>
>             // (This)->lpVtbl MemorySegment vtbl2 
> =asSegment(IDXGIAdapter1.lpVtbl$get(pAdapter),IDXGIAdapter1Vtbl.$LAYOUT());
>             // lpVtbl->EnumAdapters1 // 
> HRESULT(*)(IDXGIAdapter1*,DXGI_ADAPTER_DESC1*) MemoryAddress 
> addrGetDesc1 =IDXGIAdapter1Vtbl.GetDesc1$get(vtbl2);
>
>             // link the pointer MethodHandle MH_GetDesc1 
> =getSystemLinker().downcallHandle(
>                 addrGetDesc1,
> MethodType.methodType(int.class,MemoryAddress.class,MemoryAddress.class),
>                 FunctionDescriptor.of(C_INT,C_POINTER,C_POINTER));
>
>             /* DXGI_ADAPTER_DESC1* */ MemorySegment pDesc 
> =DXGI_ADAPTER_DESC1.allocate(scope);
> checkResult((int)MH_GetDesc1.invokeExact(pAdapter.address(),pDesc.address()));
>
>             // print description MemorySegment descStr 
> =DXGI_ADAPTER_DESC1.Description$slice(pDesc);
>             String str =new 
> String(descStr.toByteArray(),StandardCharsets.UTF_16LE);
>             System.out.println(str);
>         }
>     }
>
>     public static MemorySegment asSegment(MemoryAddress 
> addr,MemoryLayout layout) {
>         return MemorySegment.ofNativeRestricted(addr, 
> layout.byteSize(),Thread.currentThread(),null,null);
>     }
>
>     static final MemorySegment IID_IDXGIFactory1 =GUID(
>             (int)0x770aae78,
>             (short)0xf26f,
>             (short)0x4dba,
>             new byte[]{(byte)0xa8,0x29,0x25,0x3c, (byte)0x83, 
> (byte)0xd1, (byte)0xb3, (byte)0x87});
>
>     static final MemorySegment GUID(int Data1,short Data2,short 
> Data3,byte[] Data4) {
>         MemorySegment ms 
> =MemorySegment.allocateNative(guiddef_h.GUID.$LAYOUT());
>         guiddef_h.GUID.Data1$set(ms, Data1);
>         guiddef_h.GUID.Data2$set(ms, Data2);
>         guiddef_h.GUID.Data3$set(ms, Data3);
> guiddef_h.GUID.Data4$slice(ms).copyFrom(MemorySegment.ofArray(Data4));
>         return ms;
>     }
>
>     private static final int S_OK =0x00000000;
>
>     private static void checkResult(int result) {
>         switch (result) {
>             case S_OK -> {}
>             default ->throw new IllegalStateException("Unknown result: 
> " +String.format("%X8", result));
>         }
>     }
> }
>
>
> Which on my machine prints: NVIDIA GeForce GTX 1050 Ti
>
> HTH,
> Jorn
>
> On 14/09/2020 12:52, Maurizio Cimadamore wrote:
>> I think there's something off in here:
>>
>>> MemorySegment segment =
>>> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize()); 
>>>
>>> MemoryAddress address = segment.address().addOffset(64);
>> I see a couple of issues:
>>
>> 1) how do you determine that the offset of the function address you 
>> want to obtain is 64 byte from the start? Didn't jextract give you a 
>> getter for that?
>>
>> 2) Even assuming 64 byte is the correct offset, note that the segment 
>> will be initialized to all zeros - I presume this vtable must be 
>> filled in somehow, or perhaps obtained from a global variable?
>>
>> From your earlier email I see this:
>>
>>> interface IDXGIFactory
>>>       {
>>>           CONST_VTBL struct IDXGIFactoryVtbl *lpVtbl;
>>>       };
>> So... perhaps once yo create a IDXGIFactory, you can just grab the 
>> pointer to the vtable by accessing its `lpVtbl` field - no need to 
>> allocate a new segment (the library has done the allocation for you).
>>
>> If I'm correct, this can be achieved with something like (not sure if 
>> the names are going to be 100% correct since I don't have a 
>> jextracted version of the API with me - so beware, I have NOT tested 
>> this :-) ):
>>
>> var dxgiFactoryPtr = 
>> MemoryAccess.getAddress(MemorySegment.ofNativeRestricted(), 
>> dxgiFactory);
>> var lpVtbl = 
>> MemoryAccess.getAddress(MemorySegment.ofNativeRestricted(), 
>> dxgiFactoryPtr);
>> var vtable = RuntimeHelper.ofArrayRestricted(lpVtbl, 
>> IDXGIFactory1Vtbl.$LAYOUT(), 1); //1
>> var address = IDXGIFactory1Vtbl$EnumAdapters$get(vtable);
>>
>>
>> And this should give the address pointer you are looking for. We need 
>> to smooth the edges especially around (1) - e.g. to turn a random 
>> native pointer into a struct with given layout (jextract should 
>> generate a static helper for that, see [1]) - but with the code above 
>> you should be able to get there, I hope.
>>
>> P.S.
>> In these situations, my suggestion is, especially when attacking a 
>> native library for the first time, to always try the library directly 
>> using C and see what happens, to understand exactly what kind of 
>> pattern/idiom the library requires. I did that many times and 
>> realized my assumptions on how library worked were wrong; other users 
>> have posted similar instances in this mailing list. Once you get 
>> things working in C, porting the code in Java using the Panama API is 
>> typically a trivial matter.
>>
>> Maurizio
>>
>> [1] - https://bugs.openjdk.java.net/browse/JDK-8253102
>>
>>
>> On 13/09/2020 02:37, Michael Ennen wrote:
>>> Well, progress of a kind? This crashes the VM instead of not 
>>> compiling or
>>> throwing an exception:
>>>
>>> // IDXGIFactory1** dxgiFactory;
>>> var dxgiFactory = scope.allocate(C_POINTER);
>>> // HRESULT = CreateDXGIFactory1(_uuid(dxgiFactory), &dxgiFactory))
>>> int hresult = dxgi_h.CreateDXGIFactory1(GUID(IID.IID_IDXGIFactory1),
>>> dxgiFactory);
>>> System.out.println("hresult: " + hresult);
>>> var dxgiAdapter = scope.allocate(C_POINTER);
>>> System.out.println("IDXGIFactory1Vtbl byte size: " +
>>> dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize()); //112
>>> MemorySegment segment =
>>> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize()); 
>>>
>>> MemoryAddress address = segment.address().addOffset(64);
>>> FunctionDescriptor functionDescriptor = FunctionDescriptor.of(C_INT, 
>>> C_INT,
>>> C_POINTER);
>>> MethodType methodType = MethodType.methodType(int.class, int.class,
>>> MemoryAddress.class);
>>> MethodHandle methodHandle = getSystemLinker().downcallHandle(address,
>>> methodType, functionDescriptor);
>>> try {
>>> methodHandle.invokeWithArguments(0, dxgiAdapter.address());
>>> } catch (Throwable throwable) {
>>> throwable.printStackTrace();
>>> }
>>>
>>> On Sat, Sep 12, 2020 at 6:34 PM Michael Ennen <mike.ennen at gmail.com> 
>>> wrote:
>>>
>>>> I think I see why. It's because I am passing in a MemorySegment, 
>>>> which is
>>>> the dxgiAdapter which I initialize thusly:
>>>>
>>>> var dxgiAdapter = scope.allocate(C_POINTER);
>>>>
>>>> I guess I need to make it a MemoryAddress instead.
>>>>
>>>> On Sat, Sep 12, 2020 at 2:25 PM Michael Ennen <mike.ennen at gmail.com>
>>>> wrote:
>>>>
>>>>> Thanks so much Ty. That's super helpful. I think I was able to 
>>>>> make quite
>>>>> a bit of progress:
>>>>>
>>>>> var dxgiAdapter = scope.allocate(C_POINTER);
>>>>> System.out.println("IDXGIFactory1Vtbl byte size: " +
>>>>> dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize());
>>>>> MemorySegment segment =
>>>>> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize()); 
>>>>>
>>>>> MemoryAddress address = segment.address().addOffset(64);
>>>>> FunctionDescriptor functionDescriptor = FunctionDescriptor.of(C_INT,
>>>>> C_INT, C_POINTER);
>>>>> MethodType methodType = MethodType.methodType(int.class, int.class,
>>>>> MemoryAddress.class);
>>>>> MethodHandle methodHandle = getSystemLinker().downcallHandle(address,
>>>>> methodType, functionDescriptor);
>>>>> try {
>>>>> methodHandle.invokeWithArguments(0, dxgiAdapter);
>>>>> } catch (Throwable throwable) {
>>>>> throwable.printStackTrace();
>>>>> }
>>>>>
>>>>> Note that the EnumAdapters1 function signature is actually:
>>>>>
>>>>> HRESULT EnumAdapters1(
>>>>>    UINT          Adapter,
>>>>>    IDXGIAdapter1 **ppAdapter
>>>>> );
>>>>>
>>>>>
>>>>> So that's why I went with:
>>>>>
>>>>> FunctionDescriptor functionDescriptor = FunctionDescriptor.of(C_INT,
>>>>> C_INT, C_POINTER);
>>>>>
>>>>> and then
>>>>>
>>>>> methodHandle.invokeWithArguments(0, dxgiAdapter);
>>>>>
>>>>> I did some fancy stuff as per your suggestion which I feel should be
>>>>> getting the address of the EumAdapters1 function
>>>>> pointer (basically start at the base address of the struct and 
>>>>> then move
>>>>> 64 bytes past, which should be the 8th function
>>>>> pointer which in this case is EnumAdapters1).
>>>>>
>>>>> I do get the following exception on invoking the method handle, 
>>>>> though:
>>>>>
>>>>> hresult: 0
>>>>> factory: MemorySegment{ id=0x3898fd8a limit: 8 }
>>>>> IDXGIFactory1Vtbl byte size: 112
>>>>> java.lang.ClassCastException: Cannot cast
>>>>> jdk.internal.foreign.NativeMemorySegmentImpl to
>>>>> jdk.incubator.foreign.MemoryAddress
>>>>>          at java.base/java.lang.Class.cast(Class.java:3816)
>>>>>          at
>>>>> java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733) 
>>>>>
>>>>>          at com.dx12.DX12.main(DX12.java:91)
>>>>>          at
>>>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native 
>>>>>
>>>>> Method)
>>>>>          at
>>>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) 
>>>>>
>>>>>          at
>>>>> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
>>>>>
>>>>>          at 
>>>>> java.base/java.lang.reflect.Method.invoke(Method.java:564)
>>>>>          at
>>>>> jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:415)
>>>>>          at
>>>>> jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
>>>>>          at
>>>>> jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
>>>>> vh: VarHandle[varType=jdk.incubator.foreign.MemoryAddress,
>>>>> coord=[interface jdk.incubator.foreign.MemorySegment]]
>>>>>
>>>>> Any more assistance would be greatly appreciate but undeserved :).
>>>>>
>>>>>
>>>>> On Sat, Sep 12, 2020 at 1:41 AM Ty Young <youngty1997 at gmail.com> 
>>>>> wrote:
>>>>>
>>>>>> Not a JDK developer, but if you want to do this by hand(aka no
>>>>>> jextract), I had to do this for NVAPI which obfuscates function 
>>>>>> pointers
>>>>>> using keys, e.g.:
>>>>>>
>>>>>>
>>>>>> nvapi_h.nvapi_QueryInterface(0x0150e828);
>>>>>>
>>>>>>
>>>>>> where "0x0150e828" is the "NvAPI_Initialize" function key as per the
>>>>>> Open Source headers Nvidia released sometime ago.
>>>>>>
>>>>>>
>>>>>> The only difference is that, since the function pointer is in a 
>>>>>> struct,
>>>>>> you need to get the segment in the struct containing the function
>>>>>> pointer(see "slice" MemorySegment method) and actually read from it
>>>>>> using a VarHandle. You then take that MemoryAddress, with a
>>>>>> FunctionDescriptor and MethodType, and create a MethodHandle. For
>>>>>> reference, this my working code("NativeFunction" and 
>>>>>> "NativeTypes" do
>>>>>> not exist in Panama, those are mine but they dont matter) for the
>>>>>> NvAPI_Initalize API:
>>>>>>
>>>>>>
>>>>>> public class NvAPI_Initialize implements NativeFunction
>>>>>> {
>>>>>>       private final MemoryAddress address;
>>>>>>       private final FunctionDescriptor descriptor;
>>>>>>       private final MethodType type;
>>>>>>
>>>>>>       private final MethodHandle handle;
>>>>>>
>>>>>>       public NvAPI_Initialize() throws NoSuchMethodException, 
>>>>>> Throwable
>>>>>>       {
>>>>>>           this.address = nvapi_h.nvapi_QueryInterface(0x0150e828);
>>>>>>
>>>>>>           this.descriptor = FunctionDescriptor.of(NativeTypes.INT);
>>>>>>
>>>>>>           this.type = MethodType.methodType(int.class);
>>>>>>
>>>>>>           this.handle =
>>>>>> CSupport.getSystemLinker().downcallHandle(this.address, this.type,
>>>>>> this.descriptor);
>>>>>>       }
>>>>>>
>>>>>>       // etc
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> It looks like in your case the FunctionDescriptor would be:
>>>>>>
>>>>>>
>>>>>> this.descriptor = FunctionDescriptor.of(CSupport.C_POINTER,
>>>>>> CSupport.C_INT, CSupport.C_POINTER);
>>>>>>
>>>>>>
>>>>>> for MethodType:
>>>>>>
>>>>>>
>>>>>> MethodType.methodType(MemoryAddress.class, int.class,
>>>>>> MemoryAddress.class);
>>>>>>
>>>>>>
>>>>>> where the first argument takes in a IDXGIFactory, the second an 
>>>>>> unsigned
>>>>>> int, and the third a pointer to what looks like an opaque device 
>>>>>> that
>>>>>> you pass to other functions.
>>>>>>
>>>>>>
>>>>>> If you haven't already, it might help to make bindings with a 
>>>>>> smaller,
>>>>>> less complicated library just to get a feel with how things work 
>>>>>> under
>>>>>> the hood.
>>>>>>
>>>>>>
>>>>>> Hope this helps.
>>>>>>
>>>>>>
>>>>>> On 9/12/20 2:23 AM, Michael Ennen wrote:
>>>>>>> Looking into this a bit further I think I chose a really bad 
>>>>>>> library to
>>>>>>> start with as the function I need to call, EnumAdapters, is inside
>>>>>>> some type of "VTbl" struct that is trying to emulate a C++ class 
>>>>>>> with
>>>>>>> virtual functions. What jextract is returning is most likely 
>>>>>>> *correct*
>>>>>>> but in this case so complicated because of how it is laid out in 
>>>>>>> C. It
>>>>>> is
>>>>>>> not clear at all how to grab the EnumAdapters function from
>>>>>>> this mess, and it is probably above my head.
>>>>>>>
>>>>>>> EXTERN_C const IID IID_IDXGIFactory;
>>>>>>>
>>>>>>> #if defined(__cplusplus) && !defined(CINTERFACE)
>>>>>>>
>>>>>>> MIDL_INTERFACE("7b7166ec-21c7-44ae-b21a-c9ae321ae369")
>>>>>>>       IDXGIFactory : public IDXGIObject
>>>>>>>       {
>>>>>>>       public:
>>>>>>>           virtual HRESULT STDMETHODCALLTYPE EnumAdapters(
>>>>>>>               /* [in] */ UINT Adapter,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGIAdapter **ppAdapter) = 0;
>>>>>>>
>>>>>>>           virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation(
>>>>>>>               HWND WindowHandle,
>>>>>>>               UINT Flags) = 0;
>>>>>>>
>>>>>>>           virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation(
>>>>>>>               /* [annotation][out] */
>>>>>>>               _Out_  HWND *pWindowHandle) = 0;
>>>>>>>
>>>>>>>           virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  IUnknown *pDevice,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  DXGI_SWAP_CHAIN_DESC *pDesc,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGISwapChain **ppSwapChain) = 0;
>>>>>>>
>>>>>>>           virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter(
>>>>>>>               /* [in] */ HMODULE Module,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGIAdapter **ppAdapter) = 0;
>>>>>>>
>>>>>>>       };
>>>>>>>
>>>>>>>
>>>>>>> #else /* C style interface */
>>>>>>>
>>>>>>>       typedef struct IDXGIFactoryVtbl
>>>>>>>       {
>>>>>>>           BEGIN_INTERFACE
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [in] */ REFIID riid,
>>>>>>>               /* [annotation][iid_is][out] */
>>>>>>>               _COM_Outptr_  void **ppvObject);
>>>>>>>
>>>>>>>           ULONG ( STDMETHODCALLTYPE *AddRef )(
>>>>>>>               IDXGIFactory * This);
>>>>>>>
>>>>>>>           ULONG ( STDMETHODCALLTYPE *Release )(
>>>>>>>               IDXGIFactory * This);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  REFGUID Name,
>>>>>>>               /* [in] */ UINT DataSize,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_reads_bytes_(DataSize)  const void *pData);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  REFGUID Name,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_opt_  const IUnknown *pUnknown);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  REFGUID Name,
>>>>>>>               /* [annotation][out][in] */
>>>>>>>               _Inout_  UINT *pDataSize,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _Out_writes_bytes_(*pDataSize)  void *pData);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *GetParent )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  REFIID riid,
>>>>>>>               /* [annotation][retval][out] */
>>>>>>>               _COM_Outptr_  void **ppParent);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *EnumAdapters )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [in] */ UINT Adapter,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGIAdapter **ppAdapter);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *MakeWindowAssociation )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               HWND WindowHandle,
>>>>>>>               UINT Flags);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *GetWindowAssociation )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _Out_  HWND *pWindowHandle);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *CreateSwapChain )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  IUnknown *pDevice,
>>>>>>>               /* [annotation][in] */
>>>>>>>               _In_  DXGI_SWAP_CHAIN_DESC *pDesc,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGISwapChain **ppSwapChain);
>>>>>>>
>>>>>>>           HRESULT ( STDMETHODCALLTYPE *CreateSoftwareAdapter )(
>>>>>>>               IDXGIFactory * This,
>>>>>>>               /* [in] */ HMODULE Module,
>>>>>>>               /* [annotation][out] */
>>>>>>>               _COM_Outptr_  IDXGIAdapter **ppAdapter);
>>>>>>>
>>>>>>>           END_INTERFACE
>>>>>>>       } IDXGIFactoryVtbl;
>>>>>>>
>>>>>>>       interface IDXGIFactory
>>>>>>>       {
>>>>>>>           CONST_VTBL struct IDXGIFactoryVtbl *lpVtbl;
>>>>>>>       };
>>>>>>>
>>>>>>>
>>>>>
>>>>> -- 
>>>>> Michael Ennen
>>>>>
>>>>
>>>> -- 
>>>> Michael Ennen
>>>>
>>>


More information about the panama-dev mailing list