[PATCH 2/3] wined3d: Allow initial texture contents to be specified with wined3d_texture_create().

Henri Verbeet hverbeet at codeweavers.com
Mon Jan 5 06:24:58 CST 2015


---
 dlls/d3d10core/d3d10core_private.h |    4 +-
 dlls/d3d10core/device.c            |    8 ++--
 dlls/d3d10core/texture.c           |   14 +++---
 dlls/d3d8/device.c                 |    4 +-
 dlls/d3d8/texture.c                |    6 +--
 dlls/d3d9/device.c                 |    4 +-
 dlls/d3d9/texture.c                |    6 +--
 dlls/ddraw/ddraw.c                 |    2 +-
 dlls/ddraw/surface.c               |    4 +-
 dlls/wined3d/device.c              |    6 +--
 dlls/wined3d/surface.c             |   12 +++--
 dlls/wined3d/texture.c             |   91 ++++++++++++++++++++++++++++++++++--
 dlls/wined3d/volume.c              |   24 +++++-----
 dlls/wined3d/wined3d_private.h     |   21 ++++++++-
 include/wine/wined3d.h             |   11 ++++-
 15 files changed, 164 insertions(+), 53 deletions(-)

diff --git a/dlls/d3d10core/d3d10core_private.h b/dlls/d3d10core/d3d10core_private.h
index 29f5653..b777900 100644
--- a/dlls/d3d10core/d3d10core_private.h
+++ b/dlls/d3d10core/d3d10core_private.h
@@ -90,7 +90,7 @@ struct d3d10_texture2d
 };
 
 HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_device *device,
-        const D3D10_TEXTURE2D_DESC *desc) DECLSPEC_HIDDEN;
+        const D3D10_TEXTURE2D_DESC *desc, const D3D10_SUBRESOURCE_DATA *initial_data) DECLSPEC_HIDDEN;
 struct d3d10_texture2d *unsafe_impl_from_ID3D10Texture2D(ID3D10Texture2D *iface) DECLSPEC_HIDDEN;
 
 /* ID3D10Texture3D */
@@ -105,7 +105,7 @@ struct d3d10_texture3d
 };
 
 HRESULT d3d10_texture3d_init(struct d3d10_texture3d *texture, struct d3d10_device *device,
-        const D3D10_TEXTURE3D_DESC *desc) DECLSPEC_HIDDEN;
+        const D3D10_TEXTURE3D_DESC *desc, const D3D10_SUBRESOURCE_DATA *data) DECLSPEC_HIDDEN;
 
 /* ID3D10Buffer */
 struct d3d10_buffer
diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c
index 44a8085..ccac3f2 100644
--- a/dlls/d3d10core/device.c
+++ b/dlls/d3d10core/device.c
@@ -1414,7 +1414,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateTexture2D(ID3D10Device1 *ifa
         const D3D10_TEXTURE2D_DESC *desc, const D3D10_SUBRESOURCE_DATA *data,
         ID3D10Texture2D **texture)
 {
-    struct d3d10_device *This = impl_from_ID3D10Device(iface);
+    struct d3d10_device *device = impl_from_ID3D10Device(iface);
     struct d3d10_texture2d *object;
     HRESULT hr;
 
@@ -1424,8 +1424,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateTexture2D(ID3D10Device1 *ifa
     if (!object)
         return E_OUTOFMEMORY;
 
-    hr = d3d10_texture2d_init(object, This, desc);
-    if (FAILED(hr))
+    if (FAILED(hr = d3d10_texture2d_init(object, device, desc, data)))
     {
         WARN("Failed to initialize texture, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
@@ -1453,8 +1452,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateTexture3D(ID3D10Device1 *ifa
     if (!object)
         return E_OUTOFMEMORY;
 
-    hr = d3d10_texture3d_init(object, device, desc);
-    if (FAILED(hr))
+    if (FAILED(hr = d3d10_texture3d_init(object, device, desc, data)))
     {
         WARN("Failed to initialize texture, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, object);
diff --git a/dlls/d3d10core/texture.c b/dlls/d3d10core/texture.c
index d9354ee..330dea9 100644
--- a/dlls/d3d10core/texture.c
+++ b/dlls/d3d10core/texture.c
@@ -248,7 +248,7 @@ static const struct wined3d_parent_ops d3d10_texture2d_wined3d_parent_ops =
 };
 
 HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_device *device,
-        const D3D10_TEXTURE2D_DESC *desc)
+        const D3D10_TEXTURE2D_DESC *desc, const D3D10_SUBRESOURCE_DATA *data)
 {
     struct wined3d_resource_desc wined3d_desc;
     unsigned int levels;
@@ -303,8 +303,9 @@ HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_devic
 
     levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(desc->Width, desc->Height)) + 1;
 
-    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, levels,
-            0, texture, &d3d10_texture2d_wined3d_parent_ops, &texture->wined3d_texture)))
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc,
+            levels, 0, (struct wined3d_sub_resource_data *)data, texture,
+            &d3d10_texture2d_wined3d_parent_ops, &texture->wined3d_texture)))
     {
         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
         if (texture->dxgi_surface)
@@ -517,7 +518,7 @@ static const struct wined3d_parent_ops d3d10_texture3d_wined3d_parent_ops =
 };
 
 HRESULT d3d10_texture3d_init(struct d3d10_texture3d *texture, struct d3d10_device *device,
-        const D3D10_TEXTURE3D_DESC *desc)
+        const D3D10_TEXTURE3D_DESC *desc, const D3D10_SUBRESOURCE_DATA *data)
 {
     struct wined3d_resource_desc wined3d_desc;
     unsigned int levels;
@@ -540,8 +541,9 @@ HRESULT d3d10_texture3d_init(struct d3d10_texture3d *texture, struct d3d10_devic
 
     levels = desc->MipLevels ? desc->MipLevels : wined3d_log2i(max(max(desc->Width, desc->Height), desc->Depth)) + 1;
 
-    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc, levels,
-            0, texture, &d3d10_texture3d_wined3d_parent_ops, &texture->wined3d_texture)))
+    if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &wined3d_desc,
+            levels, 0, (struct wined3d_sub_resource_data *)data, texture,
+            &d3d10_texture3d_wined3d_parent_ops, &texture->wined3d_texture)))
     {
         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 659cae6..6a4802d 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -941,7 +941,7 @@ static HRESULT d3d8_device_create_surface(struct d3d8_device *device, UINT width
     wined3d_mutex_lock();
 
     if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
-            1, flags, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
+            1, flags, NULL, NULL, &d3d8_null_wined3d_parent_ops, &texture)))
     {
         wined3d_mutex_unlock();
         WARN("Failed to create texture, hr %#x.\n", hr);
@@ -3012,7 +3012,7 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     texture_desc = *desc;
     texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
     if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
+            WINED3D_SURFACE_MAPPABLE, NULL, &device->IDirect3DDevice8_iface, &d3d8_null_wined3d_parent_ops, &texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index 24c0b28..269ce4e 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -1177,7 +1177,7 @@ HRESULT texture_init(struct d3d8_texture *texture, struct d3d8_device *device,
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
-            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1222,7 +1222,7 @@ HRESULT cubetexture_init(struct d3d8_texture *texture, struct d3d8_device *devic
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
-            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1263,7 +1263,7 @@ HRESULT volumetexture_init(struct d3d8_texture *texture, struct d3d8_device *dev
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
-            texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d8_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index e2e3504..a80b30a 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -1041,7 +1041,7 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, UINT width
     wined3d_mutex_lock();
 
     if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &desc,
-            1, flags, NULL, &d3d9_null_wined3d_parent_ops, &texture)))
+            1, flags, NULL, NULL, &d3d9_null_wined3d_parent_ops, &texture)))
     {
         wined3d_mutex_unlock();
         WARN("Failed to create texture, hr %#x.\n", hr);
@@ -3547,7 +3547,7 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     texture_desc = *desc;
     texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
     if (FAILED(hr = wined3d_texture_create(device->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
+            WINED3D_SURFACE_MAPPABLE, NULL, container_parent, &d3d9_null_wined3d_parent_ops, &texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index c35ccdd..c1a0277 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -1306,7 +1306,7 @@ HRESULT texture_init(struct d3d9_texture *texture, struct d3d9_device *device,
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
-            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1356,7 +1356,7 @@ HRESULT cubetexture_init(struct d3d9_texture *texture, struct d3d9_device *devic
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, surface_flags,
-            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
@@ -1402,7 +1402,7 @@ HRESULT volumetexture_init(struct d3d9_texture *texture, struct d3d9_device *dev
 
     wined3d_mutex_lock();
     hr = wined3d_texture_create(device->wined3d_device, &desc, levels, 0,
-            texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
+            NULL, texture, &d3d9_texture_wined3d_parent_ops, &texture->wined3d_texture);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index f0ebc52..fcbc3bf 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -4786,7 +4786,7 @@ static HRESULT CDECL device_parent_create_swapchain_surface(struct wined3d_devic
     texture_desc = *desc;
     texture_desc.resource_type = WINED3D_RTYPE_TEXTURE;
     if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &texture_desc, 1,
-            WINED3D_SURFACE_MAPPABLE, ddraw, &ddraw_frontbuffer_parent_ops, &texture)))
+            WINED3D_SURFACE_MAPPABLE, NULL, ddraw, &ddraw_frontbuffer_parent_ops, &texture)))
     {
         WARN("Failed to create texture, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index a4184b8..a387d12 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -5992,7 +5992,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
      * Commandos: Behind Enemy Lines is another. We set
      * WINED3D_SURFACE_PIN_SYSMEM because of this. */
     if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, levels,
-            WINED3D_SURFACE_PIN_SYSMEM, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
+            WINED3D_SURFACE_PIN_SYSMEM, NULL, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
     {
         WARN("Failed to create wined3d texture, hr %#x.\n", hr);
         HeapFree(GetProcessHeap(), 0, texture);
@@ -6104,7 +6104,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
             desc->dwBackBufferCount = 0;
 
             if (FAILED(hr = wined3d_texture_create(ddraw->wined3d_device, &wined3d_desc, 1,
-                    WINED3D_SURFACE_PIN_SYSMEM, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
+                    WINED3D_SURFACE_PIN_SYSMEM, NULL, texture, &ddraw_texture_wined3d_parent_ops, &wined3d_texture)))
             {
                 HeapFree(GetProcessHeap(), 0, texture);
                 hr = hr_ddraw_from_wined3d(hr);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 89ec00a..d26d3f9 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -591,7 +591,7 @@ static void device_load_logo(struct wined3d_device *device, const char *filename
     desc.depth = 1;
     desc.size = 0;
     if (FAILED(hr = wined3d_texture_create(device, &desc, 1, WINED3D_SURFACE_MAPPABLE,
-            NULL, &wined3d_null_parent_ops, &device->logo_texture)))
+            NULL, NULL, &wined3d_null_parent_ops, &device->logo_texture)))
     {
         ERR("Wine logo requested, but failed to create texture, hr %#x.\n", hr);
         goto out;
@@ -3455,9 +3455,9 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device
 static HRESULT device_update_volume(struct wined3d_device *device,
         struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume)
 {
+    struct wined3d_const_bo_address data;
     struct wined3d_map_desc src;
     HRESULT hr;
-    struct wined3d_bo_address data;
     struct wined3d_context *context;
 
     TRACE("device %p, src_volume %p, dst_volume %p.\n",
@@ -4016,7 +4016,7 @@ static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined
     desc.size = 0;
 
     if (FAILED(wined3d_texture_create(device, &desc, 1, WINED3D_SURFACE_MAPPABLE,
-            NULL, &wined3d_null_parent_ops, &texture)))
+            NULL, NULL, &wined3d_null_parent_ops, &texture)))
     {
         ERR("Failed to create cursor texture.\n");
         wined3d_surface_unmap(cursor_image);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 092cbe6..fb27c8a 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1469,9 +1469,9 @@ static void surface_download_data(struct wined3d_surface *surface, const struct
 /* This call just uploads data, the caller is responsible for binding the
  * correct texture. */
 /* Context activation is done by the caller. */
-static void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
+void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
         const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
-        BOOL srgb, const struct wined3d_bo_address *data)
+        BOOL srgb, const struct wined3d_const_bo_address *data)
 {
     UINT update_w = src_rect->right - src_rect->left;
     UINT update_h = src_rect->bottom - src_rect->top;
@@ -1700,7 +1700,8 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
     surface_get_memory(src_surface, &data, src_surface->locations);
     src_pitch = wined3d_surface_get_pitch(src_surface);
 
-    surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_pitch, dst_point, FALSE, &data);
+    wined3d_surface_upload_data(dst_surface, gl_info, src_format, src_rect,
+            src_pitch, dst_point, FALSE, wined3d_const_bo_address(&data));
 
     context_invalidate_active_texture(context);
 
@@ -2468,7 +2469,7 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_surface *so
     desc.usage = 0;
     desc.pool = WINED3D_POOL_SCRATCH;
     if (FAILED(wined3d_texture_create(source->resource.device, &desc, 1,
-            WINED3D_SURFACE_MAPPABLE | WINED3D_SURFACE_DISCARD, NULL, &wined3d_null_parent_ops, &ret)))
+            WINED3D_SURFACE_MAPPABLE | WINED3D_SURFACE_DISCARD, NULL, NULL, &wined3d_null_parent_ops, &ret)))
     {
         ERR("Failed to create a destination surface for conversion.\n");
         return NULL;
@@ -4254,7 +4255,8 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
         data.addr = mem;
     }
 
-    surface_upload_data(surface, gl_info, &format, &src_rect, src_pitch, &dst_point, srgb, &data);
+    wined3d_surface_upload_data(surface, gl_info, &format, &src_rect,
+            src_pitch, &dst_point, srgb, wined3d_const_bo_address(&data));
 
     context_release(context);
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index dfcf02d..d33bad1 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -816,6 +816,29 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
     return WINED3D_OK;
 }
 
