st/nine: Catch setting the same shader
[mesa.git] / src / gallium / state_trackers / nine / volumetexture9.c
index 65d320c6645ed00ebe09193d82474f1e13735256..e5b2b53148de7966f8e29a3cee9d86a4c07410eb 100644 (file)
@@ -37,27 +37,43 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
                          HANDLE *pSharedHandle )
 {
     struct pipe_resource *info = &This->base.base.info;
+    struct pipe_screen *screen = pParams->device->screen;
+    enum pipe_format pf;
     unsigned l;
     D3DVOLUME_DESC voldesc;
     HRESULT hr;
 
+    DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u "
+        "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n",
+        This, pParams, Width, Height, Depth, Levels,
+        Usage, Format, Pool, pSharedHandle);
+
     /* An IDirect3DVolume9 cannot be bound as a render target can it ? */
     user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)),
                 D3DERR_INVALIDCALL);
-    user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
-                (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
+    user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
 
     user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
 
-    if (Usage & D3DUSAGE_AUTOGENMIPMAP)
-        Levels = 0;
+    pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0,
+                                     PIPE_BIND_SAMPLER_VIEW, FALSE);
+    if (pf == PIPE_FORMAT_NONE)
+        return D3DERR_INVALIDCALL;
+
+    /* We support ATI1 and ATI2 hacks only for 2D textures */
+    if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
+        return D3DERR_INVALIDCALL;
 
-    This->base.format = Format;
-    This->base.base.usage = Usage;
+    if (compressed_format(Format)) {
+        const unsigned w = util_format_get_blockwidth(pf);
+        const unsigned h = util_format_get_blockheight(pf);
+        /* Compressed formats are not compressed on depth component */
+        user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
+    }
 
     info->screen = pParams->device->screen;
     info->target = PIPE_TEXTURE_3D;
-    info->format = d3d9_to_pipe_format(Format);
+    info->format = pf;
     info->width0 = Width;
     info->height0 = Height;
     info->depth0 = Depth;
@@ -77,14 +93,17 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
             PIPE_BIND_TRANSFER_READ |
             PIPE_BIND_TRANSFER_WRITE;
     }
+    if (Usage & D3DUSAGE_SOFTWAREPROCESSING)
+        DBG("Application asked for Software Vertex Processing, "
+            "but this is unimplemented\n");
 
     This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes));
     if (!This->volumes)
         return E_OUTOFMEMORY;
     This->base.pstype = 3;
 
-    hr = NineBaseTexture9_ctor(&This->base, pParams,
-                               D3DRTYPE_VOLUMETEXTURE, Pool);
+    hr = NineBaseTexture9_ctor(&This->base, pParams, NULL,
+                               D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage);
     if (FAILED(hr))
         return hr;
 
@@ -104,6 +123,9 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
             return hr;
     }
 
+    /* Textures start initially dirty */
+    NineVolumeTexture9_AddDirtyBox(This, NULL);
+
     return D3D_OK;
 }
 
@@ -129,8 +151,6 @@ NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This,
                                  D3DVOLUME_DESC *pDesc )
 {
     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
-    user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
-                D3DERR_INVALIDCALL);
 
     *pDesc = This->volumes[Level]->desc;
 
@@ -143,8 +163,6 @@ NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This,
                                    IDirect3DVolume9 **ppVolumeLevel )
 {
     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
-    user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
-                D3DERR_INVALIDCALL);
 
     NineUnknown_AddRef(NineUnknown(This->volumes[Level]));
     *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level];
@@ -159,9 +177,10 @@ NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This,
                             const D3DBOX *pBox,
                             DWORD Flags )
 {
+    DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n",
+        This, Level, pLockedVolume, pBox, Flags);
+
     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
-    user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
-                D3DERR_INVALIDCALL);
 
     return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox,
                                Flags);
@@ -171,6 +190,8 @@ HRESULT WINAPI
 NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This,
                               UINT Level )
 {
+    DBG("This=%p Level=%u\n", This, Level);
+
     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
 
     return NineVolume9_UnlockBox(This->volumes[Level]);
@@ -180,14 +201,16 @@ HRESULT WINAPI
 NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
                                 const D3DBOX *pDirtyBox )
 {
-    if (This->base.base.pool != D3DPOOL_MANAGED) {
-        if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
-            This->base.dirty_mip = TRUE;
+    DBG("This=%p pDirtybox=%p\n", This, pDirtyBox);
+
+    if (This->base.base.pool == D3DPOOL_DEFAULT) {
         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 (!pDirtyBox) {
         This->dirty_box.x = 0;
@@ -200,6 +223,15 @@ NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
         struct pipe_box box;
         d3dbox_to_pipe_box(&box, pDirtyBox);
         u_box_union_3d(&This->dirty_box, &This->dirty_box, &box);
+        This->dirty_box.x = MAX2(This->dirty_box.x, 0);
+        This->dirty_box.y = MAX2(This->dirty_box.y, 0);
+        This->dirty_box.z = MAX2(This->dirty_box.z, 0);
+        This->dirty_box.width = MIN2(This->dirty_box.width,
+                                     This->base.base.info.width0 - This->dirty_box.x);
+        This->dirty_box.height = MIN2(This->dirty_box.height,
+                                     This->base.base.info.height0 - This->dirty_box.y);
+        This->dirty_box.depth = MIN2(This->dirty_box.depth,
+                                     This->base.base.info.depth0 - This->dirty_box.z);
     }
     return D3D_OK;
 }