st/nine: Allocate surface resources in surface ctor
authorPatrick Rudolph <siro@das-labor.org>
Thu, 15 Sep 2016 18:28:17 +0000 (20:28 +0200)
committerAxel Davy <axel.davy@ens.fr>
Mon, 10 Oct 2016 21:43:51 +0000 (23:43 +0200)
Allocate resources in surface ctor.
Allows to use statetracker internal memory accounting.

Fix for issue #231.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Signed-off-by: Axel Davy <axel.davy@ens.fr>
src/gallium/state_trackers/nine/device9.c
src/gallium/state_trackers/nine/surface9.c

index 298af86e484590e2af6437174b3d25e799c5041f..50565b876ddcc910f72f20559d1c2cf0fe0e5f38 100644 (file)
@@ -1134,11 +1134,8 @@ create_zs_or_rt_surface(struct NineDevice9 *This,
                         HANDLE *pSharedHandle)
 {
     struct NineSurface9 *surface;
-    struct pipe_screen *screen = This->screen;
-    struct pipe_resource *resource = NULL;
     HRESULT hr;
     D3DSURFACE_DESC desc;
-    struct pipe_resource templ;
 
     DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
         "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
@@ -1152,31 +1149,6 @@ create_zs_or_rt_surface(struct NineDevice9 *This,
     user_assert(Width && Height, D3DERR_INVALIDCALL);
     user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
 
-    memset(&templ, 0, sizeof(templ));
-    templ.target = PIPE_TEXTURE_2D;
-    templ.width0 = Width;
-    templ.height0 = Height;
-    templ.depth0 = 1;
-    templ.array_size = 1;
-    templ.last_level = 0;
-    templ.nr_samples = (unsigned)MultiSample;
-    templ.usage = PIPE_USAGE_DEFAULT;
-    templ.flags = 0;
-    templ.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
-    switch (type) {
-    case 0: templ.bind |= PIPE_BIND_RENDER_TARGET; break;
-    case 1: templ.bind = d3d9_get_pipe_depth_format_bindings(Format); break;
-    default:
-        assert(type == 2);
-        break;
-    }
-    templ.format = d3d9_to_pipe_format_checked(screen, Format, templ.target,
-                                               templ.nr_samples, templ.bind,
-                                               FALSE, Pool == D3DPOOL_SCRATCH);
-
-    if (templ.format == PIPE_FORMAT_NONE && Format != D3DFMT_NULL)
-        return D3DERR_INVALIDCALL;
-
     desc.Format = Format;
     desc.Type = D3DRTYPE_SURFACE;
     desc.Usage = 0;
@@ -1188,31 +1160,17 @@ create_zs_or_rt_surface(struct NineDevice9 *This,
     switch (type) {
     case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;
     case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;
-    default: break;
+    default: assert(type == 2); break;
     }
 
-    if (compressed_format(Format)) {
-        const unsigned w = util_format_get_blockwidth(templ.format);
-        const unsigned h = util_format_get_blockheight(templ.format);
+    hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface);
+    if (SUCCEEDED(hr)) {
+        *ppSurface = (IDirect3DSurface9 *)surface;
 
-        user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
+        if (surface->base.resource && Discard_or_Lockable && (type != 1))
+            surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
     }
 
-    if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) {
-        /* resource_create doesn't return an error code, so check format here */
-        user_assert(templ.format != PIPE_FORMAT_NONE, D3DERR_INVALIDCALL);
-        resource = screen->resource_create(screen, &templ);
-        user_assert(resource, D3DERR_OUTOFVIDEOMEMORY);
-        if (Discard_or_Lockable && (desc.Usage & D3DUSAGE_RENDERTARGET))
-            resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
-    } else {
-        resource = NULL;
-    }
-    hr = NineSurface9_new(This, NULL, resource, NULL, 0, 0, 0, &desc, &surface);
-    pipe_resource_reference(&resource, NULL);
-
-    if (SUCCEEDED(hr))
-        *ppSurface = (IDirect3DSurface9 *)surface;
     return hr;
 }
 
index 508fa9a508df9cf075f21e6017b01c203e6a7980..e6a48e2041b75fb8812b64f636ef02b623efb0f6 100644 (file)
@@ -57,30 +57,34 @@ NineSurface9_ctor( struct NineSurface9 *This,
     union pipe_color_union rgba = {0};
     struct pipe_surface *surf;
     struct pipe_context *pipe = pParams->device->pipe;
+    bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL;
 
     DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n",
         This, pParams->device, pResource, Level, Layer, pDesc);
 
     /* Mark this as a special surface held by another internal resource. */
     pParams->container = pContainer;
+    /* Make sure there's a Desc */
+    assert(pDesc);
 
+    /* D3DUSAGE_DYNAMIC isn't allowed on managed buffers */
     user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
                 (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
 
-    assert(pResource || (user_buffer && pDesc->Pool != D3DPOOL_DEFAULT) ||
-           (!pContainer && pDesc->Pool != D3DPOOL_DEFAULT) ||
+    assert(allocate || pResource || user_buffer ||
            pDesc->Format == D3DFMT_NULL);
-
+    assert(!allocate || (!pResource && !user_buffer));
     assert(!pResource || !user_buffer);
     assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT);
-    /* The only way we can have !pContainer is being created
-     * from create_zs_or_rt_surface with params 0 0 0 */
-    assert(pContainer || (Level == 0 && Layer == 0 && TextureType == 0));
-    /* Make sure no resource is passed for pool systemmem */
-    assert(pDesc->Pool != D3DPOOL_SYSTEMMEM || !pResource);
+    assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT);
+    /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */
+    assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0));
 
     This->data = (uint8_t *)user_buffer;
 