+static void wined3d_texture_upload_data(struct wined3d_texture *texture, const struct wined3d_sub_resource_data *data)
+{
+    unsigned int sub_count = texture->level_count * texture->layer_count;
+    struct wined3d_context *context;
+    unsigned int i;
+
+    context = context_acquire(texture->resource.device, NULL);
+
+    wined3d_texture_prepare_texture(texture, context, FALSE);
+    wined3d_texture_bind(texture, context, FALSE);
+
+    for (i = 0; i < sub_count; ++i)
+    {
+        struct wined3d_resource *sub_resource = texture->sub_resources[i];
+
+        texture->texture_ops->texture_sub_resource_upload_data(sub_resource, context, &data[i]);
+        texture->texture_ops->texture_sub_resource_validate_location(sub_resource, WINED3D_LOCATION_TEXTURE_RGB);
+        texture->texture_ops->texture_sub_resource_invalidate_location(sub_resource, ~WINED3D_LOCATION_TEXTURE_RGB);
+    }
+
+    context_release(context);
+}
+
 static void texture2d_sub_resource_load(struct wined3d_resource *sub_resource,
         struct wined3d_context *context, BOOL srgb)
 {
@@ -846,6 +869,33 @@ static void texture2d_sub_resource_invalidate_location(struct wined3d_resource *
     surface_invalidate_location(surface, location);
 }
 
+static void texture2d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location)
+{
+    struct wined3d_surface *surface = surface_from_resource(sub_resource);
+
+    surface_validate_location(surface, location);
+}
+
+static void texture2d_sub_resource_upload_data(struct wined3d_resource *sub_resource,
+        const struct wined3d_context *context, const struct wined3d_sub_resource_data *data)
+{
+    struct wined3d_surface *surface = surface_from_resource(sub_resource);
+    static const POINT dst_point = {0, 0};
+    struct wined3d_const_bo_address addr;
+    RECT src_rect;
+
+    src_rect.left = 0;
+    src_rect.top = 0;
+    src_rect.right = surface->resource.width;
+    src_rect.bottom = surface->resource.height;
+
+    addr.buffer_object = 0;
+    addr.addr = data->data;
+
+    wined3d_surface_upload_data(surface, context->gl_info, surface->container->resource.format,
+            &src_rect, data->row_pitch, &dst_point, FALSE, &addr);
+}
+
 /* Context activation is done by the caller. */
 static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
 {
@@ -951,6 +1001,8 @@ static const struct wined3d_texture_ops texture2d_ops =
     texture2d_sub_resource_add_dirty_region,
     texture2d_sub_resource_cleanup,
     texture2d_sub_resource_invalidate_location,
+    texture2d_sub_resource_validate_location,
+    texture2d_sub_resource_upload_data,
     texture2d_prepare_texture,
 };
 
