st/nine: Fix volumetexture dtor on ctor failure
[mesa.git] / src / gallium / state_trackers / nine / cubetexture9.c
index 8e1659a06ee8adc0db691e042f4eef7b80e31556..89821682f8f293c710e698ea4f7026bca9e8ad3e 100644 (file)
@@ -20,6 +20,8 @@
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
 
+#include "c99_alloca.h"
+
 #include "device9.h"
 #include "cubetexture9.h"
 #include "nine_helpers.h"
@@ -40,8 +42,10 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
     struct pipe_resource *info = &This->base.base.info;
     struct pipe_screen *screen = pParams->device->screen;
     enum pipe_format pf;
-    unsigned i;
+    unsigned i, l, f, offset, face_size = 0;
+    unsigned *level_offsets = NULL;
     D3DSURFACE_DESC sfdesc;
+    void *p;
     HRESULT hr;
 
     DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
@@ -49,24 +53,31 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
         This, pParams, EdgeLength, Levels, Usage,
         Format, Pool, pSharedHandle);
 
-    user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
-                (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+    user_assert(EdgeLength, D3DERR_INVALIDCALL);
 
+    /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */
     user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
 
+    user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
+                (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+
     if (Usage & D3DUSAGE_AUTOGENMIPMAP)
         Levels = 0;
 
-    pf = d3d9_to_pipe_format(Format);
-    if (pf == PIPE_FORMAT_NONE ||
-        !screen->is_format_supported(screen, pf, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW)) {
-        return D3DERR_INVALIDCALL;
-    }
+    pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0,
+                                     PIPE_BIND_SAMPLER_VIEW, FALSE,
+                                     Pool == D3DPOOL_SCRATCH);
 
-    /* We support ATI1 and ATI2 hacks only for 2D textures */
-    if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
+    if (pf == PIPE_FORMAT_NONE)
         return D3DERR_INVALIDCALL;
 
+    if (compressed_format(Format)) {
+        const unsigned w = util_format_get_blockwidth(pf);
+        const unsigned h = util_format_get_blockheight(pf);
+
+        user_assert(!(EdgeLength % w) && !(EdgeLength % h), D3DERR_INVALIDCALL);
+    }
+
     info->screen = pParams->device->screen;
     info->target = PIPE_TEXTURE_CUBE;
     info->format = pf;
@@ -79,6 +90,7 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
         info->last_level = util_logbase2(EdgeLength);
     info->array_size = 6;
     info->nr_samples = 0;
+    info->nr_storage_samples = 0;
     info->bind = PIPE_BIND_SAMPLER_VIEW;
     info->usage = PIPE_USAGE_DEFAULT;
     info->flags = 0;
@@ -90,9 +102,19 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
 
     if (Usage & D3DUSAGE_DYNAMIC) {
         info->usage = PIPE_USAGE_DYNAMIC;
-        info->bind |=
-            PIPE_BIND_TRANSFER_READ |
-            PIPE_BIND_TRANSFER_WRITE;
+    }
+    if (Usage & D3DUSAGE_SOFTWAREPROCESSING)
+        DBG("Application asked for Software Vertex Processing, "
+            "but this is unimplemented\n");
+
+    if (Pool != D3DPOOL_DEFAULT) {
+        level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
+        face_size = nine_format_get_size_and_offsets(pf, level_offsets,
+                                                     EdgeLength, EdgeLength,
+                                                     info->last_level);
+        This->managed_buffer = align_calloc(6 * face_size, 32);
+        if (!This->managed_buffer)
+            return E_OUTOFMEMORY;
     }
 
     This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
@@ -115,18 +137,31 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
     sfdesc.Pool = Pool;
     sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
     sfdesc.MultiSampleQuality = 0;
-    for (i = 0; i < (info->last_level + 1) * 6; ++i) {
-        sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, i / 6);
-
-        hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
-                              This->base.base.resource, NULL, D3DRTYPE_CUBETEXTURE,
-                              i / 6, i % 6,
-                              &sfdesc, &This->surfaces[i]);
-        if (FAILED(hr))
-            return hr;
+    /* We allocate the memory for the surfaces as continous blocks.
+     * This is the expected behaviour, however we haven't tested for
+     * cube textures in which order the faces/levels should be in memory
+     */
+    for (f = 0; f < 6; f++) {
+        offset = f * face_size;
+        for (l = 0; l <= info->last_level; l++) {
+            sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l);
+            p = This->managed_buffer ? This->managed_buffer + offset +
+                    level_offsets[l] : NULL;
+
+            hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
+                                  This->base.base.resource, p, D3DRTYPE_CUBETEXTURE,
+                                  l, f, &sfdesc, &This->surfaces[f + 6 * l]);
+            if (FAILED(hr))
+                return hr;
+        }
     }
