RenderTarget-> GetSize不起作用 [英] RenderTarget->GetSize not working

查看:124
本文介绍了RenderTarget-> GetSize不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要学习Direct2D,我正在关注此示例.

To learn myself Direct2D i'm following this example from the MSDN.

但是我有一个问题.调用D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();始终返回大小为0,0,并且在调试器中导致DrawLine调用发生异常.如果我不执行GetSize()调用,并使用有效值填充D2D1_SIZE_F结构,那么它将起作用.

I have however one issue. The call D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize(); allways returns a size of 0,0 and in the debugger causes an exception on the DrawLine call. If I leave out the GetSize() call and fill in the D2D1_SIZE_F structure with valid values it works.

初始化渲染目标的相关代码为:

The relevant code for initializing the render target is:

    RECT rc;
    GetClientRect(m_hwnd, &rc);

    D2D1_SIZE_U size = D2D1::SizeU(
        rc.right - rc.left,
        rc.bottom - rc.top
        );

    // Create a Direct2D render target.
    hr = m_pDirect2dFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(m_hwnd, size),
        &m_pRenderTarget
        );

我已通过调试器验证有效值超出了大小.

I have verified with the debugger that valid values are past in size.

绘图代码中称为GetSize的部分:

The part of the drawing code where GetSize is called:

    m_pRenderTarget->BeginDraw();

    m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

    m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();
    // Draw a grid background.
    int width = static_cast<int>(rtSize.width);
    int height = static_cast<int>(rtSize.height);

    for (int x = 0; x < width; x += 10)
    {
        m_pRenderTarget->DrawLine(
            D2D1::Point2F(static_cast<FLOAT>(x), 0.0f),
            D2D1::Point2F(static_cast<FLOAT>(x), rtSize.height),
            m_pLightSlateGrayBrush,
            0.5f
            );
    }

所以我的问题是,为什么GetSize()返回0,0并在以后导致AV?

So my question is why does GetSize() return 0,0 and causes an AV later on?

顺便说一句:我正在使用: Windows 7 Ultimate 64位 代码:: Blocks IDE TDM-GCC-64 gcc编译器v4.8.1 我正在以Unicode模式#define UNICODE进行编译 如果我编译为32位或64位,则会出现问题(是的,我对64位模式做了一些小的调整,以确保我有一个指向WndProc中应用程序对象的有效指针)

BTW: I'm using: Windows 7 Ultimate 64-bits Code::Blocks IDE TDM-GCC-64 gcc compiler v4.8.1 I'm compiling in Unicode mode #define UNICODE Problem occurs regardles if I compile to 32-bits or 64-bits (yes I made a few minor adjustments for 64-bits mode to make sure I had a valid pointer to the application object in WndProc)

推荐答案

为什么GetSize()返回0,0并在以后导致AV?

Why does GetSize() return 0,0 and causes an AV later on?

因为由GCC/MinGW-W64生成的GetSize调用与d2d1.dll中的实现的调用约定不匹配. GetSize的返回类型D2D_SIZE_F是一个结构.根据 Microsoft Docs 有两种从函数返回结构的方法:

Because the call to GetSize generated by GCC/MinGW-W64 doesn't match the calling convention of the implementation in d2d1.dll. The return type D2D_SIZE_F of GetSize is a struct. According to Microsoft Docs there are two ways to return a struct from a function:

可以通过全局函数和静态成员函数的值返回用户定义的类型.要通过RAX中的值返回用户定义的类型,它的长度必须为1、2、4、8、16、32或64位.它还必须没有用户定义的构造函数,析构函数或副本分配运算符.它不能具有私有或受保护的非静态数据成员,也不能具有引用类型的非静态数据成员.它不能具有基类或虚函数.并且,它只能具有满足这些要求的数据成员. (此定义在本质上与C ++ 03 POD类型相同.由于C ++ 11标准中的定义已更改,因此我们不建议在此测试中使用std :: is_pod.)否则,调用者必须分配返回值的内存,并将指向它的指针作为第一个参数传递.

User-defined types can be returned by value from global functions and static member functions. To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator. It can have no private or protected non-static data members, and no non-static data members of reference type. It can't have base classes or virtual functions. And, it can only have data members that also meet these requirements. (This definition is essentially the same as a C++03 POD type. Because the definition has changed in the C++11 standard, we don't recommend using std::is_pod for this test.) Otherwise, the caller must allocate memory for the return value and pass a pointer to it as the first argument.

当GCC/MinGW-W64编译本文中的示例代码时,调用方仅为GetSize调用设置一个参数(在rcx中),并期望在rax中返回该值:

When GCC/MinGW-W64 compiles the sample code from the article, the caller only sets up one argument (in rcx) for the call to GetSize, and expects the value to be returned in rax:

# AT&T syntax (destination operand last)
mov 0x10(%rbx),%rcx    # rcx <- pointer to IRenderContext
mov (%rcx),%rax        # rax <- pointer to virtual function table
callq *0x1a8(%rax)     # virtual function call (expect result in rax)

在Visual Studio生成的代码中,调用方在调用GetSize之前将rdx设置为指向堆栈上的某个位置:

In the code generated by Visual Studio, the caller sets up rdx to point to a location on the stack before calling GetSize:

# Intel syntax (destination operand first)
mov rax,qword ptr [rsp+168h]     # rax <- pointer to IRenderContext
mov rax,qword ptr [rax]          # rax <- pointer to virtual function table
lea rdx,[rsp+68h]                # rdx <- address of return value (hidden argument)
mov rcx,qword ptr [rsp+168h]     # rcx <- this pointer (hidden argument)
call qword ptr [rax+1A8h]        # virtual function call (expect result at [rdx])

在GCC/MinGW-W64上,rdx中的值不是有效地址,因此,当GetSize的实现尝试将返回值存储在内存中时,就会发生访问冲突.

On GCC/MinGW-W64 the value in rdx is not a valid address, so when the implementation of GetSize attempts to store the return value in memory there, an access violation occurs.

D2D_SIZE_F是64位POD结构(只是两个浮点数的结构),所以在我看来,GCC在rax寄存器中返回它是正确的.我不知道是什么使Visual Studio使用按指针返回,也不担心如何使GCC出于兼容性而做同样的事情.

D2D_SIZE_F is a 64-bit POD struct (just a struct of two floats), so it seems to me that GCC is correct to return it in the rax register. I don't know what it is that makes Visual Studio use return-by-pointer, nor, I'm afraid, how to make GCC do the same for compatibility.

这篇关于RenderTarget-&gt; GetSize不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