d3d10core: Implement d3d10_device_UpdateSubresource().

This commit is contained in:
Henri Verbeet 2015-08-18 11:24:11 +02:00 committed by Alexandre Julliard
parent ee9b1311cd
commit 62a02a047f
5 changed files with 374 additions and 1 deletions

View File

@ -737,8 +737,28 @@ static void STDMETHODCALLTYPE d3d10_device_UpdateSubresource(ID3D10Device1 *ifac
ID3D10Resource *resource, UINT subresource_idx, const D3D10_BOX *box,
const void *data, UINT row_pitch, UINT depth_pitch)
{
FIXME("iface %p, resource %p, subresource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u stub!\n",
struct d3d10_device *device = impl_from_ID3D10Device(iface);
struct wined3d_resource *wined3d_resource;
struct wined3d_box wined3d_box;
TRACE("iface %p, resource %p, subresource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u.\n",
iface, resource, subresource_idx, box, data, row_pitch, depth_pitch);
if (box)
{
wined3d_box.left = box->left;
wined3d_box.top = box->top;
wined3d_box.front = box->front;
wined3d_box.right = box->right;
wined3d_box.bottom = box->bottom;
wined3d_box.back = box->back;
}
wined3d_resource = wined3d_resource_from_resource(resource);
wined3d_mutex_lock();
wined3d_device_update_sub_resource(device->wined3d_device, wined3d_resource,
subresource_idx, box ? &wined3d_box : NULL, data, row_pitch, depth_pitch);
wined3d_mutex_unlock();
}
static void STDMETHODCALLTYPE d3d10_device_ClearRenderTargetView(ID3D10Device1 *iface,

View File

@ -37,6 +37,16 @@ struct vec4
float x, y, z, w;
};
static void set_box(D3D10_BOX *box, UINT left, UINT top, UINT front, UINT right, UINT bottom, UINT back)
{
box->left = left;
box->top = top;
box->front = front;
box->right = right;
box->bottom = bottom;
box->back = back;
}
static ULONG get_refcount(IUnknown *iface)
{
IUnknown_AddRef(iface);
@ -3162,6 +3172,264 @@ static void test_fragment_coords(void)
DestroyWindow(window);
}
static void test_update_subresource(void)
{
ID3D10RenderTargetView *backbuffer_rtv;
D3D10_SUBRESOURCE_DATA resource_data;
D3D10_TEXTURE2D_DESC texture_desc;
ID3D10SamplerState *sampler_state;
ID3D10ShaderResourceView *ps_srv;
D3D10_SAMPLER_DESC sampler_desc;
ID3D10InputLayout *input_layout;
D3D10_BUFFER_DESC buffer_desc;
ID3D10Texture2D *backbuffer;
unsigned int stride, offset;
IDXGISwapChain *swapchain;
ID3D10Texture2D *texture;
ID3D10VertexShader *vs;
ID3D10PixelShader *ps;
ID3D10Device *device;
D3D10_VIEWPORT vp;
unsigned int i, j;
ID3D10Buffer *vb;
ULONG refcount;
D3D10_BOX box;
DWORD color;
HWND window;
HRESULT hr;
static const D3D10_INPUT_ELEMENT_DESC layout_desc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
};
static const DWORD vs_code[] =
{
#if 0
float4 main(float4 position : POSITION) : SV_POSITION
{
return position;
}
#endif
0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040,
0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e,
};
static const DWORD ps_code[] =
{
#if 0
Texture2D t;
SamplerState s;
float4 main(float4 position : SV_POSITION) : SV_Target
{
float2 p;
p.x = position.x / 640.0f;
p.y = position.y / 480.0f;
return t.Sample(s, p);
}
#endif
0x43425844, 0x1ce9b612, 0xc8176faa, 0xd37844af, 0xdb515605, 0x00000001, 0x00000134, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000098, 0x00000040,
0x00000026, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068,
0x00000001, 0x0a000038, 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x3acccccd,
0x3b088889, 0x00000000, 0x00000000, 0x09000045, 0x001020f2, 0x00000000, 0x00100046, 0x00000000,
0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0100003e,
};
static const struct
{
float x, y;
}
quad[] =
{
{-1.0f, -1.0f},
{-1.0f, 1.0f},
{ 1.0f, -1.0f},
{ 1.0f, 1.0f},
};
static const float red[] = {1.0f, 0.0f, 0.0f, 0.5f};
static const DWORD bitmap_data[] =
{
0xff0000ff, 0xff00ffff, 0xff00ff00, 0xffffff00,
0xffff0000, 0xffff00ff, 0xff000000, 0xff7f7f7f,
0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
0xffffffff, 0xff000000, 0xff000000, 0xff000000,
};
static const DWORD expected_colors[] =
{
0xffffffff, 0xff000000, 0xffffffff, 0xff000000,
0xff00ff00, 0xff0000ff, 0xff00ffff, 0x00000000,
0xffffff00, 0xffff0000, 0xffff00ff, 0x00000000,
0xff000000, 0xff7f7f7f, 0xffffffff, 0x00000000,
};
if (!(device = create_device()))
{
skip("Failed to create device, skipping tests.\n");
return;
}
window = CreateWindowA("static", "d3d10core_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, NULL, NULL, NULL, NULL);
swapchain = create_swapchain(device, window, TRUE);
hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&backbuffer);
ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
hr = ID3D10Device_CreateInputLayout(device, layout_desc, sizeof(layout_desc) / sizeof(*layout_desc),
vs_code, sizeof(vs_code), &input_layout);
ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr);
buffer_desc.ByteWidth = sizeof(quad);
buffer_desc.Usage = D3D10_USAGE_DEFAULT;
buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
buffer_desc.CPUAccessFlags = 0;
buffer_desc.MiscFlags = 0;
resource_data.pSysMem = quad;
resource_data.SysMemPitch = 0;
resource_data.SysMemSlicePitch = 0;
hr = ID3D10Device_CreateBuffer(device, &buffer_desc, &resource_data, &vb);
ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
texture_desc.Width = 4;
texture_desc.Height = 4;
texture_desc.MipLevels = 1;
texture_desc.ArraySize = 1;
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texture_desc.SampleDesc.Count = 1;
texture_desc.SampleDesc.Quality = 0;
texture_desc.Usage = D3D10_USAGE_DEFAULT;
texture_desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
texture_desc.CPUAccessFlags = 0;
texture_desc.MiscFlags = 0;
hr = ID3D10Device_CreateTexture2D(device, &texture_desc, NULL, &texture);
ok(SUCCEEDED(hr), "Failed to create a 2d texture, hr %#x\n", hr);
hr = ID3D10Device_CreateShaderResourceView(device, (ID3D10Resource *)texture, NULL, &ps_srv);
ok(SUCCEEDED(hr), "Failed to create shader resource view, hr %#x\n", hr);
sampler_desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
sampler_desc.MipLODBias = 0.0f;
sampler_desc.MaxAnisotropy = 0;
sampler_desc.ComparisonFunc = D3D10_COMPARISON_NEVER;
sampler_desc.BorderColor[0] = 0.0f;
sampler_desc.BorderColor[1] = 0.0f;
sampler_desc.BorderColor[2] = 0.0f;
sampler_desc.BorderColor[3] = 0.0f;
sampler_desc.MinLOD = 0.0f;
sampler_desc.MaxLOD = 0.0f;
hr = ID3D10Device_CreateSamplerState(device, &sampler_desc, &sampler_state);
ok(SUCCEEDED(hr), "Failed to create sampler state, hr %#x.\n", hr);
hr = ID3D10Device_CreateVertexShader(device, vs_code, sizeof(vs_code), &vs);
ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr);
hr = ID3D10Device_CreatePixelShader(device, ps_code, sizeof(ps_code), &ps);
ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
hr = ID3D10Device_CreateRenderTargetView(device, (ID3D10Resource *)backbuffer, NULL, &backbuffer_rtv);
ok(SUCCEEDED(hr), "Failed to create rendertarget view, hr %#x.\n", hr);
ID3D10Device_OMSetRenderTargets(device, 1, &backbuffer_rtv, NULL);
ID3D10Device_IASetInputLayout(device, input_layout);
ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
stride = sizeof(*quad);
offset = 0;
ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &stride, &offset);
ID3D10Device_VSSetShader(device, vs);
ID3D10Device_PSSetShaderResources(device, 0, 1, &ps_srv);
ID3D10Device_PSSetSamplers(device, 0, 1, &sampler_state);
ID3D10Device_PSSetShader(device, ps);
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = 640;
vp.Height = 480;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
ID3D10Device_RSSetViewports(device, 1, &vp);
ID3D10Device_ClearRenderTargetView(device, backbuffer_rtv, red);
ID3D10Device_Draw(device, 4, 0);
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
color = get_texture_color(backbuffer, 80 + j * 160, 60 + i * 120);
ok(compare_color(color, 0x00000000, 0),
"Got unexpected color 0x%08x at (%u, %u).\n", color, j, i);
}
}
set_box(&box, 1, 1, 0, 3, 3, 1);
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, &box,
bitmap_data, 4 * sizeof(*bitmap_data), 0);
set_box(&box, 0, 3, 0, 3, 4, 1);
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, &box,
&bitmap_data[6], 4 * sizeof(*bitmap_data), 0);
set_box(&box, 0, 0, 0, 4, 1, 1);
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, &box,
&bitmap_data[10], 4 * sizeof(*bitmap_data), 0);
set_box(&box, 0, 1, 0, 1, 3, 1);
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, &box,
&bitmap_data[2], sizeof(*bitmap_data), 0);
set_box(&box, 4, 4, 0, 3, 1, 1);
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, &box,
bitmap_data, sizeof(*bitmap_data), 0);
ID3D10Device_Draw(device, 4, 0);
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
color = get_texture_color(backbuffer, 80 + j * 160, 60 + i * 120);
ok(compare_color(color, expected_colors[j + i * 4], 1),
"Got unexpected color 0x%08x at (%u, %u), expected 0x%08x.\n",
color, j, i, expected_colors[j + i * 4]);
}
}
ID3D10Device_UpdateSubresource(device, (ID3D10Resource *)texture, 0, NULL,
bitmap_data, 4 * sizeof(*bitmap_data), 0);
ID3D10Device_Draw(device, 4, 0);
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
color = get_texture_color(backbuffer, 80 + j * 160, 60 + i * 120);
ok(compare_color(color, bitmap_data[j + i * 4], 1),
"Got unexpected color 0x%08x at (%u, %u), expected 0x%08x.\n",
color, j, i, bitmap_data[j + i * 4]);
}
}
ID3D10PixelShader_Release(ps);
ID3D10VertexShader_Release(vs);
ID3D10SamplerState_Release(sampler_state);
ID3D10ShaderResourceView_Release(ps_srv);
ID3D10Texture2D_Release(texture);
ID3D10Buffer_Release(vb);
ID3D10InputLayout_Release(input_layout);
ID3D10RenderTargetView_Release(backbuffer_rtv);
ID3D10Texture2D_Release(backbuffer);
IDXGISwapChain_Release(swapchain);
refcount = ID3D10Device_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
DestroyWindow(window);
}
START_TEST(device)
{
test_create_texture2d();
@ -3183,4 +3451,5 @@ START_TEST(device)
test_private_data();
test_il_append_aligned();
test_fragment_coords();
test_update_subresource();
}