-    for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
+
+    for (i = 0; i < 6; ++i) {
+        /* Textures start initially dirty */
+        This->dirty_rect[i].width = EdgeLength;
+        This->dirty_rect[i].height = EdgeLength;
         This->dirty_rect[i].depth = 1;
+    }
 
     return D3D_OK;
 }
@@ -139,15 +174,18 @@ NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
     DBG("This=%p\n", This);
 
     if (This->surfaces) {
-        for (i = 0; i < This->base.base.info.last_level * 6; ++i)
+        for (i = 0; i < (This->base.base.info.last_level + 1) * 6; ++i)
             NineUnknown_Destroy(&This->surfaces[i]->base.base);
         FREE(This->surfaces);
     }
 
+    if (This->managed_buffer)
+        align_free(This->managed_buffer);
+
     NineBaseTexture9_dtor(&This->base);
 }
 
-HRESULT WINAPI
+HRESULT NINE_WINAPI
 NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
                                UINT Level,
                                D3DSURFACE_DESC *pDesc )
@@ -163,7 +201,7 @@ NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
     return D3D_OK;
 }
 
-HRESULT WINAPI
+HRESULT NINE_WINAPI
 NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
                                     D3DCUBEMAP_FACES FaceType,
                                     UINT Level,
@@ -185,7 +223,7 @@ NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
     return D3D_OK;
 }
 
-HRESULT WINAPI
+HRESULT NINE_WINAPI
 NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
                            D3DCUBEMAP_FACES FaceType,
                            UINT Level,
@@ -206,7 +244,7 @@ NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
     return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags);
 }
 
-HRESULT WINAPI
+HRESULT NINE_WINAPI
 NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
                              D3DCUBEMAP_FACES FaceType,
                              UINT Level )
@@ -221,7 +259,7 @@ NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
     return NineSurface9_UnlockRect(This->surfaces[s]);
 }
 
-HRESULT WINAPI
+HRESULT NINE_WINAPI
 NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
                                D3DCUBEMAP_FACES FaceType,
                                const RECT *pDirtyRect )
@@ -231,23 +269,35 @@ NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
     user_assert(FaceType < 6, D3DERR_INVALIDCALL);
 
     if (This->base.base.pool != D3DPOOL_MANAGED) {
-        if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+        if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) {
             This->base.dirty_mip = TRUE;
+            BASETEX_REGISTER_UPDATE(&This->base);
+        }
         return D3D_OK;
     }
-    This->base.dirty = TRUE;
 
-    BASETEX_REGISTER_UPDATE(&This->base);
+    if (This->base.base.pool == D3DPOOL_MANAGED) {
+        This->base.managed.dirty = TRUE;
+        BASETEX_REGISTER_UPDATE(&This->base);
+    }
 
     if (!pDirtyRect) {
         u_box_origin_2d(This->base.base.info.width0,
                         This->base.base.info.height0,
                         &This->dirty_rect[FaceType]);
     } else {
-        struct pipe_box box;
-        rect_to_pipe_box_clamp(&box, pDirtyRect);
-        u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType],
-                       &box);
+        if (This->dirty_rect[FaceType].width == 0) {
+            rect_to_pipe_box_clamp(&This->dirty_rect[FaceType], pDirtyRect);
+        } else {
+            struct pipe_box box;
+            rect_to_pipe_box_clamp(&box, pDirtyRect);
+            u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType],
+                           &box);
+        }
+        (void) u_box_clip_2d(&This->dirty_rect[FaceType],
+                             &This->dirty_rect[FaceType],
+                             This->base.base.info.width0,
+                             This->base.base.info.height0);
     }
     return D3D_OK;
 }
@@ -257,9 +307,9 @@ IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = {
     (void *)NineUnknown_AddRef,
     (void *)NineUnknown_Release,
     (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
-    (void *)NineResource9_SetPrivateData,
-    (void *)NineResource9_GetPrivateData,
-    (void *)NineResource9_FreePrivateData,
+    (void *)NineUnknown_SetPrivateData,
+    (void *)NineUnknown_GetPrivateData,
+    (void *)NineUnknown_FreePrivateData,
     (void *)NineResource9_SetPriority,
     (void *)NineResource9_GetPriority,
     (void *)NineBaseTexture9_PreLoad,