@@ -1274,6 +1326,30 @@ static void texture3d_sub_resource_invalidate_location(struct wined3d_resource *
     wined3d_volume_invalidate_location(volume, location);
 }
 
+static void texture3d_sub_resource_validate_location(struct wined3d_resource *sub_resource, DWORD location)
+{
+    struct wined3d_volume *volume = volume_from_resource(sub_resource);
+
+    wined3d_volume_validate_location(volume, location);
+}
+
+static void texture3d_sub_resource_upload_data(struct wined3d_resource *sub_resource,
+        const struct wined3d_context *context, const struct wined3d_sub_resource_data *data)
+{
+    struct wined3d_volume *volume = volume_from_resource(sub_resource);
+    struct wined3d_const_bo_address addr;
+    unsigned int row_pitch, slice_pitch;
+
+    wined3d_volume_get_pitch(volume, &row_pitch, &slice_pitch);
+    if (row_pitch != data->row_pitch || slice_pitch != data->slice_pitch)
+        FIXME("Ignoring row/slice pitch (%u/%u).\n", data->row_pitch, data->slice_pitch);
+
+    addr.buffer_object = 0;
+    addr.addr = data->data;
+
+    wined3d_volume_upload_data(volume, context, &addr);
+}
+
 static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
@@ -1318,6 +1394,8 @@ static const struct wined3d_texture_ops texture3d_ops =
     texture3d_sub_resource_add_dirty_region,
     texture3d_sub_resource_cleanup,
     texture3d_sub_resource_invalidate_location,