View File

@ -3818,6 +3818,8 @@ float CDECL wined3d_device_get_npatch_mode(const struct wined3d_device *device)
return 0.0f;
}
/* FIXME: Callers should probably use wined3d_device_update_sub_resource()
* instead. */
HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device,
struct wined3d_surface *src_surface, const RECT *src_rect,
struct wined3d_surface *dst_surface, const POINT *dst_point)
@ -3981,6 +3983,84 @@ void CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *device
ERR("Failed to blit, hr %#x.\n", hr);
}
void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
unsigned int depth_pitch)
{
struct wined3d_resource *sub_resource;
const struct wined3d_gl_info *gl_info;
struct wined3d_const_bo_address addr;
struct wined3d_context *context;
struct wined3d_texture *texture;
struct wined3d_surface *surface;
POINT dst_point;
RECT src_rect;
TRACE("device %p, resource %p, sub_resource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u.\n",
device, resource, sub_resource_idx, box, data, row_pitch, depth_pitch);
if (resource->type != WINED3D_RTYPE_TEXTURE)
{
FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
return;
}
texture = wined3d_texture_from_resource(resource);
if (!(sub_resource = wined3d_texture_get_sub_resource(texture, sub_resource_idx)))
{
WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
return;
}
surface = surface_from_resource(sub_resource);
src_rect.left = 0;
src_rect.top = 0;
if (box)
{
if (box->left >= box->right || box->right > sub_resource->width
|| box->top >= box->bottom || box->bottom > sub_resource->height)
{
WARN("Invalid box (%u, %u, %u)->(%u, %u, %u) specified.\n",
box->left, box->top, box->front, box->right, box->bottom, box->back);
return;
}
src_rect.right = box->right - box->left;
src_rect.bottom = box->bottom - box->top;
dst_point.x = box->left;
dst_point.y = box->top;
}
else
{
src_rect.right = sub_resource->width;
src_rect.bottom = sub_resource->height;
dst_point.x = 0;
dst_point.y = 0;
}
addr.buffer_object = 0;
addr.addr = data;
context = context_acquire(resource->device, NULL);
gl_info = context->gl_info;
/* Only load the surface for partial updates. */
if (!dst_point.x && !dst_point.y && src_rect.right == sub_resource->width
&& src_rect.bottom == sub_resource->height)
wined3d_texture_prepare_texture(texture, context, FALSE);
else
surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB);
wined3d_texture_bind_and_dirtify(texture, context, FALSE);
wined3d_surface_upload_data(surface, gl_info, resource->format,
&src_rect, row_pitch, &dst_point, FALSE, &addr);
context_release(context);
surface_validate_location(surface, WINED3D_LOCATION_TEXTURE_RGB);
surface_invalidate_location(surface, ~WINED3D_LOCATION_TEXTURE_RGB);
}
HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device,
struct wined3d_rendertarget_view *view, const RECT *rect, const struct wined3d_color *color)
{

View File

@ -161,6 +161,7 @@
@ cdecl wined3d_device_show_cursor(ptr long)
@ cdecl wined3d_device_uninit_3d(ptr)
@ cdecl wined3d_device_uninit_gdi(ptr)
@ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long)
@ cdecl wined3d_device_update_surface(ptr ptr ptr ptr ptr)
@ cdecl wined3d_device_update_texture(ptr ptr ptr)
@ cdecl wined3d_device_validate_device(ptr ptr)

View File

@ -2329,6 +2329,9 @@ void __cdecl wined3d_device_setup_fullscreen_window(struct wined3d_device *devic
BOOL __cdecl wined3d_device_show_cursor(struct wined3d_device *device, BOOL show);
HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device);
HRESULT __cdecl wined3d_device_uninit_gdi(struct wined3d_device *device);
void __cdecl wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
unsigned int depth_pitch);
HRESULT __cdecl wined3d_device_update_surface(struct wined3d_device *device, struct wined3d_surface *src_surface,
const RECT *src_rect, struct wined3d_surface *dst_surface, const POINT *dst_point);
HRESULT __cdecl wined3d_device_update_texture(struct wined3d_device *device,