+    /* TODO: this is (except width and height) duplicate from
+     * container info (in the pContainer case). Some refactoring is
+     * needed to avoid duplication */
     This->base.info.screen = pParams->device->screen;
     This->base.info.target = PIPE_TEXTURE_2D;
     This->base.info.width0 = pDesc->Width;
@@ -90,7 +94,16 @@ NineSurface9_ctor( struct NineSurface9 *This,
     This->base.info.array_size = 1;
     This->base.info.nr_samples = pDesc->MultiSampleType;
     This->base.info.usage = PIPE_USAGE_DEFAULT;
-    This->base.info.bind = PIPE_BIND_SAMPLER_VIEW;
+    This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
+
+    if (pDesc->Usage & D3DUSAGE_RENDERTARGET) {
+        This->base.info.bind |= PIPE_BIND_RENDER_TARGET;
+    } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) {
+        This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format);
+        if (TextureType)
+            This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW;
+    }
+
     This->base.info.flags = 0;
     This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen,
                                                          pDesc->Format,
@@ -100,10 +113,16 @@ NineSurface9_ctor( struct NineSurface9 *This,
                                                          FALSE,
                                                          pDesc->Pool == D3DPOOL_SCRATCH);
 
-    if (pDesc->Usage & D3DUSAGE_RENDERTARGET)
-        This->base.info.bind |= PIPE_BIND_RENDER_TARGET;
-    if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL)
-        This->base.info.bind |= PIPE_BIND_DEPTH_STENCIL;
+    if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL)
+        return D3DERR_INVALIDCALL;
+
+    if (allocate && compressed_format(pDesc->Format)) {
+        const unsigned w = util_format_get_blockwidth(This->base.info.format);
+        const unsigned h = util_format_get_blockheight(This->base.info.format);
+
+        /* Note: In the !allocate case, the test could fail (lower levels of a texture) */
+        user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL);
+    }
 
     /* Get true format */
     This->format_conversion = d3d9_to_pipe_format_checked(This->base.info.screen,
@@ -125,8 +144,8 @@ NineSurface9_ctor( struct NineSurface9 *This,
                                                          pDesc->Width);
     }
 
-    /* Ram buffer with no parent. Has to allocate the resource itself */
-    if (!pResource && !pContainer) {
+    if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) {
+        /* Ram buffer with no parent. Has to allocate the resource itself */
         assert(!user_buffer);
         This->data = align_malloc(
             nine_format_get_level_alloc_size(This->base.info.format,
@@ -137,11 +156,10 @@ NineSurface9_ctor( struct NineSurface9 *This,
             return E_OUTOFMEMORY;
     }
 
-    if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
-        pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
+    hr = NineResource9_ctor(&This->base, pParams, pResource,
+                            allocate && (pDesc->Pool == D3DPOOL_DEFAULT),
+                            D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage);
 
-    hr = NineResource9_ctor(&This->base, pParams, pResource, FALSE, D3DRTYPE_SURFACE,
-                            pDesc->Pool, pDesc->Usage);
     if (FAILED(hr))
         return hr;
 
@@ -156,7 +174,7 @@ NineSurface9_ctor( struct NineSurface9 *This,
 
     This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);
 
-    if (pResource && NineSurface9_IsOffscreenPlain(This))
+    if (pDesc->Usage & D3DUSAGE_DYNAMIC)
         pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
 
     /* TODO: investigate what else exactly needs to be cleared */