+    texture3d_sub_resource_validate_location,
+    texture3d_sub_resource_upload_data,
     texture3d_prepare_texture,
 };
 
@@ -1426,14 +1504,14 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct
 }
 
 HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
-        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
-        struct wined3d_texture **texture)
+        UINT level_count, DWORD surface_flags, const struct wined3d_sub_resource_data *data, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
 {
     struct wined3d_texture *object;
     HRESULT hr;
 
-    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, parent %p, parent_ops %p, texture %p.\n",
-            device, desc, level_count, surface_flags, parent, parent_ops, texture);
+    TRACE("device %p, desc %p, level_count %u, surface_flags %#x, data %p, parent %p, parent_ops %p, texture %p.\n",
+            device, desc, level_count, surface_flags, data, parent, parent_ops, texture);
 
     if (!level_count)
     {
@@ -1471,6 +1549,11 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct
         return hr;
     }
 
+    /* FIXME: We'd like to avoid ever allocating system memory for the texture
+     * in this case. */
+    if (data)
+        wined3d_texture_upload_data(object, data);
+
     TRACE("Created texture %p.\n", object);
     *texture = object;
 
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 58d7321..b5ab862 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -40,8 +40,7 @@ BOOL volume_prepare_system_memory(struct wined3d_volume *volume)
     return TRUE;
 }
 
-static void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch,
-        UINT *slice_pitch)
+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch)
 {
     const struct wined3d_format *format = volume->resource.format;
 
@@ -67,14 +66,15 @@ static void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *
 
 /* Context activation is done by the caller. */
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
-        const struct wined3d_bo_address *data)
+        const struct wined3d_const_bo_address *data)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_format *format = volume->resource.format;
     UINT width = volume->resource.width;
     UINT height = volume->resource.height;
     UINT depth = volume->resource.depth;
-    BYTE *mem = data->addr;
+    const void *mem = data->addr;
+    void *converted_mem = NULL;
 
     TRACE("volume %p, context %p, level %u, format %s (%#x).\n",
             volume, context, volume->texture_level, debug_d3dformat(format->id),
@@ -97,9 +97,10 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
 
         wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch);
 
-        mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth);
-        format->convert(data->addr, mem, src_row_pitch, src_slice_pitch,
+        converted_mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth);
+        format->convert(data->addr, converted_mem, src_row_pitch, src_slice_pitch,
                 dst_row_pitch, dst_slice_pitch, width, height, depth);
+        mem = converted_mem;
     }
 
     if (data->buffer_object)
@@ -119,11 +120,10 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine
         checkGLcall("glBindBufferARB");
     }
 
-    if (mem != data->addr)
-        HeapFree(GetProcessHeap(), 0, mem);
+    HeapFree(GetProcessHeap(), 0, converted_mem);
 }
 
-static void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location)
+void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location)
 {
     TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location));
     volume->locations |= location;
@@ -217,7 +217,7 @@ static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume,
     wined3d_texture_bind_and_dirtify(volume->container, context, !dest_is_srgb);
     wined3d_volume_download_data(volume, context, &data);
     wined3d_texture_bind_and_dirtify(volume->container, context, dest_is_srgb);
-    wined3d_volume_upload_data(volume, context, &data);
+    wined3d_volume_upload_data(volume, context, wined3d_const_bo_address(&data));
 
     HeapFree(GetProcessHeap(), 0, data.addr);
 }
