st/nine: Add Render state validation layer
[mesa.git] / src / gallium / state_trackers / nine / resource9.c
index 8f535580bbfe22630eae803db24a778115f0d17f..b929c50a83c739ae401ad78ab9be222c2b47912e 100644 (file)
 
 #include "util/u_hash_table.h"
 #include "util/u_inlines.h"
+#include "util/u_resource.h"
 
 #include "nine_pdata.h"
 
 #define DBG_CHANNEL DBG_RESOURCE
 
-
 HRESULT
 NineResource9_ctor( struct NineResource9 *This,
                     struct NineUnknownParams *pParams,
+                    struct pipe_resource *initResource,
                     BOOL Allocate,
                     D3DRESOURCETYPE Type,
-                    D3DPOOL Pool )
+                    D3DPOOL Pool,
+                    DWORD Usage)
 {
     struct pipe_screen *screen;
     HRESULT hr;
 
+    DBG("This=%p pParams=%p initResource=%p Allocate=%d "
+        "Type=%d Pool=%d Usage=%d\n",
+        This, pParams, initResource, (int) Allocate,
+        Type, Pool, Usage);
+
     hr = NineUnknown_ctor(&This->base, pParams);
     if (FAILED(hr))
         return hr;
 
     This->info.screen = screen = This->base.device->screen;
+    if (initResource)
+        pipe_resource_reference(&This->resource, initResource);
 
     if (Allocate) {
+        assert(!initResource);
+
+        /* On Windows it is possible allocation fails when
+         * IDirect3DDevice9::GetAvailableTextureMem() still reports
+         * enough free space.
+         *
+         * Some games allocate surfaces
+         * in a loop until they receive D3DERR_OUTOFVIDEOMEMORY to measure
+         * the available texture memory size.
+         *
+         * We are not using the drivers VRAM statistics because:
+         *  * This would add overhead to each resource allocation.
+         *  * Freeing memory is lazy and takes some time, but applications
+         *    expects the memory counter to change immediately after allocating
+         *    or freeing memory.
+         *
+         * Vertexbuffers and indexbuffers are not accounted !
+         */
+        if (This->info.target != PIPE_BUFFER) {
+            This->size = util_resource_size(&This->info);
+
+            This->base.device->available_texture_mem -= This->size;
+            if (This->base.device->available_texture_mem <=
+                    This->base.device->available_texture_limit) {
+                return D3DERR_OUTOFVIDEOMEMORY;
+            }
+        }
+
         DBG("(%p) Creating pipe_resource.\n", This);
         This->resource = screen->resource_create(screen, &This->info);
         if (!This->resource)
             return D3DERR_OUTOFVIDEOMEMORY;
     }
 
-    This->data = NULL; /* FIXME remove, rather set it to null in surface9.c*/
     This->type = Type;
     This->pool = Pool;
+    This->usage = Usage;
     This->priority = 0;
 
     This->pdata = util_hash_table_create(ht_guid_hash, ht_guid_compare);
@@ -82,9 +119,9 @@ NineResource9_dtor( struct NineResource9 *This )
      * still hold a reference. */
     pipe_resource_reference(&This->resource, NULL);
 
-    /* release allocated system memory for non-D3DPOOL_DEFAULT resources */
-    if (This->data)
-        FREE(This->data);
+    /* NOTE: size is 0, unless something has actually been allocated */
+    if (This->base.device)
+        This->base.device->available_texture_mem += This->size;
 
     NineUnknown_dtor(&This->base);
 }
@@ -111,9 +148,10 @@ NineResource9_SetPrivateData( struct NineResource9 *This,
     enum pipe_error err;
     struct pheader *header;
     const void *user_data = pData;
+    char guid_str[64];
 
-    DBG("This=%p refguid=%p pData=%p SizeOfData=%u Flags=%x\n",
-        This, refguid, pData, SizeOfData, Flags);
+    DBG("This=%p GUID=%s pData=%p SizeOfData=%u Flags=%x\n",
+        This, GUID_sprintf(guid_str, refguid), pData, SizeOfData, Flags);
 
     if (Flags & D3DSPD_IUNKNOWN)
         user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL);
@@ -135,8 +173,9 @@ NineResource9_SetPrivateData( struct NineResource9 *This,
 
     header->size = SizeOfData;
     memcpy(header->data, user_data, header->size);
+    memcpy(&header->guid, refguid, sizeof(header->guid));
 
-    err = util_hash_table_set(This->pdata, refguid, header);
+    err = util_hash_table_set(This->pdata, &header->guid, header);
     if (err == PIPE_OK) {
         if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
         return D3D_OK;
@@ -155,20 +194,23 @@ NineResource9_GetPrivateData( struct NineResource9 *This,
                               DWORD *pSizeOfData )
 {
     struct pheader *header;
+    DWORD sizeofdata;
+    char guid_str[64];
 
-    DBG("This=%p refguid=%p pData=%p pSizeOfData=%p\n",
-        This, refguid, pData, pSizeOfData);
-
-    user_assert(pSizeOfData, E_POINTER);
+    DBG("This=%p GUID=%s pData=%p pSizeOfData=%p\n",
+        This, GUID_sprintf(guid_str, refguid), pData, pSizeOfData);
 
     header = util_hash_table_get(This->pdata, refguid);
     if (!header) { return D3DERR_NOTFOUND; }
 
+    user_assert(pSizeOfData, E_POINTER);
+    sizeofdata = *pSizeOfData;
+    *pSizeOfData = header->size;
+
     if (!pData) {
-        *pSizeOfData = header->size;
         return D3D_OK;
     }
-    if (*pSizeOfData < header->size) {
+    if (sizeofdata < header->size) {
         return D3DERR_MOREDATA;
     }
 
@@ -183,8 +225,9 @@ NineResource9_FreePrivateData( struct NineResource9 *This,
                                REFGUID refguid )
 {
     struct pheader *header;
+    char guid_str[64];
 
-    DBG("This=%p refguid=%p\n", This, refguid);
+    DBG("This=%p GUID=%s\n", This, GUID_sprintf(guid_str, refguid));
 
     header = util_hash_table_get(This->pdata, refguid);
     if (!header)
@@ -200,7 +243,13 @@ DWORD WINAPI
 NineResource9_SetPriority( struct NineResource9 *This,
                            DWORD PriorityNew )
 {
-    DWORD prev = This->priority;
+    DWORD prev;
+    DBG("This=%p, PriorityNew=%d\n", This, PriorityNew);
+
+    if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
+        return 0;
+
+    prev = This->priority;
     This->priority = PriorityNew;
     return prev;
 }
@@ -208,6 +257,9 @@ NineResource9_SetPriority( struct NineResource9 *This,
 DWORD WINAPI
 NineResource9_GetPriority( struct NineResource9 *This )
 {
+    if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
+        return 0;
+
     return This->priority;
 }