Exemplo n.º 1
0
Arquivo: core.c Projeto: bilboed/wine
static void test_ID3DXSprite(IDirect3DDevice9 *device)
{
    ID3DXSprite *sprite;
    IDirect3D9 *d3d;
    IDirect3DDevice9 *cmpdev;
    IDirect3DTexture9 *tex1, *tex2;
    D3DXMATRIX mat, cmpmat;
    D3DVIEWPORT9 vp;
    RECT rect;
    D3DXVECTOR3 pos, center;
    HRESULT hr;

    IDirect3DDevice9_GetDirect3D(device, &d3d);
    hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
    IDirect3D9_Release(d3d);
    ok (hr == D3D_OK, "D3DFMT_A8R8G8B8 not supported\n");
    if (FAILED(hr)) return;

    hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
    ok (hr == D3D_OK, "Failed to create first texture (error code: %#x)\n", hr);
    if (FAILED(hr)) return;

    hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
    ok (hr == D3D_OK, "Failed to create second texture (error code: %#x)\n", hr);
    if (FAILED(hr)) {
        IDirect3DTexture9_Release(tex1);
        return;
    }

    /* Test D3DXCreateSprite */
    hr = D3DXCreateSprite(device, NULL);
    ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    hr = D3DXCreateSprite(NULL, &sprite);
    ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    hr = D3DXCreateSprite(device, &sprite);
    ok (hr == D3D_OK, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3D_OK);


    /* Test ID3DXSprite_GetDevice */
    hr = ID3DXSprite_GetDevice(sprite, NULL);
    ok (hr == D3DERR_INVALIDCALL, "GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    hr = ID3DXSprite_GetDevice(sprite, &cmpdev);  /* cmpdev == NULL */
    ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK);

    hr = ID3DXSprite_GetDevice(sprite, &cmpdev);  /* cmpdev != NULL */
    ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK);

    IDirect3DDevice9_Release(device);
    IDirect3DDevice9_Release(device);


    /* Test ID3DXSprite_GetTransform */
    hr = ID3DXSprite_GetTransform(sprite, NULL);
    ok (hr == D3DERR_INVALIDCALL, "GetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
    hr = ID3DXSprite_GetTransform(sprite, &mat);
    ok (hr == D3D_OK, "GetTransform returned %#x, expected %#x\n", hr, D3D_OK);
    if(SUCCEEDED(hr)) {
        D3DXMATRIX identity;
        D3DXMatrixIdentity(&identity);
        check_mat(mat, identity);
    }

    /* Test ID3DXSprite_SetTransform */
    /* Set a transform and test if it gets returned correctly */
    U(mat).m[0][0]=2.1f;  U(mat).m[0][1]=6.5f;  U(mat).m[0][2]=-9.6f; U(mat).m[0][3]=1.7f;
    U(mat).m[1][0]=4.2f;  U(mat).m[1][1]=-2.5f; U(mat).m[1][2]=2.1f;  U(mat).m[1][3]=5.5f;
    U(mat).m[2][0]=-2.6f; U(mat).m[2][1]=0.3f;  U(mat).m[2][2]=8.6f;  U(mat).m[2][3]=8.4f;
    U(mat).m[3][0]=6.7f;  U(mat).m[3][1]=-5.1f; U(mat).m[3][2]=6.1f;  U(mat).m[3][3]=2.2f;

    hr = ID3DXSprite_SetTransform(sprite, NULL);
    ok (hr == D3DERR_INVALIDCALL, "SetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    hr = ID3DXSprite_SetTransform(sprite, &mat);
    ok (hr == D3D_OK, "SetTransform returned %#x, expected %#x\n", hr, D3D_OK);
    if(SUCCEEDED(hr)) {
        hr=ID3DXSprite_GetTransform(sprite, &cmpmat);
        if(SUCCEEDED(hr)) check_mat(cmpmat, mat);
        else skip("GetTransform returned %#x\n", hr);
    }

    /* Test ID3DXSprite_SetWorldViewLH/RH */
    todo_wine {
        hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, &mat);
        ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, &mat);
        ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, NULL);
        ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, NULL);
        ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK);

        hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, &mat);
        ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, &mat);
        ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, NULL);
        ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, NULL);
        ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK);
    }
    IDirect3DDevice9_BeginScene(device);

    /* Test ID3DXSprite_Begin*/
    hr = ID3DXSprite_Begin(sprite, 0);
    ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);

    IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &mat);
    D3DXMatrixIdentity(&cmpmat);
    check_mat(mat, cmpmat);

    IDirect3DDevice9_GetTransform(device, D3DTS_VIEW, &mat);
    check_mat(mat, cmpmat);

    IDirect3DDevice9_GetTransform(device, D3DTS_PROJECTION, &mat);
    IDirect3DDevice9_GetViewport(device, &vp);
    D3DXMatrixOrthoOffCenterLH(&cmpmat, vp.X+0.5f, (float)vp.Width+vp.X+0.5f, (float)vp.Height+vp.Y+0.5f, vp.Y+0.5f, vp.MinZ, vp.MaxZ);
    check_mat(mat, cmpmat);

    /* Test ID3DXSprite_Flush and ID3DXSprite_End */
    hr = ID3DXSprite_Flush(sprite);
    ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);

    hr = ID3DXSprite_End(sprite);
    ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);

    hr = ID3DXSprite_Flush(sprite); /* May not be called before next Begin */
    ok (hr == D3DERR_INVALIDCALL, "Flush returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
    hr = ID3DXSprite_End(sprite);
    ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    /* Test ID3DXSprite_Draw */
    hr = ID3DXSprite_Begin(sprite, 0);
    ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);

    if(FAILED(hr)) skip("Couldn't ID3DXSprite_Begin, can't test ID3DXSprite_Draw\n");
    else { /* Feed the sprite batch */
        int texref1, texref2;

        SetRect(&rect, 53, 12, 142, 165);
        pos.x    =  2.2f; pos.y    = 4.5f; pos.z    = 5.1f;
        center.x = 11.3f; center.y = 3.4f; center.z = 1.2f;

        texref1 = get_ref((IUnknown*)tex1);
        texref2 = get_ref((IUnknown*)tex2);

        hr = ID3DXSprite_Draw(sprite, NULL, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
        ok (hr == D3DERR_INVALIDCALL, "Draw returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

        hr = ID3DXSprite_Draw(sprite, tex1, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Draw(sprite, tex2, &rect, &center, &pos, D3DCOLOR_XRGB(  3,  45,  66));
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Draw(sprite, tex1,  NULL, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Draw(sprite, tex1, &rect,    NULL, &pos, D3DCOLOR_XRGB(255, 255, 255));
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Draw(sprite, tex1, &rect, &center, NULL, D3DCOLOR_XRGB(255, 255, 255));
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Draw(sprite, tex1,  NULL,    NULL, NULL,                            0);
        ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);

        check_ref((IUnknown*)tex1, texref1+5); check_ref((IUnknown*)tex2, texref2+1);
        hr = ID3DXSprite_Flush(sprite);
        ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
        hr = ID3DXSprite_Flush(sprite);   /* Flushing twice should work */
        ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
        check_ref((IUnknown*)tex1, texref1);   check_ref((IUnknown*)tex2, texref2);

        hr = ID3DXSprite_End(sprite);
        ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);
    }

    /* Test ID3DXSprite_OnLostDevice and ID3DXSprite_OnResetDevice */
    /* Both can be called twice */
    hr = ID3DXSprite_OnLostDevice(sprite);
    ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_OnLostDevice(sprite);
    ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_OnResetDevice(sprite);
    ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_OnResetDevice(sprite);
    ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);

    /* Make sure everything works like before */
    hr = ID3DXSprite_Begin(sprite, 0);
    ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_Draw(sprite, tex2, &rect, &center, &pos, D3DCOLOR_XRGB(255, 255, 255));
    ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_Flush(sprite);
    ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_End(sprite);
    ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK);

    /* OnResetDevice makes the interface "forget" the Begin call */
    hr = ID3DXSprite_Begin(sprite, 0);
    ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_OnResetDevice(sprite);
    ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK);
    hr = ID3DXSprite_End(sprite);
    ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);

    IDirect3DDevice9_EndScene(device);
    check_release((IUnknown*)sprite, 0);
    check_release((IUnknown*)tex2, 0);
    check_release((IUnknown*)tex1, 0);
}
Exemplo n.º 2
0
static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
        const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR color)
{
    struct d3dx_font *This = impl_from_ID3DXFont(iface);
    RECT calc_rect;
    INT height;

    TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x\n",
            iface,  sprite, debugstr_w(string), count, wine_dbgstr_rect(rect), format, color);

    if (!string || count == 0)
        return 0;

    if (count < 0)
       count = lstrlenW(string);

    /* Strip terminating NULL characters */
    while (count > 0 && !string[count-1])
        count--;

    if (rect)
        calc_rect = *rect;

    height = DrawTextW(This->hdc, string, count, &calc_rect, format | DT_CALCRECT);

    if (format & DT_CALCRECT)
    {
        if (rect)
            *rect = calc_rect;
        return height;
    }

    if (format & DT_CENTER)
    {
        UINT new_width = calc_rect.right - calc_rect.left;
        calc_rect.left = (rect->right + rect->left - new_width) / 2;
        calc_rect.right = calc_rect.left + new_width;
    }

    if (height && (calc_rect.left < calc_rect.right))
    {
        D3DLOCKED_RECT locked_rect;
        D3DXVECTOR3 position;
        UINT text_width, text_height;
        RECT text_rect;
        ID3DXSprite *target = sprite;
        HRESULT hr;
        int i, j;

        /* Get rect position and dimensions */
        position.x = calc_rect.left;
        position.y = calc_rect.top;
        position.z = 0;
        text_width = calc_rect.right - calc_rect.left;
        text_height = calc_rect.bottom - calc_rect.top;
        text_rect.left = 0;
        text_rect.top = 0;
        text_rect.right = text_width;
        text_rect.bottom = text_height;

        /* We need to flush as it seems all draws in the begin/end sequence use only the latest updated texture */
        if (sprite)
            ID3DXSprite_Flush(sprite);

        /* Extend texture and DIB section to contain text */
        if ((text_width > This->tex_width) || (text_height > This->tex_height))
        {
            BITMAPINFOHEADER header;

            if (text_width > This->tex_width)
                This->tex_width = make_pow2(text_width);
            if (text_height > This->tex_height)
                This->tex_height = make_pow2(text_height);

            if (This->texture)
            {
                IDirect3DTexture9_Release(This->texture);
                DeleteObject(This->bitmap);
            }

            hr = D3DXCreateTexture(This->device, This->tex_width, This->tex_height, 1, 0,
                                   D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &This->texture);
            if (FAILED(hr))
            {
                This->texture = NULL;
                return 0;
            }

            header.biSize = sizeof(header);
            header.biWidth = This->tex_width;
            header.biHeight = -This->tex_height;
            header.biPlanes = 1;
            header.biBitCount = 32;
            header.biCompression = BI_RGB;
            header.biSizeImage = sizeof(DWORD) * This->tex_width * This->tex_height;
            header.biXPelsPerMeter = 0;
            header.biYPelsPerMeter = 0;
            header.biClrUsed = 0;
            header.biClrImportant = 0;

            This->bitmap = CreateDIBSection(This->hdc, (const BITMAPINFO*)&header,
                                            DIB_RGB_COLORS, (void**)&This->bits, NULL, 0);
            if (!This->bitmap)
            {
                IDirect3DTexture9_Release(This->texture);
                This->texture = NULL;
                return 0;
            }

            SelectObject(This->hdc, This->bitmap);
        }

        if (FAILED(IDirect3DTexture9_LockRect(This->texture, 0, &locked_rect, &text_rect, D3DLOCK_DISCARD)))
            return 0;

        /* Clear rect */
        for (i = 0; i < text_height; i++)
            memset(This->bits + i * This->tex_width * sizeof(DWORD), 0,
                   text_width * sizeof(DWORD));

        DrawTextW(This->hdc, string, count, &text_rect, format);

        /* All RGB components are equal so take one as alpha and set RGB
         * color to white, so it can be modulated with color parameter */
        for (i = 0; i < text_height; i++)
        {
            DWORD *src = (DWORD *)This->bits + i * This->tex_width;
            DWORD *dst = (DWORD *)((BYTE *)locked_rect.pBits + i * locked_rect.Pitch);
            for (j = 0; j < text_width; j++)
            {
                *dst++ = (*src++ << 24) | 0xFFFFFF;
            }
        }

        IDirect3DTexture9_UnlockRect(This->texture, 0);

        if (!sprite)
        {
            hr = D3DXCreateSprite(This->device, &target);
            if (FAILED(hr))
                 return 0;
            ID3DXSprite_Begin(target, 0);
        }

        hr = target->lpVtbl->Draw(target, This->texture, &text_rect, NULL, &position, color);

        if (!sprite)
        {
            ID3DXSprite_End(target);
            ID3DXSprite_Release(target);
        }

        if (FAILED(hr))
            return 0;
    }

    return height;
}