@@ -274,12 +274,12 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume,
             }
             else if (volume->locations & WINED3D_LOCATION_SYSMEM)
             {
-                struct wined3d_bo_address data = {0, volume->resource.heap_memory};
+                struct wined3d_const_bo_address data = {0, volume->resource.heap_memory};
                 wined3d_volume_upload_data(volume, context, &data);
             }
             else if (volume->locations & WINED3D_LOCATION_BUFFER)
             {
-                struct wined3d_bo_address data = {volume->pbo, NULL};
+                struct wined3d_const_bo_address data = {volume->pbo, NULL};
                 wined3d_volume_upload_data(volume, context, &data);
             }
             else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7935a5d..047946b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -948,6 +948,17 @@ struct wined3d_bo_address
     BYTE *addr;
 };
 
+struct wined3d_const_bo_address
+{
+    GLuint buffer_object;
+    const BYTE *addr;
+};
+
+static inline struct wined3d_const_bo_address *wined3d_const_bo_address(struct wined3d_bo_address *data)
+{
+    return (struct wined3d_const_bo_address *)data;
+}
+
 struct wined3d_stream_info_element
 {
     const struct wined3d_format *format;
@@ -2146,6 +2157,9 @@ struct wined3d_texture_ops
             const struct wined3d_box *dirty_region);
     void (*texture_sub_resource_cleanup)(struct wined3d_resource *sub_resource);
     void (*texture_sub_resource_invalidate_location)(struct wined3d_resource *sub_resource, DWORD location);
+    void (*texture_sub_resource_validate_location)(struct wined3d_resource *sub_resource, DWORD location);
+    void (*texture_sub_resource_upload_data)(struct wined3d_resource *sub_resource,
+            const struct wined3d_context *context, const struct wined3d_sub_resource_data *data);
     void (*texture_prepare_texture)(struct wined3d_texture *texture,
             struct wined3d_context *context, BOOL srgb);
 };
@@ -2250,11 +2264,13 @@ BOOL volume_prepare_system_memory(struct wined3d_volume *volume) DECLSPEC_HIDDEN
 HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wined3d_resource_desc *desc,
         unsigned int level, struct wined3d_volume **volume) DECLSPEC_HIDDEN;
 void wined3d_volume_destroy(struct wined3d_volume *volume) DECLSPEC_HIDDEN;
+void wined3d_volume_get_pitch(const struct wined3d_volume *volume, UINT *row_pitch, UINT *slice_pitch) DECLSPEC_HIDDEN;
 void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context,
         BOOL srgb_mode) DECLSPEC_HIDDEN;
 void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN;
+void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) DECLSPEC_HIDDEN;
 void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context,
-        const struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
+        const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
 
 struct wined3d_surface_dib
 {
@@ -2372,6 +2388,9 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w
         struct wined3d_surface **surface) DECLSPEC_HIDDEN;
 void wined3d_surface_destroy(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
 void surface_prepare_map_memory(struct wined3d_surface *surface) DECLSPEC_HIDDEN;
+void wined3d_surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info,
+        const struct wined3d_format *format, const RECT *src_rect, UINT src_pitch, const POINT *dst_point,
+        BOOL srgb, const struct wined3d_const_bo_address *data) DECLSPEC_HIDDEN;
 
 void draw_textured_quad(const struct wined3d_surface *src_surface, struct wined3d_context *context,
         const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 0cf26e1..6e06388 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1721,6 +1721,13 @@ struct wined3d_map_desc
     void *data;
 };
 
+struct wined3d_sub_resource_data
+{
+    const void *data;
+    unsigned int row_pitch;
+    unsigned int slice_pitch;
+};
+
 struct wined3d_box
 {
     UINT left;
@@ -2516,8 +2523,8 @@ void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, H
 HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
         UINT layer, const struct wined3d_box *dirty_region);
 HRESULT __cdecl wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc,
-        UINT level_count, DWORD surface_flags, void *parent, const struct wined3d_parent_ops *parent_ops,
-        struct wined3d_texture **texture);
+        UINT level_count, DWORD surface_flags, const struct wined3d_sub_resource_data *data, void *parent,
+        const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture);
 ULONG __cdecl wined3d_texture_decref(struct wined3d_texture *texture);
 void __cdecl wined3d_texture_generate_mipmaps(struct wined3d_texture *texture);
 enum wined3d_texture_filter_type __cdecl wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture);
-- 
1.7.10.4




More information about the wine-patches mailing list